@defai.digital/ax-cli 3.5.4 → 3.6.0
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/memory.json +8 -8
- package/README.md +7 -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/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.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 +30 -0
- package/dist/schemas/settings-schemas.js +30 -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/ui/components/chat-history.js +1 -1
- package/dist/ui/components/chat-history.js.map +1 -1
- package/dist/ui/components/chat-interface.js +3 -2
- 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/status-bar.js +2 -2
- package/dist/ui/components/status-bar.js.map +1 -1
- package/dist/{hooks → ui/hooks}/use-chat-reducer.d.ts +1 -1
- package/dist/ui/hooks/use-chat-reducer.js.map +1 -0
- package/dist/{hooks → ui/hooks}/use-enhanced-input.js +8 -3
- package/dist/ui/hooks/use-enhanced-input.js.map +1 -0
- package/dist/{hooks → ui/hooks}/use-input-handler.d.ts +1 -1
- package/dist/{hooks → ui/hooks}/use-input-handler.js +28 -24
- package/dist/ui/hooks/use-input-handler.js.map +1 -0
- package/dist/utils/audit-logger.d.ts +247 -0
- package/dist/utils/audit-logger.js +374 -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/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 +207 -0
- package/dist/utils/rate-limiter.js +303 -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 +1 -1
- package/dist/hooks/use-chat-reducer.js.map +0 -1
- package/dist/hooks/use-enhanced-input.js.map +0 -1
- package/dist/hooks/use-input-handler.js.map +0 -1
- package/dist/hooks/use-input-history.d.ts +0 -9
- package/dist/hooks/use-input-history.js +0 -112
- package/dist/hooks/use-input-history.js.map +0 -1
- /package/dist/{hooks → ui/hooks}/use-chat-reducer.js +0 -0
- /package/dist/{hooks → ui/hooks}/use-enhanced-input.d.ts +0 -0
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Input Sanitization Framework (REQ-SEC-007)
|
|
3
|
+
*
|
|
4
|
+
* Provides comprehensive input validation and sanitization to prevent:
|
|
5
|
+
* - ReDoS (Regular Expression Denial of Service)
|
|
6
|
+
* - Command injection
|
|
7
|
+
* - Path traversal
|
|
8
|
+
* - Unicode attacks
|
|
9
|
+
* - Buffer overflow
|
|
10
|
+
*
|
|
11
|
+
* Security: CVSS 7.3 (High Priority)
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Default maximum input lengths for different contexts
|
|
15
|
+
*/
|
|
16
|
+
export const MAX_INPUT_LENGTHS = {
|
|
17
|
+
COMMAND: 10_000, // Shell commands
|
|
18
|
+
FILE_PATH: 4_096, // File system paths
|
|
19
|
+
USER_INPUT: 50_000, // General user input (prompts, etc.)
|
|
20
|
+
SEARCH_QUERY: 1_000, // Search queries
|
|
21
|
+
ENV_VALUE: 10_000, // Environment variable values
|
|
22
|
+
CONFIG_VALUE: 10_000, // Configuration values
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Dangerous patterns that indicate potential attacks
|
|
26
|
+
* These patterns are designed to be fast and avoid ReDoS
|
|
27
|
+
*/
|
|
28
|
+
const DANGEROUS_PATTERNS = {
|
|
29
|
+
// Null bytes (path traversal, command injection)
|
|
30
|
+
NULL_BYTE: /\0/,
|
|
31
|
+
// Excessive repetition (ReDoS indicator)
|
|
32
|
+
// Using fixed quantifier to prevent ReDoS
|
|
33
|
+
EXCESSIVE_REPETITION: /(.)\1{100,}/,
|
|
34
|
+
// Control characters (except common ones like \n, \t)
|
|
35
|
+
CONTROL_CHARS: /[\x00-\x08\x0B-\x0C\x0E-\x1F\x7F]/,
|
|
36
|
+
// Unicode direction override (used in homograph attacks)
|
|
37
|
+
UNICODE_OVERRIDE: /[\u202A-\u202E\u2066-\u2069]/,
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Safe characters for different contexts
|
|
41
|
+
*/
|
|
42
|
+
export const SAFE_PATTERNS = {
|
|
43
|
+
/**
|
|
44
|
+
* Alphanumeric, spaces, and common punctuation
|
|
45
|
+
*/
|
|
46
|
+
BASIC: /^[a-zA-Z0-9\s.,!?'"()\-_]+$/,
|
|
47
|
+
/**
|
|
48
|
+
* Safe for file paths (no directory traversal)
|
|
49
|
+
*/
|
|
50
|
+
FILE_PATH: /^[a-zA-Z0-9/._\-]+$/,
|
|
51
|
+
/**
|
|
52
|
+
* Safe for environment variable values
|
|
53
|
+
*/
|
|
54
|
+
ENV_VALUE: /^[a-zA-Z0-9._\-:/=]+$/,
|
|
55
|
+
/**
|
|
56
|
+
* Printable ASCII only (most restrictive)
|
|
57
|
+
*/
|
|
58
|
+
ASCII_PRINTABLE: /^[\x20-\x7E]+$/,
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Normalize Unicode string to prevent homograph attacks
|
|
62
|
+
*
|
|
63
|
+
* Uses NFC (Canonical Decomposition, followed by Canonical Composition)
|
|
64
|
+
* which is the recommended normalization form for most use cases
|
|
65
|
+
*
|
|
66
|
+
* @param input - String to normalize
|
|
67
|
+
* @returns Normalized string
|
|
68
|
+
*/
|
|
69
|
+
export function normalizeUnicode(input) {
|
|
70
|
+
return input.normalize('NFC');
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Check for dangerous patterns in input
|
|
74
|
+
*
|
|
75
|
+
* @param input - String to check
|
|
76
|
+
* @returns Array of detected dangerous patterns
|
|
77
|
+
*/
|
|
78
|
+
export function detectDangerousPatterns(input) {
|
|
79
|
+
const detected = [];
|
|
80
|
+
if (DANGEROUS_PATTERNS.NULL_BYTE.test(input)) {
|
|
81
|
+
detected.push('Null byte detected');
|
|
82
|
+
}
|
|
83
|
+
if (DANGEROUS_PATTERNS.EXCESSIVE_REPETITION.test(input)) {
|
|
84
|
+
detected.push('Excessive character repetition detected');
|
|
85
|
+
}
|
|
86
|
+
if (DANGEROUS_PATTERNS.CONTROL_CHARS.test(input)) {
|
|
87
|
+
detected.push('Control characters detected');
|
|
88
|
+
}
|
|
89
|
+
if (DANGEROUS_PATTERNS.UNICODE_OVERRIDE.test(input)) {
|
|
90
|
+
detected.push('Unicode direction override detected');
|
|
91
|
+
}
|
|
92
|
+
return detected;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Sanitize general user input with configurable options
|
|
96
|
+
*
|
|
97
|
+
* @param input - Raw input string
|
|
98
|
+
* @param options - Sanitization options
|
|
99
|
+
* @returns Sanitization result
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```typescript
|
|
103
|
+
* const result = sanitizeInput('User input here', {
|
|
104
|
+
* maxLength: 1000,
|
|
105
|
+
* normalizeUnicode: true,
|
|
106
|
+
* allowedPattern: SAFE_PATTERNS.BASIC,
|
|
107
|
+
* });
|
|
108
|
+
*
|
|
109
|
+
* if (result.valid) {
|
|
110
|
+
* // Use result.value safely
|
|
111
|
+
* } else {
|
|
112
|
+
* console.error(result.error);
|
|
113
|
+
* }
|
|
114
|
+
* ```
|
|
115
|
+
*/
|
|
116
|
+
export function sanitizeInput(input, options = {}) {
|
|
117
|
+
const { maxLength = MAX_INPUT_LENGTHS.USER_INPUT, normalizeUnicode: shouldNormalize = true, allowedPattern, trim = true, allowEmpty = false, } = options;
|
|
118
|
+
const warnings = [];
|
|
119
|
+
let value = input;
|
|
120
|
+
// 1. Trim if requested
|
|
121
|
+
if (trim) {
|
|
122
|
+
value = value.trim();
|
|
123
|
+
}
|
|
124
|
+
// 2. Check if empty
|
|
125
|
+
if (!allowEmpty && value.length === 0) {
|
|
126
|
+
return {
|
|
127
|
+
valid: false,
|
|
128
|
+
error: 'Input cannot be empty',
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
// 3. Check length BEFORE normalization (prevent DoS via normalization)
|
|
132
|
+
if (value.length > maxLength) {
|
|
133
|
+
return {
|
|
134
|
+
valid: false,
|
|
135
|
+
error: `Input exceeds maximum length of ${maxLength} characters (got ${value.length})`,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
// 4. Unicode normalization (prevent homograph attacks)
|
|
139
|
+
if (shouldNormalize) {
|
|
140
|
+
const normalized = normalizeUnicode(value);
|
|
141
|
+
if (normalized !== value) {
|
|
142
|
+
warnings.push('Input was normalized (Unicode)');
|
|
143
|
+
value = normalized;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// 5. Check for dangerous patterns
|
|
147
|
+
const dangerous = detectDangerousPatterns(value);
|
|
148
|
+
if (dangerous.length > 0) {
|
|
149
|
+
return {
|
|
150
|
+
valid: false,
|
|
151
|
+
error: `Dangerous patterns detected: ${dangerous.join(', ')}`,
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
// 6. Apply character whitelist if provided
|
|
155
|
+
if (allowedPattern && !allowedPattern.test(value)) {
|
|
156
|
+
return {
|
|
157
|
+
valid: false,
|
|
158
|
+
error: 'Input contains disallowed characters',
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
return {
|
|
162
|
+
valid: true,
|
|
163
|
+
value,
|
|
164
|
+
warnings: warnings.length > 0 ? warnings : undefined,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Sanitize file path input to prevent path traversal
|
|
169
|
+
*
|
|
170
|
+
* @param path - File path to sanitize
|
|
171
|
+
* @returns Sanitization result
|
|
172
|
+
*
|
|
173
|
+
* @example
|
|
174
|
+
* ```typescript
|
|
175
|
+
* const result = sanitizeFilePath('../../../etc/passwd');
|
|
176
|
+
* if (!result.valid) {
|
|
177
|
+
* console.error('Invalid path:', result.error);
|
|
178
|
+
* }
|
|
179
|
+
* ```
|
|
180
|
+
*/
|
|
181
|
+
export function sanitizeFilePath(path) {
|
|
182
|
+
const result = sanitizeInput(path, {
|
|
183
|
+
maxLength: MAX_INPUT_LENGTHS.FILE_PATH,
|
|
184
|
+
trim: true,
|
|
185
|
+
allowEmpty: false,
|
|
186
|
+
});
|
|
187
|
+
if (!result.valid) {
|
|
188
|
+
return result;
|
|
189
|
+
}
|
|
190
|
+
const value = result.value;
|
|
191
|
+
// Additional path-specific checks
|
|
192
|
+
const warnings = result.warnings || [];
|
|
193
|
+
// Check for path traversal patterns
|
|
194
|
+
if (value.includes('..')) {
|
|
195
|
+
warnings.push('Path contains parent directory references (..)');
|
|
196
|
+
}
|
|
197
|
+
// Check for absolute paths (may be intentional, so just warn)
|
|
198
|
+
if (value.startsWith('/') || /^[A-Z]:/i.test(value)) {
|
|
199
|
+
warnings.push('Absolute path detected');
|
|
200
|
+
}
|
|
201
|
+
// Check for hidden files (Unix)
|
|
202
|
+
if (value.split('/').some(part => part.startsWith('.'))) {
|
|
203
|
+
warnings.push('Path contains hidden file/directory');
|
|
204
|
+
}
|
|
205
|
+
return {
|
|
206
|
+
valid: true,
|
|
207
|
+
value,
|
|
208
|
+
warnings: warnings.length > 0 ? warnings : undefined,
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Sanitize shell command input
|
|
213
|
+
*
|
|
214
|
+
* NOTE: This is a last line of defense. Prefer execFile over exec
|
|
215
|
+
* and use argument arrays instead of concatenating commands.
|
|
216
|
+
*
|
|
217
|
+
* @param command - Command string to sanitize
|
|
218
|
+
* @returns Sanitization result
|
|
219
|
+
*
|
|
220
|
+
* @example
|
|
221
|
+
* ```typescript
|
|
222
|
+
* const result = sanitizeCommand('ls -la');
|
|
223
|
+
* if (result.valid) {
|
|
224
|
+
* // Still prefer execFile with args array
|
|
225
|
+
* execFile(result.value.split(' ')[0], result.value.split(' ').slice(1));
|
|
226
|
+
* }
|
|
227
|
+
* ```
|
|
228
|
+
*/
|
|
229
|
+
export function sanitizeCommand(command) {
|
|
230
|
+
const result = sanitizeInput(command, {
|
|
231
|
+
maxLength: MAX_INPUT_LENGTHS.COMMAND,
|
|
232
|
+
trim: true,
|
|
233
|
+
allowEmpty: false,
|
|
234
|
+
});
|
|
235
|
+
if (!result.valid) {
|
|
236
|
+
return result;
|
|
237
|
+
}
|
|
238
|
+
const value = result.value;
|
|
239
|
+
// Check for shell metacharacters that could enable injection
|
|
240
|
+
const shellMetaChars = /[;&|`$()<>\\]/;
|
|
241
|
+
if (shellMetaChars.test(value)) {
|
|
242
|
+
return {
|
|
243
|
+
valid: false,
|
|
244
|
+
error: 'Command contains dangerous shell metacharacters',
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
return {
|
|
248
|
+
valid: true,
|
|
249
|
+
value,
|
|
250
|
+
warnings: result.warnings,
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Sanitize search query input
|
|
255
|
+
*
|
|
256
|
+
* @param query - Search query to sanitize
|
|
257
|
+
* @returns Sanitization result
|
|
258
|
+
*/
|
|
259
|
+
export function sanitizeSearchQuery(query) {
|
|
260
|
+
return sanitizeInput(query, {
|
|
261
|
+
maxLength: MAX_INPUT_LENGTHS.SEARCH_QUERY,
|
|
262
|
+
trim: true,
|
|
263
|
+
allowEmpty: false,
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Sanitize environment variable value
|
|
268
|
+
*
|
|
269
|
+
* @param value - Environment variable value to sanitize
|
|
270
|
+
* @returns Sanitization result
|
|
271
|
+
*/
|
|
272
|
+
export function sanitizeEnvValue(value) {
|
|
273
|
+
return sanitizeInput(value, {
|
|
274
|
+
maxLength: MAX_INPUT_LENGTHS.ENV_VALUE,
|
|
275
|
+
trim: true,
|
|
276
|
+
allowEmpty: true, // Empty env vars are valid
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Escape shell arguments for safe execution
|
|
281
|
+
*
|
|
282
|
+
* NOTE: This is a defense-in-depth measure. Always prefer:
|
|
283
|
+
* 1. execFile with argument array over exec
|
|
284
|
+
* 2. Argument validation/whitelisting
|
|
285
|
+
* 3. This escaping function as a last resort
|
|
286
|
+
*
|
|
287
|
+
* @param arg - Argument to escape
|
|
288
|
+
* @returns Safely escaped argument
|
|
289
|
+
*/
|
|
290
|
+
export function escapeShellArg(arg) {
|
|
291
|
+
// On Windows, use double quotes
|
|
292
|
+
if (process.platform === 'win32') {
|
|
293
|
+
// Escape double quotes and backslashes
|
|
294
|
+
return `"${arg.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`;
|
|
295
|
+
}
|
|
296
|
+
// On Unix, use single quotes (safest - no interpolation)
|
|
297
|
+
// To include a single quote, end the quote, add escaped quote, resume quote
|
|
298
|
+
return `'${arg.replace(/'/g, "'\\''")}'`;
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Validate regex pattern for ReDoS protection
|
|
302
|
+
*
|
|
303
|
+
* Checks for common ReDoS patterns:
|
|
304
|
+
* - Nested quantifiers (e.g., (a+)+)
|
|
305
|
+
* - Alternation with overlapping patterns
|
|
306
|
+
* - Excessive backtracking potential
|
|
307
|
+
*
|
|
308
|
+
* @param pattern - Regex pattern to validate
|
|
309
|
+
* @returns Validation result
|
|
310
|
+
*
|
|
311
|
+
* @example
|
|
312
|
+
* ```typescript
|
|
313
|
+
* const result = validateRegexPattern('(a+)+b');
|
|
314
|
+
* if (!result.valid) {
|
|
315
|
+
* console.error('Unsafe regex:', result.error);
|
|
316
|
+
* }
|
|
317
|
+
* ```
|
|
318
|
+
*/
|
|
319
|
+
export function validateRegexPattern(pattern) {
|
|
320
|
+
// Check length first
|
|
321
|
+
if (pattern.length > 1000) {
|
|
322
|
+
return {
|
|
323
|
+
valid: false,
|
|
324
|
+
error: 'Regex pattern too long (max 1000 characters)',
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
const warnings = [];
|
|
328
|
+
// Check for nested quantifiers (major ReDoS risk)
|
|
329
|
+
// Pattern: quantifier inside a group that is itself quantified
|
|
330
|
+
const nestedQuantifiers = /\([^)]*[*+?{][^)]*\)[*+?{]/;
|
|
331
|
+
if (nestedQuantifiers.test(pattern)) {
|
|
332
|
+
return {
|
|
333
|
+
valid: false,
|
|
334
|
+
error: 'Regex contains nested quantifiers (ReDoS risk)',
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
// Check for excessive alternation
|
|
338
|
+
const alternations = pattern.split('|');
|
|
339
|
+
if (alternations.length > 20) {
|
|
340
|
+
warnings.push('Regex has many alternations (may be slow)');
|
|
341
|
+
}
|
|
342
|
+
// Check for backreferences (can cause exponential backtracking)
|
|
343
|
+
if (/\\[1-9]/.test(pattern)) {
|
|
344
|
+
warnings.push('Regex contains backreferences (may be slow)');
|
|
345
|
+
}
|
|
346
|
+
// Try to compile the regex to catch syntax errors
|
|
347
|
+
try {
|
|
348
|
+
new RegExp(pattern);
|
|
349
|
+
}
|
|
350
|
+
catch (error) {
|
|
351
|
+
return {
|
|
352
|
+
valid: false,
|
|
353
|
+
error: `Invalid regex: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
return {
|
|
357
|
+
valid: true,
|
|
358
|
+
value: pattern,
|
|
359
|
+
warnings: warnings.length > 0 ? warnings : undefined,
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
//# sourceMappingURL=input-sanitizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input-sanitizer.js","sourceRoot":"","sources":["../../src/utils/input-sanitizer.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* JSON Parsing Utilities
|
|
3
3
|
* Centralized JSON operations with validation and error handling
|
|
4
|
+
*
|
|
5
|
+
* Security: REQ-SEC-005 - Prototype Pollution Prevention
|
|
6
|
+
* - Sanitizes dangerous keys (__proto__, constructor, prototype)
|
|
7
|
+
* - Validates JSON structure before use
|
|
8
|
+
* - Prevents object property injection attacks
|
|
4
9
|
*/
|
|
5
10
|
import { z } from 'zod';
|
|
6
11
|
/**
|
|
@@ -57,3 +62,11 @@ export declare function parseJsonWithFallback<T>(jsonString: string, fallback: T
|
|
|
57
62
|
* Parse JSON file with fallback value on error
|
|
58
63
|
*/
|
|
59
64
|
export declare function parseJsonFileWithFallback<T>(filePath: string, fallback: T, schema?: z.ZodSchema<T>): T;
|
|
65
|
+
/**
|
|
66
|
+
* Sanitize an object to prevent prototype pollution
|
|
67
|
+
* Exported for testing purposes
|
|
68
|
+
*
|
|
69
|
+
* @param obj - Object to sanitize
|
|
70
|
+
* @returns Sanitized object
|
|
71
|
+
*/
|
|
72
|
+
export declare function sanitizeJson<T>(obj: T): T;
|
package/dist/utils/json-utils.js
CHANGED
|
@@ -1,15 +1,59 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* JSON Parsing Utilities
|
|
3
3
|
* Centralized JSON operations with validation and error handling
|
|
4
|
+
*
|
|
5
|
+
* Security: REQ-SEC-005 - Prototype Pollution Prevention
|
|
6
|
+
* - Sanitizes dangerous keys (__proto__, constructor, prototype)
|
|
7
|
+
* - Validates JSON structure before use
|
|
8
|
+
* - Prevents object property injection attacks
|
|
4
9
|
*/
|
|
5
10
|
import { readFileSync, writeFileSync, renameSync, unlinkSync, existsSync, copyFileSync, mkdirSync } from 'fs';
|
|
6
11
|
import { dirname } from 'path';
|
|
12
|
+
/**
|
|
13
|
+
* Dangerous keys that can cause prototype pollution
|
|
14
|
+
* These keys should never be allowed in parsed JSON
|
|
15
|
+
*/
|
|
16
|
+
const DANGEROUS_KEYS = ['__proto__', 'constructor', 'prototype'];
|
|
17
|
+
/**
|
|
18
|
+
* Sanitize parsed JSON by removing dangerous keys
|
|
19
|
+
* Prevents prototype pollution attacks (REQ-SEC-005)
|
|
20
|
+
*
|
|
21
|
+
* @param obj - Object to sanitize (recursively)
|
|
22
|
+
* @returns Sanitized object with dangerous keys removed
|
|
23
|
+
*/
|
|
24
|
+
function sanitizeObject(obj) {
|
|
25
|
+
if (obj === null || typeof obj !== 'object') {
|
|
26
|
+
return obj;
|
|
27
|
+
}
|
|
28
|
+
// Handle arrays
|
|
29
|
+
if (Array.isArray(obj)) {
|
|
30
|
+
return obj.map(item => sanitizeObject(item));
|
|
31
|
+
}
|
|
32
|
+
// Handle objects
|
|
33
|
+
const sanitized = {};
|
|
34
|
+
for (const key in obj) {
|
|
35
|
+
// Skip dangerous keys
|
|
36
|
+
if (DANGEROUS_KEYS.includes(key)) {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
// Skip inherited properties
|
|
40
|
+
if (!Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
// Recursively sanitize nested objects
|
|
44
|
+
const value = obj[key];
|
|
45
|
+
sanitized[key] = sanitizeObject(value);
|
|
46
|
+
}
|
|
47
|
+
return sanitized;
|
|
48
|
+
}
|
|
7
49
|
/**
|
|
8
50
|
* Parse JSON string with Zod schema validation
|
|
9
51
|
*/
|
|
10
52
|
export function parseJson(jsonString, schema) {
|
|
11
53
|
try {
|
|
12
|
-
const
|
|
54
|
+
const rawData = JSON.parse(jsonString);
|
|
55
|
+
// SECURITY: Sanitize to prevent prototype pollution (REQ-SEC-005)
|
|
56
|
+
const data = sanitizeObject(rawData);
|
|
13
57
|
if (schema) {
|
|
14
58
|
const result = schema.safeParse(data);
|
|
15
59
|
if (!result.success) {
|
|
@@ -169,4 +213,14 @@ export function parseJsonFileWithFallback(filePath, fallback, schema) {
|
|
|
169
213
|
const result = parseJsonFile(filePath, schema);
|
|
170
214
|
return result.success ? result.data : fallback;
|
|
171
215
|
}
|
|
216
|
+
/**
|
|
217
|
+
* Sanitize an object to prevent prototype pollution
|
|
218
|
+
* Exported for testing purposes
|
|
219
|
+
*
|
|
220
|
+
* @param obj - Object to sanitize
|
|
221
|
+
* @returns Sanitized object
|
|
222
|
+
*/
|
|
223
|
+
export function sanitizeJson(obj) {
|
|
224
|
+
return sanitizeObject(obj);
|
|
225
|
+
}
|
|
172
226
|
//# sourceMappingURL=json-utils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"json-utils.js","sourceRoot":"","sources":["../../src/utils/json-utils.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"json-utils.js","sourceRoot":"","sources":["../../src/utils/json-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,90 @@
|
|
|
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
|
+
/**
|
|
10
|
+
* Result of path validation
|
|
11
|
+
*/
|
|
12
|
+
export interface PathValidationResult {
|
|
13
|
+
success: boolean;
|
|
14
|
+
path?: string;
|
|
15
|
+
error?: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Options for path validation
|
|
19
|
+
*/
|
|
20
|
+
export interface PathValidationOptions {
|
|
21
|
+
allowSymlinks?: boolean;
|
|
22
|
+
allowedRoots?: string[];
|
|
23
|
+
checkExists?: boolean;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Get OS-specific dangerous paths that should never be accessed.
|
|
27
|
+
*
|
|
28
|
+
* @returns Array of dangerous path prefixes
|
|
29
|
+
*/
|
|
30
|
+
export declare function getDangerousPathsForOS(): string[];
|
|
31
|
+
/**
|
|
32
|
+
* Get dangerous file patterns that should be blocked.
|
|
33
|
+
*
|
|
34
|
+
* @returns Array of dangerous file patterns (strings or regexes)
|
|
35
|
+
*/
|
|
36
|
+
export declare function getDangerousFilePatterns(): Array<string | RegExp>;
|
|
37
|
+
/**
|
|
38
|
+
* Check if a path matches a dangerous file pattern.
|
|
39
|
+
*
|
|
40
|
+
* @param filePath - Path to check
|
|
41
|
+
* @returns True if file matches dangerous pattern
|
|
42
|
+
*/
|
|
43
|
+
export declare function isDangerousFile(filePath: string): boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Canonicalize a path by resolving symlinks and normalizing.
|
|
46
|
+
*
|
|
47
|
+
* @param filePath - Path to canonicalize
|
|
48
|
+
* @returns Canonicalized path or original if canonicalization fails
|
|
49
|
+
*/
|
|
50
|
+
export declare function canonicalizePath(filePath: string): Promise<string>;
|
|
51
|
+
/**
|
|
52
|
+
* Check if a path contains symlinks in any component.
|
|
53
|
+
*
|
|
54
|
+
* @param filePath - Path to check
|
|
55
|
+
* @returns True if any component is a symlink
|
|
56
|
+
*/
|
|
57
|
+
export declare function containsSymlinks(filePath: string): Promise<boolean>;
|
|
58
|
+
/**
|
|
59
|
+
* Validate a file path for security.
|
|
60
|
+
*
|
|
61
|
+
* Performs comprehensive checks:
|
|
62
|
+
* 1. Canonicalization (resolve symlinks)
|
|
63
|
+
* 2. Allowed root validation
|
|
64
|
+
* 3. Dangerous path blocking
|
|
65
|
+
* 4. Symlink detection
|
|
66
|
+
* 5. Dangerous file detection
|
|
67
|
+
*
|
|
68
|
+
* @param filePath - Path to validate
|
|
69
|
+
* @param options - Validation options
|
|
70
|
+
* @returns Validation result with success status and validated path
|
|
71
|
+
*/
|
|
72
|
+
export declare function validatePathSecure(filePath: string, options?: PathValidationOptions): Promise<PathValidationResult>;
|
|
73
|
+
/**
|
|
74
|
+
* Synchronous version of validatePathSecure.
|
|
75
|
+
* Less secure (doesn't resolve symlinks), use async version when possible.
|
|
76
|
+
*
|
|
77
|
+
* @param filePath - Path to validate
|
|
78
|
+
* @param options - Validation options
|
|
79
|
+
* @returns Validation result
|
|
80
|
+
*/
|
|
81
|
+
export declare function validatePathSecureSync(filePath: string, options?: PathValidationOptions): PathValidationResult;
|
|
82
|
+
/**
|
|
83
|
+
* Create a safe path joiner that validates the result.
|
|
84
|
+
*
|
|
85
|
+
* @param basePath - Base directory path
|
|
86
|
+
* @param relativePath - Relative path to join
|
|
87
|
+
* @param options - Validation options
|
|
88
|
+
* @returns Validated joined path or null if invalid
|
|
89
|
+
*/
|
|
90
|
+
export declare function safePathJoin(basePath: string, relativePath: string, options?: PathValidationOptions): Promise<string | null>;
|