SECURITY.md
SECURITY.md
Comprehensive documentation of security features, threat models, and responsible disclosure for the AI Toolbox plugin.
The AI Toolbox plugin implements a multi-layered security approach:
All user inputs are validated using Zod schemas before processing:
| Parameter | Validation | Purpose |
|---|---|---|
file_name | z.string() + path validation | Prevent empty/malformed paths |
max_length | z.number().min(1).max(50000) | Enforce character limits |
pattern (grep) | Regex safety check (isSafeRegex()) | Prevent ReDoS attacks |
command | Sanitization (sanitizeCommand()) | Block dangerous shell commands |
All file paths pass through validatePath() in src/security.ts:
Threats Mitigated:
../, ..\\)\\\\server\\share)Shell commands undergo multi-layer sanitization in sanitizeCommand():
Threats Mitigated:
;, &&, ||)rm -rf, sudo, etc.)Tools are gated by configuration categories in src/config.ts:
| Category | Default State | Purpose |
|---|---|---|
fileSystem | Enabled | File read/write/search operations |
webSearch | Enabled | Web research tools |
browserAutomation | Disabled | Prevent unauthorized browser control |
gitOperations | Disabled | Require explicit opt-in for Git access |
executionJavaScript | Disabled | Prevent arbitrary code execution |
executionPython | Disabled | Prevent arbitrary code execution |
executionShell | Disabled | Prevent shell command injection |
God Mode Bypass: Setting godMode: true enables ALL tool categories regardless of individual toggle settings. Use with extreme caution.
| Asset | Sensitivity | Protection Level |
|---|---|---|
| User files in working directory | High | Path validation, atomic writes |
| Plugin configuration | Medium | Zod schema validation |
| Session state (JSON/msgpack) | Medium | Atomic file writes, size limits |
| Network requests | Low-Medium | SSRF protection, protocol whitelisting |
Risk: High
Mitigation: validatePath() with base path enforcement
Test Case: file_name=../../../etc/passwd → Should be rejected
Risk: Critical
Mitigation: sanitizeCommand() blocks dangerous patterns, category enforcement
Test Case: command="; rm -rf /" → Should be blocked with reason "Dangerous command"
Risk: Medium
Mitigation: Multi-layer defense against catastrophic backtracking:
Transparency: The grep_files tool returns a patternMode: 'regex' | 'literal' | 'auto_escaped' field indicating whether the pattern was matched as regex, escaped to literal text, or split into separate regexes for top-level alternation.
Test Case: pattern="((a+)+)b" → Treated as literal string; pattern="(a|b)+" → Accepted as valid regex; pattern="validateImageFile\(|\.resolvedPath!|await validateImageFile" → Split into 3 separate regexes tested independently
Risk: High
Mitigation: URL protocol validation (http/https only), private IP blocking
Test Case: url="file:///etc/passwd" → Should be rejected with "Protocol not allowed"
Risk: Medium
Mitigation: Size limits on file operations (10MB for save_file, 50KB for web fetch)
Test Case: save_file(content="<1GB string>") → Should be rejected with size limit error
Risk: High
Mitigation: Four-layer defense-in-depth (max_content_length, max_file_size, max_results, max_depth):
max_content_length: 150 chars/line (balance readability and token economy)max_file_size: 100KB per file (skip larger files to prevent processing overhead)max_results: 20 results default — prevents excessive outputmax_depth: 10 directory depth default (range: 1–50) — prevents infinite recursion into nested directoriesMAX_LINES_PER_FILE: 5,000 line limit per file in processing loop — prevents hanging on large filesTest Case: grep_files(pattern="." , max_results=500) → Should be capped at default limit (20)
All user inputs are validated using Zod schemas before processing:
Validation Rules Applied:
All file paths pass through validatePath() before any filesystem operation:
Edge Cases Handled:
\\server\share) → Rejected.. traversal → Resolved and validated against baseShell commands undergo multi-layer sanitization:
Execution tools block dangerous patterns before running code:
JavaScript Sandbox:
Python Sandbox:
Database queries are validated against unsafe patterns:
URL validation prevents access to internal/private resources:
All dangerous tool categories are disabled by default:
| Category | Default State | Rationale |
|---|---|---|
browserAutomation | false | Prevent unauthorized browser control |
gitOperations | false | Require explicit opt-in for Git access |
databaseQueries | false | Prevent accidental database modifications |
executionJavaScript | false | Prevent arbitrary code execution |
executionPython | false | Prevent arbitrary code execution |
executionShell | false | Prevent shell command injection |
Conservative defaults prevent resource exhaustion:
| Operation | Default Limit | Rationale |
|---|---|---|
File read (max_length) | 5,000 chars | Balance between utility and memory usage |
File write (save_file) | 10 MB | Prevent disk exhaustion |
Web fetch (fetch_web_content) | 50 KB | Prevent OOM from large pages |
grep search (max_results) | 20 results | Prevent token explosion |
| grep content length | 150 chars/line | Balance readability and token economy |
All dependencies are regularly audited for known vulnerabilities:
| Date | Package | Issue | Fix Applied |
|---|---|---|---|
| 2026-05-31 | glob v10.3.10 → v13.0.6 | CVE-2025-64756 (command injection) | Upgraded to patched version via overrides |
| 2026-05-31 | uuid v8.x → v11.0.4 | Math.random weakness deprecation | Upgraded to cryptographically secure implementation |
If you discover a security vulnerability:
[SECURITY] in title| Stage | Target Timeframe |
|---|---|
| Acknowledge receipt | 24 hours |
| Assess severity | 48 hours |
| Develop fix | 7 days (critical), 30 days (medium) |
| Release patch | Within SLA timeframe |
For each new feature or tool:
validatePath()This security documentation is based on the actual implementation in src/security.ts and individual tool modules. All security controls are actively enforced at runtime, not just documented.
For questions about security features or to report vulnerabilities, please contact the maintainers through secure channels.
Comprehensive documentation of security features, threat models, and responsible disclosure for the AI Toolbox plugin.
The AI Toolbox plugin implements a multi-layered security approach:
All user inputs are validated using Zod schemas before processing:
| Parameter | Validation | Purpose |
|---|---|---|
file_name | z.string() + path validation | Prevent empty/malformed paths |
max_length | z.number().min(1).max(50000) | Enforce character limits |
pattern (grep) | Regex safety check (isSafeRegex()) | Prevent ReDoS attacks |
command | Sanitization (sanitizeCommand()) | Block dangerous shell commands |
All file paths pass through validatePath() in src/security.ts:
Threats Mitigated:
../, ..\\)\\\\server\\share)Shell commands undergo multi-layer sanitization in sanitizeCommand():
Threats Mitigated:
;, &&, ||)rm -rf, sudo, etc.)Tools are gated by configuration categories in src/config.ts:
| Category | Default State | Purpose |
|---|---|---|
fileSystem | Enabled | File read/write/search operations |
webSearch | Enabled | Web research tools |
browserAutomation | Disabled | Prevent unauthorized browser control |
gitOperations | Disabled | Require explicit opt-in for Git access |
executionJavaScript | Disabled | Prevent arbitrary code execution |
executionPython | Disabled | Prevent arbitrary code execution |
executionShell | Disabled | Prevent shell command injection |
God Mode Bypass: Setting godMode: true enables ALL tool categories regardless of individual toggle settings. Use with extreme caution.
| Asset | Sensitivity | Protection Level |
|---|---|---|
| User files in working directory | High | Path validation, atomic writes |
| Plugin configuration | Medium | Zod schema validation |
| Session state (JSON/msgpack) | Medium | Atomic file writes, size limits |
| Network requests | Low-Medium | SSRF protection, protocol whitelisting |
Risk: High
Mitigation: validatePath() with base path enforcement
Test Case: file_name=../../../etc/passwd → Should be rejected
Risk: Critical
Mitigation: sanitizeCommand() blocks dangerous patterns, category enforcement
Test Case: command="; rm -rf /" → Should be blocked with reason "Dangerous command"
Risk: Medium
Mitigation: Multi-layer defense against catastrophic backtracking:
Transparency: The grep_files tool returns a patternMode: 'regex' | 'literal' | 'auto_escaped' field indicating whether the pattern was matched as regex, escaped to literal text, or split into separate regexes for top-level alternation.
Test Case: pattern="((a+)+)b" → Treated as literal string; pattern="(a|b)+" → Accepted as valid regex; pattern="validateImageFile\(|\.resolvedPath!|await validateImageFile" → Split into 3 separate regexes tested independently
Risk: High
Mitigation: URL protocol validation (http/https only), private IP blocking
Test Case: url="file:///etc/passwd" → Should be rejected with "Protocol not allowed"
Risk: Medium
Mitigation: Size limits on file operations (10MB for save_file, 50KB for web fetch)
Test Case: save_file(content="<1GB string>") → Should be rejected with size limit error
Risk: High
Mitigation: Four-layer defense-in-depth (max_content_length, max_file_size, max_results, max_depth):
max_content_length: 150 chars/line (balance readability and token economy)max_file_size: 100KB per file (skip larger files to prevent processing overhead)max_results: 20 results default — prevents excessive outputmax_depth: 10 directory depth default (range: 1–50) — prevents infinite recursion into nested directoriesMAX_LINES_PER_FILE: 5,000 line limit per file in processing loop — prevents hanging on large filesTest Case: grep_files(pattern="." , max_results=500) → Should be capped at default limit (20)
All user inputs are validated using Zod schemas before processing:
Validation Rules Applied:
All file paths pass through validatePath() before any filesystem operation:
Edge Cases Handled:
\\server\share) → Rejected.. traversal → Resolved and validated against baseShell commands undergo multi-layer sanitization:
Execution tools block dangerous patterns before running code:
JavaScript Sandbox:
Python Sandbox:
Database queries are validated against unsafe patterns:
URL validation prevents access to internal/private resources:
All dangerous tool categories are disabled by default:
| Category | Default State | Rationale |
|---|---|---|
browserAutomation | false | Prevent unauthorized browser control |
gitOperations | false | Require explicit opt-in for Git access |
databaseQueries | false | Prevent accidental database modifications |
executionJavaScript | false | Prevent arbitrary code execution |
executionPython | false | Prevent arbitrary code execution |
executionShell | false | Prevent shell command injection |
Conservative defaults prevent resource exhaustion:
| Operation | Default Limit | Rationale |
|---|---|---|
File read (max_length) | 5,000 chars | Balance between utility and memory usage |
File write (save_file) | 10 MB | Prevent disk exhaustion |
Web fetch (fetch_web_content) | 50 KB | Prevent OOM from large pages |
grep search (max_results) | 20 results | Prevent token explosion |
| grep content length | 150 chars/line | Balance readability and token economy |
All dependencies are regularly audited for known vulnerabilities:
| Date | Package | Issue | Fix Applied |
|---|---|---|---|
| 2026-05-31 | glob v10.3.10 → v13.0.6 | CVE-2025-64756 (command injection) | Upgraded to patched version via overrides |
| 2026-05-31 | uuid v8.x → v11.0.4 | Math.random weakness deprecation | Upgraded to cryptographically secure implementation |
If you discover a security vulnerability:
[SECURITY] in title| Stage | Target Timeframe |
|---|---|
| Acknowledge receipt | 24 hours |
| Assess severity | 48 hours |
| Develop fix | 7 days (critical), 30 days (medium) |
| Release patch | Within SLA timeframe |
For each new feature or tool:
validatePath()This security documentation is based on the actual implementation in src/security.ts and individual tool modules. All security controls are actively enforced at runtime, not just documented.
For questions about security features or to report vulnerabilities, please contact the maintainers through secure channels.
isSafeRegex() — Nested repetition detection: Precise pattern analysis detecting genuinely dangerous structures:
(.+)+, (a*)*) — exponential backtracking risk((a|b)+)+) — catastrophic backtracking(a|b)+, [a-z]+, ^import\s+ are correctly acceptedhasTopLevelAlternation() — Top-level alternation detection (v1.9.3): Character-by-character scanner tracking parenthesis depth to detect unescaped \| at depth 0. Patterns like 'validateImageFile\(|\.resolvedPath!|await validateImageFile' that contain shared substrings across branches are now caught.
Split-Regex Processing (v1.9.3): When top-level alternation is detected, the pattern is split on \| into individual RegExp[], each compiled and tested independently per line with early-exit on first match. This eliminates cross-branch backtracking entirely since each branch runs in isolation within V8's NFA engine.
Literal fallback: Patterns that fail all safety checks are converted to literal string matching (not silently dropped).
Quantifier count check (v1.9.8): isSafeRegex() counts total quantifiers (+, *, ?) in the pattern — returns false if more than 5 quantifiers detected, preventing patterns like (a+)(b+)(c+)(d+)(e+)(f+) that could cause exponential backtracking.
Consecutive quantified character class detection (v1.9.8): Detects patterns with multiple consecutive quantified character classes (e.g., [[^]]+]+[+*]) that can trigger catastrophic backtracking in V8's NFA engine, even when nested repetition is absent.
Code-signature heuristic (REV-24 refinement, v1.9.10): Patterns pairing an unescaped *, + or ? with C++-style signature indicators (::, →) are treated as code searches and auto-escaped to literal. Since REV-24 (28.08), a bare & no longer triggers this — it is not a JS regex metacharacter (zero backtracking risk); prose alternations like "Backup & Restore|Git & GitHub" stay in regex mode. Genuine code signatures containing & are still caught when paired with an unescaped quantifier char; forced-literal responses now carry an explanatory hint string.
Hard time limits (v1.9.9): GREP_SCAN_DEADLINE_MS = 15000 caps the total scan — overrun returns partial results with an explicit aborted: true flag; a per-regex budget of 500 ms (PER_REGEX_TIMEOUT_MS) abandons runaway candidates and continues. These gates bound wall time but cannot preempt synchronous JS mid-evaluation — see layer 9.
Worker-isolated evaluation (FIX-HANG-5, 29.–30.08): patterns the stricter patternNeedsWorkerIsolation() triage gate cannot cheaply PROVE safe are evaluated for the whole file inside an isolated node:worker_threads Worker — hard-killed via worker.terminate() after 2 s (WORKER_KILL_MS = 2000) if catastrophic backtracking is suspected; a killed file lands in skipped_files (reason "likely ReDoS-prone pattern") and the scan continues. Proven-safe patterns keep the inline fast path with zero overhead. This layer exists because no cooperative timer can preempt synchronous RegExp.test() on the main thread — only another thread can.
User Input → Validation Layer → Sanitization → Execution → Output
(Zod schemas) (Path/SQL/cmd) (Gated) (Truncated)
│ │ │ │
▼ ▼ ▼ ▼
Type & Format Path Traversal Category Content Size
Validation Prevention Enforcement Limits
function validatePath(userPath: string, basePath: string): boolean {
// Empty check
if (!userPath) return false;
// UNC path prevention
if (userPath.startsWith('\\\\')) return false;
// Resolve against base path and verify within allowed boundaries
const resolved = resolvePath(userPath);
return isWithinAllowedBase(resolved, basePath);
}
function sanitizeCommand(command: string): { safe: boolean; reason?: string } {
// Layer 1: Dangerous pattern blocking
if (command.includes('rm -rf') || command.includes('sudo')) return { safe: false, reason: 'Dangerous command' };
// Layer 2: Category enforcement
const categories = classifyCommand(command);
if (!isCategoryEnabled(categories)) return { safe: false, reason: 'Category disabled' };
return { safe: true };
}
// Example from fileSystemTools.ts
parameters: {
file_name: z.string().describe('The name of the file to read'),
max_length: z.number().int().min(1).max(50000).optional().default(5000),
}
// Example from executionTools.ts
parameters: {
javascript: z.string(), // Dangerous pattern detection applied in implementation
timeout_seconds: z.number().min(0.1).max(60).optional().default(5),
}
// In security.ts
export function validatePath(userPath: string, basePath: string): boolean {
if (!userPath || userPath.startsWith('\\\\')) return false;
const resolved = resolvePath(userPath);
return isWithinAllowedBase(resolved, basePath);
}
// Helper to check if path is within allowed boundaries
function isWithinAllowedBase(path: string, base: string): boolean {
const normalizedPath = path.replace(/\\/g, '/').toLowerCase();
const normalizedBase = base.replace(/\\/g, '/').toLowerCase();
return normalizedPath.startsWith(normalizedBase + '/') || normalizedPath === normalizedBase;
}
// In security.ts
export function sanitizeCommand(command: string): { safe: boolean; reason?: string } {
// Layer 1: Dangerous pattern blocking
const dangerousPatterns = [
/rm\s+-rf/i, // Mass deletion
/sudo\s+/i, // Privilege escalation
/;\s*exit\b/i, // Session termination
/\$\(/i, // Command substitution
/`[^`]+`/i, // Backtick command execution
];
for (const pattern of dangerousPatterns) {
if (pattern.test(command)) return { safe: false, reason: 'Dangerous command detected' };
}
// Layer 2: Pipe and semicolon limits
const pipeCount = (command.match(/\|/g) || []).length;
if (pipeCount > 2) return { safe: false, reason: 'Too many pipes' };
const semiCount = (command.match(/;/g) || []).length;
if (semiCount > 1) return { safe: false, reason: 'Too many semicolons' };
// Layer 3: Category enforcement (checked in toolsProvider.ts)
return { safe: true };
}
const dangerousPatterns = [
/\beval\s*\(/i, // Code injection
/\bexec\s*\(/i, // Code execution
/Function\s*\(/i, // Function constructor (eval alternative)
/String\.fromCharCode\s*\(/i, // fromCharCode bypass
/__proto__/i, // Prototype pollution
/require\.resolve/i, // Module resolution abuse
/\bchild_process\b/i, // Process spawning
/os\.system/i, // OS command execution
];
for (const pattern of dangerousPatterns) {
if (pattern.test(code)) return { success: false, error: `Dangerous code detected` };
}
const dangerousPatterns = [
/\bimport\s+os\b/i,
/import\s+subprocess\b/i,
/__import__\s*\(/i,
/\beval\s*\(/i,
/\bexec\s*\(/i,
];
for (const pattern of dangerousPatterns) {
if (pattern.test(code)) return { success: false, error: `Dangerous Python import detected` };
}
export function validateSQLQuery(query: string): { valid: boolean; reason?: string } {
const dangerousPatterns = [
/\bDROP\s+/i, // Destructive operations
/\bDELETE\s+FROM/i, // Data deletion
/\bUPDATE\s+\w+\s+SET\b/i, // Data modification without WHERE
/;\s*SELECT\b/i, // Stacked queries
];
for (const pattern of dangerousPatterns) {
if (pattern.test(query)) return { valid: false, reason: 'Unsafe SQL query detected' };
}
return { valid: true };
}
function validateUrl(url: string): { valid: boolean; error?: string } {
const parsed = new URL(url);
// Block non-HTTP protocols
if (!['http:', 'https:'].includes(parsed.protocol)) {
return { valid: false, error: `Protocol "${parsed.protocol}" is not allowed` };
}
// Block private IP ranges (basic check)
const hostname = parsed.hostname;
const blockedPatterns = [
/^127\./, // localhost
/^10\./, // 10.0.0.0/8
/^172\.1[6-9]\./, // 172.16.0.0/12
/^172\.2[0-9]\./, // 172.16.0.0/12
/^172\.3[0-1]\./, // 172.16.0.0/12
/^192\.168\./, // 192.168.0.0/16
/^localhost$/, // localhost hostname
];
if (blockedPatterns.some(pattern => pattern.test(hostname))) {
return { valid: false, error: `Access to ${hostname} is blocked for security reasons` };
}
return { valid: true };
}
# Check for outdated packages with security issues
npm audit
# Update vulnerable dependencies
npm update
{
"overrides": {
"glob": "^13.0.6",
"uuid": "^11.0.4"
}
}
isSafeRegex() — Nested repetition detection: Precise pattern analysis detecting genuinely dangerous structures:
(.+)+, (a*)*) — exponential backtracking risk((a|b)+)+) — catastrophic backtracking(a|b)+, [a-z]+, ^import\s+ are correctly acceptedhasTopLevelAlternation() — Top-level alternation detection (v1.9.3): Character-by-character scanner tracking parenthesis depth to detect unescaped \| at depth 0. Patterns like 'validateImageFile\(|\.resolvedPath!|await validateImageFile' that contain shared substrings across branches are now caught.
Split-Regex Processing (v1.9.3): When top-level alternation is detected, the pattern is split on \| into individual RegExp[], each compiled and tested independently per line with early-exit on first match. This eliminates cross-branch backtracking entirely since each branch runs in isolation within V8's NFA engine.
Literal fallback: Patterns that fail all safety checks are converted to literal string matching (not silently dropped).
Quantifier count check (v1.9.8): isSafeRegex() counts total quantifiers (+, *, ?) in the pattern — returns false if more than 5 quantifiers detected, preventing patterns like (a+)(b+)(c+)(d+)(e+)(f+) that could cause exponential backtracking.
Consecutive quantified character class detection (v1.9.8): Detects patterns with multiple consecutive quantified character classes (e.g., [[^]]+]+[+*]) that can trigger catastrophic backtracking in V8's NFA engine, even when nested repetition is absent.
Code-signature heuristic (REV-24 refinement, v1.9.10): Patterns pairing an unescaped *, + or ? with C++-style signature indicators (::, →) are treated as code searches and auto-escaped to literal. Since REV-24 (28.08), a bare & no longer triggers this — it is not a JS regex metacharacter (zero backtracking risk); prose alternations like "Backup & Restore|Git & GitHub" stay in regex mode. Genuine code signatures containing & are still caught when paired with an unescaped quantifier char; forced-literal responses now carry an explanatory hint string.
Hard time limits (v1.9.9): GREP_SCAN_DEADLINE_MS = 15000 caps the total scan — overrun returns partial results with an explicit aborted: true flag; a per-regex budget of 500 ms (PER_REGEX_TIMEOUT_MS) abandons runaway candidates and continues. These gates bound wall time but cannot preempt synchronous JS mid-evaluation — see layer 9.
Worker-isolated evaluation (FIX-HANG-5, 29.–30.08): patterns the stricter patternNeedsWorkerIsolation() triage gate cannot cheaply PROVE safe are evaluated for the whole file inside an isolated node:worker_threads Worker — hard-killed via worker.terminate() after 2 s (WORKER_KILL_MS = 2000) if catastrophic backtracking is suspected; a killed file lands in skipped_files (reason "likely ReDoS-prone pattern") and the scan continues. Proven-safe patterns keep the inline fast path with zero overhead. This layer exists because no cooperative timer can preempt synchronous RegExp.test() on the main thread — only another thread can.
User Input → Validation Layer → Sanitization → Execution → Output
(Zod schemas) (Path/SQL/cmd) (Gated) (Truncated)
│ │ │ │
▼ ▼ ▼ ▼
Type & Format Path Traversal Category Content Size
Validation Prevention Enforcement Limits
function validatePath(userPath: string, basePath: string): boolean {
// Empty check
if (!userPath) return false;
// UNC path prevention
if (userPath.startsWith('\\\\')) return false;
// Resolve against base path and verify within allowed boundaries
const resolved = resolvePath(userPath);
return isWithinAllowedBase(resolved, basePath);
}
function sanitizeCommand(command: string): { safe: boolean; reason?: string } {
// Layer 1: Dangerous pattern blocking
if (command.includes('rm -rf') || command.includes('sudo')) return { safe: false, reason: 'Dangerous command' };
// Layer 2: Category enforcement
const categories = classifyCommand(command);
if (!isCategoryEnabled(categories)) return { safe: false, reason: 'Category disabled' };
return { safe: true };
}
// Example from fileSystemTools.ts
parameters: {
file_name: z.string().describe('The name of the file to read'),
max_length: z.number().int().min(1).max(50000).optional().default(5000),
}
// Example from executionTools.ts
parameters: {
javascript: z.string(), // Dangerous pattern detection applied in implementation
timeout_seconds: z.number().min(0.1).max(60).optional().default(5),
}
// In security.ts
export function validatePath(userPath: string, basePath: string): boolean {
if (!userPath || userPath.startsWith('\\\\')) return false;
const resolved = resolvePath(userPath);
return isWithinAllowedBase(resolved, basePath);
}
// Helper to check if path is within allowed boundaries
function isWithinAllowedBase(path: string, base: string): boolean {
const normalizedPath = path.replace(/\\/g, '/').toLowerCase();
const normalizedBase = base.replace(/\\/g, '/').toLowerCase();
return normalizedPath.startsWith(normalizedBase + '/') || normalizedPath === normalizedBase;
}
// In security.ts
export function sanitizeCommand(command: string): { safe: boolean; reason?: string } {
// Layer 1: Dangerous pattern blocking
const dangerousPatterns = [
/rm\s+-rf/i, // Mass deletion
/sudo\s+/i, // Privilege escalation
/;\s*exit\b/i, // Session termination
/\$\(/i, // Command substitution
/`[^`]+`/i, // Backtick command execution
];
for (const pattern of dangerousPatterns) {
if (pattern.test(command)) return { safe: false, reason: 'Dangerous command detected' };
}
// Layer 2: Pipe and semicolon limits
const pipeCount = (command.match(/\|/g) || []).length;
if (pipeCount > 2) return { safe: false, reason: 'Too many pipes' };
const semiCount = (command.match(/;/g) || []).length;
if (semiCount > 1) return { safe: false, reason: 'Too many semicolons' };
// Layer 3: Category enforcement (checked in toolsProvider.ts)
return { safe: true };
}
const dangerousPatterns = [
/\beval\s*\(/i, // Code injection
/\bexec\s*\(/i, // Code execution
/Function\s*\(/i, // Function constructor (eval alternative)
/String\.fromCharCode\s*\(/i, // fromCharCode bypass
/__proto__/i, // Prototype pollution
/require\.resolve/i, // Module resolution abuse
/\bchild_process\b/i, // Process spawning
/os\.system/i, // OS command execution
];
for (const pattern of dangerousPatterns) {
if (pattern.test(code)) return { success: false, error: `Dangerous code detected` };
}
const dangerousPatterns = [
/\bimport\s+os\b/i,
/import\s+subprocess\b/i,
/__import__\s*\(/i,
/\beval\s*\(/i,
/\bexec\s*\(/i,
];
for (const pattern of dangerousPatterns) {
if (pattern.test(code)) return { success: false, error: `Dangerous Python import detected` };
}
export function validateSQLQuery(query: string): { valid: boolean; reason?: string } {
const dangerousPatterns = [
/\bDROP\s+/i, // Destructive operations
/\bDELETE\s+FROM/i, // Data deletion
/\bUPDATE\s+\w+\s+SET\b/i, // Data modification without WHERE
/;\s*SELECT\b/i, // Stacked queries
];
for (const pattern of dangerousPatterns) {
if (pattern.test(query)) return { valid: false, reason: 'Unsafe SQL query detected' };
}
return { valid: true };
}
function validateUrl(url: string): { valid: boolean; error?: string } {
const parsed = new URL(url);
// Block non-HTTP protocols
if (!['http:', 'https:'].includes(parsed.protocol)) {
return { valid: false, error: `Protocol "${parsed.protocol}" is not allowed` };
}
// Block private IP ranges (basic check)
const hostname = parsed.hostname;
const blockedPatterns = [
/^127\./, // localhost
/^10\./, // 10.0.0.0/8
/^172\.1[6-9]\./, // 172.16.0.0/12
/^172\.2[0-9]\./, // 172.16.0.0/12
/^172\.3[0-1]\./, // 172.16.0.0/12
/^192\.168\./, // 192.168.0.0/16
/^localhost$/, // localhost hostname
];
if (blockedPatterns.some(pattern => pattern.test(hostname))) {
return { valid: false, error: `Access to ${hostname} is blocked for security reasons` };
}
return { valid: true };
}
# Check for outdated packages with security issues
npm audit
# Update vulnerable dependencies
npm update
{
"overrides": {
"glob": "^13.0.6",
"uuid": "^11.0.4"
}
}