circle-ir 4.14.2 → 4.16.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.
Files changed (168) hide show
  1. package/configs/sinks/golang.json +4 -4
  2. package/dist/analysis/config-loader.d.ts.map +1 -1
  3. package/dist/analysis/config-loader.js +11 -7
  4. package/dist/analysis/config-loader.js.map +1 -1
  5. package/dist/analysis/const-table-lookup.d.ts +29 -0
  6. package/dist/analysis/const-table-lookup.d.ts.map +1 -0
  7. package/dist/analysis/const-table-lookup.js +145 -0
  8. package/dist/analysis/const-table-lookup.js.map +1 -0
  9. package/dist/analysis/constant-caller-gate.d.ts +39 -0
  10. package/dist/analysis/constant-caller-gate.d.ts.map +1 -0
  11. package/dist/analysis/constant-caller-gate.js +298 -0
  12. package/dist/analysis/constant-caller-gate.js.map +1 -0
  13. package/dist/analysis/constant-propagation/evaluator.d.ts.map +1 -1
  14. package/dist/analysis/constant-propagation/evaluator.js +3 -1
  15. package/dist/analysis/constant-propagation/evaluator.js.map +1 -1
  16. package/dist/analysis/constant-propagation/patterns.d.ts +19 -0
  17. package/dist/analysis/constant-propagation/patterns.d.ts.map +1 -1
  18. package/dist/analysis/constant-propagation/patterns.js +33 -0
  19. package/dist/analysis/constant-propagation/patterns.js.map +1 -1
  20. package/dist/analysis/constant-propagation/propagator.d.ts +59 -0
  21. package/dist/analysis/constant-propagation/propagator.d.ts.map +1 -1
  22. package/dist/analysis/constant-propagation/propagator.js +396 -49
  23. package/dist/analysis/constant-propagation/propagator.js.map +1 -1
  24. package/dist/analysis/constant-propagation/types.d.ts +9 -0
  25. package/dist/analysis/constant-propagation/types.d.ts.map +1 -1
  26. package/dist/analysis/findings.d.ts.map +1 -1
  27. package/dist/analysis/findings.js +149 -4
  28. package/dist/analysis/findings.js.map +1 -1
  29. package/dist/analysis/go-strings-replacer.d.ts +21 -0
  30. package/dist/analysis/go-strings-replacer.d.ts.map +1 -0
  31. package/dist/analysis/go-strings-replacer.js +145 -0
  32. package/dist/analysis/go-strings-replacer.js.map +1 -0
  33. package/dist/analysis/interprocedural.d.ts.map +1 -1
  34. package/dist/analysis/interprocedural.js +148 -0
  35. package/dist/analysis/interprocedural.js.map +1 -1
  36. package/dist/analysis/java-array-element-keys.d.ts +14 -0
  37. package/dist/analysis/java-array-element-keys.d.ts.map +1 -0
  38. package/dist/analysis/java-array-element-keys.js +36 -0
  39. package/dist/analysis/java-array-element-keys.js.map +1 -0
  40. package/dist/analysis/java-canonical-prefix.d.ts +42 -0
  41. package/dist/analysis/java-canonical-prefix.d.ts.map +1 -0
  42. package/dist/analysis/java-canonical-prefix.js +145 -0
  43. package/dist/analysis/java-canonical-prefix.js.map +1 -0
  44. package/dist/analysis/java-crlf-strip.d.ts +30 -0
  45. package/dist/analysis/java-crlf-strip.d.ts.map +1 -0
  46. package/dist/analysis/java-crlf-strip.js +195 -0
  47. package/dist/analysis/java-crlf-strip.js.map +1 -0
  48. package/dist/analysis/js-crlf-strip.d.ts +26 -0
  49. package/dist/analysis/js-crlf-strip.d.ts.map +1 -0
  50. package/dist/analysis/js-crlf-strip.js +244 -0
  51. package/dist/analysis/js-crlf-strip.js.map +1 -0
  52. package/dist/analysis/passes/cleartext-credential-transport-pass.d.ts +2 -0
  53. package/dist/analysis/passes/cleartext-credential-transport-pass.d.ts.map +1 -1
  54. package/dist/analysis/passes/cleartext-credential-transport-pass.js +64 -12
  55. package/dist/analysis/passes/cleartext-credential-transport-pass.js.map +1 -1
  56. package/dist/analysis/passes/cross-file-pass.d.ts.map +1 -1
  57. package/dist/analysis/passes/cross-file-pass.js +43 -0
  58. package/dist/analysis/passes/cross-file-pass.js.map +1 -1
  59. package/dist/analysis/passes/csharp-sanitizer-credit.d.ts +12 -0
  60. package/dist/analysis/passes/csharp-sanitizer-credit.d.ts.map +1 -1
  61. package/dist/analysis/passes/csharp-sanitizer-credit.js +127 -12
  62. package/dist/analysis/passes/csharp-sanitizer-credit.js.map +1 -1
  63. package/dist/analysis/passes/interprocedural-pass.d.ts +28 -0
  64. package/dist/analysis/passes/interprocedural-pass.d.ts.map +1 -1
  65. package/dist/analysis/passes/interprocedural-pass.js +20 -1
  66. package/dist/analysis/passes/interprocedural-pass.js.map +1 -1
  67. package/dist/analysis/passes/language-sources-pass.d.ts +76 -2
  68. package/dist/analysis/passes/language-sources-pass.d.ts.map +1 -1
  69. package/dist/analysis/passes/language-sources-pass.js +2045 -156
  70. package/dist/analysis/passes/language-sources-pass.js.map +1 -1
  71. package/dist/analysis/passes/param-source-flow-gate-pass.d.ts +8 -0
  72. package/dist/analysis/passes/param-source-flow-gate-pass.d.ts.map +1 -1
  73. package/dist/analysis/passes/param-source-flow-gate-pass.js +214 -6
  74. package/dist/analysis/passes/param-source-flow-gate-pass.js.map +1 -1
  75. package/dist/analysis/passes/plaintext-password-storage-pass.d.ts +6 -0
  76. package/dist/analysis/passes/plaintext-password-storage-pass.d.ts.map +1 -1
  77. package/dist/analysis/passes/plaintext-password-storage-pass.js +160 -0
  78. package/dist/analysis/passes/plaintext-password-storage-pass.js.map +1 -1
  79. package/dist/analysis/passes/scan-secrets-pass.d.ts +1 -1
  80. package/dist/analysis/passes/scan-secrets-pass.d.ts.map +1 -1
  81. package/dist/analysis/passes/scan-secrets-pass.js +7 -1
  82. package/dist/analysis/passes/scan-secrets-pass.js.map +1 -1
  83. package/dist/analysis/passes/sink-filter-pass.d.ts +1 -1
  84. package/dist/analysis/passes/sink-filter-pass.d.ts.map +1 -1
  85. package/dist/analysis/passes/sink-filter-pass.js +509 -27
  86. package/dist/analysis/passes/sink-filter-pass.js.map +1 -1
  87. package/dist/analysis/passes/taint-matcher-pass.d.ts.map +1 -1
  88. package/dist/analysis/passes/taint-matcher-pass.js +2 -2
  89. package/dist/analysis/passes/taint-matcher-pass.js.map +1 -1
  90. package/dist/analysis/passes/taint-propagation-pass.d.ts.map +1 -1
  91. package/dist/analysis/passes/taint-propagation-pass.js +1606 -60
  92. package/dist/analysis/passes/taint-propagation-pass.js.map +1 -1
  93. package/dist/analysis/passes/weak-hash-pass.d.ts +6 -0
  94. package/dist/analysis/passes/weak-hash-pass.d.ts.map +1 -1
  95. package/dist/analysis/passes/weak-hash-pass.js +191 -4
  96. package/dist/analysis/passes/weak-hash-pass.js.map +1 -1
  97. package/dist/analysis/passes/weak-random-pass.d.ts +5 -0
  98. package/dist/analysis/passes/weak-random-pass.d.ts.map +1 -1
  99. package/dist/analysis/passes/weak-random-pass.js +30 -0
  100. package/dist/analysis/passes/weak-random-pass.js.map +1 -1
  101. package/dist/analysis/project-callee-escape-gate.d.ts +40 -0
  102. package/dist/analysis/project-callee-escape-gate.d.ts.map +1 -0
  103. package/dist/analysis/project-callee-escape-gate.js +243 -0
  104. package/dist/analysis/project-callee-escape-gate.js.map +1 -0
  105. package/dist/analysis/rust-literal-guard-rebind.d.ts +34 -0
  106. package/dist/analysis/rust-literal-guard-rebind.d.ts.map +1 -0
  107. package/dist/analysis/rust-literal-guard-rebind.js +197 -0
  108. package/dist/analysis/rust-literal-guard-rebind.js.map +1 -0
  109. package/dist/analysis/rust-literal-guard.d.ts +33 -0
  110. package/dist/analysis/rust-literal-guard.d.ts.map +1 -0
  111. package/dist/analysis/rust-literal-guard.js +422 -0
  112. package/dist/analysis/rust-literal-guard.js.map +1 -0
  113. package/dist/analysis/scalar-derivation.d.ts +33 -0
  114. package/dist/analysis/scalar-derivation.d.ts.map +1 -0
  115. package/dist/analysis/scalar-derivation.js +368 -0
  116. package/dist/analysis/scalar-derivation.js.map +1 -0
  117. package/dist/analysis/taint-matcher.d.ts +2 -2
  118. package/dist/analysis/taint-matcher.d.ts.map +1 -1
  119. package/dist/analysis/taint-matcher.js +695 -34
  120. package/dist/analysis/taint-matcher.js.map +1 -1
  121. package/dist/analysis/taint-propagation.d.ts +26 -1
  122. package/dist/analysis/taint-propagation.d.ts.map +1 -1
  123. package/dist/analysis/taint-propagation.js +375 -24
  124. package/dist/analysis/taint-propagation.js.map +1 -1
  125. package/dist/analyzer.d.ts +16 -2
  126. package/dist/analyzer.d.ts.map +1 -1
  127. package/dist/analyzer.js +19 -2
  128. package/dist/analyzer.js.map +1 -1
  129. package/dist/browser/circle-ir.js +25539 -19200
  130. package/dist/core/circle-ir-core.cjs +3945 -2126
  131. package/dist/core/circle-ir-core.js +3945 -2126
  132. package/dist/core/extractors/calls.d.ts +12 -1
  133. package/dist/core/extractors/calls.d.ts.map +1 -1
  134. package/dist/core/extractors/calls.js +332 -22
  135. package/dist/core/extractors/calls.js.map +1 -1
  136. package/dist/core/extractors/dfg.js +336 -10
  137. package/dist/core/extractors/dfg.js.map +1 -1
  138. package/dist/core/extractors/types.d.ts +5 -1
  139. package/dist/core/extractors/types.d.ts.map +1 -1
  140. package/dist/core/extractors/types.js +62 -0
  141. package/dist/core/extractors/types.js.map +1 -1
  142. package/dist/graph/analysis-pass.d.ts +6 -1
  143. package/dist/graph/analysis-pass.d.ts.map +1 -1
  144. package/dist/graph/analysis-pass.js +2 -1
  145. package/dist/graph/analysis-pass.js.map +1 -1
  146. package/dist/graph/code-graph.d.ts +9 -0
  147. package/dist/graph/code-graph.d.ts.map +1 -1
  148. package/dist/graph/code-graph.js +11 -0
  149. package/dist/graph/code-graph.js.map +1 -1
  150. package/dist/navigation/navigation-index.d.ts +134 -14
  151. package/dist/navigation/navigation-index.d.ts.map +1 -1
  152. package/dist/navigation/navigation-index.js +1158 -104
  153. package/dist/navigation/navigation-index.js.map +1 -1
  154. package/dist/navigation/types.d.ts +59 -2
  155. package/dist/navigation/types.d.ts.map +1 -1
  156. package/dist/resolution/cross-file.d.ts +16 -0
  157. package/dist/resolution/cross-file.d.ts.map +1 -1
  158. package/dist/resolution/cross-file.js +110 -42
  159. package/dist/resolution/cross-file.js.map +1 -1
  160. package/dist/resolution/type-hierarchy.d.ts +3 -0
  161. package/dist/resolution/type-hierarchy.d.ts.map +1 -1
  162. package/dist/resolution/type-hierarchy.js +45 -1
  163. package/dist/resolution/type-hierarchy.js.map +1 -1
  164. package/dist/types/index.d.ts +33 -0
  165. package/dist/types/index.d.ts.map +1 -1
  166. package/dist/types/index.js.map +1 -1
  167. package/dist/wasm/web-tree-sitter.wasm +0 -0
  168. package/package.json +3 -3
