UNPKG

simple-task-master

Version:
106 lines 5.04 kB
"use strict"; /** * Path validation utilities for STM */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.validateTasksDir = validateTasksDir; const path = __importStar(require("path")); const fs = __importStar(require("fs")); const errors_1 = require("./errors"); /** * Validates the custom tasks directory path * @param tasksDir - The proposed tasks directory path * @returns The normalized tasks directory path * @throws ValidationError if the path is invalid */ function validateTasksDir(tasksDir) { // Prevent directory traversal attacks - check before normalization if (tasksDir.includes('..')) { throw new errors_1.ValidationError('Tasks directory path cannot contain directory traversal sequences (..)'); } // Normalize the path and remove trailing slashes const normalized = path.normalize(tasksDir).replace(/\/+$/, ''); // Prevent absolute paths outside the project if (path.isAbsolute(normalized)) { // Allow absolute paths only if they're not system directories // For shared directories, we'll be more permissive and allow sibling directories // First, check if it's a system directory (but allow temp directories for testing) const isTempDir = normalized.includes('/tmp/') || normalized.includes('\\Temp\\') || normalized.includes('\\TEMP\\') || normalized.includes('/var/folders/') || // macOS temp directories normalized.includes('/private/var/folders/'); // macOS private temp const systemPaths = ['/', '/etc', '/usr', '/bin', '/sbin', '/dev', '/proc', '/sys']; const isSystemPath = systemPaths.some((sysPath) => normalized === sysPath || normalized.startsWith(sysPath + path.sep)); if (isSystemPath && !isTempDir) { throw new errors_1.ValidationError('Cannot use system directories for task storage'); } // For non-system paths, allow more flexibility for shared directories // Only reject if the path is clearly outside any reasonable project structure const cwd = fs.realpathSync(process.cwd()); try { // Try to find a common root between cwd and the target path const normalizedDir = path.dirname(normalized); let resolvedDir; try { resolvedDir = fs.realpathSync(normalizedDir); } catch { resolvedDir = path.resolve(normalizedDir); } const resolvedPath = path.join(resolvedDir, path.basename(normalized)); // Calculate relative path from cwd to target const relative = path.relative(cwd, resolvedPath); // Allow paths that go up but not too far (max 5 levels up for shared directories) const upLevels = relative.split(path.sep).filter((part) => part === '..').length; if (upLevels > 5) { throw new errors_1.ValidationError('Absolute paths too far outside the project directory'); } } catch { // If we can't resolve paths, be conservative and reject throw new errors_1.ValidationError('Invalid absolute path for task storage'); } } // Ensure the path doesn't point to a file // We'll check this during actual creation, but validate obvious cases if (normalized.includes('.') && (normalized.endsWith('.json') || normalized.endsWith('.md') || normalized.endsWith('.txt'))) { throw new errors_1.ValidationError('Tasks directory path appears to be a file, not a directory'); } return normalized; } //# sourceMappingURL=path-validation.js.map