@kevinrabun/judges 2.3.0 → 3.0.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 +177 -12
- package/dist/api.d.ts +40 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +56 -0
- package/dist/api.js.map +1 -0
- package/dist/ast/cross-file-taint.d.ts +43 -0
- package/dist/ast/cross-file-taint.d.ts.map +1 -0
- package/dist/ast/cross-file-taint.js +713 -0
- package/dist/ast/cross-file-taint.js.map +1 -0
- package/dist/ast/index.d.ts +4 -0
- package/dist/ast/index.d.ts.map +1 -1
- package/dist/ast/index.js +5 -0
- package/dist/ast/index.js.map +1 -1
- package/dist/ast/structural-parser.d.ts.map +1 -1
- package/dist/ast/structural-parser.js +66 -11
- package/dist/ast/structural-parser.js.map +1 -1
- package/dist/ast/taint-tracker.d.ts +35 -0
- package/dist/ast/taint-tracker.d.ts.map +1 -0
- package/dist/ast/taint-tracker.js +518 -0
- package/dist/ast/taint-tracker.js.map +1 -0
- package/dist/ast/types.d.ts +2 -0
- package/dist/ast/types.d.ts.map +1 -1
- package/dist/ast/typescript-ast.d.ts.map +1 -1
- package/dist/ast/typescript-ast.js +25 -5
- package/dist/ast/typescript-ast.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +10 -9
- package/dist/config.js.map +1 -1
- package/dist/dedup.d.ts +19 -0
- package/dist/dedup.d.ts.map +1 -0
- package/dist/dedup.js +222 -0
- package/dist/dedup.js.map +1 -0
- package/dist/errors.d.ts +37 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +57 -0
- package/dist/errors.js.map +1 -0
- package/dist/evaluators/accessibility.d.ts +1 -1
- package/dist/evaluators/accessibility.d.ts.map +1 -1
- package/dist/evaluators/accessibility.js +22 -16
- package/dist/evaluators/accessibility.js.map +1 -1
- package/dist/evaluators/agent-instructions.d.ts +1 -1
- package/dist/evaluators/agent-instructions.d.ts.map +1 -1
- package/dist/evaluators/agent-instructions.js +1 -2
- package/dist/evaluators/agent-instructions.js.map +1 -1
- package/dist/evaluators/ai-code-safety.d.ts +1 -1
- package/dist/evaluators/ai-code-safety.d.ts.map +1 -1
- package/dist/evaluators/ai-code-safety.js +2 -6
- package/dist/evaluators/ai-code-safety.js.map +1 -1
- package/dist/evaluators/api-design.d.ts +1 -1
- package/dist/evaluators/api-design.d.ts.map +1 -1
- package/dist/evaluators/api-design.js +2 -1
- package/dist/evaluators/api-design.js.map +1 -1
- package/dist/evaluators/app-builder.d.ts +34 -0
- package/dist/evaluators/app-builder.d.ts.map +1 -0
- package/dist/evaluators/app-builder.js +156 -0
- package/dist/evaluators/app-builder.js.map +1 -0
- package/dist/evaluators/authentication.d.ts +1 -1
- package/dist/evaluators/authentication.d.ts.map +1 -1
- package/dist/evaluators/authentication.js +2 -66
- package/dist/evaluators/authentication.js.map +1 -1
- package/dist/evaluators/backwards-compatibility.d.ts +1 -1
- package/dist/evaluators/backwards-compatibility.d.ts.map +1 -1
- package/dist/evaluators/backwards-compatibility.js.map +1 -1
- package/dist/evaluators/caching.d.ts +1 -1
- package/dist/evaluators/caching.d.ts.map +1 -1
- package/dist/evaluators/caching.js.map +1 -1
- package/dist/evaluators/ci-cd.d.ts +1 -1
- package/dist/evaluators/ci-cd.d.ts.map +1 -1
- package/dist/evaluators/ci-cd.js +4 -4
- package/dist/evaluators/ci-cd.js.map +1 -1
- package/dist/evaluators/cloud-readiness.d.ts +1 -1
- package/dist/evaluators/cloud-readiness.d.ts.map +1 -1
- package/dist/evaluators/cloud-readiness.js.map +1 -1
- package/dist/evaluators/code-structure.d.ts +1 -1
- package/dist/evaluators/code-structure.d.ts.map +1 -1
- package/dist/evaluators/code-structure.js +2 -6
- package/dist/evaluators/code-structure.js.map +1 -1
- package/dist/evaluators/compliance.d.ts +1 -1
- package/dist/evaluators/compliance.d.ts.map +1 -1
- package/dist/evaluators/compliance.js +15 -6
- package/dist/evaluators/compliance.js.map +1 -1
- package/dist/evaluators/concurrency.d.ts +1 -1
- package/dist/evaluators/concurrency.d.ts.map +1 -1
- package/dist/evaluators/concurrency.js +9 -4
- package/dist/evaluators/concurrency.js.map +1 -1
- package/dist/evaluators/configuration-management.d.ts +1 -1
- package/dist/evaluators/configuration-management.d.ts.map +1 -1
- package/dist/evaluators/configuration-management.js +7 -2
- package/dist/evaluators/configuration-management.js.map +1 -1
- package/dist/evaluators/cost-effectiveness.d.ts +1 -1
- package/dist/evaluators/cost-effectiveness.d.ts.map +1 -1
- package/dist/evaluators/cost-effectiveness.js +1 -3
- package/dist/evaluators/cost-effectiveness.js.map +1 -1
- package/dist/evaluators/cybersecurity.d.ts +1 -1
- package/dist/evaluators/cybersecurity.d.ts.map +1 -1
- package/dist/evaluators/cybersecurity.js +50 -1
- package/dist/evaluators/cybersecurity.js.map +1 -1
- package/dist/evaluators/data-security.d.ts +1 -1
- package/dist/evaluators/data-security.d.ts.map +1 -1
- package/dist/evaluators/data-security.js +9 -66
- package/dist/evaluators/data-security.js.map +1 -1
- package/dist/evaluators/data-sovereignty.d.ts +1 -1
- package/dist/evaluators/data-sovereignty.d.ts.map +1 -1
- package/dist/evaluators/data-sovereignty.js +4 -2
- package/dist/evaluators/data-sovereignty.js.map +1 -1
- package/dist/evaluators/database.d.ts +1 -1
- package/dist/evaluators/database.d.ts.map +1 -1
- package/dist/evaluators/database.js +3 -1
- package/dist/evaluators/database.js.map +1 -1
- package/dist/evaluators/dependencies.d.ts +6 -0
- package/dist/evaluators/dependencies.d.ts.map +1 -0
- package/dist/evaluators/dependencies.js +204 -0
- package/dist/evaluators/dependencies.js.map +1 -0
- package/dist/evaluators/dependency-health.d.ts +1 -1
- package/dist/evaluators/dependency-health.d.ts.map +1 -1
- package/dist/evaluators/dependency-health.js +198 -6
- package/dist/evaluators/dependency-health.js.map +1 -1
- package/dist/evaluators/documentation.d.ts +1 -1
- package/dist/evaluators/documentation.d.ts.map +1 -1
- package/dist/evaluators/documentation.js +5 -2
- package/dist/evaluators/documentation.js.map +1 -1
- package/dist/evaluators/error-handling.d.ts +1 -1
- package/dist/evaluators/error-handling.d.ts.map +1 -1
- package/dist/evaluators/error-handling.js.map +1 -1
- package/dist/evaluators/ethics-bias.d.ts +1 -1
- package/dist/evaluators/ethics-bias.d.ts.map +1 -1
- package/dist/evaluators/ethics-bias.js +10 -5
- package/dist/evaluators/ethics-bias.js.map +1 -1
- package/dist/evaluators/framework-safety.d.ts +13 -0
- package/dist/evaluators/framework-safety.d.ts.map +1 -0
- package/dist/evaluators/framework-safety.js +424 -0
- package/dist/evaluators/framework-safety.js.map +1 -0
- package/dist/evaluators/index.d.ts +20 -24
- package/dist/evaluators/index.d.ts.map +1 -1
- package/dist/evaluators/index.js +294 -728
- package/dist/evaluators/index.js.map +1 -1
- package/dist/evaluators/internationalization.d.ts +1 -1
- package/dist/evaluators/internationalization.d.ts.map +1 -1
- package/dist/evaluators/internationalization.js +14 -6
- package/dist/evaluators/internationalization.js.map +1 -1
- package/dist/evaluators/logging-privacy.d.ts +1 -1
- package/dist/evaluators/logging-privacy.d.ts.map +1 -1
- package/dist/evaluators/logging-privacy.js +3 -1
- package/dist/evaluators/logging-privacy.js.map +1 -1
- package/dist/evaluators/maintainability.d.ts +1 -1
- package/dist/evaluators/maintainability.d.ts.map +1 -1
- package/dist/evaluators/maintainability.js +15 -9
- package/dist/evaluators/maintainability.js.map +1 -1
- package/dist/evaluators/observability.d.ts +1 -1
- package/dist/evaluators/observability.d.ts.map +1 -1
- package/dist/evaluators/observability.js +2 -1
- package/dist/evaluators/observability.js.map +1 -1
- package/dist/evaluators/performance.d.ts +1 -1
- package/dist/evaluators/performance.d.ts.map +1 -1
- package/dist/evaluators/performance.js +181 -4
- package/dist/evaluators/performance.js.map +1 -1
- package/dist/evaluators/portability.d.ts +1 -1
- package/dist/evaluators/portability.d.ts.map +1 -1
- package/dist/evaluators/portability.js +2 -1
- package/dist/evaluators/portability.js.map +1 -1
- package/dist/evaluators/project.d.ts +16 -0
- package/dist/evaluators/project.d.ts.map +1 -0
- package/dist/evaluators/project.js +353 -0
- package/dist/evaluators/project.js.map +1 -0
- package/dist/evaluators/rate-limiting.d.ts +1 -1
- package/dist/evaluators/rate-limiting.d.ts.map +1 -1
- package/dist/evaluators/rate-limiting.js.map +1 -1
- package/dist/evaluators/reliability.d.ts +1 -1
- package/dist/evaluators/reliability.d.ts.map +1 -1
- package/dist/evaluators/reliability.js.map +1 -1
- package/dist/evaluators/scalability.d.ts +1 -1
- package/dist/evaluators/scalability.d.ts.map +1 -1
- package/dist/evaluators/scalability.js +3 -1
- package/dist/evaluators/scalability.js.map +1 -1
- package/dist/evaluators/shared.d.ts +24 -2
- package/dist/evaluators/shared.d.ts.map +1 -1
- package/dist/evaluators/shared.js +190 -2
- package/dist/evaluators/shared.js.map +1 -1
- package/dist/evaluators/software-practices.d.ts +1 -1
- package/dist/evaluators/software-practices.d.ts.map +1 -1
- package/dist/evaluators/software-practices.js +3 -3
- package/dist/evaluators/software-practices.js.map +1 -1
- package/dist/evaluators/testing.d.ts +1 -1
- package/dist/evaluators/testing.d.ts.map +1 -1
- package/dist/evaluators/testing.js +12 -4
- package/dist/evaluators/testing.js.map +1 -1
- package/dist/evaluators/ux.d.ts +1 -1
- package/dist/evaluators/ux.d.ts.map +1 -1
- package/dist/evaluators/ux.js.map +1 -1
- package/dist/evaluators/v2.d.ts +1 -1
- package/dist/evaluators/v2.d.ts.map +1 -1
- package/dist/evaluators/v2.js +13 -35
- package/dist/evaluators/v2.js.map +1 -1
- package/dist/formatters/sarif.d.ts +75 -0
- package/dist/formatters/sarif.d.ts.map +1 -0
- package/dist/formatters/sarif.js +93 -0
- package/dist/formatters/sarif.js.map +1 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -806
- package/dist/index.js.map +1 -1
- package/dist/judges/accessibility.d.ts +1 -1
- package/dist/judges/accessibility.d.ts.map +1 -1
- package/dist/judges/agent-instructions.d.ts +1 -1
- package/dist/judges/agent-instructions.d.ts.map +1 -1
- package/dist/judges/ai-code-safety.d.ts +1 -1
- package/dist/judges/ai-code-safety.d.ts.map +1 -1
- package/dist/judges/api-design.d.ts +1 -1
- package/dist/judges/api-design.d.ts.map +1 -1
- package/dist/judges/authentication.d.ts +1 -1
- package/dist/judges/authentication.d.ts.map +1 -1
- package/dist/judges/backwards-compatibility.d.ts +1 -1
- package/dist/judges/backwards-compatibility.d.ts.map +1 -1
- package/dist/judges/caching.d.ts +1 -1
- package/dist/judges/caching.d.ts.map +1 -1
- package/dist/judges/ci-cd.d.ts +1 -1
- package/dist/judges/ci-cd.d.ts.map +1 -1
- package/dist/judges/cloud-readiness.d.ts +1 -1
- package/dist/judges/cloud-readiness.d.ts.map +1 -1
- package/dist/judges/code-structure.d.ts +1 -1
- package/dist/judges/code-structure.d.ts.map +1 -1
- package/dist/judges/code-structure.js +7 -1
- package/dist/judges/code-structure.js.map +1 -1
- package/dist/judges/compliance.d.ts +1 -1
- package/dist/judges/compliance.d.ts.map +1 -1
- package/dist/judges/concurrency.d.ts +1 -1
- package/dist/judges/concurrency.d.ts.map +1 -1
- package/dist/judges/configuration-management.d.ts +1 -1
- package/dist/judges/configuration-management.d.ts.map +1 -1
- package/dist/judges/cost-effectiveness.d.ts +1 -1
- package/dist/judges/cost-effectiveness.d.ts.map +1 -1
- package/dist/judges/cybersecurity.d.ts +1 -1
- package/dist/judges/cybersecurity.d.ts.map +1 -1
- package/dist/judges/data-security.d.ts +1 -1
- package/dist/judges/data-security.d.ts.map +1 -1
- package/dist/judges/data-sovereignty.d.ts +1 -1
- package/dist/judges/data-sovereignty.d.ts.map +1 -1
- package/dist/judges/database.d.ts +1 -1
- package/dist/judges/database.d.ts.map +1 -1
- package/dist/judges/dependency-health.d.ts +1 -1
- package/dist/judges/dependency-health.d.ts.map +1 -1
- package/dist/judges/documentation.d.ts +1 -1
- package/dist/judges/documentation.d.ts.map +1 -1
- package/dist/judges/error-handling.d.ts +1 -1
- package/dist/judges/error-handling.d.ts.map +1 -1
- package/dist/judges/ethics-bias.d.ts +1 -1
- package/dist/judges/ethics-bias.d.ts.map +1 -1
- package/dist/judges/framework-safety.d.ts +3 -0
- package/dist/judges/framework-safety.d.ts.map +1 -0
- package/dist/judges/framework-safety.js +31 -0
- package/dist/judges/framework-safety.js.map +1 -0
- package/dist/judges/index.d.ts +1 -1
- package/dist/judges/index.d.ts.map +1 -1
- package/dist/judges/index.js +74 -0
- package/dist/judges/index.js.map +1 -1
- package/dist/judges/internationalization.d.ts +1 -1
- package/dist/judges/internationalization.d.ts.map +1 -1
- package/dist/judges/logging-privacy.d.ts +1 -1
- package/dist/judges/logging-privacy.d.ts.map +1 -1
- package/dist/judges/maintainability.d.ts +1 -1
- package/dist/judges/maintainability.d.ts.map +1 -1
- package/dist/judges/observability.d.ts +1 -1
- package/dist/judges/observability.d.ts.map +1 -1
- package/dist/judges/performance.d.ts +1 -1
- package/dist/judges/performance.d.ts.map +1 -1
- package/dist/judges/portability.d.ts +1 -1
- package/dist/judges/portability.d.ts.map +1 -1
- package/dist/judges/rate-limiting.d.ts +1 -1
- package/dist/judges/rate-limiting.d.ts.map +1 -1
- package/dist/judges/reliability.d.ts +1 -1
- package/dist/judges/reliability.d.ts.map +1 -1
- package/dist/judges/scalability.d.ts +1 -1
- package/dist/judges/scalability.d.ts.map +1 -1
- package/dist/judges/software-practices.d.ts +1 -1
- package/dist/judges/software-practices.d.ts.map +1 -1
- package/dist/judges/testing.d.ts +1 -1
- package/dist/judges/testing.d.ts.map +1 -1
- package/dist/judges/ux.d.ts +1 -1
- package/dist/judges/ux.d.ts.map +1 -1
- package/dist/language-patterns.d.ts +37 -0
- package/dist/language-patterns.d.ts.map +1 -1
- package/dist/language-patterns.js +58 -3
- package/dist/language-patterns.js.map +1 -1
- package/dist/patches/index.d.ts +10 -0
- package/dist/patches/index.d.ts.map +1 -0
- package/dist/patches/index.js +533 -0
- package/dist/patches/index.js.map +1 -0
- package/dist/reports/public-repo-report.d.ts +1 -1
- package/dist/reports/public-repo-report.d.ts.map +1 -1
- package/dist/scoring.d.ts +18 -0
- package/dist/scoring.d.ts.map +1 -0
- package/dist/scoring.js +178 -0
- package/dist/scoring.js.map +1 -0
- package/dist/tools/deep-review.d.ts +4 -0
- package/dist/tools/deep-review.d.ts.map +1 -0
- package/dist/tools/deep-review.js +56 -0
- package/dist/tools/deep-review.js.map +1 -0
- package/dist/tools/prompts.d.ts +8 -0
- package/dist/tools/prompts.d.ts.map +1 -0
- package/dist/tools/prompts.js +66 -0
- package/dist/tools/prompts.js.map +1 -0
- package/dist/tools/register-evaluation.d.ts +7 -0
- package/dist/tools/register-evaluation.d.ts.map +1 -0
- package/dist/tools/register-evaluation.js +303 -0
- package/dist/tools/register-evaluation.js.map +1 -0
- package/dist/tools/register-workflow.d.ts +7 -0
- package/dist/tools/register-workflow.d.ts.map +1 -0
- package/dist/tools/register-workflow.js +395 -0
- package/dist/tools/register-workflow.js.map +1 -0
- package/dist/tools/register.d.ts +7 -0
- package/dist/tools/register.d.ts.map +1 -0
- package/dist/tools/register.js +14 -0
- package/dist/tools/register.js.map +1 -0
- package/dist/tools/schemas.d.ts +26 -0
- package/dist/tools/schemas.d.ts.map +1 -0
- package/dist/tools/schemas.js +42 -0
- package/dist/tools/schemas.js.map +1 -0
- package/dist/types.d.ts +29 -2
- package/dist/types.d.ts.map +1 -1
- package/package.json +42 -3
- package/server.json +51 -3
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
import { getLineNumbers, getLangFamily } from "./shared.js";
|
|
2
|
+
/**
|
|
3
|
+
* Framework-specific deep safety rules.
|
|
4
|
+
*
|
|
5
|
+
* Detects misuse patterns unique to popular frameworks that generic rules miss:
|
|
6
|
+
* - React: hook violations, unsafe lifecycle, XSS via dangerouslySetInnerHTML
|
|
7
|
+
* - Express/Koa/Fastify: middleware ordering, body-parser pitfalls, error middleware
|
|
8
|
+
* - Next.js: SSR data leaks, getServerSideProps security, API route exposure
|
|
9
|
+
* - Angular: bypassSecurityTrust, template injection, zone.js anti-patterns
|
|
10
|
+
* - Vue: v-html without sanitization, computed vs watch misuse
|
|
11
|
+
*/
|
|
12
|
+
export function analyzeFrameworkSafety(code, language) {
|
|
13
|
+
const findings = [];
|
|
14
|
+
const lines = code.split("\n");
|
|
15
|
+
let ruleNum = 1;
|
|
16
|
+
const prefix = "FW";
|
|
17
|
+
const lang = getLangFamily(language);
|
|
18
|
+
if (lang !== "javascript" && lang !== "typescript")
|
|
19
|
+
return findings;
|
|
20
|
+
// ── React Hook Violations ────────────────────────────────────────────────
|
|
21
|
+
// Conditional hook call — breaks Rules of Hooks
|
|
22
|
+
const conditionalHookLines = [];
|
|
23
|
+
let inConditional = 0;
|
|
24
|
+
for (let i = 0; i < lines.length; i++) {
|
|
25
|
+
const line = lines[i];
|
|
26
|
+
if (/\bif\s*\(|\bswitch\s*\(|\?\s*$/.test(line))
|
|
27
|
+
inConditional++;
|
|
28
|
+
if (inConditional > 0 &&
|
|
29
|
+
/\buse(?:State|Effect|Memo|Callback|Ref|Context|Reducer|LayoutEffect|ImperativeHandle|DebugValue)\s*\(/i.test(line)) {
|
|
30
|
+
conditionalHookLines.push(i + 1);
|
|
31
|
+
}
|
|
32
|
+
if (/^\s*\}/.test(line) && inConditional > 0)
|
|
33
|
+
inConditional--;
|
|
34
|
+
}
|
|
35
|
+
if (conditionalHookLines.length > 0) {
|
|
36
|
+
findings.push({
|
|
37
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
38
|
+
severity: "critical",
|
|
39
|
+
title: "React hook called conditionally — Rules of Hooks violation",
|
|
40
|
+
description: "Hooks must be called at the top level of a React component/custom hook, never inside conditions, loops, or nested functions. Conditional hooks cause stale state and render crashes.",
|
|
41
|
+
lineNumbers: conditionalHookLines,
|
|
42
|
+
recommendation: "Move hook calls to the top level of the component. Use the hook's value conditionally instead of calling the hook conditionally.",
|
|
43
|
+
reference: "React Rules of Hooks — https://react.dev/reference/rules/rules-of-hooks",
|
|
44
|
+
suggestedFix: "Move the hook call outside the if block: const [value, setValue] = useState(initial); then use value conditionally.",
|
|
45
|
+
confidence: 0.9,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
// Hook inside loop
|
|
49
|
+
const hookInLoopLines = [];
|
|
50
|
+
let inLoop = 0;
|
|
51
|
+
for (let i = 0; i < lines.length; i++) {
|
|
52
|
+
const line = lines[i];
|
|
53
|
+
if (/\bfor\s*\(|\bwhile\s*\(|\.forEach\s*\(|\.map\s*\(/.test(line))
|
|
54
|
+
inLoop++;
|
|
55
|
+
if (inLoop > 0 && /\buse(?:State|Effect|Memo|Callback|Ref|Context|Reducer)\s*\(/i.test(line)) {
|
|
56
|
+
hookInLoopLines.push(i + 1);
|
|
57
|
+
}
|
|
58
|
+
if (/^\s*\}/.test(line) && inLoop > 0)
|
|
59
|
+
inLoop--;
|
|
60
|
+
}
|
|
61
|
+
if (hookInLoopLines.length > 0) {
|
|
62
|
+
findings.push({
|
|
63
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
64
|
+
severity: "critical",
|
|
65
|
+
title: "React hook called inside a loop — Rules of Hooks violation",
|
|
66
|
+
description: "Hooks must not be called inside loops. The number of hook calls must be the same on every render. Looped hooks cause unpredictable state corruption.",
|
|
67
|
+
lineNumbers: hookInLoopLines,
|
|
68
|
+
recommendation: "Extract the looped logic into a child component that uses its own hooks, or restructure to call hooks at the top level with array state.",
|
|
69
|
+
reference: "React Rules of Hooks — https://react.dev/reference/rules/rules-of-hooks",
|
|
70
|
+
confidence: 0.9,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
// useEffect with missing cleanup for subscriptions/timers
|
|
74
|
+
const effectNoCleanupLines = [];
|
|
75
|
+
for (let i = 0; i < lines.length; i++) {
|
|
76
|
+
if (/\buseEffect\s*\(\s*\(\s*\)\s*=>\s*\{/.test(lines[i])) {
|
|
77
|
+
const effectBody = lines.slice(i, Math.min(lines.length, i + 20)).join("\n");
|
|
78
|
+
const hasSubscription = /addEventListener|subscribe|setInterval|setTimeout|\.on\(|\.listen\(|socket\.|EventSource|WebSocket/.test(effectBody);
|
|
79
|
+
const hasCleanup = /return\s*\(\s*\)\s*=>|return\s*\(\)\s*=>|return\s+function|removeEventListener|unsubscribe|clearInterval|clearTimeout|\.off\(|\.close\(/.test(effectBody);
|
|
80
|
+
if (hasSubscription && !hasCleanup) {
|
|
81
|
+
effectNoCleanupLines.push(i + 1);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
if (effectNoCleanupLines.length > 0) {
|
|
86
|
+
findings.push({
|
|
87
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
88
|
+
severity: "high",
|
|
89
|
+
title: "useEffect subscribes without cleanup — memory leak risk",
|
|
90
|
+
description: "useEffect sets up event listeners, timers, or subscriptions but does not return a cleanup function. On unmount or re-render, old subscriptions accumulate, causing memory leaks.",
|
|
91
|
+
lineNumbers: effectNoCleanupLines,
|
|
92
|
+
recommendation: "Return a cleanup function from useEffect that removes listeners/clears timers: return () => { window.removeEventListener('resize', handler); };",
|
|
93
|
+
reference: "React useEffect cleanup — https://react.dev/reference/react/useEffect",
|
|
94
|
+
suggestedFix: "Add cleanup: useEffect(() => { const id = setInterval(fn, 1000); return () => clearInterval(id); }, []);",
|
|
95
|
+
confidence: 0.85,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
// useEffect with object/array literal as dependency → infinite re-render
|
|
99
|
+
const effectObjDepLines = [];
|
|
100
|
+
for (let i = 0; i < lines.length; i++) {
|
|
101
|
+
if (/\buseEffect\s*\(/.test(lines[i]) || /\buseMemo\s*\(/.test(lines[i]) || /\buseCallback\s*\(/.test(lines[i])) {
|
|
102
|
+
const ctx = lines.slice(i, Math.min(lines.length, i + 5)).join(" ");
|
|
103
|
+
// Matches dep arrays containing inline object/array literals: [{ ... }] or [[ ... ]]
|
|
104
|
+
if (/\],\s*\[(?:[^\]]*\{[^}]*\}|[^\]]*\[[^\]]*\])/.test(ctx)) {
|
|
105
|
+
effectObjDepLines.push(i + 1);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
if (effectObjDepLines.length > 0) {
|
|
110
|
+
findings.push({
|
|
111
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
112
|
+
severity: "high",
|
|
113
|
+
title: "Inline object/array in hook dependency array — infinite re-render",
|
|
114
|
+
description: "Object or array literals in useEffect/useMemo/useCallback dependency arrays create new references every render, causing the hook to fire on every render cycle.",
|
|
115
|
+
lineNumbers: effectObjDepLines,
|
|
116
|
+
recommendation: "Extract the object/array to a useMemo or define it outside the component. Compare by primitive values or use a stable reference.",
|
|
117
|
+
reference: "React hook dependency array — https://react.dev/reference/react/useEffect",
|
|
118
|
+
confidence: 0.8,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
// setState in useEffect without dependency guard → infinite loop
|
|
122
|
+
const setStateInEffectLines = [];
|
|
123
|
+
for (let i = 0; i < lines.length; i++) {
|
|
124
|
+
if (/\buseEffect\s*\(\s*\(\s*\)\s*=>\s*\{/.test(lines[i])) {
|
|
125
|
+
const effectCtx = lines.slice(i, Math.min(lines.length, i + 15)).join("\n");
|
|
126
|
+
const hasSetState = /\bset\w+\s*\(/.test(effectCtx);
|
|
127
|
+
const hasDeps = /\],\s*\[/.test(effectCtx) || /\}\s*,\s*\[\s*\]/.test(effectCtx);
|
|
128
|
+
if (hasSetState && !hasDeps) {
|
|
129
|
+
setStateInEffectLines.push(i + 1);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (setStateInEffectLines.length > 0) {
|
|
134
|
+
findings.push({
|
|
135
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
136
|
+
severity: "high",
|
|
137
|
+
title: "setState in useEffect without dependency array — potential infinite loop",
|
|
138
|
+
description: "Calling setState inside a useEffect with no dependency array causes the component to re-render, which re-runs the effect, which calls setState again — infinite loop.",
|
|
139
|
+
lineNumbers: setStateInEffectLines,
|
|
140
|
+
recommendation: "Add a dependency array to useEffect. Use an empty array [] for mount-only effects, or specify the values that should trigger re-run.",
|
|
141
|
+
reference: "React useEffect — https://react.dev/reference/react/useEffect",
|
|
142
|
+
confidence: 0.8,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
// ── Express/Koa/Fastify Middleware Rules ─────────────────────────────────
|
|
146
|
+
// Error-handling middleware position (Express error middleware must be last)
|
|
147
|
+
const expressErrorMwLines = [];
|
|
148
|
+
const hasExpressApp = /\bexpress\s*\(\s*\)|require\s*\(\s*["']express["']\s*\)|from\s+["']express["']/i.test(code);
|
|
149
|
+
if (hasExpressApp) {
|
|
150
|
+
let lastErrorMw = -1;
|
|
151
|
+
let hasRouteAfterErrorMw = false;
|
|
152
|
+
for (let i = 0; i < lines.length; i++) {
|
|
153
|
+
// Express error middleware: app.use((err, req, res, next) => {})
|
|
154
|
+
if (/app\.use\s*\(\s*(?:function\s*\(\s*err|(?:\(\s*err\s*,\s*req\s*,\s*res\s*,\s*next\s*\))|(?:\(\s*error\s*,\s*req\s*,\s*res\s*,\s*next\s*\)))/i.test(lines[i])) {
|
|
155
|
+
lastErrorMw = i;
|
|
156
|
+
}
|
|
157
|
+
// Route registered after error middleware
|
|
158
|
+
if (lastErrorMw >= 0 && i > lastErrorMw && /app\.(?:get|post|put|patch|delete|all)\s*\(\s*["']/i.test(lines[i])) {
|
|
159
|
+
hasRouteAfterErrorMw = true;
|
|
160
|
+
expressErrorMwLines.push(i + 1);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
if (hasRouteAfterErrorMw && lastErrorMw >= 0) {
|
|
164
|
+
findings.push({
|
|
165
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
166
|
+
severity: "high",
|
|
167
|
+
title: "Express error middleware registered before routes",
|
|
168
|
+
description: "Express error-handling middleware (4-parameter function) is registered before route handlers. Routes added after it won't have their errors caught, leading to unhandled rejections.",
|
|
169
|
+
lineNumbers: [lastErrorMw + 1, ...expressErrorMwLines],
|
|
170
|
+
recommendation: "Move error-handling middleware to after all route registrations: first register all routes, then app.use(errorHandler).",
|
|
171
|
+
reference: "Express Error Handling — https://expressjs.com/en/guide/error-handling.html",
|
|
172
|
+
suggestedFix: "Move app.use((err, req, res, next) => { ... }) to the very end, after all app.get/post/put/delete routes.",
|
|
173
|
+
confidence: 0.9,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
// CORS before auth middleware (information leak)
|
|
177
|
+
let corsLine = -1;
|
|
178
|
+
let authLine = -1;
|
|
179
|
+
for (let i = 0; i < lines.length; i++) {
|
|
180
|
+
if (/app\.use\s*\(\s*cors\s*\(/i.test(lines[i]) && corsLine < 0)
|
|
181
|
+
corsLine = i;
|
|
182
|
+
if (/app\.use\s*\(.*(?:passport|auth|jwt|bearer|session)\b/i.test(lines[i]) && authLine < 0)
|
|
183
|
+
authLine = i;
|
|
184
|
+
}
|
|
185
|
+
// Body parser without size limit
|
|
186
|
+
const bodyParserNoLimitLines = [];
|
|
187
|
+
for (let i = 0; i < lines.length; i++) {
|
|
188
|
+
if (/(?:express\.json|bodyParser\.json|express\.urlencoded|bodyParser\.urlencoded)\s*\(\s*\)/i.test(lines[i])) {
|
|
189
|
+
bodyParserNoLimitLines.push(i + 1);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
if (bodyParserNoLimitLines.length > 0) {
|
|
193
|
+
findings.push({
|
|
194
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
195
|
+
severity: "medium",
|
|
196
|
+
title: "Express body parser without size limit — DoS risk",
|
|
197
|
+
description: "Body parser middleware is configured without a payload size limit. Attackers can send extremely large request bodies to exhaust server memory.",
|
|
198
|
+
lineNumbers: bodyParserNoLimitLines,
|
|
199
|
+
recommendation: "Set a limit: express.json({ limit: '1mb' }) or express.urlencoded({ limit: '1mb', extended: true }).",
|
|
200
|
+
reference: "Express Body Parser — https://expressjs.com/en/api.html#express.json",
|
|
201
|
+
suggestedFix: "Add limit: app.use(express.json({ limit: '1mb' }));",
|
|
202
|
+
confidence: 0.9,
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
// Express static serving from project root
|
|
206
|
+
const staticRootLines = getLineNumbers(code, /express\.static\s*\(\s*(?:__dirname|["']\.\/?["']|["']\.\.\/?\/?["']|process\.cwd\(\))\s*\)/gi);
|
|
207
|
+
if (staticRootLines.length > 0) {
|
|
208
|
+
findings.push({
|
|
209
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
210
|
+
severity: "high",
|
|
211
|
+
title: "Express.static serves project root or parent — file exposure risk",
|
|
212
|
+
description: "express.static is configured to serve the project root directory. This exposes source code, .env files, package.json, and other sensitive files to the internet.",
|
|
213
|
+
lineNumbers: staticRootLines,
|
|
214
|
+
recommendation: "Serve a dedicated directory: express.static(path.join(__dirname, 'public')). Never serve the project root.",
|
|
215
|
+
reference: "Express Static Files — https://expressjs.com/en/starter/static-files.html",
|
|
216
|
+
suggestedFix: "Change to: app.use(express.static(path.join(__dirname, 'public')));",
|
|
217
|
+
confidence: 0.95,
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
// Missing helmet() or security headers middleware
|
|
221
|
+
const hasHelmet = /helmet\s*\(|require\s*\(\s*["']helmet["']\)|from\s+["']helmet["']/i.test(code);
|
|
222
|
+
const hasRoutes = /app\.(?:get|post|put|patch|delete)\s*\(\s*["']/i.test(code);
|
|
223
|
+
if (!hasHelmet && hasRoutes) {
|
|
224
|
+
findings.push({
|
|
225
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
226
|
+
severity: "medium",
|
|
227
|
+
title: "Express app without helmet() — missing security headers",
|
|
228
|
+
description: "No security headers middleware (helmet) detected in Express app. Without it, responses lack X-Content-Type-Options, X-Frame-Options, CSP, and other defensive headers.",
|
|
229
|
+
lineNumbers: [1],
|
|
230
|
+
recommendation: "Install and use helmet: npm install helmet, then app.use(helmet()). This sets 11 security headers with sensible defaults.",
|
|
231
|
+
reference: "Helmet.js — https://helmetjs.github.io/",
|
|
232
|
+
suggestedFix: "Add: import helmet from 'helmet'; app.use(helmet());",
|
|
233
|
+
confidence: 0.8,
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
// Trust proxy not set when behind reverse proxy
|
|
237
|
+
const hasTrustProxy = /app\.set\s*\(\s*["']trust proxy["']|trustProxy|trust_proxy/i.test(code);
|
|
238
|
+
const hasRateLimit = /rateLimit|rate-limit|express-rate-limit/i.test(code);
|
|
239
|
+
const hasProxy = /nginx|reverse.?proxy|load.?balanc|X-Forwarded/i.test(code);
|
|
240
|
+
if (!hasTrustProxy && (hasRateLimit || hasProxy)) {
|
|
241
|
+
findings.push({
|
|
242
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
243
|
+
severity: "medium",
|
|
244
|
+
title: "Express 'trust proxy' not configured behind reverse proxy",
|
|
245
|
+
description: "Rate limiting and IP-based security won't work correctly behind a reverse proxy without 'trust proxy'. All requests appear from 127.0.0.1, making per-IP rate limiting ineffective.",
|
|
246
|
+
lineNumbers: [1],
|
|
247
|
+
recommendation: "Set app.set('trust proxy', 1) when behind one proxy, or 'trust proxy' to the number of proxies in the chain.",
|
|
248
|
+
reference: "Express trust proxy — https://expressjs.com/en/guide/behind-proxies.html",
|
|
249
|
+
confidence: 0.75,
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
// ── Next.js SSR Security ────────────────────────────────────────────────
|
|
254
|
+
// getServerSideProps leaking secrets to client
|
|
255
|
+
const gssp = /export\s+(?:async\s+)?function\s+getServerSideProps|getStaticProps/;
|
|
256
|
+
if (gssp.test(code)) {
|
|
257
|
+
const serverPropLines = [];
|
|
258
|
+
for (let i = 0; i < lines.length; i++) {
|
|
259
|
+
if (gssp.test(lines[i])) {
|
|
260
|
+
const fnBody = lines.slice(i, Math.min(lines.length, i + 30)).join("\n");
|
|
261
|
+
// Checks if secrets/env vars are returned in props without filtering
|
|
262
|
+
if (/process\.env\.\w+/.test(fnBody) && /return\s*\{[^}]*props\s*:/i.test(fnBody)) {
|
|
263
|
+
const propReturn = fnBody.match(/props\s*:\s*\{([^}]*)\}/);
|
|
264
|
+
if (propReturn && /process\.env|secret|key|token|password|api_key/i.test(propReturn[1])) {
|
|
265
|
+
serverPropLines.push(i + 1);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
if (serverPropLines.length > 0) {
|
|
271
|
+
findings.push({
|
|
272
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
273
|
+
severity: "critical",
|
|
274
|
+
title: "Next.js getServerSideProps leaks secrets to client props",
|
|
275
|
+
description: "Server-side environment variables or secrets are passed directly in getServerSideProps/getStaticProps return props. These values are serialized into the page HTML and visible to anyone.",
|
|
276
|
+
lineNumbers: serverPropLines,
|
|
277
|
+
recommendation: "Never pass secrets, API keys, or sensitive env vars in props. Use them server-side only and return sanitized results.",
|
|
278
|
+
reference: "Next.js Data Fetching — https://nextjs.org/docs/basic-features/data-fetching",
|
|
279
|
+
suggestedFix: "Use secrets server-side only: const data = await fetch(url, { headers: { Authorization: process.env.API_KEY } }); return { props: { data } };",
|
|
280
|
+
confidence: 0.9,
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
// Next.js API routes without authentication checks
|
|
285
|
+
const nextApiRoutePattern = /export\s+(?:default\s+)?(?:async\s+)?function\s+handler|export\s+(?:default\s+)?(?:async\s+)?\(\s*req\s*(?::\s*\w+)?\s*,\s*res\s*(?::\s*\w+)?\s*\)/;
|
|
286
|
+
const isNextApiRoute = /pages\/api\/|app\/api\//i.test(language) ||
|
|
287
|
+
(nextApiRoutePattern.test(code) && /NextApiRequest|NextRequest/i.test(code));
|
|
288
|
+
if (isNextApiRoute) {
|
|
289
|
+
const hasAuthCheck = /getSession|getServerSession|getToken|auth\(\)|withAuth|requireAuth|session\?\.user|req\.headers\.authorization|Bearer/i.test(code);
|
|
290
|
+
if (!hasAuthCheck) {
|
|
291
|
+
const handlerLine = lines.findIndex((l) => nextApiRoutePattern.test(l));
|
|
292
|
+
findings.push({
|
|
293
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
294
|
+
severity: "high",
|
|
295
|
+
title: "Next.js API route without authentication check",
|
|
296
|
+
description: "API route handler does not check for user session, auth token, or authorization. This endpoint is publicly accessible to anyone who knows the URL.",
|
|
297
|
+
lineNumbers: [Math.max(1, handlerLine + 1)],
|
|
298
|
+
recommendation: "Add authentication: const session = await getServerSession(req, res, authOptions); if (!session) return res.status(401).json({ error: 'Unauthorized' });",
|
|
299
|
+
reference: "Next.js API Routes Auth — https://nextjs.org/docs/authentication",
|
|
300
|
+
suggestedFix: "Add auth guard: if (!req.headers.authorization) return res.status(401).json({ error: 'Unauthorized' });",
|
|
301
|
+
confidence: 0.8,
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
// ── Angular Security ──────────────────────────────────────────────────────
|
|
306
|
+
// bypassSecurityTrustHtml/Url/ResourceUrl/Style/Script
|
|
307
|
+
const bypassLines = getLineNumbers(code, /bypassSecurityTrust(?:Html|Url|ResourceUrl|Style|Script)\s*\(/gi);
|
|
308
|
+
if (bypassLines.length > 0) {
|
|
309
|
+
findings.push({
|
|
310
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
311
|
+
severity: "critical",
|
|
312
|
+
title: "Angular DomSanitizer bypass — XSS risk",
|
|
313
|
+
description: "bypassSecurityTrustHtml/Url/Script explicitly disables Angular's built-in XSS protection. If the input contains user-controlled data, this creates a direct XSS vulnerability.",
|
|
314
|
+
lineNumbers: bypassLines,
|
|
315
|
+
recommendation: "Avoid bypassing the sanitizer. If you must render dynamic HTML, sanitize it first with DOMPurify or validate against a strict whitelist. Document why the bypass is necessary.",
|
|
316
|
+
reference: "Angular Security — https://angular.io/guide/security",
|
|
317
|
+
suggestedFix: "Use DOMPurify before bypass: this.sanitizer.bypassSecurityTrustHtml(DOMPurify.sanitize(userHtml));",
|
|
318
|
+
confidence: 0.95,
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
// ── Vue Security ──────────────────────────────────────────────────────────
|
|
322
|
+
// v-html with dynamic data
|
|
323
|
+
const vHtmlLines = getLineNumbers(code, /v-html\s*=\s*["'](?!\s*$)/gi);
|
|
324
|
+
if (vHtmlLines.length > 0) {
|
|
325
|
+
const hasVueSanitize = /DOMPurify|sanitize|xss|purify/i.test(code);
|
|
326
|
+
if (!hasVueSanitize) {
|
|
327
|
+
findings.push({
|
|
328
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
329
|
+
severity: "high",
|
|
330
|
+
title: "Vue v-html without sanitization — XSS vulnerability",
|
|
331
|
+
description: "v-html renders raw HTML content. If the data source includes user input, this is a direct XSS vector. Unlike interpolation ({{ }}), v-html does not escape content.",
|
|
332
|
+
lineNumbers: vHtmlLines,
|
|
333
|
+
recommendation: "Sanitize with DOMPurify before using v-html, or use text interpolation {{ }} wherever possible. Consider vue-sanitize or vue-dompurify-html.",
|
|
334
|
+
reference: "Vue Security — https://vuejs.org/guide/best-practices/security.html",
|
|
335
|
+
suggestedFix: 'Sanitize: computed: { safeHtml() { return DOMPurify.sanitize(this.rawHtml); } } and use v-html="safeHtml".',
|
|
336
|
+
confidence: 0.85,
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
// ── General Framework Patterns ────────────────────────────────────────────
|
|
341
|
+
// Inline arrow functions in JSX event handlers (re-render performance)
|
|
342
|
+
const inlineHandlerLines = [];
|
|
343
|
+
for (let i = 0; i < lines.length; i++) {
|
|
344
|
+
if (/\bon\w+=\{(?:\(\)\s*=>|\(\w+\)\s*=>|function\s*\()/.test(lines[i])) {
|
|
345
|
+
inlineHandlerLines.push(i + 1);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
if (inlineHandlerLines.length > 3) {
|
|
349
|
+
findings.push({
|
|
350
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
351
|
+
severity: "low",
|
|
352
|
+
title: "Excessive inline arrow functions in JSX event handlers",
|
|
353
|
+
description: `${inlineHandlerLines.length} inline arrow functions in JSX event handlers detected. Each creates a new function on every render, preventing React.memo optimizations on child components.`,
|
|
354
|
+
lineNumbers: inlineHandlerLines.slice(0, 5),
|
|
355
|
+
recommendation: "Extract handlers using useCallback or define methods outside JSX: const handleClick = useCallback(() => { ... }, [deps]);",
|
|
356
|
+
reference: "React Performance — https://react.dev/reference/react/useCallback",
|
|
357
|
+
confidence: 0.75,
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
// React key prop using array index in dynamic lists
|
|
361
|
+
const keyIndexLines = [];
|
|
362
|
+
for (let i = 0; i < lines.length; i++) {
|
|
363
|
+
if (/key\s*=\s*\{\s*(?:index|i|idx|key)\s*\}/.test(lines[i]) &&
|
|
364
|
+
/\.map\s*\(/.test(lines[Math.max(0, i - 5)] + lines.slice(Math.max(0, i - 5), i).join(" "))) {
|
|
365
|
+
keyIndexLines.push(i + 1);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
if (keyIndexLines.length > 0) {
|
|
369
|
+
findings.push({
|
|
370
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
371
|
+
severity: "medium",
|
|
372
|
+
title: "React key prop using array index — may cause render bugs",
|
|
373
|
+
description: "Using array index as React key causes issues when items are reordered, added, or removed. React associates state with wrong components, leading to subtle UI bugs.",
|
|
374
|
+
lineNumbers: keyIndexLines,
|
|
375
|
+
recommendation: "Use a stable unique identifier as key: key={item.id} instead of key={index}. If items have no natural id, generate one during data creation.",
|
|
376
|
+
reference: "React Keys — https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key",
|
|
377
|
+
confidence: 0.8,
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
// React state mutation instead of immutable update
|
|
381
|
+
const stateMutationLines = [];
|
|
382
|
+
for (let i = 0; i < lines.length; i++) {
|
|
383
|
+
const line = lines[i];
|
|
384
|
+
// Detect patterns like: state.items.push(...), state.count++, state.obj.field = ...
|
|
385
|
+
if (/\bstate\.\w+\.(?:push|pop|shift|unshift|splice|sort|reverse)\s*\(/.test(line) ||
|
|
386
|
+
/\bstate\.\w+\s*(?:\+\+|--)/.test(line) ||
|
|
387
|
+
/\bstate\.\w+\.\w+\s*=\s*/.test(line)) {
|
|
388
|
+
stateMutationLines.push(i + 1);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
if (stateMutationLines.length > 0) {
|
|
392
|
+
findings.push({
|
|
393
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
394
|
+
severity: "high",
|
|
395
|
+
title: "Direct state mutation instead of immutable update",
|
|
396
|
+
description: "State object is mutated directly (push, splice, assignment). React/Redux won't detect the change, causing stale renders and bugs. State updates must be immutable.",
|
|
397
|
+
lineNumbers: stateMutationLines,
|
|
398
|
+
recommendation: "Use immutable patterns: setState(prev => ({ ...prev, items: [...prev.items, newItem] })) or use immer/structuredClone for complex updates.",
|
|
399
|
+
reference: "React Updating State — https://react.dev/learn/updating-objects-in-state",
|
|
400
|
+
suggestedFix: "Replace state.items.push(x) with setItems(prev => [...prev, x]); or use immer: produce(state, draft => { draft.items.push(x); });",
|
|
401
|
+
confidence: 0.85,
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
// dangerouslySetInnerHTML without sanitization
|
|
405
|
+
const dangerousHtmlLines = getLineNumbers(code, /dangerouslySetInnerHTML\s*=\s*\{\s*\{\s*__html\s*:/gi);
|
|
406
|
+
if (dangerousHtmlLines.length > 0) {
|
|
407
|
+
const hasSanitizer = /DOMPurify|sanitize|purify|xss|sanitizeHtml/i.test(code);
|
|
408
|
+
if (!hasSanitizer) {
|
|
409
|
+
findings.push({
|
|
410
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
411
|
+
severity: "critical",
|
|
412
|
+
title: "dangerouslySetInnerHTML without DOMPurify — XSS vulnerability",
|
|
413
|
+
description: "dangerouslySetInnerHTML injects raw HTML without any sanitization detected in scope. This is a direct XSS vector if the data includes user input.",
|
|
414
|
+
lineNumbers: dangerousHtmlLines,
|
|
415
|
+
recommendation: "Always sanitize with DOMPurify: dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(html) }}. Better yet, use a Markdown renderer or React component tree instead of raw HTML.",
|
|
416
|
+
reference: "React DOM Elements — https://react.dev/reference/react-dom/components/common#dangerously-setting-the-inner-html",
|
|
417
|
+
suggestedFix: "Add DOMPurify: dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(htmlContent) }}",
|
|
418
|
+
confidence: 0.95,
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
return findings;
|
|
423
|
+
}
|
|
424
|
+
//# sourceMappingURL=framework-safety.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"framework-safety.js","sourceRoot":"","sources":["../../src/evaluators/framework-safety.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,24 @@
|
|
|
1
|
-
import { JudgeDefinition, JudgeEvaluation, TribunalVerdict, ProjectVerdict, DiffVerdict,
|
|
1
|
+
import type { JudgeDefinition, JudgeEvaluation, TribunalVerdict, ProjectVerdict, DiffVerdict, Finding, MustFixGateOptions, JudgesConfig } from "../types.js";
|
|
2
|
+
import type { CodeStructure } from "../ast/types.js";
|
|
3
|
+
import type { TaintFlow } from "../ast/taint-tracker.js";
|
|
2
4
|
import { formatVerdictAsMarkdown, formatEvaluationAsMarkdown } from "./shared.js";
|
|
3
5
|
export interface EvaluationOptions {
|
|
4
6
|
includeAstFindings?: boolean;
|
|
5
7
|
minConfidence?: number;
|
|
6
8
|
mustFixGate?: MustFixGateOptions;
|
|
9
|
+
/** Optional file path — used for file-type gating to suppress absence-based rules on non-server files */
|
|
10
|
+
filePath?: string;
|
|
11
|
+
/** Optional config for rule/judge/severity filtering (.judgesrc) */
|
|
12
|
+
config?: JudgesConfig;
|
|
13
|
+
/** @internal — pre-computed AST structure for the file (set by evaluateWithTribunal) */
|
|
14
|
+
_astCache?: CodeStructure;
|
|
15
|
+
/** @internal — pre-computed taint flows for the file (set by evaluateWithTribunal) */
|
|
16
|
+
_taintFlows?: TaintFlow[];
|
|
7
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* Filter findings based on inline suppression comments in the source code.
|
|
20
|
+
*/
|
|
21
|
+
export declare function applyInlineSuppressions(findings: Finding[], code: string): Finding[];
|
|
8
22
|
/**
|
|
9
23
|
* Run a single judge against the provided code.
|
|
10
24
|
*/
|
|
@@ -13,10 +27,6 @@ export declare function evaluateWithJudge(judge: JudgeDefinition, code: string,
|
|
|
13
27
|
* Run the full tribunal — all judges evaluate the code.
|
|
14
28
|
*/
|
|
15
29
|
export declare function evaluateWithTribunal(code: string, language: string, context?: string, options?: EvaluationOptions): TribunalVerdict;
|
|
16
|
-
/**
|
|
17
|
-
* Evaluate multiple files as a project. Runs the full tribunal on each file,
|
|
18
|
-
* then detects cross-file architectural issues.
|
|
19
|
-
*/
|
|
20
30
|
export declare function evaluateProject(files: Array<{
|
|
21
31
|
path: string;
|
|
22
32
|
content: string;
|
|
@@ -27,24 +37,10 @@ export declare function evaluateProject(files: Array<{
|
|
|
27
37
|
* new code but filters findings to only those affecting changed line ranges.
|
|
28
38
|
*/
|
|
29
39
|
export declare function evaluateDiff(code: string, language: string, changedLines: number[], context?: string, options?: EvaluationOptions): DiffVerdict;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
export declare function analyzeDependencies(manifest: string, manifestType: string): DependencyVerdict;
|
|
34
|
-
export declare function runAppBuilderWorkflow(params: {
|
|
35
|
-
code?: string;
|
|
36
|
-
language?: string;
|
|
37
|
-
files?: Array<{
|
|
38
|
-
path: string;
|
|
39
|
-
content: string;
|
|
40
|
-
language: string;
|
|
41
|
-
}>;
|
|
42
|
-
changedLines?: number[];
|
|
43
|
-
context?: string;
|
|
44
|
-
includeAstFindings?: boolean;
|
|
45
|
-
minConfidence?: number;
|
|
46
|
-
maxFindings?: number;
|
|
47
|
-
maxTasks?: number;
|
|
48
|
-
}): AppBuilderWorkflowResult;
|
|
40
|
+
export { analyzeDependencies } from "./dependencies.js";
|
|
41
|
+
import { runAppBuilderWorkflow as _runAppBuilderWorkflow } from "./app-builder.js";
|
|
42
|
+
export declare function runAppBuilderWorkflow(params: Parameters<typeof _runAppBuilderWorkflow>[1]): ReturnType<typeof _runAppBuilderWorkflow>;
|
|
49
43
|
export { formatVerdictAsMarkdown, formatEvaluationAsMarkdown };
|
|
44
|
+
export { enrichWithPatches } from "../patches/index.js";
|
|
45
|
+
export { crossEvaluatorDedup } from "../dedup.js";
|
|
50
46
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/evaluators/index.ts"],"names":[],"mappings":"AAIA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/evaluators/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,eAAe,EACf,eAAe,EACf,eAAe,EACf,cAAc,EACd,WAAW,EACX,OAAO,EAEP,kBAAkB,EAElB,YAAY,EACb,MAAM,aAAa,CAAC;AAIrB,OAAO,KAAK,EAAE,aAAa,EAAgB,MAAM,iBAAiB,CAAC;AACnE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAGzD,OAAO,EAKL,uBAAuB,EACvB,0BAA0B,EAI3B,MAAM,aAAa,CAAC;AAqBrB,MAAM,WAAW,iBAAiB;IAChC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,yGAAyG;IACzG,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oEAAoE;IACpE,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,wFAAwF;IACxF,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B,sFAAsF;IACtF,WAAW,CAAC,EAAE,SAAS,EAAE,CAAC;CAC3B;AAoOD;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,EAAE,CAwCpF;AAcD;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,eAAe,EACtB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,eAAe,CAwCjB;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,eAAe,CA8CjB;AAMD,wBAAgB,eAAe,CAC7B,KAAK,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,EACjE,OAAO,CAAC,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,cAAc,CAGhB;AAID;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,EAAE,EACtB,OAAO,CAAC,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,WAAW,CAqBb;AAGD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAIxD,OAAO,EAAE,qBAAqB,IAAI,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAKnF,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAC,CAAC,CAAC,GACnD,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAE3C;AAID,OAAO,EAAE,uBAAuB,EAAE,0BAA0B,EAAE,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC"}
|