@@ -27,6 +27,14 @@
27
27
  * `@router.get(...)`, `@Get()`), Rust route attributes (`#[get("/<x>")]`)
28
28
  * and Rust handlers returning a web response type (`HttpResponse`,
29
29
  * `impl Responder`, `impl warp::Reply`, ...).
30
+ * - A parameter that a real source in the same file feeds is kept
31
+ * (cognium-dev #684): `function grep(t) {…}` called as
32
+ * `grep(req.query.t)`, a class method called as `svc.run(req.body.c)`,
33
+ * a class constructed with `new C(req.query.u)`, or a function handed to
34
+ * an executor that runs it (`pool.submit(fn, q)`). A bare call never
35
+ * feeds a class method and a call through a receiver never feeds a
36
+ * module function. Arguments passed through a sanitizer do not count,
37
+ * and `external_taint_escape` stays gated.
30
38
  *
31
39
  * Only flows are gated; the source list is untouched, so passes and
32
40
  * consumers that read `taint.sources` (cross-file resolution, co-occurrence
@@ -1 +1 @@
1
- {"version":3,"file":"param-source-flow-gate-pass.d.ts","sourceRoot":"","sources":["../../../src/analysis/passes/param-source-flow-gate-pass.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAG9E,OAAO,KAAK,EAAE,UAAU,EAAiB,MAAM,sBAAsB,CAAC;AAEtE,MAAM,WAAW,yBAAyB;IACxC,8DAA8D;IAC9D,OAAO,EAAE,OAAO,CAAC;IACjB,+BAA+B;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,8CAA8C;IAC9C,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC3C;AA2CD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAOjG;AAED,qBAAa,uBAAwB,YAAW,YAAY,CAAC,yBAAyB,CAAC;IAIzE,OAAO,CAAC,QAAQ,CAAC,qBAAqB;IAHlD,QAAQ,CAAC,IAAI,4BAA4B;IACzC,QAAQ,CAAC,QAAQ,EAAG,UAAU,CAAU;IAExC,YAA6B,qBAAqB,EAAE,OAAO,EAAI;IAE/D,GAAG,CAAC,GAAG,EAAE,WAAW,GAAG,yBAAyB,CA+C/C;CACF"}
1
+ {"version":3,"file":"param-source-flow-gate-pass.d.ts","sourceRoot":"","sources":["../../../src/analysis/passes/param-source-flow-gate-pass.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAG9E,OAAO,KAAK,EAAE,UAAU,EAA8B,MAAM,sBAAsB,CAAC;AAEnF,MAAM,WAAW,yBAAyB;IACxC,8DAA8D;IAC9D,OAAO,EAAE,OAAO,CAAC;IACjB,+BAA+B;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,8CAA8C;IAC9C,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC3C;AA2ED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAQjG;AA8HD,qBAAa,uBAAwB,YAAW,YAAY,CAAC,yBAAyB,CAAC;IAIzE,OAAO,CAAC,QAAQ,CAAC,qBAAqB;IAHlD,QAAQ,CAAC,IAAI,4BAA4B;IACzC,QAAQ,CAAC,QAAQ,EAAG,UAAU,CAAU;IAExC,YAA6B,qBAAqB,EAAE,OAAO,EAAI;IAE/D,GAAG,CAAC,GAAG,EAAE,WAAW,GAAG,yBAAyB,CAwF/C;CACF"}
@@ -27,6 +27,14 @@
27
27
  * `@router.get(...)`, `@Get()`), Rust route attributes (`#[get("/<x>")]`)
28
28
  * and Rust handlers returning a web response type (`HttpResponse`,
29
29
  * `impl Responder`, `impl warp::Reply`, ...).
30
+ * - A parameter that a real source in the same file feeds is kept
31
+ * (cognium-dev #684): `function grep(t) {…}` called as
32
+ * `grep(req.query.t)`, a class method called as `svc.run(req.body.c)`,
33
+ * a class constructed with `new C(req.query.u)`, or a function handed to
34
+ * an executor that runs it (`pool.submit(fn, q)`). A bare call never
35
+ * feeds a class method and a call through a receiver never feeds a
36
+ * module function. Arguments passed through a sanitizer do not count,
37
+ * and `external_taint_escape` stays gated.
30
38
  *
31
39
  * Only flows are gated; the source list is untouched, so passes and
32
40
  * consumers that read `taint.sources` (cross-file resolution, co-occurrence
@@ -69,9 +77,48 @@ function rustAttributesAbove(lines, startLine) {
69
77
  }
70
78
  return out;
71
79
  }
80
+ /**
81
+ * Well-known framework entry-point signatures (cognium-dev #685). Bare
82
+ * handler-shaped functions are not entry points in general: only these shapes
83
+ * are, and only on the signature, never on a file or fixture name.
84
+ *
85
+ * - JS/TS AWS Lambda: a module-level `handler(event, context[, callback])`
86
+ * that the module exports (`export`, `exports.handler = handler`,
87
+ * `module.exports = { handler }`, `export { handler }`).
88
+ * - Python AWS Lambda: a module-level `lambda_handler(event, context)`.
89
+ *
90
+ * `handler(event)`, `handle(req)`, `(a, b)`, a class method, and an
91
+ * allow-listed name that the module does not export are not matched.
92
+ */
93
+ function isLambdaEntryPoint(method, language, lines) {
94
+ const names = method.parameters.map(p => p.name);
95
+ const first = lines[method.start_line - 1] ?? '';
96
+ // Module level only: a method or nested function is indented.
97
+ if (/^\s/.test(first))
98
+ return false;
99
+ if (language === 'python') {
100
+ return method.name === 'lambda_handler' && names.length === 2 && names[0] === 'event' && names[1] === 'context';
101
+ }
102
+ if (language !== 'javascript' && language !== 'typescript')
103
+ return false;
104
+ if (method.name !== 'handler')
105
+ return false;
106
+ if (names.length < 2 || names.length > 3 || names[0] !== 'event' || names[1] !== 'context')
107
+ return false;
108
+ if (names.length === 3 && names[2] !== 'callback')
109
+ return false;
110
+ if (/^export\s+(?:default\s+)?(?:async\s+)?(?:function\b|(?:const|let|var)\s+handler\b)/.test(first))
111
+ return true;
112
+ const text = lines.join('\n');
113
+ return /(?:^|[^\w$.])(?:module\s*\.\s*)?exports\s*\.\s*handler\s*=\s*handler(?![\w$])/.test(text) ||
114
+ /(?:^|[^\w$.])module\s*\.\s*exports\s*=\s*\{(?:[^}]*[,\s])?handler\s*[,}]|\bmodule\s*\.\s*exports\s*=\s*\{[^}]*\bhandler\s*:\s*handler\b/.test(text) ||
115
+ /(?:^|\n)\s*export\s*\{[^}]*\bhandler\b[^}]*\}/.test(text);
116
+ }
72
117
  export function isFrameworkHandler(method, language, lines) {
73
118
  if (method.annotations.some(a => ROUTE_ANNOTATION.test(a)))
74
119
  return true;
120
+ if (isLambdaEntryPoint(method, language, lines))
121
+ return true;
75
122
  if (language === 'rust') {
76
123
  if (rustAttributesAbove(lines, method.start_line).some(a => RUST_ROUTE_ATTR.test(a)))
77
124
  return true;
@@ -80,6 +127,121 @@ export function isFrameworkHandler(method, language, lines) {
80
127
  }
81
128
  return false;
82
129
  }
130
+ /** React function components that render `dangerouslySetInnerHTML` from a prop (cognium-dev #686). */
131
+ const REACT_COMPONENT_NAME = /^[A-Z][A-Za-z0-9]*$/;
132
+ function isReactHtmlComponent(m, f, lines) {
133
+ if (f.sink_type !== 'xss')
134
+ return false;
135
+ const sinkLine = lines[f.sink_line - 1] ?? '';
136
+ if (!sinkLine.includes('dangerouslySetInnerHTML'))
137
+ return false;
138
+ if (m.parameters.length !== 1 || !REACT_COMPONENT_NAME.test(m.name))
139
+ return false;
140
+ const sig = lines[m.start_line - 1] ?? '';
141
+ return /\bfunction\s+[A-Z][A-Za-z0-9]*\s*\(\s*\{/.test(sig);
142
+ }
143
+ /** Sources that stand for a constructor-injected field or a getter over one (#78). */
144
+ const FIELD_CARRIED_SOURCE = /constructor-injected field|returns tainted field/;
145
+ /**
146
+ * Calls that invoke a function passed to them with the arguments that follow
147
+ * it, keyed by method name. The value is how many of those arguments are not
148
+ * forwarded (`setTimeout(fn, delay, a)` passes only `a`). Executor and
149
+ * scheduler shapes only: `pool.submit(fn, q)`,
150
+ * `loop.run_in_executor(None, fn, q)`, `asyncio.to_thread(fn, q)`,
151
+ * `loop.call_soon(fn, q)`, `setImmediate(fn, q)`, `process.nextTick(fn, q)`.
152
+ */
153
+ const EXECUTOR_CALLEES = new Map([
154
+ ['submit', 0], ['run_in_executor', 0], ['to_thread', 0], ['run_sync', 0],
155
+ ['call_soon', 0], ['call_soon_threadsafe', 0], ['call_later', 0], ['call_at', 0],
156
+ ['setImmediate', 0], ['nextTick', 0], ['queueMicrotask', 0],
157
+ ['setTimeout', 1], ['setInterval', 1],
158
+ ]);
159
+ /** `name` as a whole identifier (names may contain `$`). */
160
+ function identifierRe(name) {
161
+ return new RegExp(`(?:^|[^\\w$.])${name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}(?![\\w$])`);
162
+ }
163
+ function realFedParams(ctx, sources) {
164
+ const out = { params: new Set(), classes: new Set() };
165
+ const { graph } = ctx;
166
+ const seeds = new Set();
167
+ const allMethods = graph.ir.types.flatMap(t => t.methods);
168
+ // Variables a real source binds directly (`q = request.args.get("q")`),
169
+ // with the method that binds them: a `name` bound in one handler says
170
+ // nothing about a `name` local to another function. The Python DFG does
171
+ // not model every function body, so the binding is the fallback evidence.
172
+ const boundVars = new Map();
173
+ // Source reads written inline as an argument (`sink(request.args.get("q"))`),
174
+ // by line: the read's text as the source location names it.
175
+ const inlineReads = new Map();
176
+ for (const s of sources) {
177
+ if (s.type === 'interprocedural_param')
178
+ continue;
179
+ for (const d of graph.defsAtLine(s.line))
180
+ seeds.add(d.id);
181
+ if (s.variable) {
182
+ const where = boundVars.get(s.variable) ?? new Set();
183
+ where.add(enclosingMethod(allMethods, s.line));
184
+ boundVars.set(s.variable, where);
185
+ }
186
+ const read = /^([\w$.]+?)(?:\(\))? in /.exec(s.location ?? '')?.[1];
187
+ if (read && read.includes('.'))
188
+ inlineReads.set(s.line, [...(inlineReads.get(s.line) ?? []), read]);
189
+ }
190
+ const tainted = graph.propagateTaintedDefIds(seeds);
191
+ // Sanitizer calls by line, as the bare method name (`shlex.quote()` -> `quote`).
192
+ const sanitizerNames = new Map();
193
+ if (ctx.hasResult('sink-filter')) {
194
+ for (const sa of ctx.getResult('sink-filter').sanitizers) {
195
+ const name = /([\w$]+)\(?\)?$/.exec(sa.method)?.[1];
196
+ if (name)
197
+ sanitizerNames.set(sa.line, [...(sanitizerNames.get(sa.line) ?? []), name]);
198
+ }
199
+ }
200
+ const classNames = new Set(graph.ir.types.map(t => t.name));
201
+ const functionNames = new Set(graph.ir.types.flatMap(t => t.methods.map(m => m.name)));
202
+ for (const call of graph.ir.calls) {
203
+ const line = call.location.line;
204
+ const uses = graph.usesAtLine(line).filter(u => u.def_id !== null && tainted.has(u.def_id));
205
+ const reads = inlineReads.get(line) ?? [];
206
+ const sanitizersHere = sanitizerNames.get(line) ?? [];
207
+ const callMethod = enclosingMethod(allMethods, line);
208
+ const isFed = (expr, variable) =>
209
+ // An argument passed through a sanitizer is not the raw request value.
210
+ !sanitizersHere.some(n => expr.includes(`${n}(`)) && ((!!variable && !!boundVars.get(variable)?.has(callMethod)) ||
211
+ reads.some(r => expr.includes(r)) ||
212
+ // The argument's own identifiers, not those of a sibling argument.
213
+ uses.some(u => identifierRe(u.variable).test(expr)));
214
+ // A local function handed over by reference to a call that runs it
215
+ // receives the arguments that follow it (`pool.submit(render, q)`,
216
+ // `loop.run_in_executor(None, f, q)`). Only callees known to invoke their
217
+ // function argument count: `print(banner, name)` or
218
+ // `audit.record(banner, name)` only pass `banner` along.
219
+ const skipAfterCallback = EXECUTOR_CALLEES.get(call.method_name);
220
+ let callbackName = null;
221
+ let callbackPos = -1;
222
+ for (const arg of call.arguments) {
223
+ const expr = typeof arg.expression === 'string' ? arg.expression.trim() : '';
224
+ if (skipAfterCallback !== undefined && callbackName === null && functionNames.has(expr)) {
225
+ callbackName = expr;
226
+ callbackPos = arg.position;
227
+ continue;
228
+ }
229
+ if (!isFed(expr, arg.variable))
230
+ continue;
231
+ // `res.send(req.query.m)` is a call on another object; it feeds a
232
+ // class method named `send`, never a module-level `function send`.
233
+ out.params.add(`${call.receiver ? 'm' : 'f'}:${call.method_name}:${arg.position}`);
234
+ if (classNames.has(call.method_name))
235
+ out.classes.add(call.method_name);
236
+ if (callbackName !== null) {
237
+ const pos = arg.position - callbackPos - 1 - (skipAfterCallback ?? 0);
238
+ if (pos >= 0)
239
+ out.params.add(`f:${callbackName}:${pos}`);
240
+ }
241
+ }
242
+ }
243
+ return out;
244
+ }
83
245
  export class ParamSourceFlowGatePass {
84
246
  keepParamSourcedFlows;
85
247
  name = 'param-source-flow-gate';
@@ -114,13 +276,59 @@ export class ParamSourceFlowGatePass {
114
276
  // the surviving flow may cite the parameter while the evidence is the
115
277
  // real source. Those flows are kept.
116
278
  const realSourceLines = new Set();
117
- if (ctx.hasResult('sink-filter')) {
118
- const sources = ctx.getResult('sink-filter').sources;
279
+ const sources = ctx.hasResult('sink-filter') ? ctx.getResult('sink-filter').sources : [];
280
+ for (const s of sources) {
281
+ if (s.type !== 'interprocedural_param')
282
+ realSourceLines.add(s.line);
283
+ }
284
+ // Computed on first need: most files have no parameter-only flow.
285
+ let fed;
286
+ const fedByRealSource = (f, m) => {
287
+ // The CWE-668 escape fallback names no concrete sink; a fed parameter
288
+ // does not make it more than a hint, so it stays gated.
289
+ if (f.sink_type === 'external_taint_escape')
290
+ return false;
291
+ fed ??= realFedParams(ctx, sources);
292
+ if (fed.params.size === 0)
293
+ return false;
294
+ const owner = ctx.graph.ir.types.find(t => t.methods.includes(m));
295
+ // A constructor is invoked through its class name (`new C(…)`, `C(…)`).
296
+ const isCtor = (m.name === 'constructor' || m.name === '__init__') && !!owner;
297
+ const callee = isCtor && owner ? owner.name : m.name;
298
+ // A module-level function or a constructor is called without a
299
+ // receiver; a class method is reached through one (`svc.run(x)`). Each
300
+ // matches its own call shape only: a bare `send(req.query.m)` does not
301
+ // run `Mailer.prototype.send`, and `res.send(…)` does not run a
302
+ // module-level `function send`.
303
+ const viaReceiver = !isCtor && !!owner && owner.name !== '<module>';
304
+ const feeds = (pos) => fed.params.has(`${viaReceiver ? 'm' : 'f'}:${callee}:${pos}`);
305
+ // When the flow's first step names a parameter, only that parameter
306
+ // counts: every parameter shares the signature line, and `f(a, b)`
307
+ // called as `f(req.query.a, 'x')` does not feed `b`.
308
+ const head = f.path[0]?.variable;
309
+ const named = m.parameters.findIndex(p => p.name === head);
310
+ if (named >= 0)
311
+ return feeds(named);
119
312
  for (const s of sources) {
120
- if (s.type !== 'interprocedural_param')
121
- realSourceLines.add(s.line);
313
+ if (s.line !== f.source_line || s.type !== 'interprocedural_param')
314
+ continue;
315
+ if (FIELD_CARRIED_SOURCE.test(s.location ?? '')) {
316
+ if (owner && fed.classes.has(owner.name))
317
+ return true;
318
+ continue;
319
+ }
320
+ // The source names its parameter in `variable` (Java / C#) or in its
321
+ // location, `<type> <name> in <method>` (taint-matcher).
322
+ const pos = m.parameters.findIndex(p => s.variable
323
+ ? p.name === s.variable
324
+ : (s.location ?? '').endsWith(` ${p.name} in ${m.name}`));
325
+ if (pos < 0)
326
+ continue;
327
+ if (feeds(pos))
328
+ return true;
122
329
  }
123
- }
330
+ return false;
331
+ };
124
332
  // In-place filter: `additionalFlows` is the list the analyzer assigns to
125
333
  // `taint.flows` after the pipeline.
126
334
  let w = 0;
@@ -128,7 +336,7 @@ export class ParamSourceFlowGatePass {
128
336
  let keep = true;
129
337
  if (f.source_type === 'interprocedural_param' && !realSourceLines.has(f.source_line)) {
130
338
  const m = enclosingMethod(methods, f.source_line);
131
- keep = m !== undefined && isHandler(m);
339
+ keep = m !== undefined && (isHandler(m) || fedByRealSource(f, m) || isReactHtmlComponent(m, f, lines));
132
340
  }
133
341
  if (keep)
134
342
  flows[w++] = f;
@@ -1 +1 @@
1
- {"version":3,"file":"param-source-flow-gate-pass.js","sourceRoot":"","sources":["../../../src/analysis/passes/param-source-flow-gate-pass.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"param-source-flow-gate-pass.js","sourceRoot":"","sources":["../../../src/analysis/passes/param-source-flow-gate-pass.ts"],"names":[],"mappings":"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"}
@@ -26,6 +26,12 @@
26
26
  * (see _credential-helpers `isHashFunctionCall`) and consumes the
27
27
  * credential identifier, suppress.
28
28
  *
29
+ * Python owner-only destinations (#672): a write whose file handle was obtained
30
+ * from `os.open(path, flags, <owner-only mode>)` (directly or via `os.fdopen` /
31
+ * `open(fd)`), or from a path/handle that an earlier `os.chmod` / `os.fchmod`
32
+ * restricted to the owner (no group/other bits), is not reported — the secret
33
+ * stays in a file only its owner can read.
34
+ *
29
35
  * This is intentionally lightweight (no full DFG); FP risk skewed toward
30
36
  * recall loss for cross-function hashing (controller → service.hash →
31
37
  * repo.store), which is acceptable for v1.
@@ -1 +1 @@
1
- {"version":3,"file":"plaintext-password-storage-pass.d.ts","sourceRoot":"","sources":["../../../src/analysis/passes/plaintext-password-storage-pass.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAc9E,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,EAAE,KAAK,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,GAAG,EAAE,MAAM,CAAC;QACZ,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC,CAAC;CACJ;AAsED,qBAAa,4BACX,YAAW,YAAY,CAAC,8BAA8B,CAAC;IAEvD,QAAQ,CAAC,IAAI,gCAAgC;IAC7C,QAAQ,CAAC,QAAQ,EAAG,UAAU,CAAU;IAExC,GAAG,CAAC,GAAG,EAAE,WAAW,GAAG,8BAA8B,CAiEpD;CACF"}
1
+ {"version":3,"file":"plaintext-password-storage-pass.d.ts","sourceRoot":"","sources":["../../../src/analysis/passes/plaintext-password-storage-pass.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAc9E,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,EAAE,KAAK,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,GAAG,EAAE,MAAM,CAAC;QACZ,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC,CAAC;CACJ;AAyMD,qBAAa,4BACX,YAAW,YAAY,CAAC,8BAA8B,CAAC;IAEvD,QAAQ,CAAC,IAAI,gCAAgC;IAC7C,QAAQ,CAAC,QAAQ,EAAG,UAAU,CAAU;IAExC,GAAG,CAAC,GAAG,EAAE,WAAW,GAAG,8BAA8B,CAwEpD;CACF"}
@@ -26,6 +26,12 @@
26
26
  * (see _credential-helpers `isHashFunctionCall`) and consumes the
27
27
  * credential identifier, suppress.
28
28
  *
29
+ * Python owner-only destinations (#672): a write whose file handle was obtained
30
+ * from `os.open(path, flags, <owner-only mode>)` (directly or via `os.fdopen` /
31
+ * `open(fd)`), or from a path/handle that an earlier `os.chmod` / `os.fchmod`
32
+ * restricted to the owner (no group/other bits), is not reported — the secret
33
+ * stays in a file only its owner can read.
34
+ *
29
35
  * This is intentionally lightweight (no full DFG); FP risk skewed toward
30
36
  * recall loss for cross-function hashing (controller → service.hash →
31
37
  * repo.store), which is acceptable for v1.
@@ -92,6 +98,154 @@ function isWriteStorageCall(call, language) {
92
98
  }
93
99
  return null;
94
100
  }
101
+ /** Parse a Python integer literal (`0o600`, `0600`, `384`, `0x180`) or `stat.S_I*` mask; null when unknown. */
102
+ function pyModeValue(expr) {
103
+ const t = (expr ?? '').trim();
104
+ if (!t)
105
+ return null;
106
+ if (/^0[oO][0-7]+$/.test(t))
107
+ return parseInt(t.slice(2), 8);
108
+ if (/^0[0-7]+$/.test(t))
109
+ return parseInt(t, 8);
110
+ if (/^0[xX][0-9a-fA-F]+$/.test(t))
111
+ return parseInt(t.slice(2), 16);
112
+ if (/^\d+$/.test(t))
113
+ return parseInt(t, 10);
114
+ // stat.S_IRUSR | stat.S_IWUSR — owner bits only; any group/other constant is not owner-only.
115
+ const parts = t.split('|').map((x) => x.trim().replace(/^stat\./, ''));
116
+ const USR = { S_IRUSR: 0o400, S_IWUSR: 0o200, S_IXUSR: 0o100, S_IRWXU: 0o700 };
117
+ let v = 0;
118
+ for (const p of parts) {
119
+ if (p in USR)
120
+ v |= USR[p];
121
+ else if (/^S_I(?:R|W|X|RWX)(?:GRP|OTH|G|O)$/.test(p))
122
+ v |= 0o077;
123
+ else
124
+ return null;
125
+ }
126
+ return v;
127
+ }
128
+ /** True when `mode` grants nothing to group or other (and is not empty). */
129
+ const isOwnerOnlyMode = (mode) => mode !== null && mode > 0 && (mode & 0o077) === 0;
130
+ /** The `mode` argument of an `os.open` / `os.chmod` / `os.fchmod` call, owner-only? */
131
+ function callSetsOwnerOnlyMode(call) {
132
+ const recv = call.receiver ?? '';
133
+ if (recv !== 'os')
134
+ return false;
135
+ const pos = call.method_name === 'open' ? 2 : call.method_name === 'chmod' || call.method_name === 'fchmod' ? 1 : -1;
136
+ if (pos < 0)
137
+ return false;
138
+ const arg = call.arguments.find((a) => a.position === pos);
139
+ return isOwnerOnlyMode(pyModeValue(arg?.literal ?? arg?.expression));
140
+ }
141
+ const IDENT = /^[A-Za-z_]\w*$/;
142
+ const firstArg = (c) => (c.arguments.find((a) => a.position === 0)?.expression ?? '').trim();
143
+ /**
144
+ * Python: was the file handle that `write` is called on created/opened with
145
+ * owner-only permissions? Resolved from the handle's binding line
146
+ * (`with <expr> as h`, `h = <expr>`), the calls on that line, and — for a
147
+ * descriptor — the line that bound it.
148
+ */
149
+ function pyWriteTargetsOwnerOnlyFile(call, scopeCalls, lines) {
150
+ const receiver = (call.receiver ?? '').trim();
151
+ const before = scopeCalls.filter((c) => c.location.line < call.location.line);
152
+ const callsOn = (line) => scopeCalls.filter((c) => c.location.line === line);
153
+ const bindingLine = (name, from) => {
154
+ const esc = name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
155
+ const re = new RegExp(`(?:\\bas\\s+${esc}\\b|^\\s*${esc}\\s*=(?!=))`);
156
+ // `with <expr> as name: name.write(...)` — binding and use on one line.
157
+ if (new RegExp(`\\bas\\s+${esc}\\s*:`).test(lines[from - 1] ?? ''))
158
+ return from;
159
+ for (let ln = from - 1; ln >= 1; ln--) {
160
+ if (re.test(lines[ln - 1] ?? ''))
161
+ return ln;
162
+ }
163
+ return null;
164
+ };
165
+ // Column range of the expression that initializes `name` on `line`:
166
+ // the `with` item before `as name` (items split at top-level commas), or the
167
+ // right-hand side of `name = ...`. Calls elsewhere on the line belong to
168
+ // other handles and must not be attributed to this one.
169
+ const initializerSpan = (name, line) => {
170
+ const text = lines[line - 1] ?? '';
171
+ const esc = name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
172
+ const asM = new RegExp(`\\bas\\s+${esc}\\b`).exec(text);
173
+ if (asM) {
174
+ const kw = /\bwith\b/.exec(text);
175
+ let start = kw ? kw.index + kw[0].length : 0;
176
+ let depthN = 0;
177
+ for (let i = asM.index - 1; i >= start; i--) {
178
+ const ch = text[i];
179
+ if (ch === ')' || ch === ']' || ch === '}')
180
+ depthN++;
181
+ else if (ch === '(' || ch === '[' || ch === '{') {
182
+ if (depthN === 0) {
183
+ start = i + 1;
184
+ break;
185
+ }
186
+ depthN--;
187
+ }
188
+ else if (ch === ',' && depthN === 0) {
189
+ start = i + 1;
190
+ break;
191
+ }
192
+ }
193
+ return [start, asM.index];
194
+ }
195
+ const eq = new RegExp(`^\\s*${esc}\\s*=(?!=)`).exec(text);
196
+ if (eq)
197
+ return [eq[0].length, text.length];
198
+ return [0, text.length];
199
+ };
200
+ // Does the expression evaluated on `line` (within `span`) yield an owner-only file/descriptor?
201
+ const ownerOnlyAt = (line, depth, span = [0, Infinity]) => {
202
+ const here = callsOn(line).filter((c) => c.location.column >= span[0] && c.location.column < span[1]);
203
+ if (here.some((c) => c.method_name === 'open' && callSetsOwnerOnlyMode(c)))
204
+ return true;
205
+ for (const c of here) {
206
+ // os.fdopen(fd, ...) / open(fd, ...) — follow a bare descriptor variable.
207
+ if ((c.method_name === 'fdopen' && c.receiver === 'os') || (c.method_name === 'open' && !c.receiver)) {
208
+ const a0 = firstArg(c);
209
+ if (IDENT.test(a0) && depth < 3) {
210
+ const bl = bindingLine(a0, line);
211
+ if (bl !== null && ownerOnlyAt(bl, depth + 1, initializerSpan(a0, bl)))
212
+ return true;
213
+ }
214
+ // open(path, ...) — the LAST chmod of that same path expression before
215
+ // this open decides; a later permissive chmod widens it again.
216
+ if (c.method_name === 'open' && a0) {
217
+ const chmods = before.filter((p) => p.location.line < line && p.receiver === 'os' && p.method_name === 'chmod' && firstArg(p) === a0);
218
+ const last = chmods.reduce((acc, p) => !acc || p.location.line > acc.location.line ||
219
+ (p.location.line === acc.location.line && p.location.column > acc.location.column) ? p : acc, null);
220
+ if (last && callSetsOwnerOnlyMode(last))
221
+ return true;
222
+ }
223
+ }
224
+ }
225
+ return false;
226
+ };
227
+ // Receiver is an inline expression: `os.fdopen(os.open(...), "w").write(x)`.
228
+ if (!receiver || !IDENT.test(receiver))
229
+ return ownerOnlyAt(call.location.line, 0);
230
+ // os.fchmod(<handle>.fileno() | <fd>, owner-only) before the write.
231
+ const bl = bindingLine(receiver, call.location.line);
232
+ if (before.some((c) => c.method_name === 'fchmod' && callSetsOwnerOnlyMode(c) &&
233
+ new RegExp(`\\b${receiver}\\b`).test(firstArg(c))))
234
+ return true;
235
+ if (bl === null)
236
+ return false;
237
+ // os.fchmod(fd, owner-only) on the bare descriptor this handle wraps.
238
+ const hSpan = initializerSpan(receiver, bl);
239
+ const handleCalls = callsOn(bl).filter((c) => c.location.column >= hSpan[0] && c.location.column < hSpan[1]);
240
+ for (const c of handleCalls) {
241
+ if ((c.method_name === 'fdopen' && c.receiver === 'os') || (c.method_name === 'open' && !c.receiver)) {
242
+ const a0 = firstArg(c);
243
+ if (IDENT.test(a0) && before.some((p) => p.method_name === 'fchmod' && callSetsOwnerOnlyMode(p) && firstArg(p) === a0))
244
+ return true;
245
+ }
246
+ }
247
+ return ownerOnlyAt(bl, 0, hSpan);
248
+ }
95
249
  export class PlaintextPasswordStoragePass {
96
250
  name = 'plaintext-password-storage';
97
251
  category = 'security';
@@ -99,6 +253,7 @@ export class PlaintextPasswordStoragePass {
99
253
  const { graph, language } = ctx;
100
254
  const file = graph.ir.meta.file;
101
255
  const findings = [];
256
+ const codeLines = language === 'python' ? ctx.code.split('\n') : [];
102
257
  // Group calls by in_method for cheap prior-hash lookup.
103
258
  const callsByScope = new Map();
104
259
  for (const call of graph.ir.calls) {
@@ -128,6 +283,11 @@ export class PlaintextPasswordStoragePass {
128
283
  const prior = scopeCalls.filter((c) => c.location.line < call.location.line);
129
284
  if (priorHashOf(identifier, prior))
130
285
  continue;
286
+ // Python: the write lands in a file only its owner can read (#672).
287
+ if (language === 'python' && spec.api.startsWith('<file>.') &&
288
+ pyWriteTargetsOwnerOnlyFile(call, scopeCalls, codeLines)) {
289
+ continue;
290
+ }
131
291
  // Suppress if the credArg expression itself contains a hash call
132
292
  // inline: `f.write(bcrypt.hashpw(pw))`.
133
293
  if (/\b(?:hashpw|hash|sha\d+|md5|bcrypt|argon2|pbkdf2|digest)\b/i
@@ -1 +1 @@
1
- {"version":3,"file":"plaintext-password-storage-pass.js","sourceRoot":"","sources":["../../../src/analysis/passes/plaintext-password-storage-pass.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"plaintext-password-storage-pass.js","sourceRoot":"","sources":["../../../src/analysis/passes/plaintext-password-storage-pass.ts"],"names":[],"mappings":"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"}
@@ -8,7 +8,7 @@
8
8
  *
9
9
  * 1. Provider-specific regex patterns. ~18 high-confidence prefixes /
10
10
  * shapes (AWS AKIA, GitHub `ghp_`/`gho_`/`ghs_`/`ghu_`/`ghr_`,
11
- * GitLab `glpat-`, Stripe `sk_live_`/`rk_live_`/`pk_live_`/`sk_test_`/`rk_test_`, OpenAI `sk-`,
11
+ * GitLab `glpat-`, Stripe `sk_live_`/`rk_live_`/`pk_live_`/`pk_test_`/`sk_test_`/`rk_test_`, OpenAI `sk-`,
12
12
  * Anthropic `sk-ant-`, Slack `xox[baprs]-`, Google `AIza`, JWT `eyJ..eyJ..`,
13
13
  * PEM private keys, npm `npm_`). Each match emits a finding with
14
14
  * `rule_id: 'hardcoded-credential'` (matches the legacy Bash
@@ -1 +1 @@
1
- {"version":3,"file":"scan-secrets-pass.d.ts","sourceRoot":"","sources":["../../../src/analysis/passes/scan-secrets-pass.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AA+nB9E,MAAM,WAAW,qBAAqB;IACpC,wEAAwE;IACxE,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,qBAAa,eAAgB,YAAW,YAAY,CAAC,qBAAqB,CAAC;IACzE,QAAQ,CAAC,IAAI,kBAAkB;IAC/B,QAAQ,CAAC,QAAQ,EAAG,UAAU,CAAU;IAExC,GAAG,CAAC,GAAG,EAAE,WAAW,GAAG,qBAAqB,CA+N3C;IAED,mEAAmE;IACnE,OAAO,CAAC,WAAW;IAanB;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,iBAAiB;CAO1B"}
1
+ {"version":3,"file":"scan-secrets-pass.d.ts","sourceRoot":"","sources":["../../../src/analysis/passes/scan-secrets-pass.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAqoB9E,MAAM,WAAW,qBAAqB;IACpC,wEAAwE;IACxE,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,qBAAa,eAAgB,YAAW,YAAY,CAAC,qBAAqB,CAAC;IACzE,QAAQ,CAAC,IAAI,kBAAkB;IAC/B,QAAQ,CAAC,QAAQ,EAAG,UAAU,CAAU;IAExC,GAAG,CAAC,GAAG,EAAE,WAAW,GAAG,qBAAqB,CA+N3C;IAED,mEAAmE;IACnE,OAAO,CAAC,WAAW;IAanB;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,iBAAiB;CAO1B"}
@@ -8,7 +8,7 @@
8
8
  *
9
9
  * 1. Provider-specific regex patterns. ~18 high-confidence prefixes /
10
10
  * shapes (AWS AKIA, GitHub `ghp_`/`gho_`/`ghs_`/`ghu_`/`ghr_`,
11
- * GitLab `glpat-`, Stripe `sk_live_`/`rk_live_`/`pk_live_`/`sk_test_`/`rk_test_`, OpenAI `sk-`,
11
+ * GitLab `glpat-`, Stripe `sk_live_`/`rk_live_`/`pk_live_`/`pk_test_`/`sk_test_`/`rk_test_`, OpenAI `sk-`,
12
12
  * Anthropic `sk-ant-`, Slack `xox[baprs]-`, Google `AIza`, JWT `eyJ..eyJ..`,
13
13
  * PEM private keys, npm `npm_`). Each match emits a finding with
14
14
  * `rule_id: 'hardcoded-credential'` (matches the legacy Bash
@@ -162,6 +162,12 @@ const PROVIDER_PATTERNS = [
162
162
  severity: 'low', level: 'note',
163
163
  fix: 'Publishable keys are not secret. Prefer loading them from configuration rather than a backend source file.',
164
164
  },
165
+ {
166
+ name: 'Stripe test publishable key',
167
+ regex: /\bpk_test_[A-Za-z0-9]{24,}\b/,
168
+ severity: 'low', level: 'note',
169
+ fix: 'Publishable keys are not secret. Prefer loading them from configuration rather than a backend source file.',
170
+ },
165
171
  // Test-mode secret and restricted keys still authorize the test account.
166
172
  // Same length floor as the live forms. Severity is high, not critical (#576).
167
173
  {