woaru
Version:
Universal Project Setup Autopilot - Analyze and automatically configure development tools for ANY programming language
116 lines • 3.19 kB
JavaScript
/**
* Secure Command Execution Utilities
* Prevents Command Injection by using proper argument handling
*/
import { spawn } from 'child_process';
import * as path from 'path';
/**
* Sanitizes and validates a file path to prevent path traversal attacks
*/
export function sanitizeFilePath(filePath) {
const normalized = path.normalize(filePath);
// Check for directory traversal attempts
if (normalized.includes('..')) {
throw new Error('Invalid file path: Directory traversal detected');
}
// Ensure the path is absolute for consistency
return path.resolve(normalized);
}
/**
* Safely executes a command with arguments using spawn instead of shell execution
* This prevents command injection by treating arguments as separate parameters
*/
export async function safeExecAsync(command, args = [], options = {}) {
return new Promise((resolve, reject) => {
const { timeout = 30000, ...spawnOptions } = options;
const child = spawn(command, args, {
...spawnOptions,
shell: false, // CRITICAL: Never use shell to prevent injection
stdio: ['ignore', 'pipe', 'pipe'],
});
let stdout = '';
let stderr = '';
let timeoutId = null;
if (child.stdout) {
child.stdout.on('data', data => {
stdout += data.toString();
});
}
if (child.stderr) {
child.stderr.on('data', data => {
stderr += data.toString();
});
}
if (timeout > 0) {
timeoutId = setTimeout(() => {
child.kill('SIGTERM');
reject(new Error(`Command timeout after ${timeout}ms`));
}, timeout);
}
child.on('close', code => {
if (timeoutId) {
clearTimeout(timeoutId);
}
resolve({
stdout: stdout.trim(),
stderr: stderr.trim(),
exitCode: code ?? -1,
});
});
child.on('error', error => {
if (timeoutId) {
clearTimeout(timeoutId);
}
reject(error);
});
});
}
/**
* Validates that a command is in an allowed list (whitelist approach)
*/
export function validateCommand(command, allowedCommands) {
const baseCommand = path.basename(command);
return allowedCommands.includes(baseCommand);
}
/**
* Escape special characters for shell commands (only when shell is absolutely necessary)
* NOTE: Prefer safeExecAsync over shell execution
*/
export function escapeShellArg(arg) {
return `"${arg.replace(/"/g, '\\"')}"`;
}
/**
* Common allowed commands for WOARU tools
*/
export const ALLOWED_COMMANDS = [
'eslint',
'prettier',
'tsc',
'npm',
'yarn',
'pnpm',
'python',
'python3',
'pip',
'pip3',
'black',
'ruff',
'mypy',
'pytest',
'go',
'golint',
'gofmt',
'dotnet',
'mvn',
'gradle',
'rustc',
'cargo',
'clippy',
'snyk',
'trivy',
'gitleaks',
'semgrep',
'bandit',
'safety',
];
//# sourceMappingURL=secureExecution.js.map