@nahisaho/musubix-security 1.8.0 → 1.8.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/README.md +27 -0
- package/dist/analyzers/ai/index.d.ts +6 -0
- package/dist/analyzers/ai/index.d.ts.map +1 -0
- package/dist/analyzers/ai/index.js +6 -0
- package/dist/analyzers/ai/index.js.map +1 -0
- package/dist/analyzers/ai/prompt-injection-detector.d.ts +152 -0
- package/dist/analyzers/ai/prompt-injection-detector.d.ts.map +1 -0
- package/dist/analyzers/ai/prompt-injection-detector.js +468 -0
- package/dist/analyzers/ai/prompt-injection-detector.js.map +1 -0
- package/dist/analyzers/api/api-security-analyzer.d.ts +263 -0
- package/dist/analyzers/api/api-security-analyzer.d.ts.map +1 -0
- package/dist/analyzers/api/api-security-analyzer.js +581 -0
- package/dist/analyzers/api/api-security-analyzer.js.map +1 -0
- package/dist/analyzers/compliance/compliance-checker.d.ts +201 -0
- package/dist/analyzers/compliance/compliance-checker.d.ts.map +1 -0
- package/dist/analyzers/compliance/compliance-checker.js +772 -0
- package/dist/analyzers/compliance/compliance-checker.js.map +1 -0
- package/dist/analyzers/container/image-scanner.d.ts +163 -0
- package/dist/analyzers/container/image-scanner.d.ts.map +1 -0
- package/dist/analyzers/container/image-scanner.js +459 -0
- package/dist/analyzers/container/image-scanner.js.map +1 -0
- package/dist/analyzers/container/index.d.ts +6 -0
- package/dist/analyzers/container/index.d.ts.map +1 -0
- package/dist/analyzers/container/index.js +6 -0
- package/dist/analyzers/container/index.js.map +1 -0
- package/dist/analyzers/dashboard/security-dashboard.d.ts +286 -0
- package/dist/analyzers/dashboard/security-dashboard.d.ts.map +1 -0
- package/dist/analyzers/dashboard/security-dashboard.js +796 -0
- package/dist/analyzers/dashboard/security-dashboard.js.map +1 -0
- package/dist/analyzers/iac/iac-checker.d.ts +124 -0
- package/dist/analyzers/iac/iac-checker.d.ts.map +1 -0
- package/dist/analyzers/iac/iac-checker.js +755 -0
- package/dist/analyzers/iac/iac-checker.js.map +1 -0
- package/dist/analyzers/iac/index.d.ts +6 -0
- package/dist/analyzers/iac/index.d.ts.map +1 -0
- package/dist/analyzers/iac/index.js +6 -0
- package/dist/analyzers/iac/index.js.map +1 -0
- package/dist/analyzers/index.d.ts +9 -0
- package/dist/analyzers/index.d.ts.map +1 -0
- package/dist/analyzers/index.js +13 -0
- package/dist/analyzers/index.js.map +1 -0
- package/dist/analyzers/monitor/realtime-monitor.d.ts +216 -0
- package/dist/analyzers/monitor/realtime-monitor.d.ts.map +1 -0
- package/dist/analyzers/monitor/realtime-monitor.js +601 -0
- package/dist/analyzers/monitor/realtime-monitor.js.map +1 -0
- package/dist/analyzers/sast/index.d.ts +7 -0
- package/dist/analyzers/sast/index.d.ts.map +1 -0
- package/dist/analyzers/sast/index.js +7 -0
- package/dist/analyzers/sast/index.js.map +1 -0
- package/dist/analyzers/sast/interprocedural-analyzer.d.ts +276 -0
- package/dist/analyzers/sast/interprocedural-analyzer.d.ts.map +1 -0
- package/dist/analyzers/sast/interprocedural-analyzer.js +635 -0
- package/dist/analyzers/sast/interprocedural-analyzer.js.map +1 -0
- package/dist/analyzers/sast/zero-day-detector.d.ts +183 -0
- package/dist/analyzers/sast/zero-day-detector.d.ts.map +1 -0
- package/dist/analyzers/sast/zero-day-detector.js +593 -0
- package/dist/analyzers/sast/zero-day-detector.js.map +1 -0
- package/dist/analyzers/sca/dependency-scanner.d.ts +275 -0
- package/dist/analyzers/sca/dependency-scanner.d.ts.map +1 -0
- package/dist/analyzers/sca/dependency-scanner.js +642 -0
- package/dist/analyzers/sca/dependency-scanner.js.map +1 -0
- package/dist/core/index.d.ts +8 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +10 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/pipeline-manager.d.ts +105 -0
- package/dist/core/pipeline-manager.d.ts.map +1 -0
- package/dist/core/pipeline-manager.js +449 -0
- package/dist/core/pipeline-manager.js.map +1 -0
- package/dist/core/result-aggregator.d.ts +96 -0
- package/dist/core/result-aggregator.d.ts.map +1 -0
- package/dist/core/result-aggregator.js +462 -0
- package/dist/core/result-aggregator.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +68 -0
- package/dist/index.js.map +1 -1
- package/dist/integrations/ci-integration.d.ts +227 -0
- package/dist/integrations/ci-integration.d.ts.map +1 -0
- package/dist/integrations/ci-integration.js +472 -0
- package/dist/integrations/ci-integration.js.map +1 -0
- package/dist/integrations/git-hooks.d.ts +155 -0
- package/dist/integrations/git-hooks.d.ts.map +1 -0
- package/dist/integrations/git-hooks.js +425 -0
- package/dist/integrations/git-hooks.js.map +1 -0
- package/dist/integrations/index.d.ts +9 -0
- package/dist/integrations/index.d.ts.map +1 -0
- package/dist/integrations/index.js +9 -0
- package/dist/integrations/index.js.map +1 -0
- package/dist/integrations/report-aggregator.d.ts +250 -0
- package/dist/integrations/report-aggregator.d.ts.map +1 -0
- package/dist/integrations/report-aggregator.js +488 -0
- package/dist/integrations/report-aggregator.js.map +1 -0
- package/dist/integrations/vscode-integration.d.ts +245 -0
- package/dist/integrations/vscode-integration.d.ts.map +1 -0
- package/dist/integrations/vscode-integration.js +449 -0
- package/dist/integrations/vscode-integration.js.map +1 -0
- package/dist/intelligence/attack-pattern-matcher.d.ts +217 -0
- package/dist/intelligence/attack-pattern-matcher.d.ts.map +1 -0
- package/dist/intelligence/attack-pattern-matcher.js +887 -0
- package/dist/intelligence/attack-pattern-matcher.js.map +1 -0
- package/dist/intelligence/index.d.ts +12 -0
- package/dist/intelligence/index.d.ts.map +1 -0
- package/dist/intelligence/index.js +18 -0
- package/dist/intelligence/index.js.map +1 -0
- package/dist/intelligence/neuro-symbolic-core.d.ts +88 -0
- package/dist/intelligence/neuro-symbolic-core.d.ts.map +1 -0
- package/dist/intelligence/neuro-symbolic-core.js +403 -0
- package/dist/intelligence/neuro-symbolic-core.js.map +1 -0
- package/dist/intelligence/predictive-analyzer.d.ts +317 -0
- package/dist/intelligence/predictive-analyzer.d.ts.map +1 -0
- package/dist/intelligence/predictive-analyzer.js +714 -0
- package/dist/intelligence/predictive-analyzer.js.map +1 -0
- package/dist/intelligence/risk-scorer.d.ts +333 -0
- package/dist/intelligence/risk-scorer.d.ts.map +1 -0
- package/dist/intelligence/risk-scorer.js +824 -0
- package/dist/intelligence/risk-scorer.js.map +1 -0
- package/dist/intelligence/security-analytics.d.ts +349 -0
- package/dist/intelligence/security-analytics.d.ts.map +1 -0
- package/dist/intelligence/security-analytics.js +813 -0
- package/dist/intelligence/security-analytics.js.map +1 -0
- package/dist/intelligence/threat-intelligence.d.ts +288 -0
- package/dist/intelligence/threat-intelligence.d.ts.map +1 -0
- package/dist/intelligence/threat-intelligence.js +639 -0
- package/dist/intelligence/threat-intelligence.js.map +1 -0
- package/dist/policy/index.d.ts +6 -0
- package/dist/policy/index.d.ts.map +1 -0
- package/dist/policy/index.js +6 -0
- package/dist/policy/index.js.map +1 -0
- package/dist/policy/policy-engine.d.ts +254 -0
- package/dist/policy/policy-engine.d.ts.map +1 -0
- package/dist/policy/policy-engine.js +651 -0
- package/dist/policy/policy-engine.js.map +1 -0
- package/dist/remediation/auto-fixer.d.ts +179 -0
- package/dist/remediation/auto-fixer.d.ts.map +1 -0
- package/dist/remediation/auto-fixer.js +540 -0
- package/dist/remediation/auto-fixer.js.map +1 -0
- package/dist/remediation/fix-validator.d.ts +195 -0
- package/dist/remediation/fix-validator.d.ts.map +1 -0
- package/dist/remediation/fix-validator.js +462 -0
- package/dist/remediation/fix-validator.js.map +1 -0
- package/dist/remediation/index.d.ts +10 -0
- package/dist/remediation/index.d.ts.map +1 -0
- package/dist/remediation/index.js +15 -0
- package/dist/remediation/index.js.map +1 -0
- package/dist/remediation/patch-generator.d.ts +203 -0
- package/dist/remediation/patch-generator.d.ts.map +1 -0
- package/dist/remediation/patch-generator.js +533 -0
- package/dist/remediation/patch-generator.js.map +1 -0
- package/dist/remediation/remediation-planner.d.ts +262 -0
- package/dist/remediation/remediation-planner.d.ts.map +1 -0
- package/dist/remediation/remediation-planner.js +531 -0
- package/dist/remediation/remediation-planner.js.map +1 -0
- package/dist/remediation/secure-code-transformer.d.ts +222 -0
- package/dist/remediation/secure-code-transformer.d.ts.map +1 -0
- package/dist/remediation/secure-code-transformer.js +625 -0
- package/dist/remediation/secure-code-transformer.js.map +1 -0
- package/dist/types/fix.d.ts +3 -1
- package/dist/types/fix.d.ts.map +1 -1
- package/dist/types/index.d.ts +6 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +1 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/interprocedural.d.ts +203 -0
- package/dist/types/interprocedural.d.ts.map +1 -0
- package/dist/types/interprocedural.js +7 -0
- package/dist/types/interprocedural.js.map +1 -0
- package/dist/types/neuro-symbolic.d.ts +179 -0
- package/dist/types/neuro-symbolic.d.ts.map +1 -0
- package/dist/types/neuro-symbolic.js +7 -0
- package/dist/types/neuro-symbolic.js.map +1 -0
- package/dist/types/pipeline.d.ts +173 -0
- package/dist/types/pipeline.d.ts.map +1 -0
- package/dist/types/pipeline.js +7 -0
- package/dist/types/pipeline.js.map +1 -0
- package/dist/types/result.d.ts +134 -0
- package/dist/types/result.d.ts.map +1 -0
- package/dist/types/result.js +25 -0
- package/dist/types/result.js.map +1 -0
- package/dist/types/vulnerability.d.ts +2 -2
- package/dist/types/vulnerability.d.ts.map +1 -1
- package/dist/types/zero-day.d.ts +146 -0
- package/dist/types/zero-day.d.ts.map +1 -0
- package/dist/types/zero-day.js +7 -0
- package/dist/types/zero-day.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Fix Validator for Security Fixes
|
|
3
|
+
* @module @nahisaho/musubix-security/remediation/fix-validator
|
|
4
|
+
*
|
|
5
|
+
* Validates security fixes before and after application to ensure
|
|
6
|
+
* they correctly address vulnerabilities without introducing new issues.
|
|
7
|
+
*/
|
|
8
|
+
import type { Fix, Vulnerability, SourceLocation } from '../types/index.js';
|
|
9
|
+
/**
|
|
10
|
+
* Validation result
|
|
11
|
+
*/
|
|
12
|
+
export interface ValidationResult {
|
|
13
|
+
/** Whether validation passed */
|
|
14
|
+
valid: boolean;
|
|
15
|
+
/** Fix that was validated */
|
|
16
|
+
fixId: string;
|
|
17
|
+
/** Validation checks performed */
|
|
18
|
+
checks: ValidationCheck[];
|
|
19
|
+
/** Overall score (0-100) */
|
|
20
|
+
score: number;
|
|
21
|
+
/** Recommendations */
|
|
22
|
+
recommendations: string[];
|
|
23
|
+
/** Validation timestamp */
|
|
24
|
+
timestamp: Date;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Individual validation check
|
|
28
|
+
*/
|
|
29
|
+
export interface ValidationCheck {
|
|
30
|
+
/** Check name */
|
|
31
|
+
name: string;
|
|
32
|
+
/** Check category */
|
|
33
|
+
category: 'syntax' | 'semantic' | 'security' | 'regression' | 'compatibility';
|
|
34
|
+
/** Whether check passed */
|
|
35
|
+
passed: boolean;
|
|
36
|
+
/** Check details */
|
|
37
|
+
details: string;
|
|
38
|
+
/** Severity if failed */
|
|
39
|
+
severity?: 'error' | 'warning' | 'info';
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Syntax validation result
|
|
43
|
+
*/
|
|
44
|
+
export interface SyntaxValidationResult {
|
|
45
|
+
/** Whether syntax is valid */
|
|
46
|
+
valid: boolean;
|
|
47
|
+
/** Syntax errors */
|
|
48
|
+
errors: SyntaxError[];
|
|
49
|
+
/** Abstract syntax tree available */
|
|
50
|
+
hasAST: boolean;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Syntax error
|
|
54
|
+
*/
|
|
55
|
+
export interface SyntaxError {
|
|
56
|
+
/** Error message */
|
|
57
|
+
message: string;
|
|
58
|
+
/** Location */
|
|
59
|
+
location?: SourceLocation;
|
|
60
|
+
/** Error code */
|
|
61
|
+
code?: string;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Regression test result
|
|
65
|
+
*/
|
|
66
|
+
export interface RegressionTestResult {
|
|
67
|
+
/** Total tests */
|
|
68
|
+
total: number;
|
|
69
|
+
/** Passed tests */
|
|
70
|
+
passed: number;
|
|
71
|
+
/** Failed tests */
|
|
72
|
+
failed: number;
|
|
73
|
+
/** Skipped tests */
|
|
74
|
+
skipped: number;
|
|
75
|
+
/** Test details */
|
|
76
|
+
details: TestDetail[];
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Test detail
|
|
80
|
+
*/
|
|
81
|
+
export interface TestDetail {
|
|
82
|
+
/** Test name */
|
|
83
|
+
name: string;
|
|
84
|
+
/** Test status */
|
|
85
|
+
status: 'passed' | 'failed' | 'skipped';
|
|
86
|
+
/** Duration in ms */
|
|
87
|
+
duration: number;
|
|
88
|
+
/** Error if failed */
|
|
89
|
+
error?: string;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Security re-scan result
|
|
93
|
+
*/
|
|
94
|
+
export interface SecurityRescanResult {
|
|
95
|
+
/** Original vulnerability resolved */
|
|
96
|
+
vulnerabilityResolved: boolean;
|
|
97
|
+
/** New vulnerabilities introduced */
|
|
98
|
+
newVulnerabilities: Vulnerability[];
|
|
99
|
+
/** Remaining vulnerabilities */
|
|
100
|
+
remainingVulnerabilities: Vulnerability[];
|
|
101
|
+
/** Security improvement score */
|
|
102
|
+
improvementScore: number;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Fix validator options
|
|
106
|
+
*/
|
|
107
|
+
export interface FixValidatorOptions {
|
|
108
|
+
/** Enable syntax validation */
|
|
109
|
+
syntaxValidation?: boolean;
|
|
110
|
+
/** Enable semantic validation */
|
|
111
|
+
semanticValidation?: boolean;
|
|
112
|
+
/** Enable security re-scan */
|
|
113
|
+
securityRescan?: boolean;
|
|
114
|
+
/** Enable regression testing */
|
|
115
|
+
regressionTesting?: boolean;
|
|
116
|
+
/** Strict mode (fail on warnings) */
|
|
117
|
+
strictMode?: boolean;
|
|
118
|
+
/** Custom validation rules */
|
|
119
|
+
customRules?: CustomValidationRule[];
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Custom validation rule
|
|
123
|
+
*/
|
|
124
|
+
export interface CustomValidationRule {
|
|
125
|
+
/** Rule ID */
|
|
126
|
+
id: string;
|
|
127
|
+
/** Rule name */
|
|
128
|
+
name: string;
|
|
129
|
+
/** Validation function */
|
|
130
|
+
validate: (fix: Fix, originalCode: string, fixedCode: string) => ValidationCheck;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Validator for security fixes
|
|
134
|
+
*
|
|
135
|
+
* @example
|
|
136
|
+
* ```typescript
|
|
137
|
+
* const validator = createFixValidator();
|
|
138
|
+
* const result = await validator.validate(fix, originalCode, fixedCode);
|
|
139
|
+
* if (!result.valid) {
|
|
140
|
+
* console.log('Fix validation failed:', result.checks);
|
|
141
|
+
* }
|
|
142
|
+
* ```
|
|
143
|
+
*/
|
|
144
|
+
export declare class FixValidator {
|
|
145
|
+
private options;
|
|
146
|
+
private customRules;
|
|
147
|
+
constructor(options?: FixValidatorOptions);
|
|
148
|
+
/**
|
|
149
|
+
* Validate a fix
|
|
150
|
+
*/
|
|
151
|
+
validate(fix: Fix, originalCode: string, fixedCode: string, _originalVulnerability?: Vulnerability): Promise<ValidationResult>;
|
|
152
|
+
/**
|
|
153
|
+
* Validate fix syntax
|
|
154
|
+
*/
|
|
155
|
+
validateSyntax(code: string): ValidationCheck;
|
|
156
|
+
/**
|
|
157
|
+
* Validate semantic properties
|
|
158
|
+
*/
|
|
159
|
+
validateSemantics(originalCode: string, fixedCode: string): ValidationCheck[];
|
|
160
|
+
/**
|
|
161
|
+
* Validate security properties of the fix
|
|
162
|
+
*/
|
|
163
|
+
validateSecurityProperties(fix: Fix, fixedCode: string): ValidationCheck[];
|
|
164
|
+
/**
|
|
165
|
+
* Register a custom validation rule
|
|
166
|
+
*/
|
|
167
|
+
registerRule(rule: CustomValidationRule): void;
|
|
168
|
+
/**
|
|
169
|
+
* Remove a custom validation rule
|
|
170
|
+
*/
|
|
171
|
+
removeRule(ruleId: string): boolean;
|
|
172
|
+
/**
|
|
173
|
+
* Get all validation rules
|
|
174
|
+
*/
|
|
175
|
+
getRules(): CustomValidationRule[];
|
|
176
|
+
private validateFixStructure;
|
|
177
|
+
private checkBalancedBrackets;
|
|
178
|
+
private checkCommonSyntaxIssues;
|
|
179
|
+
private checkStructurePreservation;
|
|
180
|
+
private checkVariableUsage;
|
|
181
|
+
private fixAddressesVulnerabilityType;
|
|
182
|
+
private checkSecurityAntiPatterns;
|
|
183
|
+
private checkDangerousFunctions;
|
|
184
|
+
private calculateScore;
|
|
185
|
+
private determineValidity;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Create a fix validator
|
|
189
|
+
*/
|
|
190
|
+
export declare function createFixValidator(options?: FixValidatorOptions): FixValidator;
|
|
191
|
+
/**
|
|
192
|
+
* Quick validate a fix
|
|
193
|
+
*/
|
|
194
|
+
export declare function quickValidate(fix: Fix, originalCode: string, fixedCode: string): Promise<boolean>;
|
|
195
|
+
//# sourceMappingURL=fix-validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fix-validator.d.ts","sourceRoot":"","sources":["../../src/remediation/fix-validator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,462 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Fix Validator for Security Fixes
|
|
3
|
+
* @module @nahisaho/musubix-security/remediation/fix-validator
|
|
4
|
+
*
|
|
5
|
+
* Validates security fixes before and after application to ensure
|
|
6
|
+
* they correctly address vulnerabilities without introducing new issues.
|
|
7
|
+
*/
|
|
8
|
+
// ============================================================================
|
|
9
|
+
// FixValidator Class
|
|
10
|
+
// ============================================================================
|
|
11
|
+
/**
|
|
12
|
+
* Validator for security fixes
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* const validator = createFixValidator();
|
|
17
|
+
* const result = await validator.validate(fix, originalCode, fixedCode);
|
|
18
|
+
* if (!result.valid) {
|
|
19
|
+
* console.log('Fix validation failed:', result.checks);
|
|
20
|
+
* }
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export class FixValidator {
|
|
24
|
+
options;
|
|
25
|
+
customRules;
|
|
26
|
+
constructor(options = {}) {
|
|
27
|
+
this.options = {
|
|
28
|
+
syntaxValidation: options.syntaxValidation ?? true,
|
|
29
|
+
semanticValidation: options.semanticValidation ?? true,
|
|
30
|
+
securityRescan: options.securityRescan ?? true,
|
|
31
|
+
regressionTesting: options.regressionTesting ?? false,
|
|
32
|
+
strictMode: options.strictMode ?? false,
|
|
33
|
+
customRules: options.customRules ?? [],
|
|
34
|
+
};
|
|
35
|
+
this.customRules = new Map();
|
|
36
|
+
for (const rule of this.options.customRules) {
|
|
37
|
+
this.customRules.set(rule.id, rule);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Validate a fix
|
|
42
|
+
*/
|
|
43
|
+
async validate(fix, originalCode, fixedCode, _originalVulnerability) {
|
|
44
|
+
const checks = [];
|
|
45
|
+
const recommendations = [];
|
|
46
|
+
// Basic fix validation
|
|
47
|
+
checks.push(this.validateFixStructure(fix));
|
|
48
|
+
// Syntax validation
|
|
49
|
+
if (this.options.syntaxValidation) {
|
|
50
|
+
const syntaxCheck = this.validateSyntax(fixedCode);
|
|
51
|
+
checks.push(syntaxCheck);
|
|
52
|
+
if (!syntaxCheck.passed) {
|
|
53
|
+
recommendations.push('Fix the syntax errors before applying this fix');
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// Semantic validation
|
|
57
|
+
if (this.options.semanticValidation) {
|
|
58
|
+
const semanticChecks = this.validateSemantics(originalCode, fixedCode);
|
|
59
|
+
checks.push(...semanticChecks);
|
|
60
|
+
}
|
|
61
|
+
// Security checks
|
|
62
|
+
checks.push(...this.validateSecurityProperties(fix, fixedCode));
|
|
63
|
+
// Custom rules
|
|
64
|
+
for (const rule of this.customRules.values()) {
|
|
65
|
+
try {
|
|
66
|
+
const check = rule.validate(fix, originalCode, fixedCode);
|
|
67
|
+
checks.push(check);
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
checks.push({
|
|
71
|
+
name: rule.name,
|
|
72
|
+
category: 'security',
|
|
73
|
+
passed: false,
|
|
74
|
+
details: `Custom rule failed: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
75
|
+
severity: 'warning',
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// Calculate score
|
|
80
|
+
const score = this.calculateScore(checks);
|
|
81
|
+
// Determine validity
|
|
82
|
+
const valid = this.determineValidity(checks);
|
|
83
|
+
// Generate additional recommendations
|
|
84
|
+
if (fix.breakingChange) {
|
|
85
|
+
recommendations.push('This fix may cause breaking changes - review carefully');
|
|
86
|
+
}
|
|
87
|
+
if (fix.confidence < 0.8) {
|
|
88
|
+
recommendations.push('Low confidence fix - manual review recommended');
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
valid,
|
|
92
|
+
fixId: fix.id,
|
|
93
|
+
checks,
|
|
94
|
+
score,
|
|
95
|
+
recommendations,
|
|
96
|
+
timestamp: new Date(),
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Validate fix syntax
|
|
101
|
+
*/
|
|
102
|
+
validateSyntax(code) {
|
|
103
|
+
const errors = [];
|
|
104
|
+
// Basic syntax checks
|
|
105
|
+
try {
|
|
106
|
+
// Check for balanced brackets
|
|
107
|
+
const balanced = this.checkBalancedBrackets(code);
|
|
108
|
+
if (!balanced.valid) {
|
|
109
|
+
errors.push({ message: balanced.message });
|
|
110
|
+
}
|
|
111
|
+
// Check for common syntax issues
|
|
112
|
+
const commonIssues = this.checkCommonSyntaxIssues(code);
|
|
113
|
+
errors.push(...commonIssues);
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
errors.push({
|
|
117
|
+
message: error instanceof Error ? error.message : 'Unknown syntax error',
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
return {
|
|
121
|
+
name: 'Syntax Validation',
|
|
122
|
+
category: 'syntax',
|
|
123
|
+
passed: errors.length === 0,
|
|
124
|
+
details: errors.length === 0
|
|
125
|
+
? 'Syntax validation passed'
|
|
126
|
+
: `Found ${errors.length} syntax error(s): ${errors.map(e => e.message).join(', ')}`,
|
|
127
|
+
severity: errors.length > 0 ? 'error' : undefined,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Validate semantic properties
|
|
132
|
+
*/
|
|
133
|
+
validateSemantics(originalCode, fixedCode) {
|
|
134
|
+
const checks = [];
|
|
135
|
+
// Check code length change
|
|
136
|
+
const lengthRatio = fixedCode.length / originalCode.length;
|
|
137
|
+
checks.push({
|
|
138
|
+
name: 'Code Size Change',
|
|
139
|
+
category: 'semantic',
|
|
140
|
+
passed: lengthRatio > 0.5 && lengthRatio < 2.0,
|
|
141
|
+
details: `Code size changed by ${((lengthRatio - 1) * 100).toFixed(1)}%`,
|
|
142
|
+
severity: lengthRatio > 2.0 || lengthRatio < 0.5 ? 'warning' : undefined,
|
|
143
|
+
});
|
|
144
|
+
// Check for preserved structure
|
|
145
|
+
const structurePreserved = this.checkStructurePreservation(originalCode, fixedCode);
|
|
146
|
+
checks.push({
|
|
147
|
+
name: 'Structure Preservation',
|
|
148
|
+
category: 'semantic',
|
|
149
|
+
passed: structurePreserved,
|
|
150
|
+
details: structurePreserved
|
|
151
|
+
? 'Code structure largely preserved'
|
|
152
|
+
: 'Significant structural changes detected',
|
|
153
|
+
severity: !structurePreserved ? 'warning' : undefined,
|
|
154
|
+
});
|
|
155
|
+
// Check for variable usage
|
|
156
|
+
const variableCheck = this.checkVariableUsage(originalCode, fixedCode);
|
|
157
|
+
checks.push(variableCheck);
|
|
158
|
+
return checks;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Validate security properties of the fix
|
|
162
|
+
*/
|
|
163
|
+
validateSecurityProperties(fix, fixedCode) {
|
|
164
|
+
const checks = [];
|
|
165
|
+
// Check if fix addresses the vulnerability type
|
|
166
|
+
checks.push({
|
|
167
|
+
name: 'Vulnerability Type Match',
|
|
168
|
+
category: 'security',
|
|
169
|
+
passed: this.fixAddressesVulnerabilityType(fix),
|
|
170
|
+
details: `Fix strategy '${fix.strategy}' for vulnerability`,
|
|
171
|
+
});
|
|
172
|
+
// Check for security anti-patterns in fixed code
|
|
173
|
+
const antiPatterns = this.checkSecurityAntiPatterns(fixedCode);
|
|
174
|
+
checks.push({
|
|
175
|
+
name: 'Security Anti-patterns',
|
|
176
|
+
category: 'security',
|
|
177
|
+
passed: antiPatterns.length === 0,
|
|
178
|
+
details: antiPatterns.length === 0
|
|
179
|
+
? 'No security anti-patterns detected'
|
|
180
|
+
: `Found anti-patterns: ${antiPatterns.join(', ')}`,
|
|
181
|
+
severity: antiPatterns.length > 0 ? 'error' : undefined,
|
|
182
|
+
});
|
|
183
|
+
// Check for dangerous function usage
|
|
184
|
+
const dangerousFunctions = this.checkDangerousFunctions(fixedCode);
|
|
185
|
+
checks.push({
|
|
186
|
+
name: 'Dangerous Functions',
|
|
187
|
+
category: 'security',
|
|
188
|
+
passed: dangerousFunctions.length === 0,
|
|
189
|
+
details: dangerousFunctions.length === 0
|
|
190
|
+
? 'No dangerous functions detected'
|
|
191
|
+
: `Found dangerous functions: ${dangerousFunctions.join(', ')}`,
|
|
192
|
+
severity: dangerousFunctions.length > 0 ? 'warning' : undefined,
|
|
193
|
+
});
|
|
194
|
+
return checks;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Register a custom validation rule
|
|
198
|
+
*/
|
|
199
|
+
registerRule(rule) {
|
|
200
|
+
this.customRules.set(rule.id, rule);
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Remove a custom validation rule
|
|
204
|
+
*/
|
|
205
|
+
removeRule(ruleId) {
|
|
206
|
+
return this.customRules.delete(ruleId);
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Get all validation rules
|
|
210
|
+
*/
|
|
211
|
+
getRules() {
|
|
212
|
+
return Array.from(this.customRules.values());
|
|
213
|
+
}
|
|
214
|
+
// ============================================================================
|
|
215
|
+
// Private Methods
|
|
216
|
+
// ============================================================================
|
|
217
|
+
validateFixStructure(fix) {
|
|
218
|
+
const issues = [];
|
|
219
|
+
if (!fix.id)
|
|
220
|
+
issues.push('Missing fix ID');
|
|
221
|
+
if (!fix.vulnerabilityId)
|
|
222
|
+
issues.push('Missing vulnerability reference');
|
|
223
|
+
if (!fix.strategy)
|
|
224
|
+
issues.push('Missing fix strategy');
|
|
225
|
+
if (!fix.edits || fix.edits.length === 0)
|
|
226
|
+
issues.push('No edits specified');
|
|
227
|
+
return {
|
|
228
|
+
name: 'Fix Structure',
|
|
229
|
+
category: 'syntax',
|
|
230
|
+
passed: issues.length === 0,
|
|
231
|
+
details: issues.length === 0
|
|
232
|
+
? 'Fix structure is valid'
|
|
233
|
+
: `Structure issues: ${issues.join(', ')}`,
|
|
234
|
+
severity: issues.length > 0 ? 'error' : undefined,
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
checkBalancedBrackets(code) {
|
|
238
|
+
const stack = [];
|
|
239
|
+
const pairs = { '(': ')', '[': ']', '{': '}' };
|
|
240
|
+
const openers = new Set(Object.keys(pairs));
|
|
241
|
+
const closers = new Set(Object.values(pairs));
|
|
242
|
+
// Track if we're in a string or comment
|
|
243
|
+
let inString = false;
|
|
244
|
+
let stringChar = '';
|
|
245
|
+
let inSingleLineComment = false;
|
|
246
|
+
let inMultiLineComment = false;
|
|
247
|
+
for (let i = 0; i < code.length; i++) {
|
|
248
|
+
const char = code[i];
|
|
249
|
+
const prevChar = i > 0 ? code[i - 1] : '';
|
|
250
|
+
const nextChar = i < code.length - 1 ? code[i + 1] : '';
|
|
251
|
+
// Handle comments
|
|
252
|
+
if (!inString) {
|
|
253
|
+
if (char === '/' && nextChar === '/' && !inMultiLineComment) {
|
|
254
|
+
inSingleLineComment = true;
|
|
255
|
+
continue;
|
|
256
|
+
}
|
|
257
|
+
if (char === '/' && nextChar === '*' && !inSingleLineComment) {
|
|
258
|
+
inMultiLineComment = true;
|
|
259
|
+
continue;
|
|
260
|
+
}
|
|
261
|
+
if (char === '\n' && inSingleLineComment) {
|
|
262
|
+
inSingleLineComment = false;
|
|
263
|
+
continue;
|
|
264
|
+
}
|
|
265
|
+
if (char === '*' && nextChar === '/' && inMultiLineComment) {
|
|
266
|
+
inMultiLineComment = false;
|
|
267
|
+
i++; // Skip the '/'
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
if (inSingleLineComment || inMultiLineComment)
|
|
272
|
+
continue;
|
|
273
|
+
// Handle strings
|
|
274
|
+
if ((char === '"' || char === "'" || char === '`') && prevChar !== '\\') {
|
|
275
|
+
if (!inString) {
|
|
276
|
+
inString = true;
|
|
277
|
+
stringChar = char;
|
|
278
|
+
}
|
|
279
|
+
else if (char === stringChar) {
|
|
280
|
+
inString = false;
|
|
281
|
+
stringChar = '';
|
|
282
|
+
}
|
|
283
|
+
continue;
|
|
284
|
+
}
|
|
285
|
+
if (inString)
|
|
286
|
+
continue;
|
|
287
|
+
// Check brackets
|
|
288
|
+
if (openers.has(char)) {
|
|
289
|
+
stack.push(char);
|
|
290
|
+
}
|
|
291
|
+
else if (closers.has(char)) {
|
|
292
|
+
if (stack.length === 0) {
|
|
293
|
+
return { valid: false, message: `Unmatched closing bracket '${char}'` };
|
|
294
|
+
}
|
|
295
|
+
const opener = stack.pop();
|
|
296
|
+
if (pairs[opener] !== char) {
|
|
297
|
+
return { valid: false, message: `Mismatched brackets: '${opener}' and '${char}'` };
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
if (stack.length > 0) {
|
|
302
|
+
return { valid: false, message: `Unclosed brackets: ${stack.join(', ')}` };
|
|
303
|
+
}
|
|
304
|
+
return { valid: true, message: 'Brackets are balanced' };
|
|
305
|
+
}
|
|
306
|
+
checkCommonSyntaxIssues(code) {
|
|
307
|
+
const errors = [];
|
|
308
|
+
// Check for duplicate operators
|
|
309
|
+
if (/[+\-*\/]{3,}/.test(code)) {
|
|
310
|
+
errors.push({ message: 'Multiple consecutive operators detected' });
|
|
311
|
+
}
|
|
312
|
+
// Check for obvious missing semicolons (conservative)
|
|
313
|
+
// Note: Modern JS allows ASI, so we only flag clear issues
|
|
314
|
+
const lines = code.split('\n');
|
|
315
|
+
for (let i = 0; i < lines.length; i++) {
|
|
316
|
+
const trimmed = lines[i].trim();
|
|
317
|
+
// Check for specific patterns that almost always need semicolons
|
|
318
|
+
if (/^(const|let|var)\s+\w+\s*=\s*[^{[\n]+\s*$/.test(trimmed) &&
|
|
319
|
+
!trimmed.endsWith(';') &&
|
|
320
|
+
!trimmed.endsWith(',')) {
|
|
321
|
+
// Only flag if next line starts with something that would cause issues
|
|
322
|
+
const nextLine = lines[i + 1]?.trim() || '';
|
|
323
|
+
if (nextLine.startsWith('(') || nextLine.startsWith('[')) {
|
|
324
|
+
// Potential ASI hazard - but still don't flag as error
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
return errors;
|
|
329
|
+
}
|
|
330
|
+
checkStructurePreservation(original, fixed) {
|
|
331
|
+
// Count key structural elements
|
|
332
|
+
const countStructure = (code) => ({
|
|
333
|
+
functions: (code.match(/function\s+\w+/g) || []).length,
|
|
334
|
+
classes: (code.match(/class\s+\w+/g) || []).length,
|
|
335
|
+
arrows: (code.match(/=>/g) || []).length,
|
|
336
|
+
returns: (code.match(/return\s/g) || []).length,
|
|
337
|
+
});
|
|
338
|
+
const originalStructure = countStructure(original);
|
|
339
|
+
const fixedStructure = countStructure(fixed);
|
|
340
|
+
// Allow some variation but flag major changes
|
|
341
|
+
const functionDiff = Math.abs(originalStructure.functions - fixedStructure.functions);
|
|
342
|
+
const classDiff = Math.abs(originalStructure.classes - fixedStructure.classes);
|
|
343
|
+
return functionDiff <= 1 && classDiff === 0;
|
|
344
|
+
}
|
|
345
|
+
checkVariableUsage(original, fixed) {
|
|
346
|
+
// Extract variable declarations
|
|
347
|
+
const extractVars = (code) => {
|
|
348
|
+
const vars = new Set();
|
|
349
|
+
const matches = code.matchAll(/(?:const|let|var)\s+(\w+)/g);
|
|
350
|
+
for (const match of matches) {
|
|
351
|
+
vars.add(match[1]);
|
|
352
|
+
}
|
|
353
|
+
return vars;
|
|
354
|
+
};
|
|
355
|
+
const originalVars = extractVars(original);
|
|
356
|
+
const fixedVars = extractVars(fixed);
|
|
357
|
+
// Check for removed variables (might indicate important code removal)
|
|
358
|
+
const removedVars = [...originalVars].filter(v => !fixedVars.has(v));
|
|
359
|
+
return {
|
|
360
|
+
name: 'Variable Usage',
|
|
361
|
+
category: 'semantic',
|
|
362
|
+
passed: removedVars.length <= 2,
|
|
363
|
+
details: removedVars.length === 0
|
|
364
|
+
? 'All original variables preserved'
|
|
365
|
+
: `${removedVars.length} variable(s) removed: ${removedVars.join(', ')}`,
|
|
366
|
+
severity: removedVars.length > 2 ? 'warning' : undefined,
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
fixAddressesVulnerabilityType(fix) {
|
|
370
|
+
// Map strategies to what they address
|
|
371
|
+
const strategyMap = {
|
|
372
|
+
sanitization: ['xss', 'injection', 'html_injection'],
|
|
373
|
+
encoding: ['xss', 'html_injection'],
|
|
374
|
+
parameterization: ['sql_injection', 'injection'],
|
|
375
|
+
validation: ['path_traversal', 'injection', 'input_validation'],
|
|
376
|
+
configuration: ['hardcoded_secret', 'exposed_credential', 'misconfiguration'],
|
|
377
|
+
replacement: ['weak_cryptography', 'deprecated_api'],
|
|
378
|
+
access_control: ['authentication', 'authorization', 'access_control'],
|
|
379
|
+
};
|
|
380
|
+
const addressedTypes = strategyMap[fix.strategy] || [];
|
|
381
|
+
return addressedTypes.length > 0;
|
|
382
|
+
}
|
|
383
|
+
checkSecurityAntiPatterns(code) {
|
|
384
|
+
const antiPatterns = [];
|
|
385
|
+
// eval usage
|
|
386
|
+
if (/\beval\s*\(/.test(code)) {
|
|
387
|
+
antiPatterns.push('eval()');
|
|
388
|
+
}
|
|
389
|
+
// innerHTML without sanitization
|
|
390
|
+
if (/\.innerHTML\s*=/.test(code) && !/sanitize|DOMPurify/i.test(code)) {
|
|
391
|
+
antiPatterns.push('innerHTML without sanitization');
|
|
392
|
+
}
|
|
393
|
+
// document.write
|
|
394
|
+
if (/document\.write\s*\(/.test(code)) {
|
|
395
|
+
antiPatterns.push('document.write()');
|
|
396
|
+
}
|
|
397
|
+
// new Function()
|
|
398
|
+
if (/new\s+Function\s*\(/.test(code)) {
|
|
399
|
+
antiPatterns.push('new Function()');
|
|
400
|
+
}
|
|
401
|
+
return antiPatterns;
|
|
402
|
+
}
|
|
403
|
+
checkDangerousFunctions(code) {
|
|
404
|
+
const dangerous = [];
|
|
405
|
+
const dangerousPatterns = [
|
|
406
|
+
{ pattern: /child_process\.exec\s*\(/, name: 'child_process.exec' },
|
|
407
|
+
{ pattern: /\.execSync\s*\(/, name: 'execSync' },
|
|
408
|
+
{ pattern: /\$\(.*\)\.html\s*\(/, name: 'jQuery.html()' },
|
|
409
|
+
{ pattern: /setTimeout\s*\(\s*["'`]/, name: 'setTimeout with string' },
|
|
410
|
+
{ pattern: /setInterval\s*\(\s*["'`]/, name: 'setInterval with string' },
|
|
411
|
+
];
|
|
412
|
+
for (const { pattern, name } of dangerousPatterns) {
|
|
413
|
+
if (pattern.test(code)) {
|
|
414
|
+
dangerous.push(name);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
return dangerous;
|
|
418
|
+
}
|
|
419
|
+
calculateScore(checks) {
|
|
420
|
+
if (checks.length === 0)
|
|
421
|
+
return 100;
|
|
422
|
+
let score = 100;
|
|
423
|
+
const weights = { error: 25, warning: 10, info: 5 };
|
|
424
|
+
for (const check of checks) {
|
|
425
|
+
if (!check.passed) {
|
|
426
|
+
const weight = weights[check.severity || 'info'] || 5;
|
|
427
|
+
score -= weight;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
return Math.max(0, score);
|
|
431
|
+
}
|
|
432
|
+
determineValidity(checks) {
|
|
433
|
+
if (this.options.strictMode) {
|
|
434
|
+
return checks.every(c => c.passed);
|
|
435
|
+
}
|
|
436
|
+
// In non-strict mode, only fail on errors
|
|
437
|
+
return !checks.some(c => !c.passed && c.severity === 'error');
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
// ============================================================================
|
|
441
|
+
// Factory Functions
|
|
442
|
+
// ============================================================================
|
|
443
|
+
/**
|
|
444
|
+
* Create a fix validator
|
|
445
|
+
*/
|
|
446
|
+
export function createFixValidator(options) {
|
|
447
|
+
return new FixValidator(options);
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* Quick validate a fix
|
|
451
|
+
*/
|
|
452
|
+
export async function quickValidate(fix, originalCode, fixedCode) {
|
|
453
|
+
const validator = createFixValidator({
|
|
454
|
+
syntaxValidation: true,
|
|
455
|
+
semanticValidation: false,
|
|
456
|
+
securityRescan: false,
|
|
457
|
+
regressionTesting: false,
|
|
458
|
+
});
|
|
459
|
+
const result = await validator.validate(fix, originalCode, fixedCode);
|
|
460
|
+
return result.valid;
|
|
461
|
+
}
|
|
462
|
+
//# sourceMappingURL=fix-validator.js.map
|