circle-ir 3.193.0 → 3.195.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/configs/README.md +39 -0
- package/dist/analysis/config-loader.d.ts.map +1 -1
- package/dist/analysis/config-loader.js +43 -3
- package/dist/analysis/config-loader.js.map +1 -1
- package/dist/analysis/passes/language-sources-pass.d.ts.map +1 -1
- package/dist/analysis/passes/language-sources-pass.js +101 -0
- package/dist/analysis/passes/language-sources-pass.js.map +1 -1
- package/dist/analysis/passes/prompt-injection-safety-gate-pass.d.ts +75 -0
- package/dist/analysis/passes/prompt-injection-safety-gate-pass.d.ts.map +1 -0
- package/dist/analysis/passes/prompt-injection-safety-gate-pass.js +353 -0
- package/dist/analysis/passes/prompt-injection-safety-gate-pass.js.map +1 -0
- package/dist/analysis/passes/speculative-prompt-param-source-pass.d.ts +67 -0
- package/dist/analysis/passes/speculative-prompt-param-source-pass.d.ts.map +1 -0
- package/dist/analysis/passes/speculative-prompt-param-source-pass.js +193 -0
- package/dist/analysis/passes/speculative-prompt-param-source-pass.js.map +1 -0
- package/dist/analysis/taint-matcher.d.ts.map +1 -1
- package/dist/analysis/taint-matcher.js +24 -8
- package/dist/analysis/taint-matcher.js.map +1 -1
- package/dist/analyzer.d.ts +19 -0
- package/dist/analyzer.d.ts.map +1 -1
- package/dist/analyzer.js +30 -0
- package/dist/analyzer.js.map +1 -1
- package/dist/browser/circle-ir.js +587 -597
- package/dist/core/circle-ir-core.cjs +90 -15
- package/dist/core/circle-ir-core.js +90 -15
- package/dist/core/extractors/dfg.js +46 -2
- package/dist/core/extractors/dfg.js.map +1 -1
- package/dist/languages/plugins/bash.d.ts.map +1 -1
- package/dist/languages/plugins/bash.js +12 -16
- package/dist/languages/plugins/bash.js.map +1 -1
- package/dist/languages/plugins/go.d.ts +4 -0
- package/dist/languages/plugins/go.d.ts.map +1 -1
- package/dist/languages/plugins/go.js +16 -32
- package/dist/languages/plugins/go.js.map +1 -1
- package/dist/languages/plugins/java.d.ts +9 -1
- package/dist/languages/plugins/java.d.ts.map +1 -1
- package/dist/languages/plugins/java.js +16 -127
- package/dist/languages/plugins/java.js.map +1 -1
- package/dist/languages/plugins/javascript.d.ts +7 -0
- package/dist/languages/plugins/javascript.d.ts.map +1 -1
- package/dist/languages/plugins/javascript.js +10 -117
- package/dist/languages/plugins/javascript.js.map +1 -1
- package/dist/languages/plugins/python.d.ts +7 -0
- package/dist/languages/plugins/python.d.ts.map +1 -1
- package/dist/languages/plugins/python.js +24 -177
- package/dist/languages/plugins/python.js.map +1 -1
- package/dist/languages/plugins/rust.d.ts +9 -0
- package/dist/languages/plugins/rust.d.ts.map +1 -1
- package/dist/languages/plugins/rust.js +22 -110
- package/dist/languages/plugins/rust.js.map +1 -1
- package/dist/types/config.d.ts +15 -0
- package/dist/types/config.d.ts.map +1 -1
- package/package.json +3 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"language-sources-pass.d.ts","sourceRoot":"","sources":["../../../src/analysis/passes/language-sources-pass.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,cAAc,EAAwB,WAAW,EAAO,MAAM,sBAAsB,CAAC;AAC3H,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAqB9E,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;IA4E/B,CAAC;AAwDF,MAAM,WAAW,qBAAqB;IACpC,iBAAiB,EAAE,WAAW,EAAE,CAAC;IACjC,eAAe,EAAE,SAAS,EAAE,CAAC;IAC7B;;;;OAIG;IACH,oBAAoB,EAAE,cAAc,EAAE,CAAC;IACvC;;;OAGG;IACH,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC;;;OAGG;IACH,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC7B;;;OAGG;IACH,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACpC;AAMD,qBAAa,mBAAoB,YAAW,YAAY,CAAC,qBAAqB,CAAC;IAC7E,QAAQ,CAAC,IAAI,sBAAsB;IACnC,QAAQ,CAAC,QAAQ,EAAG,UAAU,CAAU;IAExC,GAAG,CAAC,GAAG,EAAE,WAAW,GAAG,qBAAqB;
|
|
1
|
+
{"version":3,"file":"language-sources-pass.d.ts","sourceRoot":"","sources":["../../../src/analysis/passes/language-sources-pass.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,cAAc,EAAwB,WAAW,EAAO,MAAM,sBAAsB,CAAC;AAC3H,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAqB9E,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;IA4E/B,CAAC;AAwDF,MAAM,WAAW,qBAAqB;IACpC,iBAAiB,EAAE,WAAW,EAAE,CAAC;IACjC,eAAe,EAAE,SAAS,EAAE,CAAC;IAC7B;;;;OAIG;IACH,oBAAoB,EAAE,cAAc,EAAE,CAAC;IACvC;;;OAGG;IACH,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC;;;OAGG;IACH,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC7B;;;OAGG;IACH,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACpC;AAMD,qBAAa,mBAAoB,YAAW,YAAY,CAAC,qBAAqB,CAAC;IAC7E,QAAQ,CAAC,IAAI,sBAAsB;IACnC,QAAQ,CAAC,QAAQ,EAAG,UAAU,CAAU;IAExC,GAAG,CAAC,GAAG,EAAE,WAAW,GAAG,qBAAqB;CAse7C;AAioBD,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAkG9E;AAED,wBAAgB,wBAAwB,CAAC,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,CAwC5G;AAED,wBAAgB,iCAAiC,CAC/C,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,KAAK,CAAC;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAoBjD;AAgMD,wBAAgB,0BAA0B,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CA8BpG;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,GACpB,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAmCrB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,GACpB,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAuDrB;AAsTD,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,WAAW,EAAE,CAsKvF;AAo2ED,wBAAgB,sCAAsC,CACpD,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,GACf,WAAW,EAAE,CAcf;AAoLD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,WAAW,EAAE,CA+HnF;AAMD;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,WAAW,EAAE,CA2BjF;AAOD;;;;;GAKG;AACH,wBAAgB,mCAAmC,CACjD,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,WAAW,EAAE,CAgCf;AAED;;;;;;GAMG;AACH,wBAAgB,8BAA8B,CAC5C,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,WAAW,EAAE,CA2Bf;AAED;;;;;GAKG;AACH,wBAAgB,iCAAiC,CAC/C,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,WAAW,EAAE,CA0Bf;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,WAAW,EAAE,CAoCf;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,WAAW,EAAE,CAwEf;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,WAAW,EAAE,CAgDf;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,WAAW,EAAE,CA6Bf;AASD;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,WAAW,EAAE,CA+C3E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iCAAiC,CAC/C,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,WAAW,EAAE,CAoFf;AAED;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,WAAW,EAAE,CA0Gf;AAED;;;;GAIG;AACH,wBAAgB,8BAA8B,CAC5C,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,WAAW,EAAE,CAoDf;AAED;;;;;;;;GAQG;AACH,wBAAgB,sCAAsC,CACpD,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,WAAW,EAAE,CAiGf;AAED;;;;;;;;GAQG;AACH,wBAAgB,gCAAgC,CAC9C,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,WAAW,EAAE,CAqDf;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,wCAAwC,CACtD,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,WAAW,EAAE,CA0Df;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,8CAA8C,CAC5D,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,WAAW,EAAE,CA4Df;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,6CAA6C,CAC3D,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,WAAW,EAAE,CAmFf;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,WAAW,EAAE,CAwKf;AAaD;;;;;;;GAOG;AACH,wBAAgB,qCAAqC,CACnD,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,WAAW,EAAE,CA2Gf;AAED;;;;;;;;GAQG;AACH,wBAAgB,uCAAuC,CACrD,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,WAAW,EAAE,CAqHf;AAED;;;;;;;GAOG;AACH,wBAAgB,qDAAqD,CACnE,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,WAAW,EAAE,CAuGf;AAED;;;;;;;;;GASG;AACH,wBAAgB,sCAAsC,CACpD,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,WAAW,EAAE,CAkKf;AAED;;;;;;;;;GASG;AACH,wBAAgB,iCAAiC,CAC/C,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,WAAW,EAAE,CAiHf;AAED;;;;;;;GAOG;AACH,wBAAgB,mCAAmC,CACjD,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,WAAW,EAAE,CA+Ef;AAED;;;;;;GAMG;AACH,wBAAgB,gDAAgD,CAC9D,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,WAAW,EAAE,CAyEf;AAwCD;;;;;;;;;GASG;AACH,wBAAgB,iCAAiC,CAC/C,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,WAAW,EAAE,CAmGf;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,qCAAqC,CACnD,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,WAAW,EAAE,CAsHf;AAED;;;;;GAKG;AACH,wBAAgB,oCAAoC,CAClD,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,WAAW,EAAE,CAoEf;AAED;;;;GAIG;AACH,wBAAgB,qCAAqC,CACnD,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,WAAW,EAAE,CA8Ff;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,WAAW,EAAE,CAgGf;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,WAAW,EAAE,CA2If;AAED;;;;;;;;;GASG;AACH,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,WAAW,EAAE,CA+Kf;AAED;;;;;;;;GAQG;AACH,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,WAAW,EAAE,CA2Jf;AAED;;;;;;;;;GASG;AACH,wBAAgB,gCAAgC,CAC9C,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,WAAW,EAAE,CAwFf;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,WAAW,EAAE,CA2Ef;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,+BAA+B,CAC7C,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,WAAW,EAAE,CAyEf;AAED;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,WAAW,EAAE,CAsDf;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mCAAmC,CACjD,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,WAAW,EAAE,CA6Ef;AAED;;;;;;;GAOG;AACH,wBAAgB,mCAAmC,CACjD,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,WAAW,EAAE,CAiFf"}
|
|
@@ -312,6 +312,7 @@ export class LanguageSourcesPass {
|
|
|
312
312
|
// recognition.
|
|
313
313
|
additionalSanitizers.push(...findPythonRegexAllowlistWrapperSanitizers(code));
|
|
314
314
|
additionalSanitizers.push(...findPythonSetMembershipXssGuardSanitizers(code));
|
|
315
|
+
additionalSanitizers.push(...findPythonTraversalRejectGuardSanitizers(code));
|
|
315
316
|
additionalSanitizers.push(...findPythonDefusedXmlSanitizers(code));
|
|
316
317
|
// Sprint 77a (#216 Pattern X): Jinja2 Environment(autoescape=...) +
|
|
317
318
|
// .render(...) sanitizer.
|
|
@@ -2954,6 +2955,106 @@ function findPythonSetMembershipXssGuardSanitizers(code) {
|
|
|
2954
2955
|
}
|
|
2955
2956
|
return sanitizers;
|
|
2956
2957
|
}
|
|
2958
|
+
/**
|
|
2959
|
+
* Detect the Python "reject-then-return" traversal guard (cognium-dev #4
|
|
2960
|
+
* residual-FP audit):
|
|
2961
|
+
*
|
|
2962
|
+
* if '../' in name:
|
|
2963
|
+
* return "File name must not include '../'"
|
|
2964
|
+
* path = f'{BASE_DIR}/{name}'
|
|
2965
|
+
* fd = open(path, 'rb')
|
|
2966
|
+
*
|
|
2967
|
+
* A guard that rejects the traversal token and leaves the function cannot be
|
|
2968
|
+
* followed by a traversal payload in that variable, so downstream `open()` /
|
|
2969
|
+
* `os.path.join()` uses of it are not CWE-22. This is the single largest FP
|
|
2970
|
+
* shape on OWASP BenchmarkPython (18 of 72 flow-level FPs, all pathtraver).
|
|
2971
|
+
*
|
|
2972
|
+
* Deliberately narrow, because an over-broad rule here erases real findings:
|
|
2973
|
+
* - only the *reject* polarity (`if '<..>' in v:` + terminator). The inverse
|
|
2974
|
+
* (`if '..' not in v:`) puts the safe path inside the block, which this
|
|
2975
|
+
* line-keyed emission cannot express.
|
|
2976
|
+
* - only `path_traversal` is sanitized. The guard says nothing about the
|
|
2977
|
+
* value reaching a shell, a query, or a template.
|
|
2978
|
+
* - the token must be a traversal token (`..`, `../`, `..\\`). A guard on
|
|
2979
|
+
* some other substring is a different check with different guarantees.
|
|
2980
|
+
*
|
|
2981
|
+
* Known gap (accepted): a guard on the decoded string does not stop an
|
|
2982
|
+
* encoded payload (`..%2f`) if decoding happens *after* the check. The
|
|
2983
|
+
* benchmark shape decodes first, and the alternative — never crediting the
|
|
2984
|
+
* guard — is the status quo that produces the FPs.
|
|
2985
|
+
*/
|
|
2986
|
+
function findPythonTraversalRejectGuardSanitizers(code) {
|
|
2987
|
+
const sanitizers = [];
|
|
2988
|
+
const lines = code.split('\n');
|
|
2989
|
+
// `if '../' in <ident>:` — quote style, and the `..` / `../` / `..\` token.
|
|
2990
|
+
const guardOpen = /^(\s*)if\s+(['"])(\.\.[/\\]?)\2\s+in\s+([A-Za-z_][A-Za-z0-9_]*)\s*:\s*$/;
|
|
2991
|
+
const terminator = /\b(return|raise|abort\s*\(|sys\.exit\s*\()/;
|
|
2992
|
+
for (let i = 0; i < lines.length; i++) {
|
|
2993
|
+
const m = guardOpen.exec(lines[i]);
|
|
2994
|
+
if (!m)
|
|
2995
|
+
continue;
|
|
2996
|
+
const guardIndent = m[1].length;
|
|
2997
|
+
const guardedVar = m[4];
|
|
2998
|
+
// Walk the guard body: it must leave the function on this path.
|
|
2999
|
+
let bodyHasTerminator = false;
|
|
3000
|
+
let blockEnd = -1;
|
|
3001
|
+
const maxScan = Math.min(lines.length, i + 26);
|
|
3002
|
+
for (let j = i + 1; j < maxScan; j++) {
|
|
3003
|
+
const line = lines[j];
|
|
3004
|
+
if (line.trim() === '')
|
|
3005
|
+
continue;
|
|
3006
|
+
const indent = line.length - line.trimStart().length;
|
|
3007
|
+
if (indent <= guardIndent) {
|
|
3008
|
+
blockEnd = j - 1;
|
|
3009
|
+
break;
|
|
3010
|
+
}
|
|
3011
|
+
if (terminator.test(line))
|
|
3012
|
+
bodyHasTerminator = true;
|
|
3013
|
+
}
|
|
3014
|
+
if (blockEnd === -1)
|
|
3015
|
+
blockEnd = Math.min(lines.length - 1, i + 25);
|
|
3016
|
+
if (!bodyHasTerminator)
|
|
3017
|
+
continue;
|
|
3018
|
+
// Var-aware emission from the first line after the guard block, following
|
|
3019
|
+
// one-hop derivations: `path = f'{BASE}/{name}'` makes `path` guarded too,
|
|
3020
|
+
// because the traversal token cannot be in `name`. Without this the credit
|
|
3021
|
+
// stops at the assignment line while the sink sits on the next one
|
|
3022
|
+
// (`open(path)`), which is precisely the benchmark shape.
|
|
3023
|
+
//
|
|
3024
|
+
// A later assignment that does NOT mention a guarded name clobbers it —
|
|
3025
|
+
// `path = request.args['p']` must not stay credited.
|
|
3026
|
+
const guarded = new Set([guardedVar]);
|
|
3027
|
+
const assignRe = /^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=(?!=)\s*(.*)$/;
|
|
3028
|
+
const mentionsGuarded = (text) => {
|
|
3029
|
+
for (const name of guarded) {
|
|
3030
|
+
if (new RegExp(`\\b${name}\\b`).test(text))
|
|
3031
|
+
return true;
|
|
3032
|
+
}
|
|
3033
|
+
return false;
|
|
3034
|
+
};
|
|
3035
|
+
for (let l = blockEnd + 2; l <= lines.length; l++) {
|
|
3036
|
+
const lineText = lines[l - 1];
|
|
3037
|
+
const assign = assignRe.exec(lineText);
|
|
3038
|
+
if (assign) {
|
|
3039
|
+
const target = assign[1];
|
|
3040
|
+
const rhs = assign[2];
|
|
3041
|
+
if (mentionsGuarded(rhs))
|
|
3042
|
+
guarded.add(target);
|
|
3043
|
+
else if (target !== guardedVar)
|
|
3044
|
+
guarded.delete(target);
|
|
3045
|
+
}
|
|
3046
|
+
if (!mentionsGuarded(lineText))
|
|
3047
|
+
continue;
|
|
3048
|
+
sanitizers.push({
|
|
3049
|
+
type: 'python_traversal_reject_guard',
|
|
3050
|
+
method: 'if',
|
|
3051
|
+
line: l,
|
|
3052
|
+
sanitizes: ['path_traversal'],
|
|
3053
|
+
});
|
|
3054
|
+
}
|
|
3055
|
+
}
|
|
3056
|
+
return sanitizers;
|
|
3057
|
+
}
|
|
2957
3058
|
/**
|
|
2958
3059
|
* Detect Python `defusedxml` import-alias usage as xxe sanitizer
|
|
2959
3060
|
* (cognium-dev #216 Sprint 74 Pattern B).
|