circle-ir 4.14.2 → 4.15.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/dist/analysis/const-table-lookup.d.ts +29 -0
- package/dist/analysis/const-table-lookup.d.ts.map +1 -0
- package/dist/analysis/const-table-lookup.js +145 -0
- package/dist/analysis/const-table-lookup.js.map +1 -0
- package/dist/analysis/findings.d.ts.map +1 -1
- package/dist/analysis/findings.js +15 -4
- package/dist/analysis/findings.js.map +1 -1
- package/dist/analysis/go-strings-replacer.d.ts +21 -0
- package/dist/analysis/go-strings-replacer.d.ts.map +1 -0
- package/dist/analysis/go-strings-replacer.js +145 -0
- package/dist/analysis/go-strings-replacer.js.map +1 -0
- package/dist/analysis/interprocedural.d.ts.map +1 -1
- package/dist/analysis/interprocedural.js +53 -0
- package/dist/analysis/interprocedural.js.map +1 -1
- package/dist/analysis/java-canonical-prefix.d.ts +42 -0
- package/dist/analysis/java-canonical-prefix.d.ts.map +1 -0
- package/dist/analysis/java-canonical-prefix.js +145 -0
- package/dist/analysis/java-canonical-prefix.js.map +1 -0
- package/dist/analysis/java-crlf-strip.d.ts +30 -0
- package/dist/analysis/java-crlf-strip.d.ts.map +1 -0
- package/dist/analysis/java-crlf-strip.js +195 -0
- package/dist/analysis/java-crlf-strip.js.map +1 -0
- package/dist/analysis/passes/cleartext-credential-transport-pass.d.ts +2 -0
- package/dist/analysis/passes/cleartext-credential-transport-pass.d.ts.map +1 -1
- package/dist/analysis/passes/cleartext-credential-transport-pass.js +64 -12
- package/dist/analysis/passes/cleartext-credential-transport-pass.js.map +1 -1
- package/dist/analysis/passes/cross-file-pass.d.ts.map +1 -1
- package/dist/analysis/passes/cross-file-pass.js +43 -0
- package/dist/analysis/passes/cross-file-pass.js.map +1 -1
- package/dist/analysis/passes/csharp-sanitizer-credit.d.ts.map +1 -1
- package/dist/analysis/passes/csharp-sanitizer-credit.js +18 -0
- package/dist/analysis/passes/csharp-sanitizer-credit.js.map +1 -1
- package/dist/analysis/passes/interprocedural-pass.d.ts +28 -0
- package/dist/analysis/passes/interprocedural-pass.d.ts.map +1 -1
- package/dist/analysis/passes/interprocedural-pass.js +20 -1
- package/dist/analysis/passes/interprocedural-pass.js.map +1 -1
- package/dist/analysis/passes/language-sources-pass.d.ts +41 -2
- package/dist/analysis/passes/language-sources-pass.d.ts.map +1 -1
- package/dist/analysis/passes/language-sources-pass.js +842 -10
- package/dist/analysis/passes/language-sources-pass.js.map +1 -1
- package/dist/analysis/passes/param-source-flow-gate-pass.d.ts +8 -0
- package/dist/analysis/passes/param-source-flow-gate-pass.d.ts.map +1 -1
- package/dist/analysis/passes/param-source-flow-gate-pass.js +162 -6
- package/dist/analysis/passes/param-source-flow-gate-pass.js.map +1 -1
- package/dist/analysis/passes/sink-filter-pass.d.ts.map +1 -1
- package/dist/analysis/passes/sink-filter-pass.js +207 -1
- package/dist/analysis/passes/sink-filter-pass.js.map +1 -1
- package/dist/analysis/passes/taint-propagation-pass.d.ts.map +1 -1
- package/dist/analysis/passes/taint-propagation-pass.js +257 -2
- package/dist/analysis/passes/taint-propagation-pass.js.map +1 -1
- package/dist/analysis/scalar-derivation.d.ts +25 -0
- package/dist/analysis/scalar-derivation.d.ts.map +1 -0
- package/dist/analysis/scalar-derivation.js +196 -0
- package/dist/analysis/scalar-derivation.js.map +1 -0
- package/dist/analysis/taint-matcher.d.ts.map +1 -1
- package/dist/analysis/taint-matcher.js +167 -6
- package/dist/analysis/taint-matcher.js.map +1 -1
- package/dist/analysis/taint-propagation.d.ts.map +1 -1
- package/dist/analysis/taint-propagation.js +149 -19
- package/dist/analysis/taint-propagation.js.map +1 -1
- package/dist/analyzer.d.ts.map +1 -1
- package/dist/analyzer.js +7 -0
- package/dist/analyzer.js.map +1 -1
- package/dist/browser/circle-ir.js +3140 -1186
- package/dist/core/circle-ir-core.cjs +485 -27
- package/dist/core/circle-ir-core.js +485 -27
- package/dist/core/extractors/dfg.js +240 -6
- package/dist/core/extractors/dfg.js.map +1 -1
- package/dist/graph/code-graph.d.ts +9 -0
- package/dist/graph/code-graph.d.ts.map +1 -1
- package/dist/graph/code-graph.js +11 -0
- package/dist/graph/code-graph.js.map +1 -1
- package/dist/resolution/cross-file.d.ts +7 -0
- package/dist/resolution/cross-file.d.ts.map +1 -1
- package/dist/resolution/cross-file.js +10 -1
- package/dist/resolution/cross-file.js.map +1 -1
- package/dist/wasm/web-tree-sitter.wasm +0 -0
- 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
|
|
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;AA2CD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAOjG;AAkHD,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
|
|
@@ -80,6 +88,108 @@ export function isFrameworkHandler(method, language, lines) {
|
|
|
80
88
|
}
|
|
81
89
|
return false;
|
|
82
90
|
}
|
|
91
|
+
/** Sources that stand for a constructor-injected field or a getter over one (#78). */
|
|
92
|
+
const FIELD_CARRIED_SOURCE = /constructor-injected field|returns tainted field/;
|
|
93
|
+
/**
|
|
94
|
+
* Calls that invoke a function passed to them with the arguments that follow
|
|
95
|
+
* it, keyed by method name. The value is how many of those arguments are not
|
|
96
|
+
* forwarded (`setTimeout(fn, delay, a)` passes only `a`). Executor and
|
|
97
|
+
* scheduler shapes only: `pool.submit(fn, q)`,
|
|
98
|
+
* `loop.run_in_executor(None, fn, q)`, `asyncio.to_thread(fn, q)`,
|
|
99
|
+
* `loop.call_soon(fn, q)`, `setImmediate(fn, q)`, `process.nextTick(fn, q)`.
|
|
100
|
+
*/
|
|
101
|
+
const EXECUTOR_CALLEES = new Map([
|
|
102
|
+
['submit', 0], ['run_in_executor', 0], ['to_thread', 0], ['run_sync', 0],
|
|
103
|
+
['call_soon', 0], ['call_soon_threadsafe', 0], ['call_later', 0], ['call_at', 0],
|
|
104
|
+
['setImmediate', 0], ['nextTick', 0], ['queueMicrotask', 0],
|
|
105
|
+
['setTimeout', 1], ['setInterval', 1],
|
|
106
|
+
]);
|
|
107
|
+
/** `name` as a whole identifier (names may contain `$`). */
|
|
108
|
+
function identifierRe(name) {
|
|
109
|
+
return new RegExp(`(?:^|[^\\w$.])${name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}(?![\\w$])`);
|
|
110
|
+
}
|
|
111
|
+
function realFedParams(ctx, sources) {
|
|
112
|
+
const out = { params: new Set(), classes: new Set() };
|
|
113
|
+
const { graph } = ctx;
|
|
114
|
+
const seeds = new Set();
|
|
115
|
+
const allMethods = graph.ir.types.flatMap(t => t.methods);
|
|
116
|
+
// Variables a real source binds directly (`q = request.args.get("q")`),
|
|
117
|
+
// with the method that binds them: a `name` bound in one handler says
|
|
118
|
+
// nothing about a `name` local to another function. The Python DFG does
|
|
119
|
+
// not model every function body, so the binding is the fallback evidence.
|
|
120
|
+
const boundVars = new Map();
|
|
121
|
+
// Source reads written inline as an argument (`sink(request.args.get("q"))`),
|
|
122
|
+
// by line: the read's text as the source location names it.
|
|
123
|
+
const inlineReads = new Map();
|
|
124
|
+
for (const s of sources) {
|
|
125
|
+
if (s.type === 'interprocedural_param')
|
|
126
|
+
continue;
|
|
127
|
+
for (const d of graph.defsAtLine(s.line))
|
|
128
|
+
seeds.add(d.id);
|
|
129
|
+
if (s.variable) {
|
|
130
|
+
const where = boundVars.get(s.variable) ?? new Set();
|
|
131
|
+
where.add(enclosingMethod(allMethods, s.line));
|
|
132
|
+
boundVars.set(s.variable, where);
|
|
133
|
+
}
|
|
134
|
+
const read = /^([\w$.]+?)(?:\(\))? in /.exec(s.location ?? '')?.[1];
|
|
135
|
+
if (read && read.includes('.'))
|
|
136
|
+
inlineReads.set(s.line, [...(inlineReads.get(s.line) ?? []), read]);
|
|
137
|
+
}
|
|
138
|
+
const tainted = graph.propagateTaintedDefIds(seeds);
|
|
139
|
+
// Sanitizer calls by line, as the bare method name (`shlex.quote()` -> `quote`).
|
|
140
|
+
const sanitizerNames = new Map();
|
|
141
|
+
if (ctx.hasResult('sink-filter')) {
|
|
142
|
+
for (const sa of ctx.getResult('sink-filter').sanitizers) {
|
|
143
|
+
const name = /([\w$]+)\(?\)?$/.exec(sa.method)?.[1];
|
|
144
|
+
if (name)
|
|
145
|
+
sanitizerNames.set(sa.line, [...(sanitizerNames.get(sa.line) ?? []), name]);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
const classNames = new Set(graph.ir.types.map(t => t.name));
|
|
149
|
+
const functionNames = new Set(graph.ir.types.flatMap(t => t.methods.map(m => m.name)));
|
|
150
|
+
for (const call of graph.ir.calls) {
|
|
151
|
+
const line = call.location.line;
|
|
152
|
+
const uses = graph.usesAtLine(line).filter(u => u.def_id !== null && tainted.has(u.def_id));
|
|
153
|
+
const reads = inlineReads.get(line) ?? [];
|
|
154
|
+
const sanitizersHere = sanitizerNames.get(line) ?? [];
|
|
155
|
+
const callMethod = enclosingMethod(allMethods, line);
|
|
156
|
+
const isFed = (expr, variable) =>
|
|
157
|
+
// An argument passed through a sanitizer is not the raw request value.
|
|
158
|
+
!sanitizersHere.some(n => expr.includes(`${n}(`)) && ((!!variable && !!boundVars.get(variable)?.has(callMethod)) ||
|
|
159
|
+
reads.some(r => expr.includes(r)) ||
|
|
160
|
+
// The argument's own identifiers, not those of a sibling argument.
|
|
161
|
+
uses.some(u => identifierRe(u.variable).test(expr)));
|
|
162
|
+
// A local function handed over by reference to a call that runs it
|
|
163
|
+
// receives the arguments that follow it (`pool.submit(render, q)`,
|
|
164
|
+
// `loop.run_in_executor(None, f, q)`). Only callees known to invoke their
|
|
165
|
+
// function argument count: `print(banner, name)` or
|
|
166
|
+
// `audit.record(banner, name)` only pass `banner` along.
|
|
167
|
+
const skipAfterCallback = EXECUTOR_CALLEES.get(call.method_name);
|
|
168
|
+
let callbackName = null;
|
|
169
|
+
let callbackPos = -1;
|
|
170
|
+
for (const arg of call.arguments) {
|
|
171
|
+
const expr = typeof arg.expression === 'string' ? arg.expression.trim() : '';
|
|
172
|
+
if (skipAfterCallback !== undefined && callbackName === null && functionNames.has(expr)) {
|
|
173
|
+
callbackName = expr;
|
|
174
|
+
callbackPos = arg.position;
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
if (!isFed(expr, arg.variable))
|
|
178
|
+
continue;
|
|
179
|
+
// `res.send(req.query.m)` is a call on another object; it feeds a
|
|
180
|
+
// class method named `send`, never a module-level `function send`.
|
|
181
|
+
out.params.add(`${call.receiver ? 'm' : 'f'}:${call.method_name}:${arg.position}`);
|
|
182
|
+
if (classNames.has(call.method_name))
|
|
183
|
+
out.classes.add(call.method_name);
|
|
184
|
+
if (callbackName !== null) {
|
|
185
|
+
const pos = arg.position - callbackPos - 1 - (skipAfterCallback ?? 0);
|
|
186
|
+
if (pos >= 0)
|
|
187
|
+
out.params.add(`f:${callbackName}:${pos}`);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return out;
|
|
192
|
+
}
|
|
83
193
|
export class ParamSourceFlowGatePass {
|
|
84
194
|
keepParamSourcedFlows;
|
|
85
195
|
name = 'param-source-flow-gate';
|
|
@@ -114,13 +224,59 @@ export class ParamSourceFlowGatePass {
|
|
|
114
224
|
// the surviving flow may cite the parameter while the evidence is the
|
|
115
225
|
// real source. Those flows are kept.
|
|
116
226
|
const realSourceLines = new Set();
|
|
117
|
-
|
|
118
|
-
|
|
227
|
+
const sources = ctx.hasResult('sink-filter') ? ctx.getResult('sink-filter').sources : [];
|
|
228
|
+
for (const s of sources) {
|
|
229
|
+
if (s.type !== 'interprocedural_param')
|
|
230
|
+
realSourceLines.add(s.line);
|
|
231
|
+
}
|
|
232
|
+
// Computed on first need: most files have no parameter-only flow.
|
|
233
|
+
let fed;
|
|
234
|
+
const fedByRealSource = (f, m) => {
|
|
235
|
+
// The CWE-668 escape fallback names no concrete sink; a fed parameter
|
|
236
|
+
// does not make it more than a hint, so it stays gated.
|
|
237
|
+
if (f.sink_type === 'external_taint_escape')
|
|
238
|
+
return false;
|
|
239
|
+
fed ??= realFedParams(ctx, sources);
|
|
240
|
+
if (fed.params.size === 0)
|
|
241
|
+
return false;
|
|
242
|
+
const owner = ctx.graph.ir.types.find(t => t.methods.includes(m));
|
|
243
|
+
// A constructor is invoked through its class name (`new C(…)`, `C(…)`).
|
|
244
|
+
const isCtor = (m.name === 'constructor' || m.name === '__init__') && !!owner;
|
|
245
|
+
const callee = isCtor && owner ? owner.name : m.name;
|
|
246
|
+
// A module-level function or a constructor is called without a
|
|
247
|
+
// receiver; a class method is reached through one (`svc.run(x)`). Each
|
|
248
|
+
// matches its own call shape only: a bare `send(req.query.m)` does not
|
|
249
|
+
// run `Mailer.prototype.send`, and `res.send(…)` does not run a
|
|
250
|
+
// module-level `function send`.
|
|
251
|
+
const viaReceiver = !isCtor && !!owner && owner.name !== '<module>';
|
|
252
|
+
const feeds = (pos) => fed.params.has(`${viaReceiver ? 'm' : 'f'}:${callee}:${pos}`);
|
|
253
|
+
// When the flow's first step names a parameter, only that parameter
|
|
254
|
+
// counts: every parameter shares the signature line, and `f(a, b)`
|
|
255
|
+
// called as `f(req.query.a, 'x')` does not feed `b`.
|
|
256
|
+
const head = f.path[0]?.variable;
|
|
257
|
+
const named = m.parameters.findIndex(p => p.name === head);
|
|
258
|
+
if (named >= 0)
|
|
259
|
+
return feeds(named);
|
|
119
260
|
for (const s of sources) {
|
|
120
|
-
if (s.type !== 'interprocedural_param')
|
|
121
|
-
|
|
261
|
+
if (s.line !== f.source_line || s.type !== 'interprocedural_param')
|
|
262
|
+
continue;
|
|
263
|
+
if (FIELD_CARRIED_SOURCE.test(s.location ?? '')) {
|
|
264
|
+
if (owner && fed.classes.has(owner.name))
|
|
265
|
+
return true;
|
|
266
|
+
continue;
|
|
267
|
+
}
|
|
268
|
+
// The source names its parameter in `variable` (Java / C#) or in its
|
|
269
|
+
// location, `<type> <name> in <method>` (taint-matcher).
|
|
270
|
+
const pos = m.parameters.findIndex(p => s.variable
|
|
271
|
+
? p.name === s.variable
|
|
272
|
+
: (s.location ?? '').endsWith(` ${p.name} in ${m.name}`));
|
|
273
|
+
if (pos < 0)
|
|
274
|
+
continue;
|
|
275
|
+
if (feeds(pos))
|
|
276
|
+
return true;
|
|
122
277
|
}
|
|
123
|
-
|
|
278
|
+
return false;
|
|
279
|
+
};
|
|
124
280
|
// In-place filter: `additionalFlows` is the list the analyzer assigns to
|
|
125
281
|
// `taint.flows` after the pipeline.
|
|
126
282
|
let w = 0;
|
|
@@ -128,7 +284,7 @@ export class ParamSourceFlowGatePass {
|
|
|
128
284
|
let keep = true;
|
|
129
285
|
if (f.source_type === 'interprocedural_param' && !realSourceLines.has(f.source_line)) {
|
|
130
286
|
const m = enclosingMethod(methods, f.source_line);
|
|
131
|
-
keep = m !== undefined && isHandler(m);
|
|
287
|
+
keep = m !== undefined && (isHandler(m) || fedByRealSource(f, m));
|
|
132
288
|
}
|
|
133
289
|
if (keep)
|
|
134
290
|
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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"}
|
|
@@ -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,
|
|
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,EAAkC,MAAM,sBAAsB,CAAC;AACnH,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAmlC9E,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,CAq4CtC;CACF;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;AA+J1G,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,CA2F5B;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,EACxB,OAAO,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,GACrC,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAuD5B"}
|
|
@@ -464,6 +464,110 @@ const SERVER_SIGNAL_RE = /["']use server["']|\b(?:getServerSideProps|getStaticPr
|
|
|
464
464
|
// interpolated, the destination host is not attacker-controlled. Matches a
|
|
465
465
|
// backtick + scheme + a literal host run (no `${` before the first `/`).
|
|
466
466
|
const FIXED_HOST_TEMPLATE_RE = /`https?:\/\/[^/${}\s`]+[/`]/;
|
|
467
|
+
/** A bash URL word whose scheme and host are literal and closed by `/` (#495). */
|
|
468
|
+
const BASH_FIXED_HOST_URL_RE = /^(?:https?|ftp):\/\/[A-Za-z0-9.-]+(?::\d+)?\//;
|
|
469
|
+
/**
|
|
470
|
+
* True when the string literal that ended at `end` is the WHOLE initializer:
|
|
471
|
+
* the next code token is `;`, `,`, end of input, or (ASI) a token on a later
|
|
472
|
+
* line that cannot continue the expression. A same-line operator (`+`, `.`,
|
|
473
|
+
* `||` …) or a next-line `+` / `.` / `(` / `[` / template continuation means
|
|
474
|
+
* the literal is only the start of a larger expression, so it is not a
|
|
475
|
+
* constant. An optional TS `as const` / `as string` suffix is skipped (it may
|
|
476
|
+
* sit on the next line).
|
|
477
|
+
* (cognium-dev#680, #681)
|
|
478
|
+
*/
|
|
479
|
+
function literalEndsInitializer(code, end) {
|
|
480
|
+
let i = end;
|
|
481
|
+
let crossedNewline = false;
|
|
482
|
+
const asConst = /^\s+as\s+(?:const|string)\b/.exec(code.slice(i, i + 64));
|
|
483
|
+
if (asConst) {
|
|
484
|
+
i += asConst[0].length;
|
|
485
|
+
crossedNewline = asConst[0].includes('\n');
|
|
486
|
+
}
|
|
487
|
+
for (;;) {
|
|
488
|
+
while (i < code.length && /\s/.test(code[i])) {
|
|
489
|
+
if (code[i] === '\n')
|
|
490
|
+
crossedNewline = true;
|
|
491
|
+
i++;
|
|
492
|
+
}
|
|
493
|
+
if (code.startsWith('//', i)) {
|
|
494
|
+
const nl = code.indexOf('\n', i);
|
|
495
|
+
i = nl === -1 ? code.length : nl;
|
|
496
|
+
}
|
|
497
|
+
else if (code.startsWith('/*', i)) {
|
|
498
|
+
const close = code.indexOf('*/', i + 2);
|
|
499
|
+
if (close === -1)
|
|
500
|
+
return false;
|
|
501
|
+
if (code.slice(i, close).includes('\n'))
|
|
502
|
+
crossedNewline = true;
|
|
503
|
+
i = close + 2;
|
|
504
|
+
}
|
|
505
|
+
else
|
|
506
|
+
break;
|
|
507
|
+
}
|
|
508
|
+
if (i >= code.length)
|
|
509
|
+
return true;
|
|
510
|
+
const c = code[i];
|
|
511
|
+
if (c === ';' || c === ',')
|
|
512
|
+
return true;
|
|
513
|
+
// ASI: a following line that begins a new statement terminates the initializer.
|
|
514
|
+
// A line that starts with `as` / `satisfies` / `in` / `instanceof` continues it.
|
|
515
|
+
if (/^(?:as|satisfies|in|instanceof)(?![\w$])/.test(code.slice(i, i + 12)))
|
|
516
|
+
return false;
|
|
517
|
+
return crossedNewline && !/[-+*/%.?:|&<>=!~^(\[`]/.test(c);
|
|
518
|
+
}
|
|
519
|
+
/** Decode `\xNN` / `\uNNNN` / `\u{…}` JS string escapes; other escapes are kept verbatim. */
|
|
520
|
+
function decodeJsHexEscapes(value) {
|
|
521
|
+
return value.replace(/\\(?:x([0-9a-fA-F]{2})|u([0-9a-fA-F]{4})|u\{([0-9a-fA-F]{1,6})\}|[\s\S])/g, (m, x, u4, ub) => {
|
|
522
|
+
const hex = x ?? u4 ?? ub;
|
|
523
|
+
if (hex === undefined)
|
|
524
|
+
return m;
|
|
525
|
+
const cp = parseInt(hex, 16);
|
|
526
|
+
return cp <= 0x10ffff ? String.fromCodePoint(cp) : m;
|
|
527
|
+
});
|
|
528
|
+
}
|
|
529
|
+
/**
|
|
530
|
+
* The value of `name` when it is bound exactly once in the file, by `const`,
|
|
531
|
+
* to a plain string literal (no interpolation) that is the whole initializer,
|
|
532
|
+
* and has no other `let` / `var` / `function` binding; otherwise null.
|
|
533
|
+
* (cognium-dev#681)
|
|
534
|
+
*/
|
|
535
|
+
function constStringLiteralValue(code, name) {
|
|
536
|
+
const esc = name.replace(/\$/g, '\\$');
|
|
537
|
+
const decl = new RegExp(`(?:^|[^\\w$.])const\\s+${esc}\\s*(?::\\s*string\\s*)?=\\s*(?:'((?:\\\\.|[^'\\\\\\n])*)'|"((?:\\\\.|[^"\\\\\\n])*)"|\`([^\`$\\\\]*)\`)`, 'g');
|
|
538
|
+
const decls = [...code.matchAll(decl)];
|
|
539
|
+
if (decls.length !== 1)
|
|
540
|
+
return null;
|
|
541
|
+
if (!literalEndsInitializer(code, decls[0].index + decls[0][0].length))
|
|
542
|
+
return null;
|
|
543
|
+
const anyBinding = new RegExp(`(?:^|[^\\w$.])(?:const|let|var|function)\\s+${esc}\\b`, 'g');
|
|
544
|
+
if ([...code.matchAll(anyBinding)].length !== 1)
|
|
545
|
+
return null;
|
|
546
|
+
return decodeJsHexEscapes(decls[0][1] ?? decls[0][2] ?? decls[0][3] ?? '');
|
|
547
|
+
}
|
|
548
|
+
/** A group that holds an unbounded quantifier and is itself quantified: `(a+)+`, `(x*)*`, `(\w{2,})+`, `(a+){2,}`. */
|
|
549
|
+
const NESTED_QUANTIFIER_RE = /\([^()]*(?:[+*]|\{\d+,\d*\})[^()]*\)\s*[+*{]/;
|
|
550
|
+
/** A template literal that starts with `${IDENT}/` (cognium-dev#680). */
|
|
551
|
+
const CONST_BASE_TEMPLATE_RE = /`\$\{\s*([A-Za-z_$][\w$]*)\s*\}\//g;
|
|
552
|
+
/**
|
|
553
|
+
* True when `name` is bound exactly once in the file, by `const`, to a string
|
|
554
|
+
* literal http(s) origin with a literal host, and is never reassigned.
|
|
555
|
+
*/
|
|
556
|
+
function isConstLiteralOrigin(code, name) {
|
|
557
|
+
const esc = name.replace(/\$/g, '\\$');
|
|
558
|
+
const decl = new RegExp(`(?:^|[^\\w$.])(const|let|var)\\s+${esc}\\s*(?::\\s*string\\s*)?=\\s*(['"\`])(https?://[^/'"\`\\s$]+(?:/[^'"\`$]*)?)\\2`, 'gm');
|
|
559
|
+
const decls = [...code.matchAll(decl)];
|
|
560
|
+
if (decls.length !== 1 || decls[0][1] !== 'const')
|
|
561
|
+
return false;
|
|
562
|
+
if (!literalEndsInitializer(code, decls[0].index + decls[0][0].length))
|
|
563
|
+
return false;
|
|
564
|
+
const anyBinding = new RegExp(`(?:^|[^\\w$.])(?:const|let|var)\\s+${esc}\\b`, 'g');
|
|
565
|
+
if ([...code.matchAll(anyBinding)].length !== 1)
|
|
566
|
+
return false;
|
|
567
|
+
const reassign = new RegExp(`(?:^|[^\\w$.])${esc}\\s*(?:[-+]?=)(?!=)`, 'g');
|
|
568
|
+
const rest = code.slice(0, decls[0].index) + code.slice(decls[0].index + decls[0][0].length);
|
|
569
|
+
return !reassign.test(rest);
|
|
570
|
+
}
|
|
467
571
|
/**
|
|
468
572
|
* Returns the 1-indexed line numbers that a Java `if (x.contains("..")) throw/
|
|
469
573
|
* return` reject-guard makes path-traversal-safe (cognium-dev#269). A line is
|
|
@@ -656,6 +760,33 @@ function isUnwrittenLocalMapKeyRead(code, source) {
|
|
|
656
760
|
return false;
|
|
657
761
|
return true;
|
|
658
762
|
}
|
|
763
|
+
/**
|
|
764
|
+
* Is this C# `Content(...)` call the controller helper writing an HTML body
|
|
765
|
+
* (cognium-dev#580)?
|
|
766
|
+
*
|
|
767
|
+
* - The helper is inherited (`ControllerBase.Content`, `PageModel.Content`),
|
|
768
|
+
* so it is called unqualified or on `this` / `base`. `note.Content(q)` is
|
|
769
|
+
* some other type's method.
|
|
770
|
+
* - The content type is argument 1. A literal or `MediaTypeNames` constant
|
|
771
|
+
* that is not HTML or a script-capable XML type serves the body as data. A computed content type is unknown and keeps the sink, as does the
|
|
772
|
+
* one-argument overload.
|
|
773
|
+
*/
|
|
774
|
+
function csharpContentServesHtml(call) {
|
|
775
|
+
if (call.receiver !== null && call.receiver !== 'this' && call.receiver !== 'base')
|
|
776
|
+
return false;
|
|
777
|
+
const contentType = call.arguments.find(a => a.position === 1)?.expression.trim();
|
|
778
|
+
if (contentType === undefined)
|
|
779
|
+
return true;
|
|
780
|
+
const literal = /^@?"([^"]*)"$/.exec(contentType);
|
|
781
|
+
// XML types (`text/xml`, `application/xml`, `image/svg+xml`, any `+xml`)
|
|
782
|
+
// render XHTML / SVG markup and run its scripts, so they count as HTML.
|
|
783
|
+
if (literal)
|
|
784
|
+
return /^\s*(?:text\/html|text\/xml|application\/xml|[\w.-]+\/[\w.-]+\+xml)\b/i.test(literal[1]);
|
|
785
|
+
const named = /^(?:System\s*\.\s*Net\s*\.\s*Mime\s*\.\s*)?MediaTypeNames\s*\.\s*(Text|Application)\s*\.\s*(\w+)$/.exec(contentType);
|
|
786
|
+
if (named)
|
|
787
|
+
return named[2] === 'Html' || named[2] === 'Xml';
|
|
788
|
+
return true;
|
|
789
|
+
}
|
|
659
790
|
/**
|
|
660
791
|
* Compute, per sink type, the set of C# variables whose value has passed through
|
|
661
792
|
* a sanitizer for that type (cognium-dev C#/.NET Phase-1). Seeds from
|
|
@@ -2042,7 +2173,51 @@ export class SinkFilterPass {
|
|
|
2042
2173
|
if (sink.type !== 'ssrf')
|
|
2043
2174
|
return true;
|
|
2044
2175
|
const sinkLineText = sourceLines[sink.line - 1] ?? '';
|
|
2045
|
-
|
|
2176
|
+
if (FIXED_HOST_TEMPLATE_RE.test(sinkLineText))
|
|
2177
|
+
return false;
|
|
2178
|
+
// `${API_BASE}/path` where API_BASE is bound once by `const` to a
|
|
2179
|
+
// literal origin: the authority is constant and closed by `/` (#680).
|
|
2180
|
+
for (const m of sinkLineText.matchAll(CONST_BASE_TEMPLATE_RE)) {
|
|
2181
|
+
if (isConstLiteralOrigin(ctx.code, m[1]))
|
|
2182
|
+
return false;
|
|
2183
|
+
}
|
|
2184
|
+
return true;
|
|
2185
|
+
});
|
|
2186
|
+
}
|
|
2187
|
+
// Stage 15k — JS/TS redos: `new RegExp(`…${CONST}…`)` whose every
|
|
2188
|
+
// interpolation is a module `const` bound to a string literal has a
|
|
2189
|
+
// constant pattern; a tainted subject alone is not ReDoS. (cognium-dev#681)
|
|
2190
|
+
if (['javascript', 'typescript'].includes(language)) {
|
|
2191
|
+
const sourceLines = ctx.code.split('\n');
|
|
2192
|
+
filtered = filtered.filter(sink => {
|
|
2193
|
+
if (sink.type !== 'redos')
|
|
2194
|
+
return true;
|
|
2195
|
+
const m = (sourceLines[sink.line - 1] ?? '').match(/new\s+RegExp\s*\(\s*`((?:\\.|[^`\\])*)`/);
|
|
2196
|
+
if (!m)
|
|
2197
|
+
return true;
|
|
2198
|
+
let pattern = m[1];
|
|
2199
|
+
let interpolations = 0;
|
|
2200
|
+
let allConst = true;
|
|
2201
|
+
// Replace each `${ NAME }` as written (whitespace inside the braces
|
|
2202
|
+
// included) by the const's literal value.
|
|
2203
|
+
pattern = pattern.replace(/\$\{([^}]*)\}/g, (_full, raw) => {
|
|
2204
|
+
interpolations++;
|
|
2205
|
+
const name = raw.trim();
|
|
2206
|
+
if (!/^[A-Za-z_$][\w$]*$/.test(name)) {
|
|
2207
|
+
allConst = false;
|
|
2208
|
+
return '';
|
|
2209
|
+
}
|
|
2210
|
+
const value = constStringLiteralValue(ctx.code, name);
|
|
2211
|
+
if (value === null) {
|
|
2212
|
+
allConst = false;
|
|
2213
|
+
return '';
|
|
2214
|
+
}
|
|
2215
|
+
return value;
|
|
2216
|
+
});
|
|
2217
|
+
if (interpolations === 0 || !allConst)
|
|
2218
|
+
return true;
|
|
2219
|
+
// A constant pattern can still backtrack on a tainted subject.
|
|
2220
|
+
return NESTED_QUANTIFIER_RE.test(pattern);
|
|
2046
2221
|
});
|
|
2047
2222
|
}
|
|
2048
2223
|
// Stage 15f — JS/TS ssrf: anchored host allow-list reject-guard.
|
|
@@ -2118,6 +2293,37 @@ export class SinkFilterPass {
|
|
|
2118
2293
|
return !covered || credit.rawTaintReaches(sink.type, sink.line, sanitizedVars, csSeeds);
|
|
2119
2294
|
});
|
|
2120
2295
|
}
|
|
2296
|
+
// Stage 15k' — C# `Content(body, contentType)` serves HTML only when the
|
|
2297
|
+
// content type is HTML (cognium-dev#580). The `Content` xss sink stays when
|
|
2298
|
+
// at least one `Content` call on its line is the controller helper with an
|
|
2299
|
+
// HTML or unknown content type.
|
|
2300
|
+
if (language === 'csharp') {
|
|
2301
|
+
filtered = filtered.filter(sink => {
|
|
2302
|
+
if (sink.type !== 'xss' || sink.method !== 'Content')
|
|
2303
|
+
return true;
|
|
2304
|
+
const contentCalls = callsByLine.get(sink.line)?.filter(c => c.method_name === 'Content') ?? [];
|
|
2305
|
+
return contentCalls.length === 0 || contentCalls.some(csharpContentServesHtml);
|
|
2306
|
+
});
|
|
2307
|
+
}
|
|
2308
|
+
// Stage 15m — bash ssrf: fixed-host URL word (cognium-dev#495, #669).
|
|
2309
|
+
// The bash analogue of Stage 15i: `curl -- "https://api.example.com/${p}"`
|
|
2310
|
+
// can only reach the literal host, whatever `$p` holds. Every word on the
|
|
2311
|
+
// line that expands a variable must be such a URL; a word like `"$url"`,
|
|
2312
|
+
// `"https://${host}/x"` or `"https://api.example.com${p}"` (no `/` to
|
|
2313
|
+
// close the authority, so `$p` may be `@evil.com`) keeps the sink.
|
|
2314
|
+
if (language === 'bash') {
|
|
2315
|
+
const sourceLines = ctx.code.split('\n');
|
|
2316
|
+
filtered = filtered.filter(sink => {
|
|
2317
|
+
if (sink.type !== 'ssrf')
|
|
2318
|
+
return true;
|
|
2319
|
+
const words = (sourceLines[sink.line - 1] ?? '').match(/"[^"]*"|'[^']*'|[^\s"']+/g) ?? [];
|
|
2320
|
+
const expanding = words.filter(w => !w.startsWith("'") && w.includes('$'));
|
|
2321
|
+
// Unquoted (`https://h/$p`), the expansion is word-split, so `$p`
|
|
2322
|
+
// can add a second URL or a flag: only a double-quoted word counts.
|
|
2323
|
+
return expanding.length === 0 ||
|
|
2324
|
+
!expanding.every(w => w.startsWith('"') && BASH_FIXED_HOST_URL_RE.test(w.slice(1, -1)));
|
|
2325
|
+
});
|
|
2326
|
+
}
|
|
2121
2327
|
// Stage 15l — C# ssrf: HttpClient with a constant BaseAddress and a
|
|
2122
2328
|
// relative request path. (cognium-dev#286 D)
|
|
2123
2329
|
//
|