circle-ir 3.152.0 → 3.154.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 +24 -8
- package/dist/analysis/config-loader.js.map +1 -1
- package/dist/analysis/passes/library-profile-sink-gate-pass.d.ts +43 -1
- package/dist/analysis/passes/library-profile-sink-gate-pass.d.ts.map +1 -1
- package/dist/analysis/passes/library-profile-sink-gate-pass.js +75 -0
- package/dist/analysis/passes/library-profile-sink-gate-pass.js.map +1 -1
- package/dist/analysis/passes/library-profile-xss-gate-pass.d.ts +104 -0
- package/dist/analysis/passes/library-profile-xss-gate-pass.d.ts.map +1 -0
- package/dist/analysis/passes/library-profile-xss-gate-pass.js +196 -0
- package/dist/analysis/passes/library-profile-xss-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 +37 -1
- package/dist/analyzer.js.map +1 -1
- package/dist/browser/circle-ir.js +437 -257
- package/dist/core/circle-ir-core.cjs +38 -9
- package/dist/core/circle-ir-core.js +38 -9
- 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,387 @@
|
|
|
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 { classifyEntryPointTier } from './entry-point-detection.js';
|
|
63
|
+
// ---------------------------------------------------------------------------
|
|
64
|
+
// Public rule id + constants
|
|
65
|
+
// ---------------------------------------------------------------------------
|
|
66
|
+
/** Rule identifier used for `disabledPasses` lookups. */
|
|
67
|
+
export const RULE_ID_REQUIRE_ENTRY_PATH = 'require-entry-path';
|
|
68
|
+
/**
|
|
69
|
+
* BFS visit budget. Chosen empirically to comfortably cover the
|
|
70
|
+
* largest-repo call graphs we see on the Tier-2 cohort (`plantuml`
|
|
71
|
+
* ~7k methods, `sentinel` ~6k) while still guaranteeing the pass
|
|
72
|
+
* terminates in bounded time. Findings whose BFS hits the budget are
|
|
73
|
+
* treated as `unknown` and preserved — never dropped on a bailout.
|
|
74
|
+
*/
|
|
75
|
+
const MAX_VISITED_METHODS = 2000;
|
|
76
|
+
/**
|
|
77
|
+
* Apply the entry-path gate + annotation to every file's findings in
|
|
78
|
+
* `fileAnalyses`, mutating each `analysis.findings` array in place.
|
|
79
|
+
*
|
|
80
|
+
* The mutation is idempotent — running twice produces the same result
|
|
81
|
+
* (BFS is deterministic; annotation always overwrites prior fields
|
|
82
|
+
* with the same values).
|
|
83
|
+
*/
|
|
84
|
+
export function applyRequireEntryPath(fileAnalyses, options = {}) {
|
|
85
|
+
const disabledSet = normalizeDisabled(options.disabledPasses);
|
|
86
|
+
if (disabledSet.has(RULE_ID_REQUIRE_ENTRY_PATH))
|
|
87
|
+
return;
|
|
88
|
+
// Build the project-wide method index + reverse-caller adjacency once.
|
|
89
|
+
const graph = buildProjectMethodGraph(fileAnalyses);
|
|
90
|
+
if (graph.methodsByKey.size === 0)
|
|
91
|
+
return;
|
|
92
|
+
// Classify entry points once — reused for every finding.
|
|
93
|
+
const entryPointKeys = collectEntryPointKeys(graph);
|
|
94
|
+
const profileResolver = makeProfileResolver(options.projectProfile);
|
|
95
|
+
for (const fa of fileAnalyses) {
|
|
96
|
+
const findings = fa.analysis.findings;
|
|
97
|
+
if (!findings || findings.length === 0)
|
|
98
|
+
continue;
|
|
99
|
+
const kept = [];
|
|
100
|
+
for (const finding of findings) {
|
|
101
|
+
const decision = classifyFinding(finding, fa.analysis, graph, entryPointKeys, profileResolver(fa.file));
|
|
102
|
+
switch (decision.action) {
|
|
103
|
+
case 'keep':
|
|
104
|
+
kept.push(finding);
|
|
105
|
+
break;
|
|
106
|
+
case 'annotate':
|
|
107
|
+
kept.push({
|
|
108
|
+
...finding,
|
|
109
|
+
entryPath: decision.entryPath,
|
|
110
|
+
entryPathTier: decision.tier,
|
|
111
|
+
});
|
|
112
|
+
break;
|
|
113
|
+
case 'drop':
|
|
114
|
+
// Findings dropped by the entry-path gate carry no
|
|
115
|
+
// side-channel signal — downstream consumers see them
|
|
116
|
+
// as if they were never emitted.
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
fa.analysis.findings = kept.length > 0 ? kept : undefined;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
function buildProjectMethodGraph(fileAnalyses) {
|
|
124
|
+
const methodsByKey = new Map();
|
|
125
|
+
const methodsByName = new Map();
|
|
126
|
+
const callersOf = new Map();
|
|
127
|
+
// Pass 1 — index every method.
|
|
128
|
+
for (const fa of fileAnalyses) {
|
|
129
|
+
const language = (fa.analysis.meta.language ?? '').toLowerCase();
|
|
130
|
+
for (const type of fa.analysis.types ?? []) {
|
|
131
|
+
for (const method of type.methods ?? []) {
|
|
132
|
+
const key = makeMethodKey(fa.file, type.name, method.name, method.start_line);
|
|
133
|
+
methodsByKey.set(key, {
|
|
134
|
+
key,
|
|
135
|
+
file: fa.file,
|
|
136
|
+
className: type.name,
|
|
137
|
+
method,
|
|
138
|
+
enclosingType: type,
|
|
139
|
+
language,
|
|
140
|
+
});
|
|
141
|
+
const bucket = methodsByName.get(method.name);
|
|
142
|
+
if (bucket)
|
|
143
|
+
bucket.push(key);
|
|
144
|
+
else
|
|
145
|
+
methodsByName.set(method.name, [key]);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
// Pass 2 — index every call and resolve callee(s) into edges.
|
|
150
|
+
for (const fa of fileAnalyses) {
|
|
151
|
+
const calls = fa.analysis.calls ?? [];
|
|
152
|
+
for (const call of calls) {
|
|
153
|
+
if (!call.in_method)
|
|
154
|
+
continue;
|
|
155
|
+
const callerKey = resolveCallerKey(fa, call.in_method, call.location.line);
|
|
156
|
+
if (!callerKey)
|
|
157
|
+
continue;
|
|
158
|
+
const calleeKeys = resolveCalleeKeys(call, methodsByKey, methodsByName);
|
|
159
|
+
if (calleeKeys.length === 0)
|
|
160
|
+
continue;
|
|
161
|
+
const code = call.receiver
|
|
162
|
+
? `${call.receiver}.${call.method_name}(...)`
|
|
163
|
+
: `${call.method_name}(...)`;
|
|
164
|
+
for (const calleeKey of calleeKeys) {
|
|
165
|
+
const edge = {
|
|
166
|
+
callerKey,
|
|
167
|
+
calleeKey,
|
|
168
|
+
callSiteLine: call.location.line,
|
|
169
|
+
code,
|
|
170
|
+
};
|
|
171
|
+
const bucket = callersOf.get(calleeKey);
|
|
172
|
+
if (bucket)
|
|
173
|
+
bucket.push(edge);
|
|
174
|
+
else
|
|
175
|
+
callersOf.set(calleeKey, [edge]);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return { methodsByKey, methodsByName, callersOf };
|
|
180
|
+
}
|
|
181
|
+
function makeMethodKey(file, className, methodName, startLine) {
|
|
182
|
+
return `${file}|${className}#${methodName}@${startLine}`;
|
|
183
|
+
}
|
|
184
|
+
function resolveCallerKey(fa, inMethod, callLine) {
|
|
185
|
+
// `in_method` is the simple method name of the enclosing method.
|
|
186
|
+
// Disambiguate by finding the type whose method range contains
|
|
187
|
+
// `callLine` (handles overloaded methods sharing the same name).
|
|
188
|
+
for (const type of fa.analysis.types ?? []) {
|
|
189
|
+
for (const method of type.methods ?? []) {
|
|
190
|
+
if (method.name !== inMethod)
|
|
191
|
+
continue;
|
|
192
|
+
if (callLine >= method.start_line && callLine <= method.end_line) {
|
|
193
|
+
return makeMethodKey(fa.file, type.name, method.name, method.start_line);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
function resolveCalleeKeys(call, methodsByKey, methodsByName) {
|
|
200
|
+
const candidates = methodsByName.get(call.method_name);
|
|
201
|
+
if (!candidates || candidates.length === 0)
|
|
202
|
+
return [];
|
|
203
|
+
// Prefer receiver-type match when we have it — cuts the fan-out on
|
|
204
|
+
// common names like `execute` / `run` / `handle` from ~50 to ~1.
|
|
205
|
+
if (call.receiver_type) {
|
|
206
|
+
const simple = call.receiver_type.replace(/<.*$/, '').trim();
|
|
207
|
+
const matches = [];
|
|
208
|
+
for (const key of candidates) {
|
|
209
|
+
const rec = methodsByKey.get(key);
|
|
210
|
+
if (rec?.className === simple)
|
|
211
|
+
matches.push(key);
|
|
212
|
+
}
|
|
213
|
+
if (matches.length > 0)
|
|
214
|
+
return matches;
|
|
215
|
+
}
|
|
216
|
+
// Fallback — name-only. Duplicates fan out the BFS but the visit
|
|
217
|
+
// budget bounds it. Wrong callees do not corrupt correctness: a
|
|
218
|
+
// spurious edge only expands the reachable set, never contracts it,
|
|
219
|
+
// and this helper only DROPS on empty-reachable.
|
|
220
|
+
return candidates;
|
|
221
|
+
}
|
|
222
|
+
// ---------------------------------------------------------------------------
|
|
223
|
+
// Entry-point classification
|
|
224
|
+
// ---------------------------------------------------------------------------
|
|
225
|
+
function collectEntryPointKeys(graph) {
|
|
226
|
+
const entryPoints = new Set();
|
|
227
|
+
for (const rec of graph.methodsByKey.values()) {
|
|
228
|
+
const tier = classifyEntryPointTier(rec.method, rec.enclosingType, {
|
|
229
|
+
types: [rec.enclosingType],
|
|
230
|
+
language: rec.language,
|
|
231
|
+
});
|
|
232
|
+
if (tier === 'TIER_1_ENTRY_POINT')
|
|
233
|
+
entryPoints.add(rec.key);
|
|
234
|
+
}
|
|
235
|
+
return entryPoints;
|
|
236
|
+
}
|
|
237
|
+
function classifyFinding(finding, ir, graph, entryPointKeys, profile) {
|
|
238
|
+
// Only taint findings from the security category are in scope.
|
|
239
|
+
if (finding.category !== 'security')
|
|
240
|
+
return { action: 'keep' };
|
|
241
|
+
// Only H+C findings are candidates for drop; lower-severity findings
|
|
242
|
+
// are preserved regardless of reachability (may still be annotated
|
|
243
|
+
// when we can).
|
|
244
|
+
const isHighOrCritical = finding.severity === 'high' || finding.severity === 'critical';
|
|
245
|
+
// Java-only. The classifier is Java-primary (`classifyEntryPointTier`
|
|
246
|
+
// returns `TIER_UNKNOWN` for every other language), so applying the
|
|
247
|
+
// reachability drop to non-Java findings would strip legitimate
|
|
248
|
+
// signal on Python / Node / Go / Rust — pass through unchanged.
|
|
249
|
+
const language = (ir.meta.language ?? '').toLowerCase();
|
|
250
|
+
if (language !== 'java')
|
|
251
|
+
return { action: 'keep' };
|
|
252
|
+
// Resolve containing method by (file, line-range) lookup.
|
|
253
|
+
const containing = findContainingMethod(finding, ir, graph);
|
|
254
|
+
if (!containing) {
|
|
255
|
+
// Sink lives in a field initializer, static block, or another
|
|
256
|
+
// no-method context — cannot classify. Never drop.
|
|
257
|
+
return { action: 'keep' };
|
|
258
|
+
}
|
|
259
|
+
// Reverse BFS from the containing method.
|
|
260
|
+
const bfs = reverseBfsToEntryPoint(containing.key, graph, entryPointKeys);
|
|
261
|
+
if (bfs.status === 'hit') {
|
|
262
|
+
const entryPath = reconstructPath(bfs.entryKey, containing.key, bfs.parent, graph, finding);
|
|
263
|
+
return {
|
|
264
|
+
action: 'annotate',
|
|
265
|
+
entryPath,
|
|
266
|
+
tier: 'tier1-entry-point',
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
if (bfs.status === 'budget') {
|
|
270
|
+
// Depth bailout — insufficient evidence, preserve.
|
|
271
|
+
return { action: 'keep' };
|
|
272
|
+
}
|
|
273
|
+
// bfs.status === 'miss' — no entry point reaches this method.
|
|
274
|
+
if (!isHighOrCritical)
|
|
275
|
+
return { action: 'keep' };
|
|
276
|
+
if (!shouldDropUnderProfile(profile))
|
|
277
|
+
return { action: 'keep' };
|
|
278
|
+
return { action: 'drop' };
|
|
279
|
+
}
|
|
280
|
+
function findContainingMethod(finding, ir, graph) {
|
|
281
|
+
const line = finding.line;
|
|
282
|
+
for (const type of ir.types ?? []) {
|
|
283
|
+
for (const method of type.methods ?? []) {
|
|
284
|
+
if (line >= method.start_line && line <= method.end_line) {
|
|
285
|
+
const key = makeMethodKey(finding.file, type.name, method.name, method.start_line);
|
|
286
|
+
const rec = graph.methodsByKey.get(key);
|
|
287
|
+
if (rec)
|
|
288
|
+
return rec;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
return null;
|
|
293
|
+
}
|
|
294
|
+
function reverseBfsToEntryPoint(startKey, graph, entryPointKeys) {
|
|
295
|
+
const parent = new Map();
|
|
296
|
+
const visited = new Set([startKey]);
|
|
297
|
+
const queue = [startKey];
|
|
298
|
+
// Corner case: the sink method is itself an entry point.
|
|
299
|
+
if (entryPointKeys.has(startKey)) {
|
|
300
|
+
return { status: 'hit', entryKey: startKey, parent };
|
|
301
|
+
}
|
|
302
|
+
while (queue.length > 0) {
|
|
303
|
+
if (visited.size > MAX_VISITED_METHODS) {
|
|
304
|
+
return { status: 'budget', entryKey: null, parent };
|
|
305
|
+
}
|
|
306
|
+
const current = queue.shift();
|
|
307
|
+
const incoming = graph.callersOf.get(current) ?? [];
|
|
308
|
+
// Deterministic ordering — sort by caller key for reproducibility.
|
|
309
|
+
incoming.sort((a, b) => a.callerKey.localeCompare(b.callerKey));
|
|
310
|
+
for (const edge of incoming) {
|
|
311
|
+
if (visited.has(edge.callerKey))
|
|
312
|
+
continue;
|
|
313
|
+
visited.add(edge.callerKey);
|
|
314
|
+
parent.set(edge.callerKey, edge);
|
|
315
|
+
if (entryPointKeys.has(edge.callerKey)) {
|
|
316
|
+
return { status: 'hit', entryKey: edge.callerKey, parent };
|
|
317
|
+
}
|
|
318
|
+
queue.push(edge.callerKey);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
return { status: 'miss', entryKey: null, parent };
|
|
322
|
+
}
|
|
323
|
+
function reconstructPath(entryKey, sinkKey, parent, graph, finding) {
|
|
324
|
+
// Walk from entry down to sink by iteratively following the parent
|
|
325
|
+
// map forward. `parent.get(x)` yields the edge whose `callerKey === x`
|
|
326
|
+
// (i.e. the call FROM x to its callee on the path).
|
|
327
|
+
const hops = [];
|
|
328
|
+
let cursor = entryKey;
|
|
329
|
+
const guard = new Set();
|
|
330
|
+
while (cursor !== sinkKey) {
|
|
331
|
+
if (guard.has(cursor))
|
|
332
|
+
break; // paranoia — should never cycle
|
|
333
|
+
guard.add(cursor);
|
|
334
|
+
const rec = graph.methodsByKey.get(cursor);
|
|
335
|
+
const edge = parent.get(cursor);
|
|
336
|
+
if (!rec || !edge)
|
|
337
|
+
break;
|
|
338
|
+
hops.push({
|
|
339
|
+
file: rec.file,
|
|
340
|
+
method: `${rec.className}.${rec.method.name}`,
|
|
341
|
+
line: edge.callSiteLine,
|
|
342
|
+
code: edge.code,
|
|
343
|
+
variable: '',
|
|
344
|
+
});
|
|
345
|
+
cursor = edge.calleeKey;
|
|
346
|
+
}
|
|
347
|
+
// Terminal hop — the sink method itself, at the finding's line.
|
|
348
|
+
const sinkRec = graph.methodsByKey.get(sinkKey);
|
|
349
|
+
if (sinkRec) {
|
|
350
|
+
hops.push({
|
|
351
|
+
file: sinkRec.file,
|
|
352
|
+
method: `${sinkRec.className}.${sinkRec.method.name}`,
|
|
353
|
+
line: finding.line,
|
|
354
|
+
code: finding.message,
|
|
355
|
+
variable: '',
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
return hops;
|
|
359
|
+
}
|
|
360
|
+
// ---------------------------------------------------------------------------
|
|
361
|
+
// Profile predicate
|
|
362
|
+
// ---------------------------------------------------------------------------
|
|
363
|
+
function shouldDropUnderProfile(profile) {
|
|
364
|
+
// #236 / #232 already own the `library/*` drop path — this helper
|
|
365
|
+
// must not double-drop findings that survived those gates on
|
|
366
|
+
// library files, so we only fire on non-library profiles.
|
|
367
|
+
if (profile === 'unknown')
|
|
368
|
+
return true;
|
|
369
|
+
if (profile.startsWith('library/'))
|
|
370
|
+
return false;
|
|
371
|
+
return true;
|
|
372
|
+
}
|
|
373
|
+
function makeProfileResolver(input) {
|
|
374
|
+
if (input === undefined)
|
|
375
|
+
return () => 'unknown';
|
|
376
|
+
if (typeof input === 'string')
|
|
377
|
+
return () => input;
|
|
378
|
+
return (file) => input.get(file) ?? 'unknown';
|
|
379
|
+
}
|
|
380
|
+
function normalizeDisabled(input) {
|
|
381
|
+
if (!input)
|
|
382
|
+
return new Set();
|
|
383
|
+
if (input instanceof Set)
|
|
384
|
+
return input;
|
|
385
|
+
return new Set(input);
|
|
386
|
+
}
|
|
387
|
+
//# sourceMappingURL=require-entry-path.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"require-entry-path.js","sourceRoot":"","sources":["../../src/analysis/require-entry-path.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"taint-matcher.d.ts","sourceRoot":"","sources":["../../src/analysis/taint-matcher.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAgB,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAkB,KAAK,EAAwB,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAClK,OAAO,KAAK,EAAE,WAAW,EAAiB,WAAW,EAAoB,MAAM,oBAAoB,CAAC;AACpG,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AA2B7E;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,QAAQ,EAAE,EACjB,KAAK,EAAE,QAAQ,EAAE,EACjB,MAAM,GAAE,WAAgC,EACxC,aAAa,CAAC,EAAE,qBAAqB,EACrC,QAAQ,CAAC,EAAE,iBAAiB,EAC5B,IAAI,CAAC,EAAE,MAAM,GACZ,KAAK,CASP;AAqID;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,WAAW,EAAE,EACtB,KAAK,EAAE,SAAS,EAAE,EAClB,IAAI,EAAE,MAAM,GACX,IAAI,CAYN;
|
|
1
|
+
{"version":3,"file":"taint-matcher.d.ts","sourceRoot":"","sources":["../../src/analysis/taint-matcher.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAgB,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAkB,KAAK,EAAwB,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAClK,OAAO,KAAK,EAAE,WAAW,EAAiB,WAAW,EAAoB,MAAM,oBAAoB,CAAC;AACpG,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AA2B7E;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,QAAQ,EAAE,EACjB,KAAK,EAAE,QAAQ,EAAE,EACjB,MAAM,GAAE,WAAgC,EACxC,aAAa,CAAC,EAAE,qBAAqB,EACrC,QAAQ,CAAC,EAAE,iBAAiB,EAC5B,IAAI,CAAC,EAAE,MAAM,GACZ,KAAK,CASP;AAqID;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,WAAW,EAAE,EACtB,KAAK,EAAE,SAAS,EAAE,EAClB,IAAI,EAAE,MAAM,GACX,IAAI,CAYN;AA2qED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,WAAW,GACnB,OAAO,CAET"}
|
|
@@ -955,7 +955,51 @@ function argIsClassLiteral(call, position) {
|
|
|
955
955
|
const expr = (arg.literal ?? arg.expression ?? '').trim();
|
|
956
956
|
if (!expr)
|
|
957
957
|
return false;
|
|
958
|
-
|
|
958
|
+
if (CLASS_LITERAL_RE.test(expr))
|
|
959
|
+
return true;
|
|
960
|
+
// Added 3.153.0 (cognium-dev #233): recognise Jackson `TypeReference<T>`
|
|
961
|
+
// and Gson `TypeToken<T>` typed generics — the anonymous inner class
|
|
962
|
+
// captures the generic type at compile time exactly like `Foo.class`
|
|
963
|
+
// does for the raw type. Only the empty-body form matches; bodied
|
|
964
|
+
// subclasses (`new TypeReference<...>() { @Override … }`) are treated
|
|
965
|
+
// as dynamic to preserve recall on suspicious overrides.
|
|
966
|
+
return TYPE_TOKEN_RE.test(expr);
|
|
967
|
+
}
|
|
968
|
+
/**
|
|
969
|
+
* Matches `new TypeReference<...>() {}` (Jackson) and
|
|
970
|
+
* `new TypeToken<...>() {}` (Gson) with an empty anonymous body — the
|
|
971
|
+
* two canonical shapes for expressing a compile-time-fixed generic
|
|
972
|
+
* type at a Java call site.
|
|
973
|
+
*
|
|
974
|
+
* Whitespace is tolerated between tokens; nested generics
|
|
975
|
+
* (`<Map<String, List<User>>>`) are captured non-greedily and the
|
|
976
|
+
* body must be empty (`{}` with only whitespace inside).
|
|
977
|
+
*/
|
|
978
|
+
const TYPE_TOKEN_RE = /^new\s+(?:TypeReference|TypeToken)\s*<[\s\S]*>\s*\(\s*\)\s*\{\s*\}$/;
|
|
979
|
+
/**
|
|
980
|
+
* Returns true when the call's argument at `position` is a compile-time
|
|
981
|
+
* string literal (not a variable / expression / concatenation).
|
|
982
|
+
*
|
|
983
|
+
* Used by `SinkPattern.safe_if_string_literal_at` — added 3.153.0 for
|
|
984
|
+
* JDBC `JdbcTemplate` query-family sinks that carry `?` placeholders
|
|
985
|
+
* (parameterised queries cannot be tainted at the SQL layer).
|
|
986
|
+
*/
|
|
987
|
+
function argIsStringLiteral(call, position) {
|
|
988
|
+
const arg = call.arguments.find(a => a.position === position);
|
|
989
|
+
if (!arg)
|
|
990
|
+
return false;
|
|
991
|
+
// Prefer `arg.literal` (the extractor's normalised literal value)
|
|
992
|
+
// when populated; fall back to `arg.expression` for languages whose
|
|
993
|
+
// extractor does not split literals out separately.
|
|
994
|
+
if (arg.literal !== undefined && arg.literal !== null && arg.literal !== '')
|
|
995
|
+
return true;
|
|
996
|
+
const expr = (arg.expression ?? '').trim();
|
|
997
|
+
if (!expr)
|
|
998
|
+
return false;
|
|
999
|
+
// Double-quoted, single-quoted (Groovy / Bash), or Java text-block (`"""…"""`).
|
|
1000
|
+
return ((expr.startsWith('"') && expr.endsWith('"') && expr.length >= 2) ||
|
|
1001
|
+
(expr.startsWith("'") && expr.endsWith("'") && expr.length >= 2) ||
|
|
1002
|
+
(expr.startsWith('"""') && expr.endsWith('"""')));
|
|
959
1003
|
}
|
|
960
1004
|
/**
|
|
961
1005
|
* CWE-78 (OS Command Injection) receiver-class allowlist (#129).
|
|
@@ -1384,6 +1428,16 @@ function findSinks(calls, patterns, typeHierarchy, language, sourceLines) {
|
|
|
1384
1428
|
argIsClassLiteral(call, pattern.safe_if_class_literal_at)) {
|
|
1385
1429
|
continue;
|
|
1386
1430
|
}
|
|
1431
|
+
// Skip parameterised SQL query overloads whose SQL is a compile-time
|
|
1432
|
+
// string literal (e.g. `JdbcTemplate.queryForObject("SELECT ... WHERE
|
|
1433
|
+
// id = ?", args, RowMapper)`) — `?` placeholders are bound by the
|
|
1434
|
+
// driver, so a literal at the query position cannot carry taint.
|
|
1435
|
+
// Non-literal overloads (variable, concat, `String.format`) still
|
|
1436
|
+
// match. Added 3.153.0 (cognium-dev #233).
|
|
1437
|
+
if (pattern.safe_if_string_literal_at !== undefined &&
|
|
1438
|
+
argIsStringLiteral(call, pattern.safe_if_string_literal_at)) {
|
|
1439
|
+
continue;
|
|
1440
|
+
}
|
|
1387
1441
|
// #129 — CWE-78 receiver-class allowlist gate.
|
|
1388
1442
|
// Suppress command_injection emissions on receivers known NOT
|
|
1389
1443
|
// to invoke OS commands. Constructors check method_name (which
|