| |
| |
| |
| |
|
|
| import path from 'path'; |
|
|
| |
| |
| |
| export class PathNotAllowedError extends Error { |
| constructor(filePath: string) { |
| super(`Path not allowed: ${filePath}. Must be within ALLOWED_ROOT_DIRECTORY or DATA_DIR.`); |
| this.name = 'PathNotAllowedError'; |
| } |
| } |
|
|
| |
| let allowedRootDirectory: string | null = null; |
|
|
| |
| let dataDirectory: string | null = null; |
|
|
| |
| |
| |
| |
| |
| export function initAllowedPaths(): void { |
| |
| const rootDir = process.env.ALLOWED_ROOT_DIRECTORY; |
| if (rootDir) { |
| allowedRootDirectory = path.resolve(rootDir); |
| console.log(`[Security] ✓ ALLOWED_ROOT_DIRECTORY configured: ${allowedRootDirectory}`); |
| } else { |
| console.log('[Security] ⚠️ ALLOWED_ROOT_DIRECTORY not set - allowing access to all paths'); |
| } |
|
|
| |
| const dataDir = process.env.DATA_DIR; |
| if (dataDir) { |
| dataDirectory = path.resolve(dataDir); |
| console.log(`[Security] ✓ DATA_DIR configured: ${dataDirectory}`); |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| export function isPathAllowed(filePath: string): boolean { |
| const resolvedPath = path.resolve(filePath); |
|
|
| |
| if (dataDirectory && isPathWithinDirectory(resolvedPath, dataDirectory)) { |
| return true; |
| } |
|
|
| |
| |
| if (!allowedRootDirectory) { |
| return true; |
| } |
|
|
| |
| if (allowedRootDirectory && isPathWithinDirectory(resolvedPath, allowedRootDirectory)) { |
| return true; |
| } |
|
|
| |
| return false; |
| } |
|
|
| |
| |
| |
| |
| export function validatePath(filePath: string): string { |
| const resolvedPath = path.resolve(filePath); |
|
|
| if (!isPathAllowed(resolvedPath)) { |
| throw new PathNotAllowedError(filePath); |
| } |
|
|
| return resolvedPath; |
| } |
|
|
| |
| |
| |
| |
| export function isPathWithinDirectory(resolvedPath: string, directoryPath: string): boolean { |
| |
| const relativePath = path.relative(directoryPath, resolvedPath); |
|
|
| |
| |
| |
| return !relativePath.startsWith('..') && !path.isAbsolute(relativePath); |
| } |
|
|
| |
| |
| |
| export function getAllowedRootDirectory(): string | null { |
| return allowedRootDirectory; |
| } |
|
|
| |
| |
| |
| export function getDataDirectory(): string | null { |
| return dataDirectory; |
| } |
|
|
| |
| |
| |
| export function getAllowedPaths(): string[] { |
| const paths: string[] = []; |
| if (allowedRootDirectory) { |
| paths.push(allowedRootDirectory); |
| } |
| if (dataDirectory) { |
| paths.push(dataDirectory); |
| } |
| return paths; |
| } |
|
|