circle-ir 3.151.0 → 3.153.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/sink-semantics.json +102 -0
- package/configs/sinks/command.yaml +0 -10
- package/configs/sinks/deserialization.yaml +54 -0
- package/configs/sinks/path.yaml +0 -94
- package/configs/sinks/sql.yaml +24 -24
- package/dist/analysis/config-loader.d.ts.map +1 -1
- package/dist/analysis/config-loader.js +14 -5
- package/dist/analysis/config-loader.js.map +1 -1
- package/dist/analysis/passes/library-profile-sink-gate-pass.d.ts +89 -0
- package/dist/analysis/passes/library-profile-sink-gate-pass.d.ts.map +1 -0
- package/dist/analysis/passes/library-profile-sink-gate-pass.js +132 -0
- package/dist/analysis/passes/library-profile-sink-gate-pass.js.map +1 -0
- package/dist/analysis/require-entry-path.d.ts +91 -0
- package/dist/analysis/require-entry-path.d.ts.map +1 -0
- package/dist/analysis/require-entry-path.js +387 -0
- package/dist/analysis/require-entry-path.js.map +1 -0
- package/dist/analysis/taint-matcher.d.ts.map +1 -1
- package/dist/analysis/taint-matcher.js +55 -1
- package/dist/analysis/taint-matcher.js.map +1 -1
- package/dist/analyzer.d.ts.map +1 -1
- package/dist/analyzer.js +23 -0
- package/dist/analyzer.js.map +1 -1
- package/dist/browser/circle-ir.js +331 -253
- package/dist/core/circle-ir-core.cjs +28 -6
- package/dist/core/circle-ir-core.js +28 -6
- package/dist/types/config.d.ts +11 -1
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/index.d.ts +25 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LibraryProfileSinkGatePass — cognium-dev #232
|
|
3
|
+
*
|
|
4
|
+
* Sink-side companion to `LibraryProfileSourceGatePass` (#236,
|
|
5
|
+
* shipped 3.151.0). Under the `library/*` project profile, drops
|
|
6
|
+
* sinks whose entire vulnerability class is off-topic for library
|
|
7
|
+
* code — currently just `log_injection` (CWE-117).
|
|
8
|
+
*
|
|
9
|
+
* Motivation:
|
|
10
|
+
*
|
|
11
|
+
* `log_injection` requires a downstream log-viewer that interprets
|
|
12
|
+
* attacker-controlled log content — the exploit ("log forging",
|
|
13
|
+
* HTML/ANSI injection into a log renderer, log-based privilege
|
|
14
|
+
* escalation) is exercised at the application-integration boundary,
|
|
15
|
+
* not inside a library. A library that calls `Logger.info(x)` where
|
|
16
|
+
* `x` originated from an HTTP parameter has not committed a defect:
|
|
17
|
+
* the consuming application decides where those log records are
|
|
18
|
+
* rendered and how their content is escaped.
|
|
19
|
+
*
|
|
20
|
+
* Empirically, `log_injection` was ~10% of H+C findings on the
|
|
21
|
+
* Tier 2 8-repo library cohort (402 findings in the audit
|
|
22
|
+
* summarised in cognium-ai#189 §1). The signal is systemically
|
|
23
|
+
* noisy for library code and provides no actionable
|
|
24
|
+
* application-security value.
|
|
25
|
+
*
|
|
26
|
+
* Where #236 dropped speculative `interprocedural_param` sources
|
|
27
|
+
* (which removed the entire `external_taint_escape` Scenario-B
|
|
28
|
+
* synthesis path), this pass drops the sinks themselves. `log_injection`
|
|
29
|
+
* has real, non-speculative sources (`http_param`, `env_input`,
|
|
30
|
+
* `db_input`, …) that flow into concrete sink calls (`Logger.info`,
|
|
31
|
+
* `logging.info`, `console.log`, …); the source-side gate does not
|
|
32
|
+
* remove them. The *sink class* is what is off-topic here.
|
|
33
|
+
*
|
|
34
|
+
* Pipeline slot: runs after `CliMainReflectionSuppressPass` (so
|
|
35
|
+
* every sink-side categorisation / suppression pass fires first)
|
|
36
|
+
* and before `TaintPropagationPass` (so no dropped sink ever
|
|
37
|
+
* reaches the flow generators).
|
|
38
|
+
*
|
|
39
|
+
* Guardrails:
|
|
40
|
+
* - Pass is a no-op when `graph.ir.meta.projectProfile` is absent,
|
|
41
|
+
* `'unknown'`, or does not start with `library/`. Callers that do
|
|
42
|
+
* not opt in to profile detection get the unmodified sink list.
|
|
43
|
+
* - Only `log_injection` is eligible in 3.152.0. Every other
|
|
44
|
+
* `SinkType` (`sql_injection`, `command_injection`, `xss`,
|
|
45
|
+
* `path_traversal`, `deserialization`, …) is preserved
|
|
46
|
+
* unconditionally. Extending the drop set is a deliberate
|
|
47
|
+
* one-line change in `DROPPED_SINK_TYPES`.
|
|
48
|
+
* - Guarded on `disabledPasses.has('library-profile-sink-gate')`
|
|
49
|
+
* at the pipeline registration site.
|
|
50
|
+
*
|
|
51
|
+
* Scope note (Rust log macros): `LanguageSourcesPass` emits
|
|
52
|
+
* `rule_id: 'log_injection'` findings directly for Rust log macros
|
|
53
|
+
* (`info!`, `println!`, `eprintln!`, …). Those findings bypass the
|
|
54
|
+
* sink pipeline entirely and therefore bypass this pass. Deferred
|
|
55
|
+
* to a follow-up if the harness rerun shows material Rust
|
|
56
|
+
* residuals; the Tier 2 8-repo cohort is Java-heavy.
|
|
57
|
+
*/
|
|
58
|
+
import type { AnalysisPass, PassContext } from '../../graph/analysis-pass.js';
|
|
59
|
+
import type { ProjectProfile, SinkType } from '../../types/index.js';
|
|
60
|
+
export interface LibraryProfileSinkGateResult {
|
|
61
|
+
/**
|
|
62
|
+
* Resolved `ProjectProfile` observed on `graph.ir.meta.projectProfile`
|
|
63
|
+
* at the time this pass ran. `undefined` when no profile was
|
|
64
|
+
* supplied by the caller.
|
|
65
|
+
*/
|
|
66
|
+
profile: ProjectProfile | undefined;
|
|
67
|
+
/**
|
|
68
|
+
* Whether the profile matched the library-shape trigger and the
|
|
69
|
+
* gate was applied. `false` for every non-library shape and for
|
|
70
|
+
* `'unknown'` / absent profiles.
|
|
71
|
+
*/
|
|
72
|
+
applied: boolean;
|
|
73
|
+
/**
|
|
74
|
+
* Number of sinks removed from the authoritative sink list. Zero
|
|
75
|
+
* when `applied === false`.
|
|
76
|
+
*/
|
|
77
|
+
dropped: number;
|
|
78
|
+
/**
|
|
79
|
+
* Breakdown of drops by `SinkType`. Empty object when
|
|
80
|
+
* `applied === false`.
|
|
81
|
+
*/
|
|
82
|
+
droppedByType: Partial<Record<SinkType, number>>;
|
|
83
|
+
}
|
|
84
|
+
export declare class LibraryProfileSinkGatePass implements AnalysisPass<LibraryProfileSinkGateResult> {
|
|
85
|
+
readonly name = "library-profile-sink-gate";
|
|
86
|
+
readonly category: "security";
|
|
87
|
+
run(ctx: PassContext): LibraryProfileSinkGateResult;
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=library-profile-sink-gate-pass.d.ts.map
|
|
@@ -0,0 +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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwDG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAC9E,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAa,MAAM,sBAAsB,CAAC;AAYhF,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"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LibraryProfileSinkGatePass — cognium-dev #232
|
|
3
|
+
*
|
|
4
|
+
* Sink-side companion to `LibraryProfileSourceGatePass` (#236,
|
|
5
|
+
* shipped 3.151.0). Under the `library/*` project profile, drops
|
|
6
|
+
* sinks whose entire vulnerability class is off-topic for library
|
|
7
|
+
* code — currently just `log_injection` (CWE-117).
|
|
8
|
+
*
|
|
9
|
+
* Motivation:
|
|
10
|
+
*
|
|
11
|
+
* `log_injection` requires a downstream log-viewer that interprets
|
|
12
|
+
* attacker-controlled log content — the exploit ("log forging",
|
|
13
|
+
* HTML/ANSI injection into a log renderer, log-based privilege
|
|
14
|
+
* escalation) is exercised at the application-integration boundary,
|
|
15
|
+
* not inside a library. A library that calls `Logger.info(x)` where
|
|
16
|
+
* `x` originated from an HTTP parameter has not committed a defect:
|
|
17
|
+
* the consuming application decides where those log records are
|
|
18
|
+
* rendered and how their content is escaped.
|
|
19
|
+
*
|
|
20
|
+
* Empirically, `log_injection` was ~10% of H+C findings on the
|
|
21
|
+
* Tier 2 8-repo library cohort (402 findings in the audit
|
|
22
|
+
* summarised in cognium-ai#189 §1). The signal is systemically
|
|
23
|
+
* noisy for library code and provides no actionable
|
|
24
|
+
* application-security value.
|
|
25
|
+
*
|
|
26
|
+
* Where #236 dropped speculative `interprocedural_param` sources
|
|
27
|
+
* (which removed the entire `external_taint_escape` Scenario-B
|
|
28
|
+
* synthesis path), this pass drops the sinks themselves. `log_injection`
|
|
29
|
+
* has real, non-speculative sources (`http_param`, `env_input`,
|
|
30
|
+
* `db_input`, …) that flow into concrete sink calls (`Logger.info`,
|
|
31
|
+
* `logging.info`, `console.log`, …); the source-side gate does not
|
|
32
|
+
* remove them. The *sink class* is what is off-topic here.
|
|
33
|
+
*
|
|
34
|
+
* Pipeline slot: runs after `CliMainReflectionSuppressPass` (so
|
|
35
|
+
* every sink-side categorisation / suppression pass fires first)
|
|
36
|
+
* and before `TaintPropagationPass` (so no dropped sink ever
|
|
37
|
+
* reaches the flow generators).
|
|
38
|
+
*
|
|
39
|
+
* Guardrails:
|
|
40
|
+
* - Pass is a no-op when `graph.ir.meta.projectProfile` is absent,
|
|
41
|
+
* `'unknown'`, or does not start with `library/`. Callers that do
|
|
42
|
+
* not opt in to profile detection get the unmodified sink list.
|
|
43
|
+
* - Only `log_injection` is eligible in 3.152.0. Every other
|
|
44
|
+
* `SinkType` (`sql_injection`, `command_injection`, `xss`,
|
|
45
|
+
* `path_traversal`, `deserialization`, …) is preserved
|
|
46
|
+
* unconditionally. Extending the drop set is a deliberate
|
|
47
|
+
* one-line change in `DROPPED_SINK_TYPES`.
|
|
48
|
+
* - Guarded on `disabledPasses.has('library-profile-sink-gate')`
|
|
49
|
+
* at the pipeline registration site.
|
|
50
|
+
*
|
|
51
|
+
* Scope note (Rust log macros): `LanguageSourcesPass` emits
|
|
52
|
+
* `rule_id: 'log_injection'` findings directly for Rust log macros
|
|
53
|
+
* (`info!`, `println!`, `eprintln!`, …). Those findings bypass the
|
|
54
|
+
* sink pipeline entirely and therefore bypass this pass. Deferred
|
|
55
|
+
* to a follow-up if the harness rerun shows material Rust
|
|
56
|
+
* residuals; the Tier 2 8-repo cohort is Java-heavy.
|
|
57
|
+
*/
|
|
58
|
+
/**
|
|
59
|
+
* Sink types eligible for the library-profile drop. Seeded with
|
|
60
|
+
* `log_injection` (CWE-117) in 3.152.0. Extending this set is a
|
|
61
|
+
* deliberate, reviewable change.
|
|
62
|
+
*/
|
|
63
|
+
const DROPPED_SINK_TYPES = new Set([
|
|
64
|
+
'log_injection',
|
|
65
|
+
]);
|
|
66
|
+
/**
|
|
67
|
+
* Returns true when the resolved profile begins with `library/`
|
|
68
|
+
* (i.e. any `library/production`, `library/dev`, `library/sample`,
|
|
69
|
+
* `library/benchmark`, `library/test` environment binding).
|
|
70
|
+
* `'unknown'` and non-library shapes return false.
|
|
71
|
+
*/
|
|
72
|
+
function isLibraryShape(profile) {
|
|
73
|
+
if (!profile || profile === 'unknown')
|
|
74
|
+
return false;
|
|
75
|
+
return profile.startsWith('library/');
|
|
76
|
+
}
|
|
77
|
+
export class LibraryProfileSinkGatePass {
|
|
78
|
+
name = 'library-profile-sink-gate';
|
|
79
|
+
category = 'security';
|
|
80
|
+
run(ctx) {
|
|
81
|
+
const { graph } = ctx;
|
|
82
|
+
const profile = graph.ir.meta.projectProfile;
|
|
83
|
+
if (!isLibraryShape(profile)) {
|
|
84
|
+
return {
|
|
85
|
+
profile,
|
|
86
|
+
applied: false,
|
|
87
|
+
dropped: 0,
|
|
88
|
+
droppedByType: {},
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
// Authoritative sink list mirrors the fetch pattern in
|
|
92
|
+
// `SinkSemanticsPass`: prefer `SinkFilterResult.sinks` (what
|
|
93
|
+
// `analyzer.ts` assembles the final `taint.sinks` from), fall
|
|
94
|
+
// back to `graph.ir.taint.sinks` for stand-alone unit tests
|
|
95
|
+
// that don't run `SinkFilterPass`.
|
|
96
|
+
const sinks = ctx.hasResult('sink-filter')
|
|
97
|
+
? ctx.getResult('sink-filter').sinks
|
|
98
|
+
: graph.ir.taint.sinks;
|
|
99
|
+
if (sinks.length === 0) {
|
|
100
|
+
return {
|
|
101
|
+
profile,
|
|
102
|
+
applied: true,
|
|
103
|
+
dropped: 0,
|
|
104
|
+
droppedByType: {},
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
const droppedByType = {};
|
|
108
|
+
const kept = [];
|
|
109
|
+
for (const sink of sinks) {
|
|
110
|
+
if (DROPPED_SINK_TYPES.has(sink.type)) {
|
|
111
|
+
droppedByType[sink.type] = (droppedByType[sink.type] ?? 0) + 1;
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
kept.push(sink);
|
|
115
|
+
}
|
|
116
|
+
const dropped = sinks.length - kept.length;
|
|
117
|
+
// Mutate the array in place so downstream passes see the
|
|
118
|
+
// filtered list. Preserves array identity for any consumer that
|
|
119
|
+
// captured a reference before this pass ran.
|
|
120
|
+
if (dropped > 0) {
|
|
121
|
+
sinks.length = 0;
|
|
122
|
+
sinks.push(...kept);
|
|
123
|
+
}
|
|
124
|
+
return {
|
|
125
|
+
profile,
|
|
126
|
+
applied: true,
|
|
127
|
+
dropped,
|
|
128
|
+
droppedByType,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=library-profile-sink-gate-pass.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"library-profile-sink-gate-pass.js","sourceRoot":"","sources":["../../../src/analysis/passes/library-profile-sink-gate-pass.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwDG;AAMH;;;;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"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Require-entry-path anchor (cognium-dev#234, ships 3.153.0).
|
|
3
|
+
*
|
|
4
|
+
* Post-pipeline, project-level helper that:
|
|
5
|
+
* 1. Annotates high+critical (H+C) taint findings with an
|
|
6
|
+
* `entryPath[]` chain of methods traversed from a classified
|
|
7
|
+
* Tier-1 entry point (Spring MVC handler, JAX-RS resource,
|
|
8
|
+
* Servlet lifecycle method, Netty channel handler, `main(String[])`,
|
|
9
|
+
* …) down to the finding's sink method.
|
|
10
|
+
* 2. Drops H+C findings under `application` / `server` / `cli` /
|
|
11
|
+
* `plugin` / `unknown` project profiles when the reverse-BFS
|
|
12
|
+
* conclusively returns no such chain — i.e. the finding lives on a
|
|
13
|
+
* method that no HTTP / RPC / lifecycle entry point in the scan can
|
|
14
|
+
* reach.
|
|
15
|
+
*
|
|
16
|
+
* # Why
|
|
17
|
+
*
|
|
18
|
+
* cognium-ai#189 §1 (2026-07 Tier-2 Java cohort — hutool, Sentinel,
|
|
19
|
+
* plantuml, mockserver) surfaced 1942 H+C findings on hutool with
|
|
20
|
+
* *zero* classified HTTP/RPC entry point and no reachable path from
|
|
21
|
+
* `main`. #236 (source-side profile gate, 3.151.0) and #232
|
|
22
|
+
* (sink-side profile gate, 3.152.0) each attacked the problem via
|
|
23
|
+
* profile-conditional per-file drops, but both leave the residual
|
|
24
|
+
* signal on files whose profile is `application/*` or `unknown` even
|
|
25
|
+
* though the enclosing method is manifestly unreachable from any
|
|
26
|
+
* classified boundary.
|
|
27
|
+
*
|
|
28
|
+
* This helper closes that hole: no entry point → no path from an
|
|
29
|
+
* entry point → no H+C finding. Every remaining H+C finding under
|
|
30
|
+
* `application/*` carries a demonstrable call chain from a real
|
|
31
|
+
* boundary as evidence, materialised on `entryPath[]` for consumers
|
|
32
|
+
* (CLI, SARIF, cognium-ai) to display.
|
|
33
|
+
*
|
|
34
|
+
* # Scope
|
|
35
|
+
*
|
|
36
|
+
* - Java only (relies on `classifyEntryPointTier`, which is Java-primary).
|
|
37
|
+
* Non-Java files: pass-through, no annotation, no drop.
|
|
38
|
+
* - Project-level only. Per-file `analyze()` never runs this helper —
|
|
39
|
+
* the reachability question is meaningful only across a full scan.
|
|
40
|
+
* - Only H+C findings from taint passes are candidates for drop. Metric
|
|
41
|
+
* findings, `medium` / `low` taint findings, and findings without a
|
|
42
|
+
* resolved containing method are always preserved.
|
|
43
|
+
*
|
|
44
|
+
* # Interaction with #236 / #232
|
|
45
|
+
*
|
|
46
|
+
* Both #236 and #232 fire when `projectProfile` starts with `library/`:
|
|
47
|
+
* the source / sink is dropped BEFORE the flow is materialised. This
|
|
48
|
+
* helper therefore no-ops under `library/*` (an already-dropped flow
|
|
49
|
+
* never reaches us) but still ANNOTATES findings with `entryPath[]`
|
|
50
|
+
* whenever a chain is available, so downstream consumers can see the
|
|
51
|
+
* anchor regardless of the drop decision.
|
|
52
|
+
*
|
|
53
|
+
* # Reference
|
|
54
|
+
*
|
|
55
|
+
* - cognium-dev#234 — this ticket.
|
|
56
|
+
* - cognium-dev#128 — entry-point tier classifier.
|
|
57
|
+
* - cognium-dev#236 (3.151.0) — source-side library-profile gate.
|
|
58
|
+
* - cognium-dev#232 (3.152.0) — sink-side library-profile gate.
|
|
59
|
+
* - cognium-ai#189 — Tier-2 Java cohort audit.
|
|
60
|
+
* - `docs/ARCHITECTURE.md` ADR-010.
|
|
61
|
+
*/
|
|
62
|
+
import type { CircleIR, ProjectProfile } from '../types/index.js';
|
|
63
|
+
/** Rule identifier used for `disabledPasses` lookups. */
|
|
64
|
+
export declare const RULE_ID_REQUIRE_ENTRY_PATH = "require-entry-path";
|
|
65
|
+
export interface ApplyRequireEntryPathOptions {
|
|
66
|
+
/**
|
|
67
|
+
* Caller-resolved profile for each file. Same semantics as
|
|
68
|
+
* `AnalyzerOptions.projectProfile`. When absent, the helper treats
|
|
69
|
+
* every file as `'unknown'` — i.e. drops still apply.
|
|
70
|
+
*/
|
|
71
|
+
projectProfile?: ProjectProfile | Map<string, ProjectProfile>;
|
|
72
|
+
/**
|
|
73
|
+
* Set of disabled pass ids (from `AnalyzerOptions.disabledPasses`).
|
|
74
|
+
* If it contains `'require-entry-path'`, the helper is a full no-op
|
|
75
|
+
* (no annotation, no drop).
|
|
76
|
+
*/
|
|
77
|
+
disabledPasses?: ReadonlySet<string> | ReadonlyArray<string>;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Apply the entry-path gate + annotation to every file's findings in
|
|
81
|
+
* `fileAnalyses`, mutating each `analysis.findings` array in place.
|
|
82
|
+
*
|
|
83
|
+
* The mutation is idempotent — running twice produces the same result
|
|
84
|
+
* (BFS is deterministic; annotation always overwrites prior fields
|
|
85
|
+
* with the same values).
|
|
86
|
+
*/
|
|
87
|
+
export declare function applyRequireEntryPath(fileAnalyses: ReadonlyArray<{
|
|
88
|
+
file: string;
|
|
89
|
+
analysis: CircleIR;
|
|
90
|
+
}>, options?: ApplyRequireEntryPathOptions): void;
|
|
91
|
+
//# sourceMappingURL=require-entry-path.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"require-entry-path.d.ts","sourceRoot":"","sources":["../../src/analysis/require-entry-path.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4DG;AAEH,OAAO,KAAK,EACV,QAAQ,EAER,cAAc,EAIf,MAAM,mBAAmB,CAAC;AAO3B,yDAAyD;AACzD,eAAO,MAAM,0BAA0B,uBAAuB,CAAC;AAe/D,MAAM,WAAW,4BAA4B;IAC3C;;;;OAIG;IACH,cAAc,CAAC,EAAE,cAAc,GAAG,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC9D;;;;OAIG;IACH,cAAc,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;CAC9D;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,YAAY,EAAE,aAAa,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,CAAC,EACjE,OAAO,GAAE,4BAAiC,GACzC,IAAI,CA6CN"}
|