mirror of
https://github.com/n8n-io/n8n.git
synced 2026-08-30 18:01:23 +08:00
feat(core): Block access to env in code and expressions by default (#22643)
This commit is contained in:
@@ -20,7 +20,6 @@ describe('DeprecationService', () => {
|
||||
// Ignore environment variables coming in from the environment when running
|
||||
// this test suite.
|
||||
process.env = {
|
||||
N8N_BLOCK_ENV_ACCESS_IN_NODE: 'false',
|
||||
N8N_GIT_NODE_DISABLE_BARE_REPOS: 'false',
|
||||
};
|
||||
|
||||
@@ -117,7 +116,6 @@ describe('DeprecationService', () => {
|
||||
beforeEach(() => {
|
||||
process.env = {
|
||||
N8N_RUNNERS_ENABLED: 'true',
|
||||
N8N_BLOCK_ENV_ACCESS_IN_NODE: 'false',
|
||||
N8N_GIT_NODE_DISABLE_BARE_REPOS: 'false',
|
||||
};
|
||||
});
|
||||
@@ -210,37 +208,10 @@ describe('DeprecationService', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('N8N_BLOCK_ENV_ACCESS_IN_NODE', () => {
|
||||
beforeEach(() => {
|
||||
process.env = {
|
||||
N8N_RUNNERS_ENABLED: 'true',
|
||||
N8N_GIT_NODE_DISABLE_BARE_REPOS: 'false',
|
||||
};
|
||||
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
test('should warn when N8N_BLOCK_ENV_ACCESS_IN_NODE is not set', () => {
|
||||
delete process.env.N8N_BLOCK_ENV_ACCESS_IN_NODE;
|
||||
deprecationService.warn();
|
||||
expect(logger.warn).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test.each(['false', 'true'])(
|
||||
'should not warn when N8N_BLOCK_ENV_ACCESS_IN_NODE is %s',
|
||||
(value) => {
|
||||
process.env.N8N_BLOCK_ENV_ACCESS_IN_NODE = value;
|
||||
deprecationService.warn();
|
||||
expect(logger.warn).not.toHaveBeenCalled();
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
describe('N8N_GIT_NODE_DISABLE_BARE_REPOS', () => {
|
||||
beforeEach(() => {
|
||||
process.env = {
|
||||
N8N_RUNNERS_ENABLED: 'true',
|
||||
N8N_BLOCK_ENV_ACCESS_IN_NODE: 'false',
|
||||
};
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
@@ -91,12 +91,6 @@ export class DeprecationService {
|
||||
'n8n does not support `own` mode since May 2023. Please remove this environment variable to allow n8n to start. If you need the isolation and performance gains, please consider queue mode: https://docs.n8n.io/hosting/scaling/queue-mode/',
|
||||
checkValue: (value: string) => value === 'own',
|
||||
},
|
||||
{
|
||||
envVar: 'N8N_BLOCK_ENV_ACCESS_IN_NODE',
|
||||
message:
|
||||
'The default value of N8N_BLOCK_ENV_ACCESS_IN_NODE will be changed from false to true in a future version. If you need to access environment variables from the Code Node or from expressions, please set N8N_BLOCK_ENV_ACCESS_IN_NODE=false. Learn more: https://docs.n8n.io/hosting/configuration/environment-variables/security/',
|
||||
checkValue: (value: string | undefined) => value === undefined || value === '',
|
||||
},
|
||||
{
|
||||
envVar: 'N8N_GIT_NODE_DISABLE_BARE_REPOS',
|
||||
message:
|
||||
|
||||
@@ -11,7 +11,7 @@ type PythonSandboxContext = {
|
||||
|
||||
type PyodideError = Error & { type: string };
|
||||
|
||||
const envAccessBlocked = process.env.N8N_BLOCK_ENV_ACCESS_IN_NODE === 'true';
|
||||
const envAccessBlocked = process.env.N8N_BLOCK_ENV_ACCESS_IN_NODE !== 'false';
|
||||
|
||||
export class PythonSandbox extends Sandbox {
|
||||
private readonly context: PythonSandboxContext;
|
||||
|
||||
@@ -282,7 +282,7 @@ export class Expression {
|
||||
typeof process !== 'undefined'
|
||||
? {
|
||||
arch: process.arch,
|
||||
env: process.env.N8N_BLOCK_ENV_ACCESS_IN_NODE === 'true' ? {} : process.env,
|
||||
env: process.env.N8N_BLOCK_ENV_ACCESS_IN_NODE !== 'false' ? {} : process.env,
|
||||
platform: process.platform,
|
||||
pid: process.pid,
|
||||
ppid: process.ppid,
|
||||
|
||||
@@ -13,7 +13,7 @@ export type EnvProviderState = {
|
||||
export function createEnvProviderState(): EnvProviderState {
|
||||
const isProcessAvailable = typeof process !== 'undefined';
|
||||
const isEnvAccessBlocked = isProcessAvailable
|
||||
? process.env.N8N_BLOCK_ENV_ACCESS_IN_NODE === 'true'
|
||||
? process.env.N8N_BLOCK_ENV_ACCESS_IN_NODE !== 'false'
|
||||
: false;
|
||||
const env: Record<string, string> =
|
||||
!isProcessAvailable || isEnvAccessBlocked ? {} : (process.env as Record<string, string>);
|
||||
|
||||
@@ -7,6 +7,8 @@ describe('createEnvProviderState', () => {
|
||||
});
|
||||
|
||||
it('should return the state with process available and env access allowed', () => {
|
||||
process.env.N8N_BLOCK_ENV_ACCESS_IN_NODE = 'false';
|
||||
|
||||
expect(createEnvProviderState()).toEqual({
|
||||
isProcessAvailable: true,
|
||||
isEnvAccessBlocked: false,
|
||||
@@ -24,6 +26,14 @@ describe('createEnvProviderState', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should block env access when N8N_BLOCK_ENV_ACCESS_IN_NODE is not set', () => {
|
||||
expect(createEnvProviderState()).toEqual({
|
||||
isProcessAvailable: true,
|
||||
isEnvAccessBlocked: true,
|
||||
env: {},
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle process not being available', () => {
|
||||
const originalProcess = global.process;
|
||||
try {
|
||||
@@ -42,12 +52,18 @@ describe('createEnvProviderState', () => {
|
||||
});
|
||||
|
||||
describe('createEnvProvider', () => {
|
||||
afterEach(() => {
|
||||
delete process.env.N8N_BLOCK_ENV_ACCESS_IN_NODE;
|
||||
});
|
||||
|
||||
it('should return true when checking for a property using "has"', () => {
|
||||
const proxy = createEnvProvider(0, 0, createEnvProviderState());
|
||||
expect('someProperty' in proxy).toBe(true);
|
||||
});
|
||||
|
||||
it('should return the value from process.env if access is allowed', () => {
|
||||
process.env.N8N_BLOCK_ENV_ACCESS_IN_NODE = 'false';
|
||||
|
||||
process.env.TEST_ENV_VAR = 'test_value';
|
||||
const proxy = createEnvProvider(0, 0, createEnvProviderState());
|
||||
expect(proxy.TEST_ENV_VAR).toBe('test_value');
|
||||
|
||||
@@ -1743,6 +1743,8 @@ describe('Workflow', () => {
|
||||
|
||||
for (const testData of tests) {
|
||||
test(testData.description, () => {
|
||||
process.env.N8N_BLOCK_ENV_ACCESS_IN_NODE = 'false';
|
||||
|
||||
const nodes: INode[] = [
|
||||
{
|
||||
name: 'Node1',
|
||||
|
||||
Reference in New Issue
Block a user