@defai.digital/ax-cli 3.5.4 → 3.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.ax-cli/checkpoints/2025-11-20/checkpoint-11e9e0ba-c39d-4fd2-aa77-bc818811c921.json +69 -0
- package/.ax-cli/checkpoints/2025-11-20/checkpoint-2b260b98-b418-4c7c-9694-e2b94967e662.json +24 -0
- package/.ax-cli/checkpoints/2025-11-20/checkpoint-7e03601e-e8ab-4cd7-9841-a74b66adf78f.json +69 -0
- package/.ax-cli/checkpoints/2025-11-20/checkpoint-7f9c6562-771f-4fd0-adcf-9e7e9ac34ae8.json +44 -0
- package/.ax-cli/checkpoints/2025-11-20/checkpoint-e1ebe666-4c3a-4367-ba5c-27fe512a9c70.json +24 -0
- package/.ax-cli/checkpoints/2025-11-21/checkpoint-15743e7d-430c-4d76-b6fc-955d7a5c250c.json +44 -0
- package/.ax-cli/checkpoints/2025-11-21/checkpoint-25cf7679-0b3f-4988-83d7-704548fbba91.json +69 -0
- package/.ax-cli/checkpoints/2025-11-21/checkpoint-54aedbac-6db0-464e-8ebb-dbb3979e6dca.json +24 -0
- package/.ax-cli/checkpoints/2025-11-21/checkpoint-7658aed8-fe5d-4222-903f-1a7c63717ea7.json +24 -0
- package/.ax-cli/checkpoints/2025-11-21/checkpoint-c9c13497-40dc-4294-a327-6a5fc854eaa1.json +69 -0
- package/.ax-cli/memory.json +15 -8
- package/README.md +423 -82
- package/ax.config.json +333 -0
- package/config-defaults/messages.yaml +75 -0
- package/config-defaults/models.yaml +66 -0
- package/config-defaults/prompts.yaml +156 -0
- package/config-defaults/settings.yaml +86 -0
- package/dist/agent/chat-history-manager.d.ts +56 -0
- package/dist/agent/chat-history-manager.js +150 -0
- package/dist/agent/chat-history-manager.js.map +1 -0
- package/dist/agent/llm-agent.js +1 -1
- package/dist/agent/llm-agent.js.map +1 -1
- package/dist/agent/tool-manager.d.ts +39 -0
- package/dist/agent/tool-manager.js +76 -0
- package/dist/agent/tool-manager.js.map +1 -0
- package/dist/analyzers/code-smells/detectors/data-clumps-detector.js +7 -9
- package/dist/analyzers/code-smells/detectors/data-clumps-detector.js.map +1 -1
- package/dist/analyzers/code-smells/detectors/dead-code-detector.js +1 -1
- package/dist/analyzers/code-smells/detectors/dead-code-detector.js.map +1 -1
- package/dist/analyzers/code-smells/detectors/duplicate-code-detector.js +22 -10
- package/dist/analyzers/code-smells/detectors/duplicate-code-detector.js.map +1 -1
- package/dist/analyzers/code-smells/detectors/feature-envy-detector.js +1 -1
- package/dist/analyzers/code-smells/detectors/feature-envy-detector.js.map +1 -1
- package/dist/analyzers/code-smells/detectors/inappropriate-intimacy-detector.js +1 -1
- package/dist/analyzers/code-smells/detectors/inappropriate-intimacy-detector.js.map +1 -1
- package/dist/analyzers/code-smells/detectors/large-class-detector.js +4 -1
- package/dist/analyzers/code-smells/detectors/large-class-detector.js.map +1 -1
- package/dist/analyzers/code-smells/detectors/long-method-detector.js +4 -1
- package/dist/analyzers/code-smells/detectors/long-method-detector.js.map +1 -1
- package/dist/analyzers/code-smells/detectors/long-parameter-list-detector.js +4 -1
- package/dist/analyzers/code-smells/detectors/long-parameter-list-detector.js.map +1 -1
- package/dist/analyzers/code-smells/detectors/magic-numbers-detector.js +4 -5
- package/dist/analyzers/code-smells/detectors/magic-numbers-detector.js.map +1 -1
- package/dist/analyzers/code-smells/detectors/nested-conditionals-detector.js +4 -1
- package/dist/analyzers/code-smells/detectors/nested-conditionals-detector.js.map +1 -1
- package/dist/commands/memory.js +1 -1
- package/dist/commands/memory.js.map +1 -1
- package/dist/commands/setup.js +19 -6
- package/dist/commands/setup.js.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.bak +664 -0
- package/dist/index.js.map +1 -1
- package/dist/llm/client.d.ts +1 -0
- package/dist/llm/client.js +44 -0
- package/dist/llm/client.js.map +1 -1
- package/dist/mcp/health.js +4 -2
- package/dist/mcp/health.js.map +1 -1
- package/dist/mcp/ssrf-protection.d.ts +86 -0
- package/dist/mcp/ssrf-protection.js +313 -0
- package/dist/mcp/ssrf-protection.js.map +1 -0
- package/dist/mcp/validation.d.ts +4 -0
- package/dist/mcp/validation.js +122 -11
- package/dist/mcp/validation.js.map +1 -1
- package/dist/schemas/settings-schemas.d.ts +53 -0
- package/dist/schemas/settings-schemas.js +47 -0
- package/dist/schemas/settings-schemas.js.map +1 -1
- package/dist/tools/bash.d.ts +3 -2
- package/dist/tools/bash.js +31 -2
- package/dist/tools/bash.js.map +1 -1
- package/dist/tools/search.d.ts +1 -1
- package/dist/tools/search.js +121 -128
- package/dist/tools/search.js.map +1 -1
- package/dist/tools/text-editor.js +52 -15
- package/dist/tools/text-editor.js.map +1 -1
- package/dist/tools/web-search/index.d.ts +0 -2
- package/dist/tools/web-search/index.js +0 -2
- package/dist/tools/web-search/index.js.map +1 -1
- package/dist/tools/web-search/router.d.ts +0 -2
- package/dist/tools/web-search/router.js +2 -37
- package/dist/tools/web-search/router.js.map +1 -1
- package/dist/tools/web-search/web-search-tool.js +2 -12
- package/dist/tools/web-search/web-search-tool.js.map +1 -1
- package/dist/ui/components/chat-history.js +1 -1
- package/dist/ui/components/chat-history.js.map +1 -1
- package/dist/ui/components/chat-input.d.ts +4 -1
- package/dist/ui/components/chat-input.js +133 -52
- package/dist/ui/components/chat-input.js.map +1 -1
- package/dist/ui/components/chat-interface.js +5 -4
- package/dist/ui/components/chat-interface.js.map +1 -1
- package/dist/ui/components/confirmation-dialog.js +1 -1
- package/dist/ui/components/confirmation-dialog.js.map +1 -1
- package/dist/ui/components/keyboard-hints.js +2 -0
- package/dist/ui/components/keyboard-hints.js.map +1 -1
- package/dist/ui/components/status-bar.js +3 -13
- package/dist/ui/components/status-bar.js.map +1 -1
- package/dist/ui/components/welcome-panel.js +4 -0
- package/dist/ui/components/welcome-panel.js.map +1 -1
- package/dist/ui/hooks/use-chat-reducer.d.ts +61 -0
- package/dist/ui/hooks/use-chat-reducer.js +118 -0
- package/dist/ui/hooks/use-chat-reducer.js.map +1 -0
- package/dist/ui/hooks/use-enhanced-input.d.ts +44 -0
- package/dist/ui/hooks/use-enhanced-input.js +364 -0
- package/dist/ui/hooks/use-enhanced-input.js.map +1 -0
- package/dist/ui/hooks/use-input-handler.d.ts +48 -0
- package/dist/ui/hooks/use-input-handler.js +1446 -0
- package/dist/ui/hooks/use-input-handler.js.map +1 -0
- package/dist/utils/audit-logger.d.ts +205 -0
- package/dist/utils/audit-logger.js +269 -0
- package/dist/utils/audit-logger.js.map +1 -0
- package/dist/utils/command-security.d.ts +85 -0
- package/dist/utils/command-security.js +200 -0
- package/dist/utils/command-security.js.map +1 -0
- package/dist/utils/config-loader.js +3 -3
- package/dist/utils/config-loader.js.map +1 -1
- package/dist/utils/encryption.d.ts +78 -0
- package/dist/utils/encryption.js +216 -0
- package/dist/utils/encryption.js.map +1 -0
- package/dist/utils/error-sanitizer.d.ts +119 -0
- package/dist/utils/error-sanitizer.js +253 -0
- package/dist/utils/error-sanitizer.js.map +1 -0
- package/dist/utils/input-sanitizer.d.ts +210 -0
- package/dist/utils/input-sanitizer.js +362 -0
- package/dist/utils/input-sanitizer.js.map +1 -0
- package/dist/utils/json-utils.d.ts +13 -0
- package/dist/utils/json-utils.js +55 -1
- package/dist/utils/json-utils.js.map +1 -1
- package/dist/utils/paste-collapse.d.ts +46 -0
- package/dist/utils/paste-collapse.js +77 -0
- package/dist/utils/paste-collapse.js.map +1 -0
- package/dist/utils/paste-utils.d.ts +99 -0
- package/dist/utils/paste-utils.js +239 -0
- package/dist/utils/paste-utils.js.map +1 -0
- package/dist/utils/path-security.d.ts +90 -0
- package/dist/utils/path-security.js +328 -0
- package/dist/utils/path-security.js.map +1 -0
- package/dist/utils/process-pool.d.ts +105 -0
- package/dist/utils/process-pool.js +326 -0
- package/dist/utils/process-pool.js.map +1 -0
- package/dist/utils/rate-limiter.d.ts +221 -0
- package/dist/utils/rate-limiter.js +317 -0
- package/dist/utils/rate-limiter.js.map +1 -0
- package/dist/utils/settings-manager.js +99 -6
- package/dist/utils/settings-manager.js.map +1 -1
- package/dist/utils/streaming-analyzer.js +9 -21
- package/dist/utils/streaming-analyzer.js.map +1 -1
- package/package.json +3 -7
- package/packages/schemas/dist/index.d.ts +14 -0
- package/packages/schemas/dist/index.d.ts.map +1 -0
- package/packages/schemas/dist/index.js +19 -0
- package/packages/schemas/dist/index.js.map +1 -0
- package/packages/schemas/dist/public/core/brand-types.d.ts +308 -0
- package/packages/schemas/dist/public/core/brand-types.d.ts.map +1 -0
- package/packages/schemas/dist/public/core/brand-types.js +243 -0
- package/packages/schemas/dist/public/core/brand-types.js.map +1 -0
- package/packages/schemas/dist/public/core/enums.d.ts +227 -0
- package/packages/schemas/dist/public/core/enums.d.ts.map +1 -0
- package/packages/schemas/dist/public/core/enums.js +222 -0
- package/packages/schemas/dist/public/core/enums.js.map +1 -0
- package/packages/schemas/dist/public/core/id-types.d.ts +286 -0
- package/packages/schemas/dist/public/core/id-types.d.ts.map +1 -0
- package/packages/schemas/dist/public/core/id-types.js +136 -0
- package/packages/schemas/dist/public/core/id-types.js.map +1 -0
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Path Security Utilities
|
|
3
|
+
*
|
|
4
|
+
* Provides comprehensive path validation to prevent path traversal,
|
|
5
|
+
* symlink attacks, and access to dangerous system directories (REQ-SEC-002).
|
|
6
|
+
*
|
|
7
|
+
* @module path-security
|
|
8
|
+
*/
|
|
9
|
+
import path from 'path';
|
|
10
|
+
import fs from 'fs-extra';
|
|
11
|
+
import os from 'os';
|
|
12
|
+
/**
|
|
13
|
+
* Get OS-specific dangerous paths that should never be accessed.
|
|
14
|
+
*
|
|
15
|
+
* @returns Array of dangerous path prefixes
|
|
16
|
+
*/
|
|
17
|
+
export function getDangerousPathsForOS() {
|
|
18
|
+
const platform = process.platform;
|
|
19
|
+
// Common dangerous paths (Unix-like)
|
|
20
|
+
const commonPaths = [
|
|
21
|
+
'/etc',
|
|
22
|
+
'/sys',
|
|
23
|
+
'/proc',
|
|
24
|
+
'/dev',
|
|
25
|
+
'/root',
|
|
26
|
+
'/boot',
|
|
27
|
+
'/var',
|
|
28
|
+
'/lib',
|
|
29
|
+
'/lib64',
|
|
30
|
+
'/usr/lib',
|
|
31
|
+
'/usr/local/lib',
|
|
32
|
+
'/bin',
|
|
33
|
+
'/sbin',
|
|
34
|
+
'/usr/bin',
|
|
35
|
+
'/usr/sbin',
|
|
36
|
+
];
|
|
37
|
+
if (platform === 'darwin') {
|
|
38
|
+
// macOS-specific
|
|
39
|
+
return [
|
|
40
|
+
...commonPaths,
|
|
41
|
+
'/System',
|
|
42
|
+
'/Library',
|
|
43
|
+
'/private/etc',
|
|
44
|
+
'/private/var',
|
|
45
|
+
'/Volumes',
|
|
46
|
+
'/Applications',
|
|
47
|
+
];
|
|
48
|
+
}
|
|
49
|
+
else if (platform === 'win32') {
|
|
50
|
+
// Windows-specific
|
|
51
|
+
return [
|
|
52
|
+
'C:\\Windows',
|
|
53
|
+
'C:\\Program Files',
|
|
54
|
+
'C:\\Program Files (x86)',
|
|
55
|
+
'C:\\ProgramData',
|
|
56
|
+
'C:\\System Volume Information',
|
|
57
|
+
'C:\\$Recycle.Bin',
|
|
58
|
+
];
|
|
59
|
+
}
|
|
60
|
+
// Linux/Unix
|
|
61
|
+
return [
|
|
62
|
+
...commonPaths,
|
|
63
|
+
'/snap',
|
|
64
|
+
'/mnt',
|
|
65
|
+
'/media',
|
|
66
|
+
'/run',
|
|
67
|
+
];
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Get dangerous file patterns that should be blocked.
|
|
71
|
+
*
|
|
72
|
+
* @returns Array of dangerous file patterns (strings or regexes)
|
|
73
|
+
*/
|
|
74
|
+
export function getDangerousFilePatterns() {
|
|
75
|
+
return [
|
|
76
|
+
// SSH keys
|
|
77
|
+
/\.ssh\/id_rsa$/,
|
|
78
|
+
/\.ssh\/id_ed25519$/,
|
|
79
|
+
/\.ssh\/id_ecdsa$/,
|
|
80
|
+
/\.ssh\/authorized_keys$/,
|
|
81
|
+
/\.ssh\/known_hosts$/,
|
|
82
|
+
// AWS credentials
|
|
83
|
+
/\.aws\/credentials$/,
|
|
84
|
+
/\.aws\/config$/,
|
|
85
|
+
// Other credentials
|
|
86
|
+
'.npmrc',
|
|
87
|
+
'.gitconfig',
|
|
88
|
+
'.docker/config.json',
|
|
89
|
+
// Shell history
|
|
90
|
+
/\.bash_history$/,
|
|
91
|
+
/\.zsh_history$/,
|
|
92
|
+
/\.sh_history$/,
|
|
93
|
+
// Environment files
|
|
94
|
+
/\.env$/,
|
|
95
|
+
/\.env\.local$/,
|
|
96
|
+
/\.env\.production$/,
|
|
97
|
+
// System files (Unix)
|
|
98
|
+
'/etc/passwd',
|
|
99
|
+
'/etc/shadow',
|
|
100
|
+
'/etc/sudoers',
|
|
101
|
+
'/etc/hosts',
|
|
102
|
+
'/etc/ssh/sshd_config',
|
|
103
|
+
];
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Check if a path matches a dangerous file pattern.
|
|
107
|
+
*
|
|
108
|
+
* @param filePath - Path to check
|
|
109
|
+
* @returns True if file matches dangerous pattern
|
|
110
|
+
*/
|
|
111
|
+
export function isDangerousFile(filePath) {
|
|
112
|
+
const normalized = filePath.replace(/\\/g, '/');
|
|
113
|
+
const patterns = getDangerousFilePatterns();
|
|
114
|
+
return patterns.some(pattern => {
|
|
115
|
+
if (typeof pattern === 'string') {
|
|
116
|
+
return normalized.includes(pattern) || normalized.endsWith(pattern);
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
return pattern.test(normalized);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Canonicalize a path by resolving symlinks and normalizing.
|
|
125
|
+
*
|
|
126
|
+
* @param filePath - Path to canonicalize
|
|
127
|
+
* @returns Canonicalized path or original if canonicalization fails
|
|
128
|
+
*/
|
|
129
|
+
export async function canonicalizePath(filePath) {
|
|
130
|
+
try {
|
|
131
|
+
// Use fs.realpath to resolve symlinks
|
|
132
|
+
const canonical = await fs.realpath(filePath);
|
|
133
|
+
return canonical;
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
// If realpath fails (e.g., file doesn't exist), just resolve
|
|
137
|
+
return path.resolve(filePath);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Check if a path contains symlinks in any component.
|
|
142
|
+
*
|
|
143
|
+
* @param filePath - Path to check
|
|
144
|
+
* @returns True if any component is a symlink
|
|
145
|
+
*/
|
|
146
|
+
export async function containsSymlinks(filePath) {
|
|
147
|
+
const resolved = path.resolve(filePath);
|
|
148
|
+
const components = resolved.split(path.sep).filter(c => c);
|
|
149
|
+
let currentPath = path.isAbsolute(filePath) ? path.sep : '.';
|
|
150
|
+
for (const component of components) {
|
|
151
|
+
currentPath = path.join(currentPath, component);
|
|
152
|
+
try {
|
|
153
|
+
const stats = await fs.lstat(currentPath);
|
|
154
|
+
if (stats.isSymbolicLink()) {
|
|
155
|
+
return true;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
// If stat fails, path doesn't exist yet - not a symlink
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Validate a file path for security.
|
|
167
|
+
*
|
|
168
|
+
* Performs comprehensive checks:
|
|
169
|
+
* 1. Canonicalization (resolve symlinks)
|
|
170
|
+
* 2. Allowed root validation
|
|
171
|
+
* 3. Dangerous path blocking
|
|
172
|
+
* 4. Symlink detection
|
|
173
|
+
* 5. Dangerous file detection
|
|
174
|
+
*
|
|
175
|
+
* @param filePath - Path to validate
|
|
176
|
+
* @param options - Validation options
|
|
177
|
+
* @returns Validation result with success status and validated path
|
|
178
|
+
*/
|
|
179
|
+
export async function validatePathSecure(filePath, options = {}) {
|
|
180
|
+
try {
|
|
181
|
+
// 1. Canonicalize path (resolves symlinks)
|
|
182
|
+
const canonical = await canonicalizePath(filePath);
|
|
183
|
+
// 2. Resolve to absolute path
|
|
184
|
+
const resolved = path.resolve(canonical);
|
|
185
|
+
// 3. Check if within allowed directory roots
|
|
186
|
+
const allowedRoots = options.allowedRoots || [
|
|
187
|
+
process.cwd(),
|
|
188
|
+
path.join(os.homedir(), '.ax-cli'),
|
|
189
|
+
];
|
|
190
|
+
const isAllowed = allowedRoots.some(root => {
|
|
191
|
+
const normalizedRoot = path.resolve(root);
|
|
192
|
+
return (resolved === normalizedRoot ||
|
|
193
|
+
resolved.startsWith(normalizedRoot + path.sep));
|
|
194
|
+
});
|
|
195
|
+
if (!isAllowed) {
|
|
196
|
+
return {
|
|
197
|
+
success: false,
|
|
198
|
+
error: `Path "${filePath}" is outside allowed directories. Allowed roots: ${allowedRoots.join(', ')}`,
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
// 4. Check for dangerous paths (OS-specific)
|
|
202
|
+
const dangerousPaths = getDangerousPathsForOS();
|
|
203
|
+
for (const dangerous of dangerousPaths) {
|
|
204
|
+
const normalizedDangerous = path.resolve(dangerous);
|
|
205
|
+
if (resolved.startsWith(normalizedDangerous + path.sep) ||
|
|
206
|
+
resolved === normalizedDangerous) {
|
|
207
|
+
return {
|
|
208
|
+
success: false,
|
|
209
|
+
error: `Access to system directory "${dangerous}" denied`,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
// 5. Check for dangerous files
|
|
214
|
+
if (isDangerousFile(resolved)) {
|
|
215
|
+
return {
|
|
216
|
+
success: false,
|
|
217
|
+
error: `Access to sensitive file denied: "${filePath}"`,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
// 6. Check for symlinks (if not allowed)
|
|
221
|
+
if (!options.allowSymlinks) {
|
|
222
|
+
const hasSymlinks = await containsSymlinks(filePath);
|
|
223
|
+
if (hasSymlinks) {
|
|
224
|
+
return {
|
|
225
|
+
success: false,
|
|
226
|
+
error: `Path contains symlinks: "${filePath}". Symlinks are not allowed for security.`,
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
// 7. Optionally check if path exists
|
|
231
|
+
if (options.checkExists) {
|
|
232
|
+
const exists = await fs.pathExists(resolved);
|
|
233
|
+
if (!exists) {
|
|
234
|
+
return {
|
|
235
|
+
success: false,
|
|
236
|
+
error: `Path does not exist: "${filePath}"`,
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
// All checks passed
|
|
241
|
+
return {
|
|
242
|
+
success: true,
|
|
243
|
+
path: resolved,
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
catch (error) {
|
|
247
|
+
return {
|
|
248
|
+
success: false,
|
|
249
|
+
error: `Path validation error: ${error.message}`,
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Synchronous version of validatePathSecure.
|
|
255
|
+
* Less secure (doesn't resolve symlinks), use async version when possible.
|
|
256
|
+
*
|
|
257
|
+
* @param filePath - Path to validate
|
|
258
|
+
* @param options - Validation options
|
|
259
|
+
* @returns Validation result
|
|
260
|
+
*/
|
|
261
|
+
export function validatePathSecureSync(filePath, options = {}) {
|
|
262
|
+
try {
|
|
263
|
+
// Resolve to absolute path (no symlink resolution in sync version)
|
|
264
|
+
const resolved = path.resolve(filePath);
|
|
265
|
+
// Check allowed roots
|
|
266
|
+
const allowedRoots = options.allowedRoots || [
|
|
267
|
+
process.cwd(),
|
|
268
|
+
path.join(os.homedir(), '.ax-cli'),
|
|
269
|
+
];
|
|
270
|
+
const isAllowed = allowedRoots.some(root => {
|
|
271
|
+
const normalizedRoot = path.resolve(root);
|
|
272
|
+
return (resolved === normalizedRoot ||
|
|
273
|
+
resolved.startsWith(normalizedRoot + path.sep));
|
|
274
|
+
});
|
|
275
|
+
if (!isAllowed) {
|
|
276
|
+
return {
|
|
277
|
+
success: false,
|
|
278
|
+
error: `Path outside allowed directories`,
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
// Check dangerous paths
|
|
282
|
+
const dangerousPaths = getDangerousPathsForOS();
|
|
283
|
+
for (const dangerous of dangerousPaths) {
|
|
284
|
+
const normalizedDangerous = path.resolve(dangerous);
|
|
285
|
+
if (resolved.startsWith(normalizedDangerous + path.sep) ||
|
|
286
|
+
resolved === normalizedDangerous) {
|
|
287
|
+
return {
|
|
288
|
+
success: false,
|
|
289
|
+
error: `Access to system directory denied`,
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
// Check dangerous files
|
|
294
|
+
if (isDangerousFile(resolved)) {
|
|
295
|
+
return {
|
|
296
|
+
success: false,
|
|
297
|
+
error: `Access to sensitive file denied`,
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
return {
|
|
301
|
+
success: true,
|
|
302
|
+
path: resolved,
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
catch (error) {
|
|
306
|
+
return {
|
|
307
|
+
success: false,
|
|
308
|
+
error: error.message,
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Create a safe path joiner that validates the result.
|
|
314
|
+
*
|
|
315
|
+
* @param basePath - Base directory path
|
|
316
|
+
* @param relativePath - Relative path to join
|
|
317
|
+
* @param options - Validation options
|
|
318
|
+
* @returns Validated joined path or null if invalid
|
|
319
|
+
*/
|
|
320
|
+
export async function safePathJoin(basePath, relativePath, options = {}) {
|
|
321
|
+
const joined = path.join(basePath, relativePath);
|
|
322
|
+
const validation = await validatePathSecure(joined, options);
|
|
323
|
+
if (!validation.success) {
|
|
324
|
+
return null;
|
|
325
|
+
}
|
|
326
|
+
return validation.path;
|
|
327
|
+
}
|
|
328
|
+
//# sourceMappingURL=path-security.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path-security.js","sourceRoot":"","sources":["../../src/utils/path-security.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Process Pool Manager
|
|
3
|
+
*
|
|
4
|
+
* Manages a pool of reusable child processes to prevent memory leaks
|
|
5
|
+
* and resource exhaustion (REQ-ARCH-002).
|
|
6
|
+
*
|
|
7
|
+
* Key features:
|
|
8
|
+
* - Limits concurrent processes to prevent resource exhaustion
|
|
9
|
+
* - Queues requests when pool is full
|
|
10
|
+
* - Automatic cleanup of idle processes
|
|
11
|
+
* - Graceful shutdown with proper cleanup
|
|
12
|
+
* - Memory leak prevention through proper event listener management
|
|
13
|
+
*
|
|
14
|
+
* @module process-pool
|
|
15
|
+
*/
|
|
16
|
+
import { EventEmitter } from 'events';
|
|
17
|
+
/**
|
|
18
|
+
* Options for process execution
|
|
19
|
+
*/
|
|
20
|
+
export interface ProcessExecutionOptions {
|
|
21
|
+
command: string;
|
|
22
|
+
args: string[];
|
|
23
|
+
timeout?: number;
|
|
24
|
+
cwd?: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Result of process execution
|
|
28
|
+
*/
|
|
29
|
+
export interface ProcessExecutionResult {
|
|
30
|
+
stdout: string;
|
|
31
|
+
stderr: string;
|
|
32
|
+
exitCode: number | null;
|
|
33
|
+
signal: string | null;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Process pool configuration
|
|
37
|
+
*/
|
|
38
|
+
export interface ProcessPoolConfig {
|
|
39
|
+
maxProcesses?: number;
|
|
40
|
+
processTimeout?: number;
|
|
41
|
+
idleTimeout?: number;
|
|
42
|
+
maxQueueSize?: number;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Process pool manager for efficient process reuse
|
|
46
|
+
*/
|
|
47
|
+
export declare class ProcessPool extends EventEmitter {
|
|
48
|
+
private readonly maxProcesses;
|
|
49
|
+
private readonly processTimeout;
|
|
50
|
+
private readonly maxQueueSize;
|
|
51
|
+
private activeProcesses;
|
|
52
|
+
private taskQueue;
|
|
53
|
+
private shuttingDown;
|
|
54
|
+
private idleTimers;
|
|
55
|
+
constructor(config?: ProcessPoolConfig);
|
|
56
|
+
/**
|
|
57
|
+
* Execute a command using the process pool
|
|
58
|
+
*/
|
|
59
|
+
execute(options: ProcessExecutionOptions): Promise<ProcessExecutionResult>;
|
|
60
|
+
/**
|
|
61
|
+
* Process the task queue
|
|
62
|
+
*/
|
|
63
|
+
private processQueue;
|
|
64
|
+
/**
|
|
65
|
+
* Execute a single task
|
|
66
|
+
*/
|
|
67
|
+
private executeTask;
|
|
68
|
+
/**
|
|
69
|
+
* Spawn a process and manage its lifecycle
|
|
70
|
+
*/
|
|
71
|
+
private spawnProcess;
|
|
72
|
+
/**
|
|
73
|
+
* Cleanup process and associated resources
|
|
74
|
+
*/
|
|
75
|
+
private cleanupProcess;
|
|
76
|
+
/**
|
|
77
|
+
* Get pool statistics
|
|
78
|
+
*/
|
|
79
|
+
getStats(): {
|
|
80
|
+
activeProcesses: number;
|
|
81
|
+
queuedTasks: number;
|
|
82
|
+
maxProcesses: number;
|
|
83
|
+
maxQueueSize: number;
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* Shutdown the pool gracefully
|
|
87
|
+
*/
|
|
88
|
+
shutdown(force?: boolean): Promise<void>;
|
|
89
|
+
/**
|
|
90
|
+
* Check if pool is idle (no active processes or queued tasks)
|
|
91
|
+
*/
|
|
92
|
+
isIdle(): boolean;
|
|
93
|
+
/**
|
|
94
|
+
* Check if pool is at capacity
|
|
95
|
+
*/
|
|
96
|
+
isAtCapacity(): boolean;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Get or create the ripgrep process pool
|
|
100
|
+
*/
|
|
101
|
+
export declare function getRipgrepPool(): ProcessPool;
|
|
102
|
+
/**
|
|
103
|
+
* Shutdown the ripgrep pool (for testing)
|
|
104
|
+
*/
|
|
105
|
+
export declare function shutdownRipgrepPool(): Promise<void>;
|