circle-ir 4.9.16 → 4.9.19

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 (28) hide show
  1. package/dist/analysis/findings.d.ts +2 -2
  2. package/dist/analysis/findings.d.ts.map +1 -1
  3. package/dist/analysis/findings.js +166 -6
  4. package/dist/analysis/findings.js.map +1 -1
  5. package/dist/analysis/passes/language-sources-pass.d.ts +3 -0
  6. package/dist/analysis/passes/language-sources-pass.d.ts.map +1 -1
  7. package/dist/analysis/passes/language-sources-pass.js +247 -1
  8. package/dist/analysis/passes/language-sources-pass.js.map +1 -1
  9. package/dist/analysis/passes/library-profile-sink-gate-pass.d.ts.map +1 -1
  10. package/dist/analysis/passes/library-profile-sink-gate-pass.js +48 -13
  11. package/dist/analysis/passes/library-profile-sink-gate-pass.js.map +1 -1
  12. package/dist/analysis/passes/library-profile-source-gate-pass.d.ts.map +1 -1
  13. package/dist/analysis/passes/library-profile-source-gate-pass.js +35 -10
  14. package/dist/analysis/passes/library-profile-source-gate-pass.js.map +1 -1
  15. package/dist/analysis/passes/sink-filter-pass.d.ts.map +1 -1
  16. package/dist/analysis/passes/sink-filter-pass.js +54 -0
  17. package/dist/analysis/passes/sink-filter-pass.js.map +1 -1
  18. package/dist/analysis/passes/taint-propagation-pass.d.ts.map +1 -1
  19. package/dist/analysis/passes/taint-propagation-pass.js +59 -1
  20. package/dist/analysis/passes/taint-propagation-pass.js.map +1 -1
  21. package/dist/analyzer.d.ts.map +1 -1
  22. package/dist/analyzer.js +16 -2
  23. package/dist/analyzer.js.map +1 -1
  24. package/dist/browser/circle-ir.js +245 -18
  25. package/dist/languages/plugins/go.d.ts.map +1 -1
  26. package/dist/languages/plugins/go.js +71 -0
  27. package/dist/languages/plugins/go.js.map +1 -1
  28. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"library-profile-sink-gate-pass.d.ts","sourceRoot":"","sources":["../../../src/analysis/passes/library-profile-sink-gate-pass.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqEG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAC9E,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,UAAU,EAA4B,MAAM,sBAAsB,CAAC;AAY3G,MAAM,WAAW,4BAA4B;IAC3C;;;;OAIG;IACH,OAAO,EAAE,cAAc,GAAG,SAAS,CAAC;IACpC;;;;OAIG;IACH,OAAO,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,aAAa,EAAE,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;CAClD;AAaD,qBAAa,0BACX,YAAW,YAAY,CAAC,4BAA4B,CAAC;IAErD,QAAQ,CAAC,IAAI,+BAA+B;IAC5C,QAAQ,CAAC,QAAQ,EAAG,UAAU,CAAU;IAExC,GAAG,CAAC,GAAG,EAAE,WAAW,GAAG,4BAA4B;CA0DpD;AAcD,MAAM,WAAW,iCAAiC;IAChD;;;;OAIG;IACH,OAAO,EAAE,cAAc,GAAG,SAAS,CAAC;IACpC;;;;OAIG;IACH,OAAO,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,mBAAmB,EAAE,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;CAC1D;AAED,qBAAa,+BACX,YAAW,YAAY,CAAC,iCAAiC,CAAC;IAE1D,QAAQ,CAAC,IAAI,qCAAqC;IAClD,QAAQ,CAAC,QAAQ,EAAG,UAAU,CAAU;IAExC,GAAG,CAAC,GAAG,EAAE,WAAW,GAAG,iCAAiC;CAuDzD"}
