aios-core 4.2.13 → 4.2.15
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/.aios-core/core/code-intel/helpers/dev-helper.js +206 -0
- package/.aios-core/core/registry/registry-schema.json +166 -166
- package/.aios-core/core/synapse/diagnostics/collectors/hook-collector.js +3 -3
- package/.aios-core/data/entity-registry.yaml +27 -0
- package/.aios-core/development/scripts/approval-workflow.js +642 -642
- package/.aios-core/development/scripts/backup-manager.js +606 -606
- package/.aios-core/development/scripts/branch-manager.js +389 -389
- package/.aios-core/development/scripts/code-quality-improver.js +1311 -1311
- package/.aios-core/development/scripts/commit-message-generator.js +849 -849
- package/.aios-core/development/scripts/conflict-resolver.js +674 -674
- package/.aios-core/development/scripts/dependency-analyzer.js +637 -637
- package/.aios-core/development/scripts/diff-generator.js +351 -351
- package/.aios-core/development/scripts/elicitation-engine.js +384 -384
- package/.aios-core/development/scripts/elicitation-session-manager.js +299 -299
- package/.aios-core/development/scripts/git-wrapper.js +461 -461
- package/.aios-core/development/scripts/manifest-preview.js +244 -244
- package/.aios-core/development/scripts/metrics-tracker.js +775 -775
- package/.aios-core/development/scripts/modification-validator.js +554 -554
- package/.aios-core/development/scripts/pattern-learner.js +1224 -1224
- package/.aios-core/development/scripts/performance-analyzer.js +757 -757
- package/.aios-core/development/scripts/refactoring-suggester.js +1138 -1138
- package/.aios-core/development/scripts/rollback-handler.js +530 -530
- package/.aios-core/development/scripts/security-checker.js +358 -358
- package/.aios-core/development/scripts/template-engine.js +239 -239
- package/.aios-core/development/scripts/template-validator.js +278 -278
- package/.aios-core/development/scripts/test-generator.js +843 -843
- package/.aios-core/development/scripts/transaction-manager.js +589 -589
- package/.aios-core/development/scripts/usage-tracker.js +673 -673
- package/.aios-core/development/scripts/validate-filenames.js +226 -226
- package/.aios-core/development/scripts/version-tracker.js +526 -526
- package/.aios-core/development/scripts/yaml-validator.js +396 -396
- package/.aios-core/development/tasks/build-autonomous.md +10 -4
- package/.aios-core/development/tasks/create-service.md +23 -0
- package/.aios-core/development/tasks/dev-develop-story.md +12 -6
- package/.aios-core/development/tasks/dev-suggest-refactoring.md +7 -1
- package/.aios-core/development/tasks/publish-npm.md +3 -3
- package/.aios-core/hooks/unified/README.md +1 -1
- package/.aios-core/install-manifest.yaml +65 -61
- package/.aios-core/manifests/schema/manifest-schema.json +190 -190
- package/.aios-core/product/templates/component-react-tmpl.tsx +98 -98
- package/.aios-core/product/templates/engine/schemas/adr.schema.json +102 -102
- package/.aios-core/product/templates/engine/schemas/dbdr.schema.json +205 -205
- package/.aios-core/product/templates/engine/schemas/epic.schema.json +175 -175
- package/.aios-core/product/templates/engine/schemas/pmdr.schema.json +175 -175
- package/.aios-core/product/templates/engine/schemas/prd-v2.schema.json +300 -300
- package/.aios-core/product/templates/engine/schemas/prd.schema.json +152 -152
- package/.aios-core/product/templates/engine/schemas/story.schema.json +222 -222
- package/.aios-core/product/templates/engine/schemas/task.schema.json +154 -154
- package/.aios-core/product/templates/eslintrc-security.json +32 -32
- package/.aios-core/product/templates/github-actions-cd.yml +212 -212
- package/.aios-core/product/templates/github-actions-ci.yml +172 -172
- package/.aios-core/product/templates/shock-report-tmpl.html +502 -502
- package/.aios-core/product/templates/token-exports-css-tmpl.css +240 -240
- package/.aios-core/quality/schemas/quality-metrics.schema.json +233 -233
- package/.aios-core/scripts/migrate-framework-docs.sh +300 -300
- package/README.en.md +747 -0
- package/README.md +4 -2
- package/bin/aios.js +7 -4
- package/package.json +1 -1
- package/packages/aios-pro-cli/src/recover.js +1 -1
- package/packages/installer/src/wizard/ide-config-generator.js +6 -6
- package/packages/installer/src/wizard/pro-setup.js +3 -3
- package/pro/license/degradation.js +220 -220
- package/pro/license/errors.js +450 -450
- package/pro/license/feature-gate.js +354 -354
- package/pro/license/index.js +181 -181
- package/pro/license/license-cache.js +523 -523
- package/pro/license/license-crypto.js +303 -303
- package/scripts/package-synapse.js +5 -5
- package/scripts/validate-package-completeness.js +3 -3
- package/.aios-core/.session/current-session.json +0 -14
- package/.aios-core/data/registry-update-log.jsonl +0 -191
- package/.aios-core/docs/SHARD-TRANSLATION-GUIDE.md +0 -335
- package/.aios-core/docs/component-creation-guide.md +0 -458
- package/.aios-core/docs/session-update-pattern.md +0 -307
- package/.aios-core/docs/standards/AIOS-FRAMEWORK-MASTER.md +0 -1963
- package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO-V2.1-SUMMARY.md +0 -1190
- package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO-V2.1.md +0 -439
- package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO.md +0 -5398
- package/.aios-core/docs/standards/V3-ARCHITECTURAL-DECISIONS.md +0 -523
- package/.aios-core/docs/template-syntax.md +0 -267
- package/.aios-core/docs/troubleshooting-guide.md +0 -625
- package/.aios-core/infrastructure/tests/utilities-audit-results.json +0 -501
- package/.aios-core/manifests/agents.csv +0 -29
- package/.aios-core/manifests/tasks.csv +0 -198
- package/.aios-core/manifests/workers.csv +0 -204
- package/.claude/rules/agent-authority.md +0 -105
- package/.claude/rules/coderabbit-integration.md +0 -93
- package/.claude/rules/ids-principles.md +0 -112
- package/.claude/rules/story-lifecycle.md +0 -139
- package/.claude/rules/workflow-execution.md +0 -150
- package/scripts/glue/README.md +0 -355
- package/scripts/glue/compose-agent-prompt.cjs +0 -362
- /package/.claude/hooks/{precompact-session-digest.js → precompact-session-digest.cjs} +0 -0
- /package/.claude/hooks/{synapse-engine.js → synapse-engine.cjs} +0 -0
|
@@ -1,359 +1,359 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Security Checker for AIOS Developer Meta-Agent
|
|
3
|
-
* Validates generated code and configurations for security vulnerabilities
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
const path = require('path');
|
|
7
|
-
const yaml = require('js-yaml');
|
|
8
|
-
|
|
9
|
-
class SecurityChecker {
|
|
10
|
-
constructor() {
|
|
11
|
-
// Patterns that indicate potential security issues
|
|
12
|
-
this.dangerousPatterns = [
|
|
13
|
-
/eval\s*\(/gi,
|
|
14
|
-
/Function\s*\(/gi,
|
|
15
|
-
/new\s+Function/gi,
|
|
16
|
-
/setTimeout\s*\([^,]+,/gi,
|
|
17
|
-
/setInterval\s*\([^,]+,/gi,
|
|
18
|
-
/require\s*\([^'"]/gi, // Dynamic require
|
|
19
|
-
/import\s*\(/gi, // Dynamic import
|
|
20
|
-
/child_process/gi,
|
|
21
|
-
/exec\s*\(/gi,
|
|
22
|
-
/spawn\s*\(/gi,
|
|
23
|
-
/\.\.\/\.\.\//g, // Path traversal
|
|
24
|
-
/process\.env/gi,
|
|
25
|
-
/__dirname/gi,
|
|
26
|
-
/__filename/gi,
|
|
27
|
-
];
|
|
28
|
-
|
|
29
|
-
// SQL injection patterns
|
|
30
|
-
this.sqlInjectionPatterns = [
|
|
31
|
-
/;\s*DROP\s+TABLE/gi,
|
|
32
|
-
/;\s*DELETE\s+FROM/gi,
|
|
33
|
-
/UNION\s+SELECT/gi,
|
|
34
|
-
/OR\s+1\s*=\s*1/gi,
|
|
35
|
-
/'\s+OR\s+'/gi,
|
|
36
|
-
];
|
|
37
|
-
|
|
38
|
-
// Command injection patterns
|
|
39
|
-
this.commandInjectionPatterns = [
|
|
40
|
-
/[;&|`$()]/g,
|
|
41
|
-
/\$\{.*\}/g,
|
|
42
|
-
/>|</g,
|
|
43
|
-
];
|
|
44
|
-
|
|
45
|
-
// Safe patterns that should be allowed
|
|
46
|
-
this.safePatterns = {
|
|
47
|
-
'eval': [
|
|
48
|
-
/\/\*.*eval.*\*\//gs, // eval in comments
|
|
49
|
-
/\/\/.*eval/g, // eval in single-line comments
|
|
50
|
-
/".*eval.*"/g, // eval in strings
|
|
51
|
-
/'.*eval.*'/g,
|
|
52
|
-
]
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Validate generated code for security vulnerabilities
|
|
58
|
-
* @param {string} code - The code to validate
|
|
59
|
-
* @param {string} [language='javascript'] - The programming language
|
|
60
|
-
* @returns {Object} Validation results with valid flag, errors, warnings, and suggestions
|
|
61
|
-
*/
|
|
62
|
-
validateCode(code, language = 'javascript') {
|
|
63
|
-
const results = {
|
|
64
|
-
valid: true,
|
|
65
|
-
errors: [],
|
|
66
|
-
warnings: [],
|
|
67
|
-
suggestions: []
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
// Validate input
|
|
71
|
-
if (!code || typeof code !== 'string') {
|
|
72
|
-
results.valid = false;
|
|
73
|
-
results.errors.push({
|
|
74
|
-
type: 'invalid_input',
|
|
75
|
-
message: 'Code must be a non-empty string'
|
|
76
|
-
});
|
|
77
|
-
return results;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Check for dangerous patterns
|
|
81
|
-
for (const pattern of this.dangerousPatterns) {
|
|
82
|
-
const matches = code.match(pattern);
|
|
83
|
-
if (matches) {
|
|
84
|
-
// Check if it's in a safe context
|
|
85
|
-
let isSafe = false;
|
|
86
|
-
const patternName = pattern.source.split('\\')[0];
|
|
87
|
-
|
|
88
|
-
if (this.safePatterns[patternName]) {
|
|
89
|
-
for (const safePattern of this.safePatterns[patternName]) {
|
|
90
|
-
if (code.match(safePattern)) {
|
|
91
|
-
isSafe = true;
|
|
92
|
-
break;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
if (!isSafe) {
|
|
98
|
-
results.valid = false;
|
|
99
|
-
results.errors.push({
|
|
100
|
-
type: 'dangerous_pattern',
|
|
101
|
-
pattern: pattern.source,
|
|
102
|
-
matches: matches,
|
|
103
|
-
message: `Dangerous pattern detected: ${matches[0]}`,
|
|
104
|
-
line: this._getLineNumber(code, matches.index)
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// Check for SQL injection (if applicable)
|
|
111
|
-
if (code.includes('SELECT') || code.includes('INSERT') || code.includes('UPDATE')) {
|
|
112
|
-
for (const pattern of this.sqlInjectionPatterns) {
|
|
113
|
-
if (pattern.test(code)) {
|
|
114
|
-
results.valid = false;
|
|
115
|
-
results.errors.push({
|
|
116
|
-
type: 'sql_injection',
|
|
117
|
-
pattern: pattern.source,
|
|
118
|
-
message: 'Potential SQL injection vulnerability detected'
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// Validate input sanitization
|
|
125
|
-
if (code.includes('req.body') || code.includes('req.query') || code.includes('req.params')) {
|
|
126
|
-
if (!code.includes('sanitize') && !code.includes('validate') && !code.includes('escape')) {
|
|
127
|
-
results.warnings.push({
|
|
128
|
-
type: 'input_validation',
|
|
129
|
-
message: 'User input detected without explicit sanitization'
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
return results;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* Validate YAML configuration for security issues
|
|
139
|
-
*/
|
|
140
|
-
validateYAML(yamlContent) {
|
|
141
|
-
const results = {
|
|
142
|
-
valid: true,
|
|
143
|
-
errors: [],
|
|
144
|
-
warnings: []
|
|
145
|
-
};
|
|
146
|
-
|
|
147
|
-
try {
|
|
148
|
-
const parsed = yaml.load(yamlContent);
|
|
149
|
-
|
|
150
|
-
// Check for dangerous YAML features
|
|
151
|
-
if (yamlContent.includes('!!') && !yamlContent.includes('!!str')) {
|
|
152
|
-
results.warnings.push({
|
|
153
|
-
type: 'yaml_tags',
|
|
154
|
-
message: 'YAML tags detected - ensure they are safe'
|
|
155
|
-
});
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// Validate structure
|
|
159
|
-
this.validateYAMLStructure(parsed, results);
|
|
160
|
-
|
|
161
|
-
} catch (error) {
|
|
162
|
-
results.valid = false;
|
|
163
|
-
results.errors.push({
|
|
164
|
-
type: 'yaml_parse',
|
|
165
|
-
message: `YAML parsing error: ${error.message}`
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
return results;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* Validate YAML structure recursively
|
|
174
|
-
*/
|
|
175
|
-
validateYAMLStructure(obj, results, path = '') {
|
|
176
|
-
if (typeof obj === 'object' && obj !== null) {
|
|
177
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
178
|
-
const currentPath = path ? `${path}.${key}` : key;
|
|
179
|
-
|
|
180
|
-
// Check for command injection in string values
|
|
181
|
-
if (typeof value === 'string') {
|
|
182
|
-
for (const pattern of this.commandInjectionPatterns) {
|
|
183
|
-
if (pattern.test(_value) && !this.isSafeCommandContext(key, value)) {
|
|
184
|
-
results.warnings.push({
|
|
185
|
-
type: 'command_injection',
|
|
186
|
-
path: currentPath,
|
|
187
|
-
message: `Potential command injection in ${currentPath}`
|
|
188
|
-
});
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
// Recurse for nested objects
|
|
194
|
-
if (typeof value === 'object') {
|
|
195
|
-
this.validateYAMLStructure(_value, results, currentPath);
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* Check if command-like string is in safe context
|
|
203
|
-
*/
|
|
204
|
-
isSafeCommandContext(key, value) {
|
|
205
|
-
const safeKeys = ['description', 'comment', 'note', 'help', 'usage'];
|
|
206
|
-
return safeKeys.some(safe => key.toLowerCase().includes(safe));
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* Validate file paths for security issues
|
|
211
|
-
*/
|
|
212
|
-
validatePath(filePath) {
|
|
213
|
-
const results = {
|
|
214
|
-
valid: true,
|
|
215
|
-
errors: []
|
|
216
|
-
};
|
|
217
|
-
|
|
218
|
-
// Normalize the path
|
|
219
|
-
const normalized = path.normalize(filePath);
|
|
220
|
-
|
|
221
|
-
// Check for path traversal
|
|
222
|
-
if (normalized.includes('..')) {
|
|
223
|
-
results.valid = false;
|
|
224
|
-
results.errors.push({
|
|
225
|
-
type: 'path_traversal',
|
|
226
|
-
message: 'Path traversal detected'
|
|
227
|
-
});
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
// Check for absolute paths (unless allowed)
|
|
231
|
-
if (path.isAbsolute(normalized)) {
|
|
232
|
-
results.errors.push({
|
|
233
|
-
type: 'absolute_path',
|
|
234
|
-
message: 'Absolute path detected - use relative paths'
|
|
235
|
-
});
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
// Check for sensitive directories
|
|
239
|
-
const sensitivePatterns = [
|
|
240
|
-
/node_modules/i,
|
|
241
|
-
/\.git/i,
|
|
242
|
-
/\.env/i,
|
|
243
|
-
/private/i,
|
|
244
|
-
/secret/i,
|
|
245
|
-
/config/i,
|
|
246
|
-
];
|
|
247
|
-
|
|
248
|
-
for (const pattern of sensitivePatterns) {
|
|
249
|
-
if (pattern.test(normalized)) {
|
|
250
|
-
results.warnings = results.warnings || [];
|
|
251
|
-
results.warnings.push({
|
|
252
|
-
type: 'sensitive_path',
|
|
253
|
-
message: `Path contains potentially sensitive directory: ${pattern.source}`
|
|
254
|
-
});
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
return results;
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
/**
|
|
262
|
-
* Validate user input for common security issues
|
|
263
|
-
*/
|
|
264
|
-
sanitizeInput(input, type = 'general') {
|
|
265
|
-
if (typeof input !== 'string') {
|
|
266
|
-
return input;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
let sanitized = input;
|
|
270
|
-
|
|
271
|
-
// Remove null bytes
|
|
272
|
-
sanitized = sanitized.replace(/\0/g, '');
|
|
273
|
-
|
|
274
|
-
// Type-specific sanitization
|
|
275
|
-
switch (type) {
|
|
276
|
-
case 'filename':
|
|
277
|
-
// Allow only alphanumeric, dash, underscore, and dot
|
|
278
|
-
sanitized = sanitized.replace(/[^a-zA-Z0-9\-_\.]/g, '');
|
|
279
|
-
break;
|
|
280
|
-
|
|
281
|
-
case 'identifier':
|
|
282
|
-
// Allow only alphanumeric, dash, and underscore
|
|
283
|
-
sanitized = sanitized.replace(/[^a-zA-Z0-9\-_]/g, '');
|
|
284
|
-
break;
|
|
285
|
-
|
|
286
|
-
case 'yaml':
|
|
287
|
-
// Escape special YAML characters
|
|
288
|
-
sanitized = sanitized
|
|
289
|
-
.replace(/:/g, '\\:')
|
|
290
|
-
.replace(/\|/g, '\\|')
|
|
291
|
-
.replace(/>/g, '\\>')
|
|
292
|
-
.replace(/</g, '\\<');
|
|
293
|
-
break;
|
|
294
|
-
|
|
295
|
-
case 'general':
|
|
296
|
-
default:
|
|
297
|
-
// Basic HTML/script escaping
|
|
298
|
-
sanitized = sanitized
|
|
299
|
-
.replace(/&/g, '&')
|
|
300
|
-
.replace(/</g, '<')
|
|
301
|
-
.replace(/>/g, '>')
|
|
302
|
-
.replace(/"/g, '"')
|
|
303
|
-
.replace(/'/g, ''')
|
|
304
|
-
.replace(/\//g, '/');
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
return sanitized;
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
/**
|
|
311
|
-
* Generate security report
|
|
312
|
-
* @param {Array} validations - Array of validation results
|
|
313
|
-
* @returns {Object} Comprehensive security report
|
|
314
|
-
*/
|
|
315
|
-
generateReport(validations) {
|
|
316
|
-
const report = {
|
|
317
|
-
timestamp: new Date().toISOString(),
|
|
318
|
-
summary: {
|
|
319
|
-
totalChecks: 0,
|
|
320
|
-
passed: 0,
|
|
321
|
-
failed: 0,
|
|
322
|
-
warnings: 0
|
|
323
|
-
},
|
|
324
|
-
details: validations
|
|
325
|
-
};
|
|
326
|
-
|
|
327
|
-
// Calculate summary
|
|
328
|
-
for (const validation of validations) {
|
|
329
|
-
report.summary.totalChecks++;
|
|
330
|
-
if (validation.valid) {
|
|
331
|
-
report.summary.passed++;
|
|
332
|
-
} else {
|
|
333
|
-
report.summary.failed++;
|
|
334
|
-
}
|
|
335
|
-
report.summary.warnings += (validation.warnings || []).length;
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
report.summary.securityScore = Math.round(
|
|
339
|
-
(report.summary.passed / report.summary.totalChecks) * 100
|
|
340
|
-
);
|
|
341
|
-
|
|
342
|
-
return report;
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
/**
|
|
346
|
-
* Get line number from string index
|
|
347
|
-
* @private
|
|
348
|
-
* @param {string} text - The text to search
|
|
349
|
-
* @param {number} index - Character index
|
|
350
|
-
* @returns {number} Line number (1-based)
|
|
351
|
-
*/
|
|
352
|
-
_getLineNumber(text, index) {
|
|
353
|
-
if (!text || index === undefined) return null;
|
|
354
|
-
const lines = text.substring(0, index).split('\n');
|
|
355
|
-
return lines.length;
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Security Checker for AIOS Developer Meta-Agent
|
|
3
|
+
* Validates generated code and configurations for security vulnerabilities
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const yaml = require('js-yaml');
|
|
8
|
+
|
|
9
|
+
class SecurityChecker {
|
|
10
|
+
constructor() {
|
|
11
|
+
// Patterns that indicate potential security issues
|
|
12
|
+
this.dangerousPatterns = [
|
|
13
|
+
/eval\s*\(/gi,
|
|
14
|
+
/Function\s*\(/gi,
|
|
15
|
+
/new\s+Function/gi,
|
|
16
|
+
/setTimeout\s*\([^,]+,/gi,
|
|
17
|
+
/setInterval\s*\([^,]+,/gi,
|
|
18
|
+
/require\s*\([^'"]/gi, // Dynamic require
|
|
19
|
+
/import\s*\(/gi, // Dynamic import
|
|
20
|
+
/child_process/gi,
|
|
21
|
+
/exec\s*\(/gi,
|
|
22
|
+
/spawn\s*\(/gi,
|
|
23
|
+
/\.\.\/\.\.\//g, // Path traversal
|
|
24
|
+
/process\.env/gi,
|
|
25
|
+
/__dirname/gi,
|
|
26
|
+
/__filename/gi,
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
// SQL injection patterns
|
|
30
|
+
this.sqlInjectionPatterns = [
|
|
31
|
+
/;\s*DROP\s+TABLE/gi,
|
|
32
|
+
/;\s*DELETE\s+FROM/gi,
|
|
33
|
+
/UNION\s+SELECT/gi,
|
|
34
|
+
/OR\s+1\s*=\s*1/gi,
|
|
35
|
+
/'\s+OR\s+'/gi,
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
// Command injection patterns
|
|
39
|
+
this.commandInjectionPatterns = [
|
|
40
|
+
/[;&|`$()]/g,
|
|
41
|
+
/\$\{.*\}/g,
|
|
42
|
+
/>|</g,
|
|
43
|
+
];
|
|
44
|
+
|
|
45
|
+
// Safe patterns that should be allowed
|
|
46
|
+
this.safePatterns = {
|
|
47
|
+
'eval': [
|
|
48
|
+
/\/\*.*eval.*\*\//gs, // eval in comments
|
|
49
|
+
/\/\/.*eval/g, // eval in single-line comments
|
|
50
|
+
/".*eval.*"/g, // eval in strings
|
|
51
|
+
/'.*eval.*'/g,
|
|
52
|
+
]
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Validate generated code for security vulnerabilities
|
|
58
|
+
* @param {string} code - The code to validate
|
|
59
|
+
* @param {string} [language='javascript'] - The programming language
|
|
60
|
+
* @returns {Object} Validation results with valid flag, errors, warnings, and suggestions
|
|
61
|
+
*/
|
|
62
|
+
validateCode(code, language = 'javascript') {
|
|
63
|
+
const results = {
|
|
64
|
+
valid: true,
|
|
65
|
+
errors: [],
|
|
66
|
+
warnings: [],
|
|
67
|
+
suggestions: []
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
// Validate input
|
|
71
|
+
if (!code || typeof code !== 'string') {
|
|
72
|
+
results.valid = false;
|
|
73
|
+
results.errors.push({
|
|
74
|
+
type: 'invalid_input',
|
|
75
|
+
message: 'Code must be a non-empty string'
|
|
76
|
+
});
|
|
77
|
+
return results;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Check for dangerous patterns
|
|
81
|
+
for (const pattern of this.dangerousPatterns) {
|
|
82
|
+
const matches = code.match(pattern);
|
|
83
|
+
if (matches) {
|
|
84
|
+
// Check if it's in a safe context
|
|
85
|
+
let isSafe = false;
|
|
86
|
+
const patternName = pattern.source.split('\\')[0];
|
|
87
|
+
|
|
88
|
+
if (this.safePatterns[patternName]) {
|
|
89
|
+
for (const safePattern of this.safePatterns[patternName]) {
|
|
90
|
+
if (code.match(safePattern)) {
|
|
91
|
+
isSafe = true;
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (!isSafe) {
|
|
98
|
+
results.valid = false;
|
|
99
|
+
results.errors.push({
|
|
100
|
+
type: 'dangerous_pattern',
|
|
101
|
+
pattern: pattern.source,
|
|
102
|
+
matches: matches,
|
|
103
|
+
message: `Dangerous pattern detected: ${matches[0]}`,
|
|
104
|
+
line: this._getLineNumber(code, matches.index)
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Check for SQL injection (if applicable)
|
|
111
|
+
if (code.includes('SELECT') || code.includes('INSERT') || code.includes('UPDATE')) {
|
|
112
|
+
for (const pattern of this.sqlInjectionPatterns) {
|
|
113
|
+
if (pattern.test(code)) {
|
|
114
|
+
results.valid = false;
|
|
115
|
+
results.errors.push({
|
|
116
|
+
type: 'sql_injection',
|
|
117
|
+
pattern: pattern.source,
|
|
118
|
+
message: 'Potential SQL injection vulnerability detected'
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Validate input sanitization
|
|
125
|
+
if (code.includes('req.body') || code.includes('req.query') || code.includes('req.params')) {
|
|
126
|
+
if (!code.includes('sanitize') && !code.includes('validate') && !code.includes('escape')) {
|
|
127
|
+
results.warnings.push({
|
|
128
|
+
type: 'input_validation',
|
|
129
|
+
message: 'User input detected without explicit sanitization'
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return results;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Validate YAML configuration for security issues
|
|
139
|
+
*/
|
|
140
|
+
validateYAML(yamlContent) {
|
|
141
|
+
const results = {
|
|
142
|
+
valid: true,
|
|
143
|
+
errors: [],
|
|
144
|
+
warnings: []
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
try {
|
|
148
|
+
const parsed = yaml.load(yamlContent);
|
|
149
|
+
|
|
150
|
+
// Check for dangerous YAML features
|
|
151
|
+
if (yamlContent.includes('!!') && !yamlContent.includes('!!str')) {
|
|
152
|
+
results.warnings.push({
|
|
153
|
+
type: 'yaml_tags',
|
|
154
|
+
message: 'YAML tags detected - ensure they are safe'
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Validate structure
|
|
159
|
+
this.validateYAMLStructure(parsed, results);
|
|
160
|
+
|
|
161
|
+
} catch (error) {
|
|
162
|
+
results.valid = false;
|
|
163
|
+
results.errors.push({
|
|
164
|
+
type: 'yaml_parse',
|
|
165
|
+
message: `YAML parsing error: ${error.message}`
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return results;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Validate YAML structure recursively
|
|
174
|
+
*/
|
|
175
|
+
validateYAMLStructure(obj, results, path = '') {
|
|
176
|
+
if (typeof obj === 'object' && obj !== null) {
|
|
177
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
178
|
+
const currentPath = path ? `${path}.${key}` : key;
|
|
179
|
+
|
|
180
|
+
// Check for command injection in string values
|
|
181
|
+
if (typeof value === 'string') {
|
|
182
|
+
for (const pattern of this.commandInjectionPatterns) {
|
|
183
|
+
if (pattern.test(_value) && !this.isSafeCommandContext(key, value)) {
|
|
184
|
+
results.warnings.push({
|
|
185
|
+
type: 'command_injection',
|
|
186
|
+
path: currentPath,
|
|
187
|
+
message: `Potential command injection in ${currentPath}`
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Recurse for nested objects
|
|
194
|
+
if (typeof value === 'object') {
|
|
195
|
+
this.validateYAMLStructure(_value, results, currentPath);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Check if command-like string is in safe context
|
|
203
|
+
*/
|
|
204
|
+
isSafeCommandContext(key, value) {
|
|
205
|
+
const safeKeys = ['description', 'comment', 'note', 'help', 'usage'];
|
|
206
|
+
return safeKeys.some(safe => key.toLowerCase().includes(safe));
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Validate file paths for security issues
|
|
211
|
+
*/
|
|
212
|
+
validatePath(filePath) {
|
|
213
|
+
const results = {
|
|
214
|
+
valid: true,
|
|
215
|
+
errors: []
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
// Normalize the path
|
|
219
|
+
const normalized = path.normalize(filePath);
|
|
220
|
+
|
|
221
|
+
// Check for path traversal
|
|
222
|
+
if (normalized.includes('..')) {
|
|
223
|
+
results.valid = false;
|
|
224
|
+
results.errors.push({
|
|
225
|
+
type: 'path_traversal',
|
|
226
|
+
message: 'Path traversal detected'
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Check for absolute paths (unless allowed)
|
|
231
|
+
if (path.isAbsolute(normalized)) {
|
|
232
|
+
results.errors.push({
|
|
233
|
+
type: 'absolute_path',
|
|
234
|
+
message: 'Absolute path detected - use relative paths'
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Check for sensitive directories
|
|
239
|
+
const sensitivePatterns = [
|
|
240
|
+
/node_modules/i,
|
|
241
|
+
/\.git/i,
|
|
242
|
+
/\.env/i,
|
|
243
|
+
/private/i,
|
|
244
|
+
/secret/i,
|
|
245
|
+
/config/i,
|
|
246
|
+
];
|
|
247
|
+
|
|
248
|
+
for (const pattern of sensitivePatterns) {
|
|
249
|
+
if (pattern.test(normalized)) {
|
|
250
|
+
results.warnings = results.warnings || [];
|
|
251
|
+
results.warnings.push({
|
|
252
|
+
type: 'sensitive_path',
|
|
253
|
+
message: `Path contains potentially sensitive directory: ${pattern.source}`
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
return results;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Validate user input for common security issues
|
|
263
|
+
*/
|
|
264
|
+
sanitizeInput(input, type = 'general') {
|
|
265
|
+
if (typeof input !== 'string') {
|
|
266
|
+
return input;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
let sanitized = input;
|
|
270
|
+
|
|
271
|
+
// Remove null bytes
|
|
272
|
+
sanitized = sanitized.replace(/\0/g, '');
|
|
273
|
+
|
|
274
|
+
// Type-specific sanitization
|
|
275
|
+
switch (type) {
|
|
276
|
+
case 'filename':
|
|
277
|
+
// Allow only alphanumeric, dash, underscore, and dot
|
|
278
|
+
sanitized = sanitized.replace(/[^a-zA-Z0-9\-_\.]/g, '');
|
|
279
|
+
break;
|
|
280
|
+
|
|
281
|
+
case 'identifier':
|
|
282
|
+
// Allow only alphanumeric, dash, and underscore
|
|
283
|
+
sanitized = sanitized.replace(/[^a-zA-Z0-9\-_]/g, '');
|
|
284
|
+
break;
|
|
285
|
+
|
|
286
|
+
case 'yaml':
|
|
287
|
+
// Escape special YAML characters
|
|
288
|
+
sanitized = sanitized
|
|
289
|
+
.replace(/:/g, '\\:')
|
|
290
|
+
.replace(/\|/g, '\\|')
|
|
291
|
+
.replace(/>/g, '\\>')
|
|
292
|
+
.replace(/</g, '\\<');
|
|
293
|
+
break;
|
|
294
|
+
|
|
295
|
+
case 'general':
|
|
296
|
+
default:
|
|
297
|
+
// Basic HTML/script escaping
|
|
298
|
+
sanitized = sanitized
|
|
299
|
+
.replace(/&/g, '&')
|
|
300
|
+
.replace(/</g, '<')
|
|
301
|
+
.replace(/>/g, '>')
|
|
302
|
+
.replace(/"/g, '"')
|
|
303
|
+
.replace(/'/g, ''')
|
|
304
|
+
.replace(/\//g, '/');
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
return sanitized;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Generate security report
|
|
312
|
+
* @param {Array} validations - Array of validation results
|
|
313
|
+
* @returns {Object} Comprehensive security report
|
|
314
|
+
*/
|
|
315
|
+
generateReport(validations) {
|
|
316
|
+
const report = {
|
|
317
|
+
timestamp: new Date().toISOString(),
|
|
318
|
+
summary: {
|
|
319
|
+
totalChecks: 0,
|
|
320
|
+
passed: 0,
|
|
321
|
+
failed: 0,
|
|
322
|
+
warnings: 0
|
|
323
|
+
},
|
|
324
|
+
details: validations
|
|
325
|
+
};
|
|
326
|
+
|
|
327
|
+
// Calculate summary
|
|
328
|
+
for (const validation of validations) {
|
|
329
|
+
report.summary.totalChecks++;
|
|
330
|
+
if (validation.valid) {
|
|
331
|
+
report.summary.passed++;
|
|
332
|
+
} else {
|
|
333
|
+
report.summary.failed++;
|
|
334
|
+
}
|
|
335
|
+
report.summary.warnings += (validation.warnings || []).length;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
report.summary.securityScore = Math.round(
|
|
339
|
+
(report.summary.passed / report.summary.totalChecks) * 100
|
|
340
|
+
);
|
|
341
|
+
|
|
342
|
+
return report;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* Get line number from string index
|
|
347
|
+
* @private
|
|
348
|
+
* @param {string} text - The text to search
|
|
349
|
+
* @param {number} index - Character index
|
|
350
|
+
* @returns {number} Line number (1-based)
|
|
351
|
+
*/
|
|
352
|
+
_getLineNumber(text, index) {
|
|
353
|
+
if (!text || index === undefined) return null;
|
|
354
|
+
const lines = text.substring(0, index).split('\n');
|
|
355
|
+
return lines.length;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
359
|
module.exports = SecurityChecker;
|