mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 01:56:46 +00:00
fix: Fix issue with restricted file access order (#17329)
This commit is contained in:
@@ -119,6 +119,36 @@ describe('isFilePathBlocked', () => {
|
|||||||
expect(isFilePathBlocked(invitePath)).toBe(true);
|
expect(isFilePathBlocked(invitePath)).toBe(true);
|
||||||
expect(isFilePathBlocked(pwResetPath)).toBe(true);
|
expect(isFilePathBlocked(pwResetPath)).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should block access to n8n files if restrict and block are set', () => {
|
||||||
|
const homeVarName = process.platform === 'win32' ? 'USERPROFILE' : 'HOME';
|
||||||
|
const userHome = process.env.N8N_USER_FOLDER ?? process.env[homeVarName] ?? process.cwd();
|
||||||
|
|
||||||
|
process.env[RESTRICT_FILE_ACCESS_TO] = userHome;
|
||||||
|
process.env[BLOCK_FILE_ACCESS_TO_N8N_FILES] = 'true';
|
||||||
|
const restrictedPath = instanceSettings.n8nFolder;
|
||||||
|
expect(isFilePathBlocked(restrictedPath)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should allow access to parent folder if restrict and block are set', () => {
|
||||||
|
const homeVarName = process.platform === 'win32' ? 'USERPROFILE' : 'HOME';
|
||||||
|
const userHome = process.env.N8N_USER_FOLDER ?? process.env[homeVarName] ?? process.cwd();
|
||||||
|
|
||||||
|
process.env[RESTRICT_FILE_ACCESS_TO] = userHome;
|
||||||
|
process.env[BLOCK_FILE_ACCESS_TO_N8N_FILES] = 'true';
|
||||||
|
const restrictedPath = join(userHome, 'somefile.txt');
|
||||||
|
expect(isFilePathBlocked(restrictedPath)).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not block similar paths', () => {
|
||||||
|
const homeVarName = process.platform === 'win32' ? 'USERPROFILE' : 'HOME';
|
||||||
|
const userHome = process.env.N8N_USER_FOLDER ?? process.env[homeVarName] ?? process.cwd();
|
||||||
|
|
||||||
|
process.env[RESTRICT_FILE_ACCESS_TO] = userHome;
|
||||||
|
process.env[BLOCK_FILE_ACCESS_TO_N8N_FILES] = 'true';
|
||||||
|
const restrictedPath = join(userHome, '.n8n_x');
|
||||||
|
expect(isFilePathBlocked(restrictedPath)).toBe(false);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('getFileSystemHelperFunctions', () => {
|
describe('getFileSystemHelperFunctions', () => {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { safeJoinPath } from '@n8n/backend-common';
|
import { isContainedWithin, safeJoinPath } from '@n8n/backend-common';
|
||||||
import { Container } from '@n8n/di';
|
import { Container } from '@n8n/di';
|
||||||
import type { FileSystemHelperFunctions, INode } from 'n8n-workflow';
|
import type { FileSystemHelperFunctions, INode } from 'n8n-workflow';
|
||||||
import { NodeOperationError } from 'n8n-workflow';
|
import { NodeOperationError } from 'n8n-workflow';
|
||||||
@@ -34,52 +34,17 @@ export function isFilePathBlocked(filePath: string): boolean {
|
|||||||
const resolvedFilePath = resolve(filePath);
|
const resolvedFilePath = resolve(filePath);
|
||||||
const blockFileAccessToN8nFiles = process.env[BLOCK_FILE_ACCESS_TO_N8N_FILES] !== 'false';
|
const blockFileAccessToN8nFiles = process.env[BLOCK_FILE_ACCESS_TO_N8N_FILES] !== 'false';
|
||||||
|
|
||||||
//if allowed paths are defined, allow access only to those paths
|
const restrictedPaths = blockFileAccessToN8nFiles ? getN8nRestrictedPaths() : [];
|
||||||
if (allowedPaths.length) {
|
if (
|
||||||
for (const path of allowedPaths) {
|
restrictedPaths.some((restrictedPath) => isContainedWithin(restrictedPath, resolvedFilePath))
|
||||||
if (resolvedFilePath.startsWith(path)) {
|
) {
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//restrict access to .n8n folder, ~/.cache/n8n/public, and other .env config related paths
|
if (allowedPaths.length) {
|
||||||
if (blockFileAccessToN8nFiles) {
|
return !allowedPaths.some((allowedPath) => isContainedWithin(allowedPath, resolvedFilePath));
|
||||||
const { n8nFolder, staticCacheDir } = Container.get(InstanceSettings);
|
|
||||||
const restrictedPaths = [n8nFolder, staticCacheDir];
|
|
||||||
|
|
||||||
if (process.env[CONFIG_FILES]) {
|
|
||||||
restrictedPaths.push(...process.env[CONFIG_FILES].split(','));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (process.env[CUSTOM_EXTENSION_ENV]) {
|
|
||||||
const customExtensionFolders = process.env[CUSTOM_EXTENSION_ENV].split(';');
|
|
||||||
restrictedPaths.push(...customExtensionFolders);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (process.env[BINARY_DATA_STORAGE_PATH]) {
|
|
||||||
restrictedPaths.push(process.env[BINARY_DATA_STORAGE_PATH]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (process.env[UM_EMAIL_TEMPLATES_INVITE]) {
|
|
||||||
restrictedPaths.push(process.env[UM_EMAIL_TEMPLATES_INVITE]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (process.env[UM_EMAIL_TEMPLATES_PWRESET]) {
|
|
||||||
restrictedPaths.push(process.env[UM_EMAIL_TEMPLATES_PWRESET]);
|
|
||||||
}
|
|
||||||
|
|
||||||
//check if the file path is restricted
|
|
||||||
for (const path of restrictedPaths) {
|
|
||||||
if (resolvedFilePath.startsWith(path)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//path is not restricted
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,3 +85,34 @@ export const getFileSystemHelperFunctions = (node: INode): FileSystemHelperFunct
|
|||||||
return await fsWriteFile(filePath, content, { encoding: 'binary', flag });
|
return await fsWriteFile(filePath, content, { encoding: 'binary', flag });
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns The restricted paths for the n8n instance.
|
||||||
|
*/
|
||||||
|
function getN8nRestrictedPaths() {
|
||||||
|
const { n8nFolder, staticCacheDir } = Container.get(InstanceSettings);
|
||||||
|
const restrictedPaths = [n8nFolder, staticCacheDir];
|
||||||
|
|
||||||
|
if (process.env[CONFIG_FILES]) {
|
||||||
|
restrictedPaths.push(...process.env[CONFIG_FILES].split(','));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.env[CUSTOM_EXTENSION_ENV]) {
|
||||||
|
const customExtensionFolders = process.env[CUSTOM_EXTENSION_ENV].split(';');
|
||||||
|
restrictedPaths.push(...customExtensionFolders);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.env[BINARY_DATA_STORAGE_PATH]) {
|
||||||
|
restrictedPaths.push(process.env[BINARY_DATA_STORAGE_PATH]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.env[UM_EMAIL_TEMPLATES_INVITE]) {
|
||||||
|
restrictedPaths.push(process.env[UM_EMAIL_TEMPLATES_INVITE]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.env[UM_EMAIL_TEMPLATES_PWRESET]) {
|
||||||
|
restrictedPaths.push(process.env[UM_EMAIL_TEMPLATES_PWRESET]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return restrictedPaths;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user