1
+ {"version":3,"file":"library-profile-sink-gate-pass.d.ts","sourceRoot":"","sources":["../../../src/analysis/passes/library-profile-sink-gate-pass.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqEG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAG9E,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,UAAU,EAA4B,MAAM,sBAAsB,CAAC;AAY3G,MAAM,WAAW,4BAA4B;IAC3C;;;;OAIG;IACH,OAAO,EAAE,cAAc,GAAG,SAAS,CAAC;IACpC;;;;OAIG;IACH,OAAO,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,aAAa,EAAE,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;CAClD;AAaD,qBAAa,0BACX,YAAW,YAAY,CAAC,4BAA4B,CAAC;IAErD,QAAQ,CAAC,IAAI,+BAA+B;IAC5C,QAAQ,CAAC,QAAQ,EAAG,UAAU,CAAU;IAExC,GAAG,CAAC,GAAG,EAAE,WAAW,GAAG,4BAA4B;CA0DpD;AAcD,MAAM,WAAW,iCAAiC;IAChD;;;;OAIG;IACH,OAAO,EAAE,cAAc,GAAG,SAAS,CAAC;IACpC;;;;OAIG;IACH,OAAO,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,mBAAmB,EAAE,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;CAC1D;AAED,qBAAa,+BACX,YAAW,YAAY,CAAC,iCAAiC,CAAC;IAE1D,QAAQ,CAAC,IAAI,qCAAqC;IAClD,QAAQ,CAAC,QAAQ,EAAG,UAAU,CAAU;IAExC,GAAG,CAAC,GAAG,EAAE,WAAW,GAAG,iCAAiC;CAwFzD"}
@@ -68,6 +68,7 @@
68
68
  * to a follow-up if the harness rerun shows material Rust
69
69
  * residuals; the Tier 2 8-repo cohort is Java-heavy.
70
70
  */
71
+ import { LIBRARY_API_SURFACE_TAG } from '../library-api-surface-downgrade.js';
71
72
  /**
72
73
  * Sink types eligible for the library-profile drop. Seeded with
73
74
  * `log_injection` (CWE-117) in 3.152.0. Extending this set is a
@@ -167,9 +168,22 @@ export class LibraryProfileCwe22PathGatePass {
167
168
  droppedBySourceType: {},
168
169
  };
169
170
  }
170
- // `TaintPropagationPass` / `InterproceduralPass` populate
171
- // `graph.ir.taint.flows`. Nothing to filter if no flow ever ran.
172
- const flows = graph.ir.taint.flows;
171
+ // cognium-dev#288 — the authoritative flow list is
172
+ // `InterproceduralPassResult.additionalFlows`, which is what the
173
+ // post-pipeline rebuild assigns to `taint.flows`. The comment here used to
174
+ // claim `TaintPropagationPass` / `InterproceduralPass` populate
175
+ // `graph.ir.taint.flows`; they do not — nothing ever assigns it, so this
176
+ // pass read `undefined` and returned early on every run.
177
+ //
178
+ // With the source gate now effective BEFORE flow generation (#288), no
179
+ // flow from a gated source should reach this point at all. That makes this
180
+ // a genuine belt-and-suspenders net rather than the primary mechanism —
181
+ // but it is wired correctly now, so if a new flow-producing path ever
182
+ // bypasses the source list it will still be caught instead of silently
183
+ // doing nothing.
184
+ const flows = ctx.hasResult('interprocedural')
185
+ ? ctx.getResult('interprocedural').additionalFlows
186
+ : graph.ir.taint.flows;
173
187
  if (!flows || flows.length === 0) {
174
188
  return {
175
189
  profile,
@@ -178,24 +192,45 @@ export class LibraryProfileCwe22PathGatePass {
178
192
  droppedBySourceType: {},
179
193
  };
180
194
  }
195
+ // cognium-dev#288 (option A) — TAG, do not delete.
196
+ //
197
+ // Previously this spliced matching flows out of the list. A flow removed
198
+ // here is unrecoverable downstream: the finding simply never exists, with
199
+ // nothing in the output to say a library-shape judgement was applied. That
200
+ // is the wrong default for the deterministic layer, whose job is to expose
201
+ // signals for adjudication (CLAUDE.md), and it is inconsistent with
202
+ // ADR-008, which keeps such findings and downgrades them.
203
+ //
204
+ // `TaintFlowInfo.tags` exists for exactly this (3.105.0): the
205
+ // `library-api-surface:caller-responsibility` tag is already understood by
206
+ // CLI/SARIF consumers as "downgrade and badge". So the flow survives,
207
+ // carrying the reason it was judged speculative.
208
+ //
209
+ // Note for whoever revisits the policy: ADR-008's
210
+ // `DOWNGRADE_ELIGIBLE_RULE_IDS` deliberately EXCLUDES `path_traversal`
211
+ // (only code_injection / template_injection / xpath_injection /
212
+ // sql_injection are eligible), on the reasoning that a library with a path
213
+ // traversal is a bug whatever its shape. So tagging a CWE-22 flow does not
214
+ // downgrade it under `applyProjectProfileTransform` today — the tag is
215
+ // carried, and the severity policy stays where ADR-008 put it. Deleting
216
+ // these flows, as this pass used to, contradicted that decision outright.
181
217
  const droppedBySourceType = {};
182
- const kept = [];
218
+ let tagged = 0;
183
219
  for (const flow of flows) {
184
220
  if (flow.sink_type === 'path_traversal' &&
185
221
  CWE22_SPECULATIVE_SOURCE_TYPES.has(flow.source_type)) {
186
222
  droppedBySourceType[flow.source_type] =
187
223
  (droppedBySourceType[flow.source_type] ?? 0) + 1;
188
- continue;
224
+ const tags = flow.tags ?? [];
225
+ if (!tags.includes(LIBRARY_API_SURFACE_TAG)) {
226
+ flow.tags = [...tags, LIBRARY_API_SURFACE_TAG];
227
+ }
228
+ tagged++;
189
229
  }
190
- kept.push(flow);
191
- }
192
- const dropped = flows.length - kept.length;
193
- // Mutate the flow array in place so downstream consumers
194
- // (`CrossFilePass`, SARIF writer) see the filtered list.
195
- if (dropped > 0) {
196
- flows.length = 0;
197
- flows.push(...kept);
198
230
  }
231
+ // `dropped` keeps its name for result-shape compatibility but now reports
232
+ // how many flows were TAGGED; none are removed.
233
+ const dropped = tagged;
199
234
  return {
200
235
  profile,
201
236
  applied: true,
@@ -1 +1 @@
1
- {"version":3,"file":"library-profile-sink-gate-pass.js","sourceRoot":"","sources":["../../../src/analysis/passes/library-profile-sink-gate-pass.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"library-profile-sink-gate-pass.js","sourceRoot":"","sources":["../../../src/analysis/passes/library-profile-sink-gate-pass.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqEG;AAIH,OAAO,EAAE,uBAAuB,EAAE,MAAM,qCAAqC,CAAC;AAI9E;;;;GAIG;AACH,MAAM,kBAAkB,GAA0B,IAAI,GAAG,CAAW;IAClE,eAAe;CAChB,CAAC,CAAC;AA2BH;;;;;GAKG;AACH,SAAS,cAAc,CAAC,OAAmC;IACzD,IAAI,CAAC,OAAO,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACpD,OAAO,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,OAAO,0BAA0B;IAG5B,IAAI,GAAG,2BAA2B,CAAC;IACnC,QAAQ,GAAG,UAAmB,CAAC;IAExC,GAAG,CAAC,GAAgB;QAClB,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,CAAC;QACtB,MAAM,OAAO,GAAG,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC;QAE7C,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,CAAC;YAC7B,OAAO;gBACL,OAAO;gBACP,OAAO,EAAE,KAAK;gBACd,OAAO,EAAE,CAAC;gBACV,aAAa,EAAE,EAAE;aAClB,CAAC;QACJ,CAAC;QAED,uDAAuD;QACvD,6DAA6D;QAC7D,8DAA8D;QAC9D,4DAA4D;QAC5D,mCAAmC;QACnC,MAAM,KAAK,GAAgB,GAAG,CAAC,SAAS,CAAC,aAAa,CAAC;YACrD,CAAC,CAAC,GAAG,CAAC,SAAS,CAAmB,aAAa,CAAC,CAAC,KAAK;YACtD,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC;QAEzB,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO;gBACL,OAAO;gBACP,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE,CAAC;gBACV,aAAa,EAAE,EAAE;aAClB,CAAC;QACJ,CAAC;QAED,MAAM,aAAa,GAAsC,EAAE,CAAC;QAC5D,MAAM,IAAI,GAAgB,EAAE,CAAC;QAC7B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBACtC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;gBAC/D,SAAS;YACX,CAAC;YACD,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAE3C,yDAAyD;QACzD,gEAAgE;QAChE,6CAA6C;QAC7C,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;YAChB,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;YACjB,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;QACtB,CAAC;QAED,OAAO;YACL,OAAO;YACP,OAAO,EAAE,IAAI;YACb,OAAO;YACP,aAAa;SACd,CAAC;IACJ,CAAC;CACF;AAED;;;;;;GAMG;AACH,MAAM,8BAA8B,GAA4B,IAAI,GAAG,CAAa;IAClF,uBAAuB;IACvB,mBAAmB;CACpB,CAAC,CAAC;AA2BH,MAAM,OAAO,+BAA+B;IAGjC,IAAI,GAAG,iCAAiC,CAAC;IACzC,QAAQ,GAAG,UAAmB,CAAC;IAExC,GAAG,CAAC,GAAgB;QAClB,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,CAAC;QACtB,MAAM,OAAO,GAAG,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC;QAE7C,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,CAAC;YAC7B,OAAO;gBACL,OAAO;gBACP,OAAO,EAAE,KAAK;gBACd,OAAO,EAAE,CAAC;gBACV,mBAAmB,EAAE,EAAE;aACxB,CAAC;QACJ,CAAC;QAED,mDAAmD;QACnD,iEAAiE;QACjE,2EAA2E;QAC3E,gEAAgE;QAChE,yEAAyE;QACzE,yDAAyD;QACzD,EAAE;QACF,uEAAuE;QACvE,2EAA2E;QAC3E,wEAAwE;QACxE,sEAAsE;QACtE,uEAAuE;QACvE,iBAAiB;QACjB,MAAM,KAAK,GAAgC,GAAG,CAAC,SAAS,CAAC,iBAAiB,CAAC;YACzE,CAAC,CAAC,GAAG,CAAC,SAAS,CAA4B,iBAAiB,CAAC,CAAC,eAAe;YAC7E,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC;QACzB,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACjC,OAAO;gBACL,OAAO;gBACP,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE,CAAC;gBACV,mBAAmB,EAAE,EAAE;aACxB,CAAC;QACJ,CAAC;QAED,mDAAmD;QACnD,EAAE;QACF,yEAAyE;QACzE,0EAA0E;QAC1E,2EAA2E;QAC3E,2EAA2E;QAC3E,oEAAoE;QACpE,0DAA0D;QAC1D,EAAE;QACF,8DAA8D;QAC9D,2EAA2E;QAC3E,sEAAsE;QACtE,iDAAiD;QACjD,EAAE;QACF,kDAAkD;QAClD,uEAAuE;QACvE,gEAAgE;QAChE,2EAA2E;QAC3E,2EAA2E;QAC3E,uEAAuE;QACvE,wEAAwE;QACxE,0EAA0E;QAC1E,MAAM,mBAAmB,GAAwC,EAAE,CAAC;QACpE,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IACE,IAAI,CAAC,SAAS,KAAK,gBAAgB;gBACnC,8BAA8B,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,EACpD,CAAC;gBACD,mBAAmB,CAAC,IAAI,CAAC,WAAW,CAAC;oBACnC,CAAC,mBAAmB,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;gBACnD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;gBAC7B,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,uBAAuB,CAAC,EAAE,CAAC;oBAC5C,IAAI,CAAC,IAAI,GAAG,CAAC,GAAG,IAAI,EAAE,uBAAuB,CAAC,CAAC;gBACjD,CAAC;gBACD,MAAM,EAAE,CAAC;YACX,CAAC;QACH,CAAC;QAED,0EAA0E;QAC1E,gDAAgD;QAChD,MAAM,OAAO,GAAG,MAAM,CAAC;QAEvB,OAAO;YACL,OAAO;YACP,OAAO,EAAE,IAAI;YACb,OAAO;YACP,mBAAmB;SACpB,CAAC;IACJ,CAAC;CACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"library-profile-source-gate-pass.d.ts","sourceRoot":"","sources":["../../../src/analysis/passes/library-profile-source-gate-pass.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAC9E,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAavE,MAAM,WAAW,8BAA8B;IAC7C;;;;OAIG;IACH,OAAO,EAAE,cAAc,GAAG,SAAS,CAAC;IACpC;;;;OAIG;IACH,OAAO,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,aAAa,EAAE,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;CACpD;AAaD,qBAAa,4BACX,YAAW,YAAY,CAAC,8BAA8B,CAAC;IAEvD,QAAQ,CAAC,IAAI,iCAAiC;IAC9C,QAAQ,CAAC,QAAQ,EAAG,UAAU,CAAU;IAExC,GAAG,CAAC,GAAG,EAAE,WAAW,GAAG,8BAA8B;CAgDtD"}
1
+ {"version":3,"file":"library-profile-source-gate-pass.d.ts","sourceRoot":"","sources":["../../../src/analysis/passes/library-profile-source-gate-pass.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAC9E,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAe,MAAM,sBAAsB,CAAC;AAcpF,MAAM,WAAW,8BAA8B;IAC7C;;;;OAIG;IACH,OAAO,EAAE,cAAc,GAAG,SAAS,CAAC;IACpC;;;;OAIG;IACH,OAAO,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,aAAa,EAAE,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;CACpD;AAaD,qBAAa,4BACX,YAAW,YAAY,CAAC,8BAA8B,CAAC;IAEvD,QAAQ,CAAC,IAAI,iCAAiC;IAC9C,QAAQ,CAAC,QAAQ,EAAG,UAAU,CAAU;IAExC,GAAG,CAAC,GAAG,EAAE,WAAW,GAAG,8BAA8B;CAuEtD"}
@@ -88,7 +88,19 @@ export class LibraryProfileSourceGatePass {
88
88
  droppedByType: {},
89
89
  };
90
90
  }
91
- const sources = graph.ir.taint.sources;
91
+ // cognium-dev#288 — read the AUTHORITATIVE source list, mirroring the
92
+ // fetch pattern `LibraryProfileSinkGatePass` already uses and proves.
93
+ //
94
+ // `graph.ir.taint.sources` is NOT that list: `analyzer.ts` constructs the
95
+ // graph with `taint: { sources: [], sinks: [], sanitizers: [] }` and
96
+ // nothing ever populates it, so this pass used to filter a permanently
97
+ // empty array and report `dropped: 0` on every run. The list that both
98
+ // `InterproceduralPass` and the final `taint` rebuild consume is
99
+ // `SinkFilterResult.sources`. The fallback keeps the stand-alone unit
100
+ // tests working, which build an IR by hand and never run SinkFilterPass.
101
+ const sources = ctx.hasResult('sink-filter')
102
+ ? ctx.getResult('sink-filter').sources
103
+ : graph.ir.taint.sources;
92
104
  if (sources.length === 0) {
93
105
  return {
94
106
  profile,
@@ -97,21 +109,34 @@ export class LibraryProfileSourceGatePass {
97
109
  droppedByType: {},
98
110
  };
99
111
  }
112
+ // cognium-dev#288 (option A) — COUNT, do not delete.
113
+ //
114
+ // This pass used to splice the speculative sources out of the authoritative
115
+ // list. Deleting them destroys information the downstream adjudication
116
+ // layer needs and is invisible in the output: a consumer cannot tell a
117
+ // clean file from a gated one, and `@cognium/project-profile-detect` can
118
+ // misclassify a repo as a library. It is also inconsistent with how this
119
+ // codebase already answers the same "caller's responsibility" question —
120
+ // `applyLibraryApiSurfaceDowngrade` and `applyProjectProfileTransform`
121
+ // (ADR-008) TAG a finding and downgrade its severity while keeping it,
122
+ // recording `original_severity` so the decision is auditable and
123
+ // reversible.
124
+ //
125
+ // So the sources survive and the signal is carried on the FLOWS instead,
126
+ // via the `library-api-surface:caller-responsibility` tag that
127
+ // `TaintFlowInfo.tags` has existed for since 3.105.0. The count is still
128
+ // reported for diagnostics.
100
129
  const droppedByType = {};
101
- const kept = [];
102
130
  for (const src of sources) {
103
131
  if (SPECULATIVE_SOURCE_TYPES.has(src.type)) {
104
132
  droppedByType[src.type] = (droppedByType[src.type] ?? 0) + 1;
105
- continue;
106
133
  }
107
- kept.push(src);
108
134
  }
109
- const dropped = sources.length - kept.length;
110
- // Mutate the array in place so downstream passes see the
111
- // filtered list. Every existing pass reads `graph.ir.taint.sources`
112
- // by reference.
113
- sources.length = 0;
114
- sources.push(...kept);
135
+ const dropped = 0;
136
+ // No mutation: `sources` is handed to `TaintPropagationPass` and
137
+ // `InterproceduralPass` and assigned to `taint.sources` by the rebuild.
138
+ // Leaving it intact is the point of option A — the sources/flows stay and
139
+ // the library-shape judgement is expressed as a tag, not a deletion.
115
140
  return {
116
141
  profile,
117
142
  applied: true,
@@ -1 +1 @@
1
- {"version":3,"file":"library-profile-source-gate-pass.js","sourceRoot":"","sources":["../../../src/analysis/passes/library-profile-source-gate-pass.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AAKH;;;;;GAKG;AACH,MAAM,wBAAwB,GAA4B,IAAI,GAAG,CAAa;IAC5E,uBAAuB;IACvB,mBAAmB;CACpB,CAAC,CAAC;AA2BH;;;;;GAKG;AACH,SAAS,cAAc,CAAC,OAAmC;IACzD,IAAI,CAAC,OAAO,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACpD,OAAO,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,OAAO,4BAA4B;IAG9B,IAAI,GAAG,6BAA6B,CAAC;IACrC,QAAQ,GAAG,UAAmB,CAAC;IAExC,GAAG,CAAC,GAAgB;QAClB,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,CAAC;QACtB,MAAM,OAAO,GAAG,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC;QAE7C,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,CAAC;YAC7B,OAAO;gBACL,OAAO;gBACP,OAAO,EAAE,KAAK;gBACd,OAAO,EAAE,CAAC;gBACV,aAAa,EAAE,EAAE;aAClB,CAAC;QACJ,CAAC;QAED,MAAM,OAAO,GAAG,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC;QACvC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO;gBACL,OAAO;gBACP,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE,CAAC;gBACV,aAAa,EAAE,EAAE;aAClB,CAAC;QACJ,CAAC;QAED,MAAM,aAAa,GAAwC,EAAE,CAAC;QAC9D,MAAM,IAAI,GAAG,EAAE,CAAC;QAChB,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;YAC1B,IAAI,wBAAwB,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC3C,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;gBAC7D,SAAS;YACX,CAAC;YACD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACjB,CAAC;QAED,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAE7C,yDAAyD;QACzD,oEAAoE;QACpE,gBAAgB;QAChB,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;QACnB,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;QAEtB,OAAO;YACL,OAAO;YACP,OAAO,EAAE,IAAI;YACb,OAAO;YACP,aAAa;SACd,CAAC;IACJ,CAAC;CACF"}
1
+ {"version":3,"file":"library-profile-source-gate-pass.js","sourceRoot":"","sources":["../../../src/analysis/passes/library-profile-source-gate-pass.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AAMH;;;;;GAKG;AACH,MAAM,wBAAwB,GAA4B,IAAI,GAAG,CAAa;IAC5E,uBAAuB;IACvB,mBAAmB;CACpB,CAAC,CAAC;AA2BH;;;;;GAKG;AACH,SAAS,cAAc,CAAC,OAAmC;IACzD,IAAI,CAAC,OAAO,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACpD,OAAO,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,OAAO,4BAA4B;IAG9B,IAAI,GAAG,6BAA6B,CAAC;IACrC,QAAQ,GAAG,UAAmB,CAAC;IAExC,GAAG,CAAC,GAAgB;QAClB,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,CAAC;QACtB,MAAM,OAAO,GAAG,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC;QAE7C,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,CAAC;YAC7B,OAAO;gBACL,OAAO;gBACP,OAAO,EAAE,KAAK;gBACd,OAAO,EAAE,CAAC;gBACV,aAAa,EAAE,EAAE;aAClB,CAAC;QACJ,CAAC;QAED,sEAAsE;QACtE,sEAAsE;QACtE,EAAE;QACF,0EAA0E;QAC1E,qEAAqE;QACrE,uEAAuE;QACvE,uEAAuE;QACvE,iEAAiE;QACjE,sEAAsE;QACtE,yEAAyE;QACzE,MAAM,OAAO,GAAkB,GAAG,CAAC,SAAS,CAAC,aAAa,CAAC;YACzD,CAAC,CAAC,GAAG,CAAC,SAAS,CAAmB,aAAa,CAAC,CAAC,OAAO;YACxD,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC;QAC3B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO;gBACL,OAAO;gBACP,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE,CAAC;gBACV,aAAa,EAAE,EAAE;aAClB,CAAC;QACJ,CAAC;QAED,qDAAqD;QACrD,EAAE;QACF,4EAA4E;QAC5E,uEAAuE;QACvE,uEAAuE;QACvE,yEAAyE;QACzE,yEAAyE;QACzE,yEAAyE;QACzE,uEAAuE;QACvE,uEAAuE;QACvE,iEAAiE;QACjE,cAAc;QACd,EAAE;QACF,yEAAyE;QACzE,+DAA+D;QAC/D,yEAAyE;QACzE,4BAA4B;QAC5B,MAAM,aAAa,GAAwC,EAAE,CAAC;QAC9D,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;YAC1B,IAAI,wBAAwB,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC3C,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;YAC/D,CAAC;QACH,CAAC;QACD,MAAM,OAAO,GAAG,CAAC,CAAC;QAElB,iEAAiE;QACjE,wEAAwE;QACxE,0EAA0E;QAC1E,qEAAqE;QACrE,OAAO;YACL,OAAO;YACP,OAAO,EAAE,IAAI;YACb,OAAO;YACP,aAAa;SACd,CAAC;IACJ,CAAC;CACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"sink-filter-pass.d.ts","sourceRoot":"","sources":["../../../src/analysis/passes/sink-filter-pass.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,cAAc,EAAwB,MAAM,sBAAsB,CAAC;AACzG,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAo+B9E,MAAM,WAAW,gBAAgB;IAC/B,wDAAwD;IACxD,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,sBAAsB;IACtB,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,UAAU,EAAE,cAAc,EAAE,CAAC;CAC9B;AA6BD,qBAAa,cAAe,YAAW,YAAY,CAAC,gBAAgB,CAAC;IACnE,QAAQ,CAAC,IAAI,iBAAiB;IAC9B,QAAQ,CAAC,QAAQ,EAAG,UAAU,CAAU;IAExC,GAAG,CAAC,GAAG,EAAE,WAAW,GAAG,gBAAgB;CAkwCxC;AAkRD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAErD,KAAK,OAAO,GAAG,GAAG,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AA4I1G,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,EACjC,KAAK,EAAE,QAAQ,CAAC,OAAO,CAAC,EACxB,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,EACxB,OAAO,EAAE,OAAO,EAChB,GAAG,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC,EACrB,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,EAC3B,iBAAiB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,EAC/B,QAAQ,CAAC,EAAE,MAAM,GAChB,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CA6E5B;AAED,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,EACjC,UAAU,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,EAC3C,KAAK,EAAE,QAAQ,CAAC,OAAO,CAAC,GACvB,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CA2C5B"}
1
+ {"version":3,"file":"sink-filter-pass.d.ts","sourceRoot":"","sources":["../../../src/analysis/passes/sink-filter-pass.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,cAAc,EAAwB,MAAM,sBAAsB,CAAC;AACzG,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAogC9E,MAAM,WAAW,gBAAgB;IAC/B,wDAAwD;IACxD,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,sBAAsB;IACtB,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,UAAU,EAAE,cAAc,EAAE,CAAC;CAC9B;AA6BD,qBAAa,cAAe,YAAW,YAAY,CAAC,gBAAgB,CAAC;IACnE,QAAQ,CAAC,IAAI,iBAAiB;IAC9B,QAAQ,CAAC,QAAQ,EAAG,UAAU,CAAU;IAExC,GAAG,CAAC,GAAG,EAAE,WAAW,GAAG,gBAAgB;CA0xCxC;AAkRD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAErD,KAAK,OAAO,GAAG,GAAG,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AA4I1G,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,EACjC,KAAK,EAAE,QAAQ,CAAC,OAAO,CAAC,EACxB,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,EACxB,OAAO,EAAE,OAAO,EAChB,GAAG,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC,EACrB,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,EAC3B,iBAAiB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,EAC/B,QAAQ,CAAC,EAAE,MAAM,GAChB,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CA6E5B;AAED,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,EACjC,UAAU,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,EAC3C,KAAK,EAAE,QAAQ,CAAC,OAAO,CAAC,GACvB,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CA2C5B"}
@@ -201,6 +201,36 @@ const PROTOCOL_CLIENT_PACKAGES = [
201
201
  // Defense-in-depth: even inside a protocol-client file, do not
202
202
  // suppress a sink whose receiver is explicitly an OS-exec class.
203
203
  const OS_EXEC_RECEIVER_RE = /\b(?:Runtime|ProcessBuilder|DefaultExecutor|Executor|Exec|Launcher|ProcStarter|ProcessExecutor|RuntimeUtil)\s*[.(]/;
204
+ // Stage 15e — Java xss: `System.out` / `System.err` are not HTTP responses.
205
+ // (cognium-dev#374 — Java over-prediction)
206
+ //
207
+ // The canonical Java xss sink set is class-scoped — `PrintWriter.println`,
208
+ // `ServletOutputStream.println`, `WikiPrinter.println` — plus a CLASSLESS
209
+ // `println` entry so an unresolved writer receiver is still caught.
210
+ // `System.out.println(x)` / `System.err.println(x)` match that classless entry,
211
+ // so every console print of a tainted value was reported as CWE-79.
212
+ //
213
+ // Stdout and stderr are not a browser context: no HTML document, no script
214
+ // execution, no HTTP response. There is no reading under which this is XSS.
215
+ //
216
+ // WHY THIS IS A DROP AND NOT A RETYPE. CWE-117 (improper output neutralisation
217
+ // for logs) would be a defensible label — container stdout is routinely shipped
218
+ // to a log aggregator, where an unneutralised newline forges entries. But Java
219
+ // `log_injection` is deliberately `Logger`-scoped (`info`/`warn`/`error`/…), and
220
+ // extending it to `System.out` is a separate, ADDITIVE decision: console prints
221
+ // are ubiquitous, so it would trade an xss flood for a log_injection flood of
222
+ // the same cardinality and buy no localization improvement. Retyping was also
223
+ // tried at the registry level and matched unpredictably — `System.err` missed
224
+ // the new entry entirely while `PrintWriter.println` gained a spurious
225
+ // `log_injection` alongside its correct xss. So these lines are now unflagged,
226
+ // and the CWE-117 question is left to its own issue with its own measurement.
227
+ //
228
+ // This matters out of proportion to its subtlety because *every* Java class
229
+ // prints. On the 500-repo vuln-localization benchmark Java emits ~306
230
+ // security-typed findings per repo against ~8 genuinely vulnerable files, so the
231
+ // real finding drowns and hit@3 collapses to 16% while recall stays at 79% —
232
+ // a ranking failure caused by FP volume, not a detection gap.
233
+ const JAVA_STDOUT_PRINT_RE = /\bSystem\s*\.\s*(?:out|err)\s*\.\s*(?:println|print|printf|write|append)\s*\(/;
204
234
  // ---------------------------------------------------------------------------
205
235
  // Stage 11 — Java command_injection (CWE-78) FP reduction.
206
236
  // (cognium-dev #179 Sink 1 — Sprint 44)
@@ -1937,6 +1967,30 @@ export class SinkFilterPass {
1937
1967
  if (language === 'java' && !HTML_CONTENT_TYPE_RE.test(ctx.code)) {
1938
1968
  filtered = filtered.filter(sink => !(sink.type === 'xss' && sink.method === 'body'));
1939
1969
  }
1970
+ // Stage 15e — Java xss on a `System.out` / `System.err` print. See
1971
+ // JAVA_STDOUT_PRINT_RE above for why this is not CWE-79, and why it is a
1972
+ // drop rather than a retype to CWE-117.
1973
+ //
1974
+ // Scoped three ways so the real XSS writers are untouched:
1975
+ // 1. `xss` sinks only;
1976
+ // 2. only sinks with NO resolved class — `sink.class` records which
1977
+ // pattern matched, so `undefined` means the classless `println` entry
1978
+ // caught it. `PrintWriter.println` / `ServletOutputStream.println`
1979
+ // resolve to their class and never reach this branch;
1980
+ // 3. only when the sink's own line actually prints via System.out/err.
1981
+ //
1982
+ // Known limitation of (3): a single line carrying BOTH a System.out print
1983
+ // and an unresolved real writer print would lose the latter. The sink
1984
+ // carries no column, and every other stage here judges on line text, so
1985
+ // this follows the existing convention rather than inventing a new one.
1986
+ if (language === 'java') {
1987
+ const sourceLines = ctx.code.split('\n');
1988
+ filtered = filtered.filter(sink => {
1989
+ if (sink.type !== 'xss' || sink.class !== undefined)
1990
+ return true;
1991
+ return !JAVA_STDOUT_PRINT_RE.test(sourceLines[sink.line - 1] ?? '');
1992
+ });
1993
+ }
1940
1994
  // Stage 15d — Java path_traversal: `if (x.contains("..")) throw/return`
1941
1995
  // reject-guard. (cognium-dev#269 CWE-22 review) A user path checked for a
1942
1996
  // `..` traversal token and rejected before any filesystem use cannot carry