Files
connectai/src/security.ts
T

91 lines
3.2 KiB
TypeScript

import * as vscode from 'vscode';
import * as path from 'path';
import * as fs from 'fs';
/**
* Validates that a path is strictly within the workspace.
* Prevents Path Traversal attacks by resolving real paths and checking boundaries.
*/
/**
* Additional trusted root paths beyond the workspace.
* Populated once from VS Code workspace folders on first call.
*/
let _trustedRoots: string[] | null = null;
function getTrustedRoots(workspaceRoot: string): string[] {
if (_trustedRoots) return _trustedRoots;
const roots = [path.normalize(workspaceRoot).toLowerCase()];
// Include all open workspace folders as trusted roots
const folders = vscode.workspace.workspaceFolders;
if (folders) {
for (const f of folders) {
roots.push(path.normalize(f.uri.fsPath).toLowerCase());
}
}
_trustedRoots = [...new Set(roots)];
return _trustedRoots;
}
/** Reset cached roots (useful when workspace folders change). */
export function resetTrustedRoots(): void {
_trustedRoots = null;
}
export function validatePath(workspaceRoot: string, targetPath: string): string {
if (!workspaceRoot) {
throw new Error("Security Violation: Workspace root not defined.");
}
const absolutePath = path.resolve(workspaceRoot, targetPath);
const normalizedTarget = path.normalize(absolutePath).toLowerCase();
const trusted = getTrustedRoots(workspaceRoot);
const isTrusted = trusted.some(root => normalizedTarget.startsWith(root));
if (!isTrusted) {
throw new Error(`Security Violation: Path traversal detected! Attempted to access ${absolutePath} which is outside allowed boundaries.`);
}
return absolutePath;
}
/**
* Sanitizes terminal commands to prevent destructive actions.
* Uses a combination of blocklist for dangerous patterns and recommendation for allowed tools.
*/
export function sanitizeCommand(command: string): string {
const trimmedCmd = command.trim();
// 1. Dangerous Shell Characters/Patterns (Blocklist)
const dangerousPatterns = [
/rm\s+-rf\s+\//, // Root deletion
/mkfs/, // Filesystem formatting
/dd\s+if=/, // Low-level disk writing
/>\s*\/dev\/sd/, // Direct disk access
/:(){:|:&};:/, // Fork bomb
/shutdown/, // System shutdown
/reboot/, // System reboot
/mv\s+.*\/dev\/null/ // Moving to null
];
for (const pattern of dangerousPatterns) {
if (pattern.test(trimmedCmd)) {
throw new Error(`Security Violation: Destructive command pattern detected! Blocked: ${trimmedCmd}`);
}
}
// 2. Allowlist of safe base commands (Optional but recommended)
// For now, we allow common development tools
const safeBaseCommands = [
'npm', 'node', 'npx', 'git', 'python', 'python3', 'pip', 'pip3',
'cargo', 'rustc', 'go', 'gcc', 'g++', 'make', 'ls', 'cat', 'echo',
'mkdir', 'cp', 'mv', 'touch'
];
const baseCmd = trimmedCmd.split(/\s+/)[0];
if (baseCmd && !safeBaseCommands.includes(baseCmd)) {
console.warn(`[Security] Warning: Running uncommon command '${baseCmd}'. Ensure this is intended.`);
}
return trimmedCmd;
}