@clear-capabilities/agentic-security-scanner 0.186.2 → 0.188.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/CHANGELOG.md +20 -0
- package/dist/1602.index.js +275 -19
- package/dist/{4d06c8944ae121d7085c.json → 92f78fd3e2dbe30fb58d.json} +5 -5
- package/dist/9560.index.js +61 -4
- package/dist/agentic-security.mjs +2 -2
- package/dist/agentic-security.mjs.sha256 +1 -1
- package/package.json +5 -5
- package/src/capabilities/decide.js +7 -1
- package/src/dataflow/CLAUDE.md +15 -0
- package/src/dataflow/catalog-haskell.js +7 -1
- package/src/dataflow/catalog.js +14 -0
- package/src/dataflow/engine.js +147 -10
- package/src/dataflow/privacy-catalog-haskell.js +2 -1
- package/src/engine.js +11 -3
- package/src/language/CLAUDE.md +26 -0
- package/src/language/compliance-map.js +6 -0
- package/src/language/context.js +20 -0
- package/src/language/haskell-comments.js +65 -0
- package/src/language/haskell-disclosure.js +16 -4
- package/src/language/haskell-findings.js +2 -1
- package/src/language/haskell-fix.js +118 -2
- package/src/language/haskell-guards.js +132 -5
- package/src/language/haskell-ir.js +228 -13
- package/src/language/haskell-models.js +108 -8
- package/src/language/haskell-security-rules.js +223 -41
- package/src/language/haskell-syntax.js +10 -1
- package/src/language/haskell-trust.js +268 -0
- package/src/language/haskell-web.js +46 -9
- package/src/language/support-registry.js +3 -2
- package/src/mcp/tools.js +54 -3
- package/src/posture/attack-taxonomy.js +10 -0
- package/src/posture/entrypoint-inventory.js +6 -2
- package/src/posture/proof-fabric/generate-haskell.js +266 -17
- package/src/posture/proof-fabric/generate.js +10 -3
- package/src/posture/proof-fabric/oracles.js +21 -0
- package/src/posture/stable-id.js +2 -1
- package/src/report/index.js +3 -0
- package/src/sast/cloud-iam.js +3 -1
- package/dist/2066.index.js +0 -851
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,26 @@
|
|
|
9
9
|
> make the history less accurate, not more.
|
|
10
10
|
|
|
11
11
|
|
|
12
|
+
## 0.188.0 - Haskell trust-boundary precision for real code
|
|
13
|
+
|
|
14
|
+
- **Who controls the input.** Haskell taint findings now carry a `trustBoundary` verdict. Flows whose only origin is the operator's own command line, environment or configuration, and thin process wrappers, are lowered to `info` (original severity kept), never dropped. Origins are now tracked through derivations, calls and returns. Unreachable-looking functions caused by ambiguous platform imports, Haskell pragmas read as JSON policy, JavaScript-syntax patterns firing on Haskell text, and comments leaking into finding snippets (and so into stable ids) were fixed. `unsafe*` boundary notes report as informational.
|
|
15
|
+
- **Remediation.** New `takeFileName` rewrite for path traversal; the SQL rewrite uses the driver the file already imports (PostgreSQL or SQLite) and refuses others. SSRF, argument injection, password hashing, predictable randomness, cookie attributes, missing auth, resource limits, TLS validation and hard-coded secrets refuse with a class-level reason. The process and path rewrites were type-checked with GHC; the SQL, HTML and hash patches were checked only against stubs of the documented API.
|
|
16
|
+
- **New guard.** A comment-invariance test scans the Haskell cases as written, with comments blanked, and with lying comments in both directions, and requires identical findings.
|
|
17
|
+
- **Measured, and mostly not generalising.** On a new 118-site development sample from eight real projects (one labeler who read every site), precision went from 4.2% to 35.7% (5 of 14 still flagged); the verification half is 1 of 4, so those counts are tiny. On six fresh projects scanned once, precision was 9.5% before and 10.6% after the first fix round, and 37.8% after follow-up fixes that the set itself motivated, so that figure is not independent. On the sealed independent Haskell set (four projects), precision is 2.9% (1 of 35 decided sites, 95% interval 0.5% to 14.5%), against 2.3% before: essentially unchanged. On unseen-v4, SAST recall is unchanged at 54.2% and taint recall fell from 73.3% to 66.7% (one case). The gains are on code the work was developed against, not on sealed code.
|
|
18
|
+
- **Recall cost on a fresh set.** Four true-positive sites in IHP's own development IDE (a command injection from an HTTP path and two request-indexed list lookups) are no longer found when scanning IHP itself; IHP request sources were added so the same flaw is found in IHP-style apps.
|
|
19
|
+
- **Real vulnerabilities found in the development sets:** weak password hashing and a predictable session id in gitit, a predictable digest nonce in hackage-server, disabled TLS verification and unbounded request bodies in IHP, an unvalidated path-traversal read in dhall's test server, reflected XSS and an open redirect in Scotty examples. None has a verified fix: all refuse honestly.
|
|
20
|
+
|
|
21
|
+
## 0.187.0 - Haskell parity work: wider exploit proof, broader SAST and taint, new unseen measurement sets
|
|
22
|
+
|
|
23
|
+
- **Haskell SAST and taint, generalised beyond the shapes they were written against.** New sources and sinks (Scotty, Yesod, WAI, Servant, Req, conduit, http-client), guards recognised by what they do rather than by name (host allow-lists, hand-written HTML escapers, `sh -c` scripts), SSRF reported at the send instead of the parse, and Haskell-scoped engine fixes for branches handed to combinators, `words`, `>>=` and common lowering forms. On unseen-v3, now a development set, SAST and taint reach 100%; that is a regression result, not a generalisation claim.
|
|
24
|
+
- **Honest unseen measurement.** A new set, unseen-v4 (78 forms, 13 families, measured once before this release's engine work), gives SAST recall 45.8% to 54.2% and taint precision 73.3% to 84.6%; taint recall is unchanged at 73.3%. Several families remain at 0 to 33% recall.
|
|
25
|
+
- **Real-code precision did not move.** On four pinned real Haskell projects (`bench/dag/independent-haskell/`, one LLM labeler, 60 of the flagged sites), default-scan precision is 2.3% (95% interval 0.4% to 12.1%), against 2.0% before. The new engine flags additional sites that are unlabeled and are not counted.
|
|
26
|
+
- **Alias fix.** A point-free alias of a library function (`tidy = takeFileName`, `run = callCommand`) was treated as an unresolved call, so a sanitizer alias left a flow unsanitized and a sink alias went undetected. Aliases of library functions are now expanded; a local binding with the same name disables the expansion.
|
|
27
|
+
- **Exploit proof.** Widened Haskell reproducer coverage and oracles.
|
|
28
|
+
- **Gates.** 56 Haskell mutation cases and 8 synthetic corpus entries (verdict-flip 460 of 460, corpus 228 of 228); layer-recall maps `.hs` and `.lhs`, taint attribution 126 to 134.
|
|
29
|
+
- **Parity outside the engine.** Haskell on the MCP `query_taint`, context, compliance mapping, capability decisions, attack taxonomy, entrypoint inventory and reports, with `docs/language-parity-haskell.md` listing what remains open.
|
|
30
|
+
- **Not done.** The container proof path is untested, `prove_finding` and `prove_fix` have no `.hs` harness builder, and `haskell-web-auth` route fixtures need a host with scotty, wai, servant and yesod to compile.
|
|
31
|
+
|
|
12
32
|
## 0.186.2 - Haskell exploit proof, a default-scan drift gate, and the measurements behind earlier claims
|
|
13
33
|
|
|
14
34
|
- **Haskell in the exploit proof fabric (GA capability, new language).** `proof doctor` now lists `haskell` and `proof generate` builds reproducers for Haskell findings. Reproducers run in GHC's interpreter (`ghc -e`), so there is no build step. Command injection and path-traversal writes are proven; server-side request forgery is refused because no HTTP client ships with GHC; SQL, argument injection and deserialization are refused by name. Only `base` and the packages that ship with GHC are allowed (read from the installed GHC); a handler that needs a web framework is refused with the package named. Template Haskell, quasi-quotes, CPP, the foreign function interface and plugin options are refused as load-time code execution. 45 of 45 fixture reproductions across 15 classes, 0 false confirmations. Limits: exercised under local confinement on macOS with GHC 9.14.1 only; the container image is wired but was not run against a real engine, and Linux was not exercised.
|
package/dist/1602.index.js
CHANGED
|
@@ -194,9 +194,19 @@ var haskell_parser = __webpack_require__(99864);
|
|
|
194
194
|
// or any Hackage package is refused with the package named where it is known. Template Haskell, quasi-quotes, CPP, the foreign
|
|
195
195
|
// function interface and compiler-plugin options are refused too: they run code at load time, before the payload is involved.
|
|
196
196
|
//
|
|
197
|
-
// Classes
|
|
198
|
-
//
|
|
199
|
-
//
|
|
197
|
+
// Classes, each with an oracle that sees its effect and nothing else:
|
|
198
|
+
// command injection (CWE-78) a nonce-named canary file the injected command alone could create;
|
|
199
|
+
// path traversal by a WRITE a file created or changed outside the directory the program writes to (CWE-22);
|
|
200
|
+
// path traversal by a READ a per-run secret, planted in a file one directory above the program's base directory, appears in the
|
|
201
|
+
// program's output (stdout, stderr or, for a function, its printed result). A read whose content never
|
|
202
|
+
// reaches the output leaves nothing to see and stays unproven;
|
|
203
|
+
// argument injection (CWE-88) the called program is replaced by a harness stand-in that acts on one planted option, but only when that
|
|
204
|
+
// option is its FIRST argument; the canary exists only if attacker data reached the first position of the
|
|
205
|
+
// argument vector. It shows the option position is attacker-controlled, not that the real program has a
|
|
206
|
+
// dangerous option, and the generated reproducer says so in its assumptions.
|
|
207
|
+
// Refused on purpose, with the construct named and the way to supply a hand-written reproducer: SSRF (no HTTP client ships with GHC), SQL
|
|
208
|
+
// (no database binding ships with GHC), deserialization, XSS, code injection, argument injection past the first argument, reads and writes
|
|
209
|
+
// whose base directory the file does not state, and any function the proof cannot fill or call. Nothing is executed on a refusal.
|
|
200
210
|
|
|
201
211
|
|
|
202
212
|
|
|
@@ -281,20 +291,189 @@ function classify(mod, pkg, boot) {
|
|
|
281
291
|
return { ok: false, name: mod };
|
|
282
292
|
}
|
|
283
293
|
|
|
294
|
+
// ---------------------------------------------------------------------------------------------------------------- parameter types
|
|
295
|
+
|
|
296
|
+
const STRING_TYPES = /^(?:String|Prelude\.String|FilePath|System\.IO\.FilePath|\[Char\])$/;
|
|
297
|
+
const unparen = (t) => { let x = t.trim(); while (x.startsWith('(') && x.endsWith(')') && splitArrows(x.slice(1, -1)).length === 1 && !x.slice(1, -1).includes(',')) x = x.slice(1, -1).trim(); return x; };
|
|
298
|
+
|
|
299
|
+
/** What the file means by `Text` and `ByteString` (an import of the real module, not a local type of the same name) and its one-line `type` aliases. */
|
|
300
|
+
function typeResolver(info, text) {
|
|
301
|
+
const textQ = new Set(); const bytesQ = new Set(); let textBare = false; let bytesBare = false;
|
|
302
|
+
for (const imp of info.imports ?? []) {
|
|
303
|
+
const isText = /^Data\.Text(?:\.Lazy)?$/.test(imp.module);
|
|
304
|
+
const isBytes = /^Data\.ByteString(?:\.(?:Char8|Lazy|Lazy\.Char8))?$/.test(imp.module);
|
|
305
|
+
if (!isText && !isBytes) continue;
|
|
306
|
+
const bare = !imp.qualified && !imp.hiding && (imp.items == null || imp.items.some((i) => /^(?:Text|ByteString)\b/.test(i)));
|
|
307
|
+
if (isText) { textQ.add(imp.as ?? imp.module); textBare ||= bare; } else { bytesQ.add(imp.as ?? imp.module); bytesBare ||= bare; }
|
|
308
|
+
}
|
|
309
|
+
const localDef = (n) => new RegExp(`^(?:data|newtype)\\s+${n}\\b`, 'm').test(text);
|
|
310
|
+
if (localDef('Text')) textBare = false;
|
|
311
|
+
if (localDef('ByteString')) bytesBare = false;
|
|
312
|
+
const aliases = new Map();
|
|
313
|
+
for (const m of text.matchAll(/^type\s+([A-Z][\w']*)\s*=\s*([^\n=]+?)\s*(?:--.*)?$/gm)) aliases.set(m[1], m[2]);
|
|
314
|
+
const resolve = (t, depth = 0) => {
|
|
315
|
+
const x = unparen(t);
|
|
316
|
+
if (depth < 4 && aliases.has(x)) return resolve(aliases.get(x), depth + 1);
|
|
317
|
+
return x;
|
|
318
|
+
};
|
|
319
|
+
const stringish = (t) => {
|
|
320
|
+
const x = resolve(t);
|
|
321
|
+
if (STRING_TYPES.test(x)) return 'string';
|
|
322
|
+
const q = /^(?:([A-Z][\w.]*)\.)?(Text|ByteString)$/.exec(x);
|
|
323
|
+
if (!q) return null;
|
|
324
|
+
if (q[2] === 'Text') return q[1] ? (textQ.has(q[1]) ? 'overloaded' : null) : (textBare ? 'overloaded' : null);
|
|
325
|
+
return q[1] ? (bytesQ.has(q[1]) ? 'overloaded' : null) : (bytesBare ? 'overloaded' : null);
|
|
326
|
+
};
|
|
327
|
+
/** `{lit}` is the Haskell expression for a value of this type holding `value`, `{needsOverloaded}` whether it relies on OverloadedStrings. */
|
|
328
|
+
const fill = (t, value) => {
|
|
329
|
+
const x = resolve(t);
|
|
330
|
+
const one = stringish(x);
|
|
331
|
+
if (one) return { expr: value, overloaded: one === 'overloaded' };
|
|
332
|
+
const list = /^\[\s*(.+?)\s*\]$/.exec(x);
|
|
333
|
+
if (list) { const e = stringish(list[1]); if (e) return { expr: `[${value}]`, overloaded: e === 'overloaded' }; }
|
|
334
|
+
const maybe = /^Maybe\s+(.+)$/.exec(x);
|
|
335
|
+
if (maybe) { const e = stringish(maybe[1]); if (e) return { expr: `(Just ${value})`, overloaded: e === 'overloaded' }; }
|
|
336
|
+
return null;
|
|
337
|
+
};
|
|
338
|
+
/** The result can be shown by `print` and carries the content a read returned (String, Text, ByteString, lists and Maybe of them). */
|
|
339
|
+
const printable = (t) => {
|
|
340
|
+
const x = resolve(t);
|
|
341
|
+
return !!(stringish(x) || (/^\[\s*(.+?)\s*\]$/.exec(x) && stringish(/^\[\s*(.+?)\s*\]$/.exec(x)[1])) || (/^Maybe\s+(.+)$/.exec(x) && stringish(/^Maybe\s+(.+)$/.exec(x)[1])));
|
|
342
|
+
};
|
|
343
|
+
return { fill, printable, resolve };
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// ---------------------------------------------------------------------------------------------------------------- path traversal: write or read
|
|
347
|
+
|
|
348
|
+
const READ_SINK = /\b(?:readFile'?|readFileBinary)\b|\b(?:openFile|withFile|openBinaryFile|withBinaryFile)\b[^\n]*\bReadMode\b/;
|
|
349
|
+
const READ_PAYLOAD = '../agentic-proof-secret.txt';
|
|
350
|
+
const READ_SECRET_FILE = 'agentic-proof-secret.txt';
|
|
351
|
+
const READ_ORACLE = { type: 'file_disclosure', params: { secret: 'file' } };
|
|
352
|
+
const WRITE_CONSTRUCTS = 'writeFile, appendFile, copyFile, renameFile, or openFile/withFile in WriteMode/AppendMode';
|
|
353
|
+
const READ_CONSTRUCTS = 'readFile, or openFile/withFile in ReadMode';
|
|
354
|
+
|
|
355
|
+
/** Which path operation the flagged line is: its own line first, then the lines around it. */
|
|
356
|
+
function pathKind(sinkLine, around, writeRe) {
|
|
357
|
+
if (writeRe.test(sinkLine)) return 'write';
|
|
358
|
+
if (READ_SINK.test(sinkLine)) return 'read';
|
|
359
|
+
if (writeRe.test(around)) return 'write';
|
|
360
|
+
if (READ_SINK.test(around)) return 'read';
|
|
361
|
+
return null;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* The directories a read is meant to stay under, as far as the source says: a literal that ends in a slash, or sits next to `</>`, or is
|
|
366
|
+
* bound to a name that says directory. The proof creates them (empty) so that `dir/../secret` resolves; a program whose base is not a
|
|
367
|
+
* relative literal cannot be modelled and is refused rather than guessed.
|
|
368
|
+
*/
|
|
369
|
+
function readBaseDirs(text) {
|
|
370
|
+
const found = [];
|
|
371
|
+
const add = (lit) => {
|
|
372
|
+
if (!lit || lit.startsWith('/') || lit.includes('..') || lit.includes('\\') || /[{}\s:*?"<>|]/.test(lit)) return;
|
|
373
|
+
const seg = lit.split('/').filter(Boolean)[0];
|
|
374
|
+
if (!seg || seg === '.' || ['canary', 'tmp'].includes(seg) || !/^[A-Za-z0-9._-]{1,32}$/.test(seg) || seg.startsWith('__oracle_')) return;
|
|
375
|
+
if (!found.includes(seg)) found.push(seg);
|
|
376
|
+
};
|
|
377
|
+
for (const m of text.matchAll(/"([^"\\\n]+\/)"/g)) add(m[1]);
|
|
378
|
+
for (const m of text.matchAll(/"([^"\\\n]+)"\s*<\/>/g)) add(m[1]);
|
|
379
|
+
for (const m of text.matchAll(/<\/>\s*"([^"\\\n]+)"/g)) add(m[1]);
|
|
380
|
+
for (const m of text.matchAll(/\b[a-z]\w*(?:Dir|Base|Root|Folder|Path|Directory)\w*'?\s*=\s*"([^"\\\n]+)"/gi)) add(m[1]);
|
|
381
|
+
return found.slice(0, 4);
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// ---------------------------------------------------------------------------------------------------------------- argument injection
|
|
385
|
+
|
|
386
|
+
// Shells and the tools the proof itself runs are never stood in for: an argument to a shell is command injection (CWE-78), and shadowing
|
|
387
|
+
// a toolchain program on PATH would break the proof rather than test the finding.
|
|
388
|
+
const NEVER_STAND_IN = new Set(['sh', 'bash', 'dash', 'zsh', 'csh', 'tcsh', 'ksh', 'fish', 'env', 'ghc', 'runghc', 'ghci', 'cc', 'gcc', 'clang', 'c++', 'g++', 'ld', 'as', 'ar', 'make', 'cabal', 'stack', 'nix', 'sudo', 'su', 'ssh', 'xargs', 'chmod', 'touch', 'node', 'python', 'python3']);
|
|
389
|
+
const PROCESS_CALL = /\b(callProcess|readProcess|readProcessWithExitCode|spawnProcess|rawSystem|proc)\s+(?:\$\s*)?"([^"\\\s]+)"\s*/;
|
|
390
|
+
const STAND_IN = `#!/bin/sh
|
|
391
|
+
# Stand-in for the program the code under test calls. It is planted by the proof runner, never by the target.
|
|
392
|
+
# It acts on exactly one option, and only when that option is its FIRST argument, by creating the file the option names.
|
|
393
|
+
case "$1" in
|
|
394
|
+
--agentic-proof-write=*) : > "\${1#--agentic-proof-write=}" ;;
|
|
395
|
+
esac
|
|
396
|
+
exit 0
|
|
397
|
+
`;
|
|
398
|
+
// PATH puts the stand-in directory first and keeps the system and toolchain directories after it
|
|
399
|
+
const STAND_IN_PATH = '{{ROOT}}/bin:/opt/ghc/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/homebrew/bin';
|
|
400
|
+
|
|
401
|
+
/** What stands in first position of the argument vector at the call: a named element, a whole list, a fixed string, or something else. */
|
|
402
|
+
function firstArgument(rest) {
|
|
403
|
+
if (rest.startsWith('[')) {
|
|
404
|
+
const inner = rest.slice(1).trimStart();
|
|
405
|
+
if (inner.startsWith('"')) return { kind: 'literal' };
|
|
406
|
+
if (inner.startsWith(']')) return { kind: 'empty' };
|
|
407
|
+
const m = /^([a-z_][\w']*)\s*(?:,|\])/.exec(inner);
|
|
408
|
+
return m ? { kind: 'element', name: m[1] } : { kind: 'complex' };
|
|
409
|
+
}
|
|
410
|
+
if (rest.startsWith('(')) {
|
|
411
|
+
const m = /^\(\s*([a-z_][\w']*)\s*:/.exec(rest);
|
|
412
|
+
return m ? { kind: 'element', name: m[1] } : { kind: 'complex' };
|
|
413
|
+
}
|
|
414
|
+
const m = /^([a-z_][\w']*)\s*(?:$|\)|"|--)/.exec(rest);
|
|
415
|
+
return m ? { kind: 'list', name: m[1] } : { kind: 'complex' };
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
const HINT = 'To prove it anyway, write a reproducer for lang "haskell" (run: ["{{GHC}}", "-ignore-dot-ghci", "-e", "<expression that calls the code>", "<File>.hs"], with an oracle such as command_execution, filesystem_mutation or file_disclosure) and pass it with --reproducer <file>; see the Haskell section of the exploit proof guide. Nothing was executed.';
|
|
419
|
+
|
|
420
|
+
/** What the flagged line is, in words, for a refusal message. */
|
|
421
|
+
function describeLine(finding, root) {
|
|
422
|
+
const src = (() => { try { return generate_haskell_readInside(root, String(finding.file)); } catch { return null; } })();
|
|
423
|
+
const line = src ? (src.text.split('\n')[finding.line - 1] ?? '').trim().replace(/\s+/g, ' ').slice(0, 90) : '';
|
|
424
|
+
return line ? `the flagged line \`${line}\`` : 'the flagged code';
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
const REFUSALS = {
|
|
428
|
+
'CWE-89': (what) => `sql-injection: ${what} reaches a database, and GHC ships no database binding, so a program that queries one imports a package outside the proof environment; a program that shells out to the sqlite3 command-line tool depends on a schema, a table and a column count the proof cannot know and a sqlite3 binary this host may not have. A SQL injection is not proven for Haskell.`,
|
|
429
|
+
'CWE-502': (what) => `deserialization: ${what} decodes data, and nothing observable happens when a decoder reads hostile bytes unless a gadget exists in the program; the decoders in common use (aeson, yaml, cereal) are packages outside GHC's own. A deserialization flaw is not proven for Haskell.`,
|
|
430
|
+
'CWE-79': (what) => `cross-site scripting: ${what} builds markup, and the effect is in a browser's DOM, which a command-line run cannot observe. XSS is not proven for Haskell.`,
|
|
431
|
+
'CWE-94': (what) => `code injection: ${what} evaluates code at run time through an interpreter package (hint, plugins) that does not ship with GHC. Code injection is not proven for Haskell.`,
|
|
432
|
+
'CWE-918': (what) => `ssrf: ${what} makes a request, and no HTTP client ships with GHC, so any program that makes one imports a package outside the proof environment. SSRF is not proven for Haskell.`,
|
|
433
|
+
'CWE-1427': (what) => `prompt injection: ${what} builds a model prompt, whose effect needs a model endpoint the proof does not have. Not proven for Haskell.`,
|
|
434
|
+
};
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* The reason a Haskell finding of a class this generator does not cover is refused, naming the construct and the way out.
|
|
438
|
+
* @param {{finding: object, root: string, cwe: string|null}} o
|
|
439
|
+
*/
|
|
440
|
+
function haskellRefusal({ finding, root, cwe }) {
|
|
441
|
+
const what = describeLine(finding, root);
|
|
442
|
+
const body = REFUSALS[cwe]?.(what) ?? `${cwe ?? 'this class'}: no payload and oracle exist for ${cwe ?? 'it'} in Haskell (${what}). Generated reproducers cover command injection (CWE-78), path traversal by a write or a read (CWE-22) and argument injection into a process call (CWE-88).`;
|
|
443
|
+
return generate_haskell_fail(`${body} ${HINT}`);
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
// ---------------------------------------------------------------------------------------------------------------- generation
|
|
447
|
+
|
|
284
448
|
/** @param {{finding: object, root: string, cls: {name: string, payload: string, oracle: object, network?: string, watch?: object, needsHs?: RegExp}, bootModules?: Set<string>}} o */
|
|
285
|
-
function generateHaskellReproducer(
|
|
449
|
+
function generateHaskellReproducer(o) {
|
|
450
|
+
const r = generateInner(o);
|
|
451
|
+
if (r.ok || r.reason.includes('Nothing was executed.')) return r;
|
|
452
|
+
return { ...r, reason: `${r.reason.replace(/\.$/, '')}. ${HINT}` };
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
function generateInner({ finding, root, cls, bootModules }) {
|
|
286
456
|
const rel = String(finding.file);
|
|
287
|
-
if (cls.name === 'ssrf') return
|
|
457
|
+
if (cls.name === 'ssrf') return haskellRefusal({ finding, root, cwe: 'CWE-918' });
|
|
288
458
|
const src = generate_haskell_readInside(root, rel);
|
|
289
459
|
if (!src) return generate_haskell_fail('the flagged file is missing, outside the repository, or too large');
|
|
290
460
|
const hazard = loadTimeHazard(src.text);
|
|
291
461
|
if (hazard) return generate_haskell_fail(`the flagged file is refused: ${hazard}`);
|
|
462
|
+
if (/\{\{[A-Z_]+(?::[a-z0-9_-]{1,32})?\}\}/.test(src.text)) return generate_haskell_fail('the flagged file contains text shaped like a proof placeholder ({{NAME}}), which the runner would substitute inside the program');
|
|
292
463
|
const info = (0,haskell_parser/* parseHaskell */.cX)(src.text);
|
|
293
464
|
if (!info || info.status !== 'parsed') return generate_haskell_fail('the flagged file could not be parsed as Haskell');
|
|
294
465
|
const lines = src.text.split('\n');
|
|
295
466
|
const sinkLine = lines[finding.line - 1] ?? '';
|
|
296
467
|
const around = lines.slice(Math.max(0, finding.line - 3), finding.line + 2).join('\n');
|
|
297
|
-
|
|
468
|
+
|
|
469
|
+
// the class decides what is planted and what is watched; for a path operation the flagged line decides which of two it is
|
|
470
|
+
let spec = cls;
|
|
471
|
+
let kind = cls.name;
|
|
472
|
+
if (cls.name === 'path-traversal') {
|
|
473
|
+
const k = pathKind(sinkLine, around, cls.needsHs);
|
|
474
|
+
if (!k) return generate_haskell_fail(`path-traversal: ${describeLine(finding, root)} is not a write (${WRITE_CONSTRUCTS}) or a read (${READ_CONSTRUCTS}); other file operations (removeFile, createDirectory, listDirectory, doesFileExist, and the like) leave nothing the oracle can observe`);
|
|
475
|
+
if (k === 'read') { kind = 'path-traversal-read'; spec = { name: 'path-traversal-read', payload: READ_PAYLOAD, oracle: READ_ORACLE }; }
|
|
476
|
+
}
|
|
298
477
|
|
|
299
478
|
const tools = (0,runner/* hostTools */.qV)();
|
|
300
479
|
const boot = bootModules ?? (tools.ghc ? bootModuleSet(tools.ghc) : null);
|
|
@@ -322,6 +501,7 @@ function generateHaskellReproducer({ finding, root, cls, bootModules }) {
|
|
|
322
501
|
const dep = (0,haskell_parser/* parseHaskell */.cX)(local.text);
|
|
323
502
|
if (!dep || dep.status !== 'parsed') return generate_haskell_fail(`the module ${mod} could not be parsed as Haskell`);
|
|
324
503
|
const h = loadTimeHazard(local.text); if (h) return generate_haskell_fail(`the module ${mod} is refused: ${h}`);
|
|
504
|
+
if (/\{\{[A-Z_]+(?::[a-z0-9_-]{1,32})?\}\}/.test(local.text)) return generate_haskell_fail(`the module ${mod} contains text shaped like a proof placeholder ({{NAME}})`);
|
|
325
505
|
sources[`${mod.replaceAll('.', '/')}.hs`] = external_node_path_.relative(rootReal, local.real);
|
|
326
506
|
const r = visit(dep.imports ?? []); if (r) return r;
|
|
327
507
|
continue;
|
|
@@ -337,18 +517,35 @@ function generateHaskellReproducer({ finding, root, cls, bootModules }) {
|
|
|
337
517
|
sources[entry] = rel;
|
|
338
518
|
|
|
339
519
|
const assumptions = [];
|
|
340
|
-
const base = { schema: 'agentic-security/reproducer', version: 1, findingId: String(finding.stableId ?? finding.id ?? 'generated'), lang: 'haskell', oracle:
|
|
341
|
-
if (
|
|
342
|
-
const ghcRun = (expr) => ['{{GHC}}', '-ignore-dot-ghci', '-e', expr, entry];
|
|
520
|
+
const base = { schema: 'agentic-security/reproducer', version: 1, findingId: String(finding.stableId ?? finding.id ?? 'generated'), lang: 'haskell', oracle: spec.oracle, network: spec.network ?? 'none', ...(spec.watch ? { watch: spec.watch } : {}) };
|
|
521
|
+
if (spec.watch) assumptions.push('the write target is assumed to be one directory below the working directory (the payload is ../escaped.txt); if the code uses another base, the proof will not confirm it');
|
|
522
|
+
const ghcRun = (expr, overloaded = false) => ['{{GHC}}', '-ignore-dot-ghci', ...(overloaded ? ['-e', ':set -XOverloadedStrings'] : []), '-e', expr, entry];
|
|
343
523
|
const literal = (s) => JSON.stringify(s); // payloads are fixed strings with no quote or backslash; this is a plain Haskell string literal
|
|
524
|
+
const resolver = typeResolver(info, src.text);
|
|
525
|
+
|
|
526
|
+
// what the class plants beside the program
|
|
527
|
+
const extras = { files: {}, build: undefined, env: undefined };
|
|
528
|
+
if (kind === 'path-traversal-read') {
|
|
529
|
+
const dirs = readBaseDirs(src.text);
|
|
530
|
+
if (!dirs.length) return generate_haskell_fail(`path-traversal: ${describeLine(finding, root)} reads a path whose base directory is not a relative literal in the file (a path built from getCurrentDirectory, an environment variable, an absolute directory or a configuration value), so the proof cannot plant the file it would escape to`);
|
|
531
|
+
extras.files = { [READ_SECRET_FILE]: '{{SECRET:file}}', ...Object.fromEntries(dirs.map((d) => [`${d}/.keep`, ''])) };
|
|
532
|
+
assumptions.push(`the read is assumed to be confined under ${dirs.map((d) => `"${d}"`).join(' or ')}, one directory below the working directory; the proof plants a file one level up (${READ_PAYLOAD}) and sees it only if it reaches the program's output (stdout, stderr or, for a function, its printed result)`);
|
|
533
|
+
}
|
|
344
534
|
|
|
345
535
|
// shape 1: a program that reads its payload from the command line
|
|
346
536
|
const hasMain = (info.functions ?? []).some((f) => f.scope === 'top' && f.name === 'main');
|
|
347
537
|
if (/\bgetArgs\b/.test(src.text) && hasMain) {
|
|
538
|
+
if (kind === 'argument-injection') {
|
|
539
|
+
const call = argumentCall(lines, finding);
|
|
540
|
+
if (!call.ok) return call;
|
|
541
|
+
if (call.first.kind !== 'list' || !new RegExp(`\\b${call.first.name}\\s*<-\\s*getArgs\\b`).test(src.text)) return generate_haskell_fail(`argument-injection: the first argument of the call to ${call.exe} is ${describeFirst(call.first)}, and the proof can place the payload only where the whole argument vector comes straight from getArgs (\`args <- getArgs\` then the call with \`args\`)`);
|
|
542
|
+
Object.assign(extras, standIn(call.exe));
|
|
543
|
+
assumptions.push(...standInAssumptions(call.exe));
|
|
544
|
+
}
|
|
348
545
|
assumptions.push('the payload is passed as the first and only command-line argument; a program that expects other arguments will not reach the flagged line');
|
|
349
|
-
const reproducer = { ...base, sources, run: ghcRun(`:main ${literal(
|
|
546
|
+
const reproducer = { ...base, sources, ...(Object.keys(extras.files).length ? { files: extras.files } : {}), ...(extras.build ? { build: extras.build } : {}), ...(extras.env ? { env: extras.env } : {}), run: ghcRun(`:main ${literal(spec.payload)}`) };
|
|
350
547
|
const errs = (0,proof_fabric_reproducer/* validateReproducer */.mC)(reproducer);
|
|
351
|
-
return errs.length ? generate_haskell_fail(`the generated reproducer is invalid: ${errs[0]}`) : { ok: true, reproducer, basis: { shape: 'script', class:
|
|
548
|
+
return errs.length ? generate_haskell_fail(`the generated reproducer is invalid: ${errs[0]}`) : { ok: true, reproducer, basis: { shape: 'script', class: spec.name, entry: rel, line: finding.line, assumptions } };
|
|
352
549
|
}
|
|
353
550
|
|
|
354
551
|
// shape 2: a top-level function around the flagged line
|
|
@@ -368,14 +565,66 @@ function generateHaskellReproducer({ finding, root, cls, bootModules }) {
|
|
|
368
565
|
const result = parts[parts.length - 1]; const params = parts.slice(0, -1);
|
|
369
566
|
if (!/^IO\b/.test(result)) return generate_haskell_fail(`${fn.name} returns ${result.slice(0, 40)}, not IO, so calling it would not perform the flagged operation`);
|
|
370
567
|
if (!params.length) return generate_haskell_fail(`${fn.name} takes no parameters, so the payload has no way in`);
|
|
371
|
-
const
|
|
372
|
-
if (
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
568
|
+
const resultInner = result.replace(/^IO\s*/, '').trim();
|
|
569
|
+
if (kind === 'path-traversal-read' && resultInner !== '()' && !resolver.printable(resultInner)) return generate_haskell_fail(`${fn.name} returns IO ${resultInner.slice(0, 40)}, whose content the proof cannot print; a read is observed only in the output, so the result must be (), String, Text, ByteString or a list or Maybe of them`);
|
|
570
|
+
|
|
571
|
+
let payloadFor = () => spec.payload; // which parameters get the payload (all, unless the class says which)
|
|
572
|
+
if (kind === 'argument-injection') {
|
|
573
|
+
const call = argumentCall(lines, finding);
|
|
574
|
+
if (!call.ok) return call;
|
|
575
|
+
const headLine = lines[fn.span.startLine - 1] ?? '';
|
|
576
|
+
const head = new RegExp(`^${fn.name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}((?:\\s+[a-z_][\\w']*)*)\\s*(?:=|\\|)`).exec(headLine);
|
|
577
|
+
const names = head ? head[1].trim().split(/\s+/).filter(Boolean) : null;
|
|
578
|
+
if (!names || names.length !== params.length) return generate_haskell_fail(`argument-injection: the parameters of ${fn.name} are patterns or the definition is point-free, so the proof cannot tell which parameter reaches the call`);
|
|
579
|
+
if (call.first.kind !== 'element' && call.first.kind !== 'list') return generate_haskell_fail(`argument-injection: the first argument of the call to ${call.exe} is ${describeFirst(call.first)}, and the proof can place the payload only where a plain parameter of ${fn.name} stands first in the argument vector`);
|
|
580
|
+
const at = names.indexOf(call.first.name);
|
|
581
|
+
if (at < 0) return generate_haskell_fail(`argument-injection: the first argument of the call to ${call.exe} is \`${call.first.name}\`, which is not a parameter of ${fn.name}, so the proof cannot place the payload there`);
|
|
582
|
+
const shape = resolver.fill(params[at], 'x');
|
|
583
|
+
if (!shape) return generate_haskell_fail(`${fn.name} takes a parameter of type ${params[at].slice(0, 40)}; only String, FilePath, Text, ByteString and lists or Maybe of them can be filled with a payload`);
|
|
584
|
+
if (call.first.kind === 'list' && !/^\[/.test(shape.expr)) return generate_haskell_fail(`argument-injection: ${call.first.name} is passed as the whole argument vector but has type ${params[at].slice(0, 40)}, not a list of strings`);
|
|
585
|
+
if (call.first.kind === 'element' && /^\[/.test(shape.expr)) return generate_haskell_fail(`argument-injection: ${call.first.name} is a list but stands as one element of the argument vector`);
|
|
586
|
+
payloadFor = (i) => (i === at ? spec.payload : 'benign');
|
|
587
|
+
Object.assign(extras, standIn(call.exe));
|
|
588
|
+
assumptions.push(...standInAssumptions(call.exe), `the payload is placed in the parameter \`${call.first.name}\` only; the other parameters get the value "benign"`);
|
|
589
|
+
} else assumptions.push('the payload is passed in every parameter (a String has no request-like stand-in), which is an approximation of how the function is really called');
|
|
590
|
+
|
|
591
|
+
const filled = [];
|
|
592
|
+
let overloaded = false;
|
|
593
|
+
for (let i = 0; i < params.length; i++) {
|
|
594
|
+
const f = resolver.fill(params[i], literal(payloadFor(i)));
|
|
595
|
+
if (!f) return generate_haskell_fail(`${fn.name} takes a parameter of type ${params[i].slice(0, 40)}; only String, FilePath, Text, ByteString and lists or Maybe of them can be filled with a payload`);
|
|
596
|
+
filled.push(f.expr); overloaded ||= f.overloaded;
|
|
597
|
+
}
|
|
598
|
+
if (overloaded) assumptions.push('Text and ByteString arguments are written as string literals under OverloadedStrings, set for the call only, not for the program');
|
|
599
|
+
const tail = kind === 'path-traversal-read' && resultInner !== '()' ? '>>= print' : '>>= \\_ -> return ()';
|
|
600
|
+
const call = `${fn.name} ${filled.join(' ')} ${tail}`;
|
|
601
|
+
const reproducer = { ...base, sources, ...(Object.keys(extras.files).length ? { files: extras.files } : {}), ...(extras.build ? { build: extras.build } : {}), ...(extras.env ? { env: extras.env } : {}), run: ghcRun(call, overloaded) };
|
|
376
602
|
const errs = (0,proof_fabric_reproducer/* validateReproducer */.mC)(reproducer);
|
|
377
|
-
return errs.length ? generate_haskell_fail(`the generated reproducer is invalid: ${errs[0]}`) : { ok: true, reproducer, basis: { shape: 'function', class:
|
|
603
|
+
return errs.length ? generate_haskell_fail(`the generated reproducer is invalid: ${errs[0]}`) : { ok: true, reproducer, basis: { shape: 'function', class: spec.name, entry: rel, line: finding.line, function: `${fn.name}(${params.length} ${params.every((p) => STRING_TYPES.test(p.trim())) ? 'String' : params.length === 1 ? 'parameter' : 'parameters'})`, assumptions } };
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
function describeFirst(first) {
|
|
607
|
+
return { literal: 'a fixed string', empty: 'absent (an empty list)', complex: 'an expression the proof cannot read as a plain parameter', element: 'a parameter', list: 'a list' }[first.kind] ?? 'unreadable';
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
/** Find the process call at the flagged line and what stands first in its argument vector. */
|
|
611
|
+
function argumentCall(lines, finding) {
|
|
612
|
+
const window = lines.slice(Math.max(0, finding.line - 1), finding.line + 2).join(' ').replace(/\s+/g, ' ');
|
|
613
|
+
const m = PROCESS_CALL.exec(window);
|
|
614
|
+
if (!m) return generate_haskell_fail('argument-injection: the flagged line is not a call to callProcess, readProcess, readProcessWithExitCode, spawnProcess, rawSystem or proc with the program named by a string literal, so the proof cannot tell which program receives the arguments');
|
|
615
|
+
const exe = m[2];
|
|
616
|
+
if (NEVER_STAND_IN.has(exe) || !/^[A-Za-z0-9][A-Za-z0-9._+-]{0,31}$/.test(exe)) return generate_haskell_fail(`argument-injection: the program is \`${exe}\`, which the proof does not stand in for (a shell, an interpreter or a toolchain program; an argument to a shell is command injection, CWE-78)`);
|
|
617
|
+
const rest = window.slice(m.index + m[0].length).trimStart();
|
|
618
|
+
const first = firstArgument(rest);
|
|
619
|
+
if (first.kind === 'literal' || first.kind === 'empty') return generate_haskell_fail(`argument-injection: the first argument of the call to ${exe} is ${describeFirst(first)}, and the proof covers only attacker data in the FIRST position, where every conventional option parser reads a leading dash as an option; later positions depend on the program's own grammar (an option such as -f takes the next word as its value)`);
|
|
620
|
+
return { ok: true, exe, first };
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
/** The stand-in program, its permission and the PATH that finds it. */
|
|
624
|
+
function standIn(exe) {
|
|
625
|
+
return { files: { [`bin/${exe}`]: STAND_IN }, build: ['/bin/chmod', '755', `bin/${exe}`], env: { PATH: STAND_IN_PATH } };
|
|
378
626
|
}
|
|
627
|
+
const standInAssumptions = (exe) => [`the program \`${exe}\` is replaced by a harness stand-in that acts on one planted option when it is the FIRST argument; a confirmation shows attacker data reaches the first argument unseparated and unvalidated, not that the real ${exe} has a dangerous option`];
|
|
379
628
|
|
|
380
629
|
;// CONCATENATED MODULE: ./src/posture/proof-fabric/generate.js
|
|
381
630
|
// Reproducer generation from a finding's own evidence (PRD 1: `triage exploit --prove` with no hand-written reproducer).
|
|
@@ -397,6 +646,8 @@ function generateHaskellReproducer({ finding, root, cls, bootModules }) {
|
|
|
397
646
|
// loads it and calls it, filling the tainted parameter with the payload. A parameter that is a request-like object
|
|
398
647
|
// (`req`) gets a stand-in whose `body`/`query`/`params` answer every property with the payload.
|
|
399
648
|
//
|
|
649
|
+
// Haskell additionally proves path-traversal READS (a planted secret appears in the output) and argument injection into the first argument
|
|
650
|
+
// of a process call (a stand-in for the called program); see `generate-haskell.js` for what each shows and does not show.
|
|
400
651
|
// Weakness classes with a payload and an oracle that can SEE the effect: CWE-78 (a canary file created by the injected command),
|
|
401
652
|
// CWE-22 (a write that lands outside the working directory, only for write sinks), CWE-918 (a request reaching the runner's loopback
|
|
402
653
|
// listener). Others (injection into a database, deserialization, memory safety) need an environment or a native harness this does not
|
|
@@ -414,6 +665,10 @@ const CLASSES = {
|
|
|
414
665
|
'CWE-22': { needsPy: /\bopen\s*\([^)]*['"][wax]b?\+?['"]|\.write_(?:text|bytes)\s*\(|\bshutil\.(?:copy|move)/, name: 'path-traversal', payload: '../escaped.txt', oracle: { type: 'filesystem_mutation', params: { canary: 'fs' } }, watch: { fs: 'escaped.txt' }, needsHs: /\b(?:writeFile|appendFile|copyFile|copyFileWithMetadata|renameFile|openBinaryFile)\b|\b(?:openFile|withFile|withBinaryFile)\b[^\n]*\b(?:WriteMode|AppendMode|ReadWriteMode)\b/, needs: /\b(?:writeFile|writeFileSync|appendFile|appendFileSync|createWriteStream)\b/ },
|
|
415
666
|
'CWE-918': { name: 'ssrf', payload: '{{CALLBACK_URL}}', oracle: { type: 'outbound_callback' }, network: 'callback' },
|
|
416
667
|
};
|
|
668
|
+
// classes only the Haskell generator builds (the other languages refuse them): argument injection needs a stand-in for the called program
|
|
669
|
+
const HASKELL_ONLY = {
|
|
670
|
+
'CWE-88': { name: 'argument-injection', payload: '--agentic-proof-write={{CANARY:arg}}', oracle: { type: 'argument_injection', params: { canary: 'arg' } } },
|
|
671
|
+
};
|
|
417
672
|
const generate_MAX_SOURCE = 256 * 1024;
|
|
418
673
|
const generate_MAX_FILES = 8;
|
|
419
674
|
const EXTS = ['', '.js', '.mjs', '.cjs', '/index.js'];
|
|
@@ -515,11 +770,12 @@ clearTimeout(timer);
|
|
|
515
770
|
|
|
516
771
|
function generateReproducer({ finding, root }) {
|
|
517
772
|
const cwe = normCwe(finding?.cwe);
|
|
518
|
-
const cls = CLASSES[cwe];
|
|
519
|
-
if (!cls) return generate_fail(`no payload and oracle exist for ${cwe ?? 'this finding'}; supported: ${Object.keys(CLASSES).join(', ')} (others need a database, a deserializer or a native harness)`);
|
|
520
773
|
const rel = String(finding?.file ?? '');
|
|
521
774
|
const isPy = /\.py$/i.test(rel);
|
|
522
775
|
const isHs = /\.hs$/i.test(rel);
|
|
776
|
+
const cls = CLASSES[cwe] ?? (isHs ? HASKELL_ONLY[cwe] : undefined);
|
|
777
|
+
if (isHs && !cls && Number.isInteger(finding?.line)) return haskellRefusal({ finding, root, cwe });
|
|
778
|
+
if (!cls) return generate_fail(`no payload and oracle exist for ${cwe ?? 'this finding'}; supported: ${Object.keys(CLASSES).join(', ')} (others need a database, a deserializer or a native harness)`);
|
|
523
779
|
if (!isPy && !isHs && !/\.(?:js|mjs|cjs)$/i.test(rel)) return generate_fail(`no harness builder for ${external_node_path_.extname(rel) || 'this file type'}; JavaScript, Python and Haskell only`);
|
|
524
780
|
if (!Number.isInteger(finding?.line)) return generate_fail('the finding has no line number');
|
|
525
781
|
if (isPy) return generatePythonReproducer({ finding, root, cls });
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clear-capabilities/agentic-security-scanner",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.188.0",
|
|
4
4
|
"description": "Scanner engine for the agentic-security Claude Code plugin: SAST, SCA with reachability and CISA KEV, secrets, IaC, Haskell and Nix/NixOS, prompt-injection, MCP/agent-tool audit, authZ analysis, SBOM, compliance attestation, and more.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
@@ -86,16 +86,16 @@
|
|
|
86
86
|
"test:ollama-e2e": "AGENTIC_SECURITY_OLLAMA_E2E=1 node --test test/ollama-e2e.test.js",
|
|
87
87
|
"test:glob": "node --test test/glob-compat.test.js",
|
|
88
88
|
"test:sast": "node --test test/dag-precision.test.js test/cpp-hardcoded-secret.test.js test/sibling-guard.test.js test/comment-blindness.test.js test/crypto-specialist.test.js test/llm.test.js test/llm-cost-advisor.test.js test/llm-owasp.test.js test/logic.test.js test/authz.test.js test/model-load.test.js test/prompt-template.test.js test/business-logic.test.js test/python-sinks.test.js test/phase1-detectors.test.js test/phase2-detectors.test.js test/phase3-v3.test.js test/phase7-extensions.test.js test/phase8-extensions.test.js test/new-cwe-detectors.test.js test/file-upload.test.js test/llmsecops-detectors.test.js test/db-taint.test.js test/dart-swift.test.js test/zip-slip-containment-guard.test.js test/zip-slip-go.test.js test/redos-anchoring.test.js test/path-guard-validator-call.test.js test/redos-nfa.test.js test/weak-randomness.test.js test/csharp-pipeline.test.js test/csharp-cross-file.test.js test/post-quantum-crypto.test.js test/web3-advanced.test.js test/cloud-iam-k8s.test.js test/crypto-protocol.test.js test/ml-supply-chain.test.js test/mcp-audit-scan.test.js test/wrong-context-sanitizer.test.js test/sanitizer-context.test.js test/frontend-hygiene.test.js test/csv-injection.test.js test/stored-taint.test.js test/tree-sitter-sinks.test.js test/kotlin-structural.test.js test/ruby-php-structural.test.js test/java-csharp-structural.test.js test/java-structural-cross-file.test.js test/guard-recognition.test.js test/guard-window-identifier-correlation.test.js test/js-python-framework-structural.test.js test/go-structural.test.js test/secret-concat.test.js test/secret-redaction.test.js test/xss-reflected-multilang.test.js test/code-injection-multilang.test.js test/xxe-multilang.test.js test/xpath-injection-multilang.test.js test/gapfill-batch13.test.js test/agent-untrusted-flow.test.js test/api-authz.test.js test/event-entrypoint.test.js test/iac-terraform.test.js test/cross-service.test.js test/rbac-consistency.test.js test/adversarial-robustness.test.js test/secret-entropy.test.js test/comment-strip.test.js test/juliet-path-filter-gate.test.js test/java-bench-shape-opt-in.test.js test/java-ast-folding.test.js test/java-bench-extras.test.js test/reachability-missing-callgraph-data.test.js test/rate-limit.test.js test/auth-signals.test.js test/convention-deviation.test.js test/resource-exhaustion.test.js test/resource-exhaustion-realworld.test.js test/redirect-toctou.test.js test/redirect-toctou-realworld.test.js test/codegen-sink.test.js test/ownership-authz.test.js test/ownership-authz-realworld.test.js test/t21-precision-audit.test.js test/secrets-coverage.test.js test/prompt-injection-payloads.test.js test/iac-cloud-templates.test.js test/ruby-path-join.test.js test/sast/manifest-line-tracking.test.js test/rust-sast.test.js test/java-deserialization-precision.test.js test/pipeline-env-secret.test.js test/mark-used-vuln-functions.test.js",
|
|
89
|
-
"test:posture": "node --test test/contracts/root-cause-sweep.contract.test.js test/contracts/model-validation.contract.test.js test/contracts/agentic-discovery.contract.test.js test/contracts/local-models.contract.test.js test/contracts/dependency-finding.contract.test.js test/contracts/taint-flow.contract.test.js test/contracts/runtime-corroboration.contract.test.js test/compliance-coverage.test.js test/contracts/blast-radius.contract.test.js test/contracts/federation.contract.test.js test/contracts/eval-lab-report.contract.test.js test/contracts/fleet.contract.test.js test/contracts/rule-compiler.contract.test.js test/contracts/release-assurance.contract.test.js test/contracts/dnr.contract.test.js test/contracts/strategic-metrics.contract.test.js test/contracts/exploit-proof.contract.test.js test/contracts/artifact-provenance.contract.test.js test/dnr/artifact-join.test.js test/rule-pack-signing.test.js test/threat-model.test.js test/git-hardening.test.js test/privacy-framework.test.js test/material-change.test.js test/drift.test.js test/scorecard.test.js test/accuracy-scorecard.test.js test/scorecard-gate.test.js test/predeploy-gate.test.js test/release-check.test.js test/pre-push-gate.test.js test/dependency-currency.test.js test/package-contents-check.test.js test/gate-verdict-cache.test.js test/run-unit-tests.test.js test/temp-leak-guard.test.js test/release-workflow.test.js test/release-workflow-structure.test.js test/independent-population.test.js test/why-missed.test.js test/independent-scoring.test.js test/evidence-bundle.test.js test/obligation-evidence-pack.test.js test/policy-bundle.test.js test/discovery-memory.test.js test/mttr.test.js test/license-policy.test.js test/aibom.test.js test/sbom.test.js test/api-inventory.test.js test/iam-policy.test.js test/container.test.js test/container-runtime.test.js test/image-packages.test.js test/kev.test.js test/dep-confusion.test.js test/sca-deprecated.test.js test/sca-batch.test.js test/composite-risk.test.js test/epss-enrich.test.js test/sca-coverage.test.js test/gradle-deps.test.js test/sca-route-reachable.test.js test/sca-policy.test.js test/sca-verdict.test.js test/install-script.test.js test/sca-linked-findings.test.js test/packs.test.js test/flow-narration.test.js test/regression-test-gen.test.js test/deterministic-fix.test.js test/falsification.test.js test/verification-separation.test.js test/logic-claims.test.js test/attestation.test.js test/verify-attestation-cli.test.js test/comparison.test.js test/determinism-cross-machine.test.js test/fix-honesty-gate.test.js test/model-routing.test.js test/root-cause-sweep.test.js test/entrypoint-inventory.test.js test/relevance.test.js test/untrusted.test.js test/agent-hardening.test.js test/rule-synthesis.test.js test/policy-gate.test.js test/agents-memory.test.js test/cve-lookup.test.js test/cve-alert-daemon.test.js test/fix-verify-loop.test.js test/fix-verify-tests.test.js test/fix-acceptance.test.js test/exploitability-probability.test.js test/history-scan.test.js test/viral-features.test.js test/viral-v074.test.js test/state-dir.test.js test/ignore-pragma.test.js test/license-graph.test.js test/secret-live-check.test.js test/attack-taxonomy.test.js test/triage-memory.test.js test/pr-augment.test.js test/chat-batch2.test.js test/chat-batch3.test.js test/chat-batch4.test.js test/chat-batch5.test.js test/chat-batch6.test.js test/risk-scenario-disclosure.test.js test/egress-policy.test.js test/egress-policy-completeness.test.js test/egress-policy-integration.test.js test/router.test.js test/legacy-alias-redirect.test.js test/cache-economics.test.js test/coverage-report.test.js test/corpus-status.test.js test/provenance.test.js test/secret-history.test.js test/execution-proof.test.js test/fix-metrics.test.js test/corpus-enroll.test.js test/prove-findings.test.js test/corpus-match.test.js test/corpus-provenance.test.js test/learning-quorum.test.js test/llm-cache-integrity.test.js test/proof-artifact.test.js test/providers.test.js test/fleet.test.js test/autopilot.test.js test/autopilot-cli.test.js test/verifier-independence.test.js test/integrity-legacy-key.test.js test/suppression-visibility.test.js test/cost-ceiling.test.js test/local-endpoint.test.js test/ollama-provider.test.js test/ollama-capabilities.test.js test/ollama-offline-egress.test.js test/ollama-fix-proposal.test.js test/ollama-explain-proposal.test.js test/ollama-poc-proposal.test.js test/ollama-model-probe.test.js test/ollama-agent-tools.test.js test/ollama-agent-loop.test.js test/ollama-e2e.test.js test/ollama-oom-feedback.test.js test/ollama-doc-drift.test.js test/model-trust.test.js test/vuln-archaeology.test.js test/scan-checkpoint.test.js test/llm-redact.test.js test/world-class-batch2.test.js test/world-class-modules.test.js test/privacy-ir-adapter.test.js test/privacy-taxonomy.test.js test/privacy-sink-policy.test.js test/privacy-governance.test.js test/privacy-inventory.test.js test/integration-end-to-end.test.js test/streak-cli-wiring.test.js test/stack-playbook.test.js test/machine-output-flag.test.js test/stdout-flush.test.js test/format-determinism.test.js test/only-flag-channels.test.js test/confidence.test.js test/security-trend.test.js test/calibration-drift.test.js test/validator-metrics.test.js test/clustering-ir-taint-line.test.js test/concurrency-cwe.test.js test/compliance-mapping-liveness.test.js test/module-artifact-liveness.test.js test/supply-chain-provenance-completeness.test.js test/compliance-severity-threshold.test.js test/compliance-severity-policy.test.js test/compliance-evidence-binding.test.js test/compliance-evidence-signing.test.js test/compliance-file-contains.test.js test/label-isolation.test.js test/evidence-grade-wording.test.js test/llm-model-status.test.js test/egress-policy-constraints.test.js test/egress-redact.test.js test/egress-audit.test.js test/egress-approved-providers.test.js test/family-registry.test.js test/coverage-strength.test.js test/framework-provenance.test.js test/framework-provenance-controlrefs.test.js test/third-party-verification.test.js test/proof-coverage.test.js test/calibration-holdout.test.js test/independent-population-gate.test.js test/catalog-freshness.test.js test/incremental-parity.test.js test/surface-smoke.test.js test/fix-coverage.test.js test/raw-source-carveout.test.js test/mlbom-conformance.test.js test/deploy-gate-replay.test.js test/sbom-conformance.test.js test/unscored-claims.test.js test/mcp-rug-pull.test.js test/agent-boundary-taint.test.js test/confinement-adversarial.test.js test/comment-strip-cost.test.js test/reachability-claim.test.js test/entrypoint-breadth.test.js test/dep-file-admission.test.js test/custom-rules-freshness.test.js test/posture/provenance-schema.test.js test/posture/provenance-cache.test.js test/helpers/build-git-fixture.test.js test/posture/provenance-git-evidence.test.js test/posture/provenance-dag-walk.test.js test/posture/provenance-confidence.test.js test/posture/provenance-predicate-replay.test.js test/posture/provenance-origin-resolver.test.js test/posture/provenance-ai-authorship.test.js test/posture/provenance-branch-entry.test.js test/posture/provenance-evidence-attribution.test.js test/posture/provenance-lifecycle.test.js test/posture/provenance-missing-control-resolver.test.js test/posture/provenance-missing-control-wiring.test.js test/posture/provenance-coordinator.test.js test/posture/provenance-sca-origin.test.js test/posture/provenance-transitive-sca.test.js test/posture/provenance-coordinator-sca.test.js test/posture/provenance-providers.test.js test/posture/provenance-evidence-bundle.test.js test/posture/provenance-repo-lineage.test.js test/posture/provenance-secrets-logic.test.js test/cli/provenance-flags.test.js test/cli/attest-provenance.test.js test/cli/attest-obligations.test.js test/cli/models.test.js test/cli/setup-llm.test.js test/cli/fix-retry.test.js test/cli/compliance-walkthrough-lineage.test.js test/cli/dataflow-export-privacy.test.js test/cli/dataflow-export-briefing.test.js test/cli/lineage-snapshot-persist.test.js test/cli/dataflow-diff.test.js test/cli/dataflow-watch.test.js test/cli/dataflow-recipients.test.js test/cli/dataflow-coverage.test.js test/security/provenance-safety.test.js test/security/provenance-injection.test.js test/posture/remediation-ledger.test.js test/posture/assurance-baseline.test.js test/posture/assurance-contracts.test.js test/posture/assurance-config.test.js test/evidence-issuer.test.js test/load-factor.test.js test/fleet/job-store.test.js test/fleet/enterprise-graph.test.js test/fleet/discover-edges.test.js test/fleet/code-boundaries.test.js test/fleet/job-runner.test.js test/fleet/fleet-org-cli.test.js test/eval-lab/dataset-neutralize.test.js test/eval-lab/arms-score-stats.test.js test/eval-lab/run-report.test.js test/eval-lab/router.test.js test/eval-lab/arm-ollama.test.js test/eval-lab/import-independent.test.js test/cli/eval-lab-cli.test.js test/dnr/ir-and-outputs.test.js test/dnr/logs-and-hunt.test.js test/dnr/window-store-view.test.js test/dnr/exploit-correlation.test.js test/cli/dnr-cli.test.js test/proof-fabric/core.test.js test/proof-fabric/container.test.js test/proof-fabric/generate.test.js test/proof-fabric/siblings.test.js test/proof-fabric/generate-python.test.js test/proof-fabric/generate-haskell.test.js test/cli/proof-lifecycle-demo.test.js test/mcp-proof.test.js test/proof-fabric/fix-store-runner.test.js test/proof-fabric/fixtures.test.js test/cli/proof-fabric-cli.test.js test/rule-compiler/core.test.js test/rule-compiler/synthesis.test.js test/rule-compiler/structure.test.js test/cli/rule-compiler-cli.test.js test/fleet/fleet-graph.test.js test/fleet/fleet-manifest.test.js test/fleet/fleet-cli.test.js test/artifact/safe-tar.test.js test/artifact/image-archive.test.js test/artifact/filesystem.test.js test/artifact/layer-secrets.test.js test/artifact/inventory.test.js test/artifact/vuln-correlate.test.js test/artifact/signature.test.js test/artifact/provenance-graph.test.js test/artifact/mismatch.test.js test/artifact/vex.test.js test/artifact/registry.test.js test/artifact/sources-cosign-evidence.test.js test/cli/artifact-sources-cli.test.js test/cli/artifact-provenance-cli.test.js test/witness-bundle.test.js",
|
|
90
|
-
"test:dataflow": "node --test test/privacy-catalog.test.js test/privacy-deep-walker.test.js test/privacy-deep-e2e.test.js test/container-taint.test.js test/stored-taint-families.test.js test/py-annotation-sources.test.js test/fn-reach.test.js test/deep-taint.test.js test/calibration.test.js test/holdout-eval.test.js test/cross-lang-meta.test.js test/cross-lang-queues.test.js test/phase5-xlang.test.js test/phase5-coverage.test.js test/phase6-taint.test.js test/llm-validator-consistency.test.js test/llm-validator-default-on.test.js test/llm-validator-preset.test.js test/parser-py-cst.test.js test/chrome-probe.test.js test/parser-cs-kt.test.js test/parser-cs-annotations.test.js test/parser-cs-control-flow.test.js test/parser-kt-control-flow.test.js test/parser-js-annotations.test.js test/parser-java-annotations.test.js test/parser-java-control-flow.test.js test/parser-java-calls.test.js test/parser-go.test.js test/parser-rust.test.js test/rust-taint-flow.test.js test/parser-php-rb.test.js test/parser-php-control-flow.test.js test/interproc-k2.test.js test/proven-clean.test.js test/backward-default.test.js test/incremental-cache.test.js test/string-regex-lattice.test.js test/closure-capture.test.js test/points-to.test.js test/type-stubs.test.js test/soft-taint.test.js test/ifds.test.js test/symbolic-exec-proof.test.js test/ifds-summary-edges.test.js test/stub-aware-filter.test.js test/cross-repo.test.js test/proof-gate.test.js test/layer-recall.test.js test/java-taint-flow.test.js test/kt-taint-flow.test.js test/sanitizer-typed-flow.test.js test/sanitizer-gate-unit.test.js test/proof-safe.test.js test/collection-taint.test.js test/kcfa-context.test.js test/kcfa-callstring.test.js test/flow-parity.test.js test/callgraph-resolve.test.js test/import-reachability.test.js test/ir-stats.test.js test/parser-cpp.test.js test/parser-js-decorators.test.js test/parser-js-if-else-cfg.test.js test/cpp-integration.test.js test/engine-reconnect.test.js test/phase2-scoping.test.js test/engine-recall.test.js test/catalog-annotation-source.test.js test/catalog-cs-p1.test.js test/catalog-expanded.test.js test/builtin-summaries.test.js test/interproc-mutation-crash.test.js test/mutated-param-taint.test.js test/return-sink-check.test.js test/higher-order-inline-callback.test.js test/interproc-findings-discard.test.js test/runscan-deep-option.test.js test/summary-cache-convergence.test.js test/parser-rb-calls.test.js test/parser-rb-module-level.test.js test/balanced-call.test.js test/destructuring-taint.test.js test/computed-member-taint.test.js test/string-interpolation-taint.test.js test/dataflow-deadcode-severity.test.js test/catalog-dotted-callee-lookup.test.js test/builtin-summary-family-blind-kill.test.js test/deep-mode-annotator-pipeline.test.js test/receiver-type-and-nested-calls.test.js test/member-write-and-loop-taint.test.js test/parser-py-module-level.test.js test/parser-php-module-level.test.js test/r14b-module-level-e2e.test.js test/annotation-taint-engine.test.js test/interproc-nested-call-taint.test.js test/catalog-xpath-injection.test.js test/catalog-ldap-injection.test.js test/catalog-xxe.test.js test/catalog-response-splitting.test.js test/catalog-code-injection.test.js test/parser-rb-control-flow.test.js test/catalog-ruby-p1.test.js test/callee-receiver-taint.test.js test/catalog-command-injection-p4.test.js test/catalog-xss-p4.test.js test/catalog-path-ssrf-p3.test.js test/catalog-ai-model-provider-precision.test.js test/catalog-orm-write.test.js test/dataflow/provenance-pipeline-integration.test.js test/dataflow-progress.test.js test/scan-progress.test.js test/sard-leakage-pipeline.test.js test/sard-split-scoring.test.js test/sard-llm-isolation.test.js test/sard-mutation-adversarial.test.js test/sard-baseline-adaptive-tolerance.test.js test/sard-independent-holdout.test.js test/sard-flow-aware-scoring.test.js test/sard-macro-score-support-floor.test.js test/sard-php-split.test.js test/parser-java-nary-concat.test.js test/sard-naive-baseline.test.js test/field-taint-cross-method.test.js test/field-taint-engine-unit.test.js test/coercion-sanitizer-kill.test.js test/constant-propagation-path-sensitivity.test.js test/parser-java-assignments.test.js test/catalog-java-sard.test.js test/parser-cs-juliet-shapes.test.js test/catalog-cs-sard-p2.test.js test/sard-cwe-key-merge.test.js test/parser-php-backtick.test.js test/parser-php-include.test.js test/php-include-merge.test.js test/parser-php-array-field-taint.test.js test/parser-php-cond-assign.test.js test/parser-rust-redos.test.js test/multi-sink-taint-chain.test.js test/static-field-cross-class-call-string.test.js test/regex-guard-narrowing.test.js test/object-instance-field-taint.test.js test/param-type-inference.test.js test/smt-path-feasibility.test.js test/cross-service-taint.test.js test/dataflow-expr-taint-scaling.test.js test/evaluation/guard-dominance.test.js test/evaluation/engine-mechanisms.test.js test/rx-exec-receiver.test.js test/incremental-dependency.test.js test/incremental-integrity.test.js test/demand-query.test.js test/ir-cache.test.js test/canonicalize-parity.test.js",
|
|
89
|
+
"test:posture": "node --test test/contracts/root-cause-sweep.contract.test.js test/contracts/model-validation.contract.test.js test/contracts/agentic-discovery.contract.test.js test/contracts/local-models.contract.test.js test/contracts/dependency-finding.contract.test.js test/contracts/taint-flow.contract.test.js test/contracts/runtime-corroboration.contract.test.js test/compliance-coverage.test.js test/contracts/blast-radius.contract.test.js test/contracts/federation.contract.test.js test/contracts/eval-lab-report.contract.test.js test/contracts/fleet.contract.test.js test/contracts/rule-compiler.contract.test.js test/contracts/release-assurance.contract.test.js test/contracts/dnr.contract.test.js test/contracts/strategic-metrics.contract.test.js test/contracts/exploit-proof.contract.test.js test/contracts/artifact-provenance.contract.test.js test/dnr/artifact-join.test.js test/rule-pack-signing.test.js test/threat-model.test.js test/git-hardening.test.js test/privacy-framework.test.js test/material-change.test.js test/drift.test.js test/scorecard.test.js test/accuracy-scorecard.test.js test/scorecard-gate.test.js test/predeploy-gate.test.js test/release-check.test.js test/pre-push-gate.test.js test/dependency-currency.test.js test/package-contents-check.test.js test/gate-verdict-cache.test.js test/run-unit-tests.test.js test/temp-leak-guard.test.js test/release-workflow.test.js test/release-workflow-structure.test.js test/independent-population.test.js test/why-missed.test.js test/independent-scoring.test.js test/evidence-bundle.test.js test/obligation-evidence-pack.test.js test/policy-bundle.test.js test/discovery-memory.test.js test/mttr.test.js test/license-policy.test.js test/aibom.test.js test/sbom.test.js test/api-inventory.test.js test/iam-policy.test.js test/container.test.js test/container-runtime.test.js test/image-packages.test.js test/kev.test.js test/dep-confusion.test.js test/sca-deprecated.test.js test/sca-batch.test.js test/composite-risk.test.js test/epss-enrich.test.js test/sca-coverage.test.js test/gradle-deps.test.js test/sca-route-reachable.test.js test/sca-policy.test.js test/sca-verdict.test.js test/install-script.test.js test/sca-linked-findings.test.js test/packs.test.js test/flow-narration.test.js test/regression-test-gen.test.js test/deterministic-fix.test.js test/falsification.test.js test/verification-separation.test.js test/logic-claims.test.js test/attestation.test.js test/verify-attestation-cli.test.js test/comparison.test.js test/determinism-cross-machine.test.js test/fix-honesty-gate.test.js test/model-routing.test.js test/root-cause-sweep.test.js test/entrypoint-inventory.test.js test/relevance.test.js test/untrusted.test.js test/agent-hardening.test.js test/rule-synthesis.test.js test/policy-gate.test.js test/agents-memory.test.js test/cve-lookup.test.js test/cve-alert-daemon.test.js test/fix-verify-loop.test.js test/fix-verify-tests.test.js test/fix-acceptance.test.js test/exploitability-probability.test.js test/history-scan.test.js test/viral-features.test.js test/viral-v074.test.js test/state-dir.test.js test/ignore-pragma.test.js test/license-graph.test.js test/secret-live-check.test.js test/attack-taxonomy.test.js test/triage-memory.test.js test/pr-augment.test.js test/chat-batch2.test.js test/chat-batch3.test.js test/chat-batch4.test.js test/chat-batch5.test.js test/chat-batch6.test.js test/risk-scenario-disclosure.test.js test/egress-policy.test.js test/egress-policy-completeness.test.js test/egress-policy-integration.test.js test/router.test.js test/legacy-alias-redirect.test.js test/cache-economics.test.js test/coverage-report.test.js test/corpus-status.test.js test/provenance.test.js test/secret-history.test.js test/execution-proof.test.js test/fix-metrics.test.js test/corpus-enroll.test.js test/prove-findings.test.js test/corpus-match.test.js test/corpus-provenance.test.js test/learning-quorum.test.js test/llm-cache-integrity.test.js test/proof-artifact.test.js test/providers.test.js test/fleet.test.js test/autopilot.test.js test/autopilot-cli.test.js test/verifier-independence.test.js test/integrity-legacy-key.test.js test/suppression-visibility.test.js test/cost-ceiling.test.js test/local-endpoint.test.js test/ollama-provider.test.js test/ollama-capabilities.test.js test/ollama-offline-egress.test.js test/ollama-fix-proposal.test.js test/ollama-explain-proposal.test.js test/ollama-poc-proposal.test.js test/ollama-model-probe.test.js test/ollama-agent-tools.test.js test/ollama-agent-loop.test.js test/ollama-e2e.test.js test/ollama-oom-feedback.test.js test/ollama-doc-drift.test.js test/model-trust.test.js test/vuln-archaeology.test.js test/scan-checkpoint.test.js test/llm-redact.test.js test/world-class-batch2.test.js test/world-class-modules.test.js test/privacy-ir-adapter.test.js test/privacy-taxonomy.test.js test/privacy-sink-policy.test.js test/privacy-governance.test.js test/privacy-inventory.test.js test/integration-end-to-end.test.js test/streak-cli-wiring.test.js test/stack-playbook.test.js test/machine-output-flag.test.js test/stdout-flush.test.js test/format-determinism.test.js test/only-flag-channels.test.js test/confidence.test.js test/security-trend.test.js test/calibration-drift.test.js test/validator-metrics.test.js test/clustering-ir-taint-line.test.js test/concurrency-cwe.test.js test/compliance-mapping-liveness.test.js test/module-artifact-liveness.test.js test/supply-chain-provenance-completeness.test.js test/compliance-severity-threshold.test.js test/compliance-severity-policy.test.js test/compliance-evidence-binding.test.js test/compliance-evidence-signing.test.js test/compliance-file-contains.test.js test/label-isolation.test.js test/evidence-grade-wording.test.js test/llm-model-status.test.js test/egress-policy-constraints.test.js test/egress-redact.test.js test/egress-audit.test.js test/egress-approved-providers.test.js test/family-registry.test.js test/coverage-strength.test.js test/framework-provenance.test.js test/framework-provenance-controlrefs.test.js test/third-party-verification.test.js test/proof-coverage.test.js test/calibration-holdout.test.js test/independent-population-gate.test.js test/catalog-freshness.test.js test/incremental-parity.test.js test/surface-smoke.test.js test/fix-coverage.test.js test/raw-source-carveout.test.js test/mlbom-conformance.test.js test/deploy-gate-replay.test.js test/sbom-conformance.test.js test/unscored-claims.test.js test/mcp-rug-pull.test.js test/agent-boundary-taint.test.js test/confinement-adversarial.test.js test/comment-strip-cost.test.js test/reachability-claim.test.js test/entrypoint-breadth.test.js test/dep-file-admission.test.js test/custom-rules-freshness.test.js test/posture/provenance-schema.test.js test/posture/provenance-cache.test.js test/helpers/build-git-fixture.test.js test/posture/provenance-git-evidence.test.js test/posture/provenance-dag-walk.test.js test/posture/provenance-confidence.test.js test/posture/provenance-predicate-replay.test.js test/posture/provenance-origin-resolver.test.js test/posture/provenance-ai-authorship.test.js test/posture/provenance-branch-entry.test.js test/posture/provenance-evidence-attribution.test.js test/posture/provenance-lifecycle.test.js test/posture/provenance-missing-control-resolver.test.js test/posture/provenance-missing-control-wiring.test.js test/posture/provenance-coordinator.test.js test/posture/provenance-sca-origin.test.js test/posture/provenance-transitive-sca.test.js test/posture/provenance-coordinator-sca.test.js test/posture/provenance-providers.test.js test/posture/provenance-evidence-bundle.test.js test/posture/provenance-repo-lineage.test.js test/posture/provenance-secrets-logic.test.js test/cli/provenance-flags.test.js test/cli/attest-provenance.test.js test/cli/attest-obligations.test.js test/cli/models.test.js test/cli/setup-llm.test.js test/cli/fix-retry.test.js test/cli/compliance-walkthrough-lineage.test.js test/cli/dataflow-export-privacy.test.js test/cli/dataflow-export-briefing.test.js test/cli/lineage-snapshot-persist.test.js test/cli/dataflow-diff.test.js test/cli/dataflow-watch.test.js test/cli/dataflow-recipients.test.js test/cli/dataflow-coverage.test.js test/security/provenance-safety.test.js test/security/provenance-injection.test.js test/posture/remediation-ledger.test.js test/posture/assurance-baseline.test.js test/posture/assurance-contracts.test.js test/posture/assurance-config.test.js test/evidence-issuer.test.js test/load-factor.test.js test/fleet/job-store.test.js test/fleet/enterprise-graph.test.js test/fleet/discover-edges.test.js test/fleet/code-boundaries.test.js test/fleet/job-runner.test.js test/fleet/fleet-org-cli.test.js test/eval-lab/dataset-neutralize.test.js test/eval-lab/arms-score-stats.test.js test/eval-lab/run-report.test.js test/eval-lab/router.test.js test/eval-lab/arm-ollama.test.js test/eval-lab/import-independent.test.js test/cli/eval-lab-cli.test.js test/dnr/ir-and-outputs.test.js test/dnr/logs-and-hunt.test.js test/dnr/window-store-view.test.js test/dnr/exploit-correlation.test.js test/cli/dnr-cli.test.js test/proof-fabric/core.test.js test/proof-fabric/container.test.js test/proof-fabric/generate.test.js test/proof-fabric/siblings.test.js test/proof-fabric/generate-python.test.js test/proof-fabric/generate-haskell.test.js test/proof-fabric/generate-haskell-widened.test.js test/cli/proof-lifecycle-demo.test.js test/mcp-proof.test.js test/proof-fabric/fix-store-runner.test.js test/proof-fabric/fixtures.test.js test/cli/proof-fabric-cli.test.js test/rule-compiler/core.test.js test/rule-compiler/synthesis.test.js test/rule-compiler/structure.test.js test/cli/rule-compiler-cli.test.js test/fleet/fleet-graph.test.js test/fleet/fleet-manifest.test.js test/fleet/fleet-cli.test.js test/artifact/safe-tar.test.js test/artifact/image-archive.test.js test/artifact/filesystem.test.js test/artifact/layer-secrets.test.js test/artifact/inventory.test.js test/artifact/vuln-correlate.test.js test/artifact/signature.test.js test/artifact/provenance-graph.test.js test/artifact/mismatch.test.js test/artifact/vex.test.js test/artifact/registry.test.js test/artifact/sources-cosign-evidence.test.js test/cli/artifact-sources-cli.test.js test/cli/artifact-provenance-cli.test.js test/witness-bundle.test.js",
|
|
90
|
+
"test:dataflow": "node --test test/privacy-catalog.test.js test/privacy-deep-walker.test.js test/privacy-deep-e2e.test.js test/container-taint.test.js test/stored-taint-families.test.js test/py-annotation-sources.test.js test/fn-reach.test.js test/deep-taint.test.js test/calibration.test.js test/holdout-eval.test.js test/cross-lang-meta.test.js test/cross-lang-queues.test.js test/phase5-xlang.test.js test/phase5-coverage.test.js test/phase6-taint.test.js test/llm-validator-consistency.test.js test/llm-validator-default-on.test.js test/llm-validator-preset.test.js test/parser-py-cst.test.js test/chrome-probe.test.js test/parser-cs-kt.test.js test/parser-cs-annotations.test.js test/parser-cs-control-flow.test.js test/parser-kt-control-flow.test.js test/parser-js-annotations.test.js test/parser-java-annotations.test.js test/parser-java-control-flow.test.js test/parser-java-calls.test.js test/parser-go.test.js test/parser-rust.test.js test/rust-taint-flow.test.js test/parser-php-rb.test.js test/parser-php-control-flow.test.js test/interproc-k2.test.js test/proven-clean.test.js test/backward-default.test.js test/incremental-cache.test.js test/string-regex-lattice.test.js test/closure-capture.test.js test/points-to.test.js test/type-stubs.test.js test/soft-taint.test.js test/ifds.test.js test/symbolic-exec-proof.test.js test/ifds-summary-edges.test.js test/stub-aware-filter.test.js test/cross-repo.test.js test/proof-gate.test.js test/layer-recall.test.js test/java-taint-flow.test.js test/kt-taint-flow.test.js test/sanitizer-typed-flow.test.js test/sanitizer-gate-unit.test.js test/proof-safe.test.js test/collection-taint.test.js test/kcfa-context.test.js test/kcfa-callstring.test.js test/flow-parity.test.js test/callgraph-resolve.test.js test/import-reachability.test.js test/ir-stats.test.js test/parser-cpp.test.js test/parser-js-decorators.test.js test/parser-js-if-else-cfg.test.js test/cpp-integration.test.js test/engine-reconnect.test.js test/phase2-scoping.test.js test/engine-recall.test.js test/catalog-annotation-source.test.js test/catalog-cs-p1.test.js test/catalog-expanded.test.js test/builtin-summaries.test.js test/interproc-mutation-crash.test.js test/mutated-param-taint.test.js test/return-sink-check.test.js test/higher-order-inline-callback.test.js test/interproc-findings-discard.test.js test/runscan-deep-option.test.js test/summary-cache-convergence.test.js test/parser-rb-calls.test.js test/parser-rb-module-level.test.js test/balanced-call.test.js test/destructuring-taint.test.js test/computed-member-taint.test.js test/string-interpolation-taint.test.js test/dataflow-deadcode-severity.test.js test/catalog-dotted-callee-lookup.test.js test/builtin-summary-family-blind-kill.test.js test/deep-mode-annotator-pipeline.test.js test/receiver-type-and-nested-calls.test.js test/member-write-and-loop-taint.test.js test/parser-py-module-level.test.js test/parser-php-module-level.test.js test/r14b-module-level-e2e.test.js test/annotation-taint-engine.test.js test/interproc-nested-call-taint.test.js test/catalog-xpath-injection.test.js test/catalog-ldap-injection.test.js test/catalog-xxe.test.js test/catalog-response-splitting.test.js test/catalog-code-injection.test.js test/parser-rb-control-flow.test.js test/catalog-ruby-p1.test.js test/callee-receiver-taint.test.js test/catalog-command-injection-p4.test.js test/catalog-xss-p4.test.js test/catalog-path-ssrf-p3.test.js test/catalog-ai-model-provider-precision.test.js test/catalog-orm-write.test.js test/dataflow/provenance-pipeline-integration.test.js test/dataflow-progress.test.js test/scan-progress.test.js test/sard-leakage-pipeline.test.js test/sard-split-scoring.test.js test/sard-llm-isolation.test.js test/sard-mutation-adversarial.test.js test/sard-baseline-adaptive-tolerance.test.js test/sard-independent-holdout.test.js test/sard-flow-aware-scoring.test.js test/sard-macro-score-support-floor.test.js test/sard-php-split.test.js test/parser-java-nary-concat.test.js test/sard-naive-baseline.test.js test/field-taint-cross-method.test.js test/field-taint-engine-unit.test.js test/coercion-sanitizer-kill.test.js test/constant-propagation-path-sensitivity.test.js test/parser-java-assignments.test.js test/catalog-java-sard.test.js test/parser-cs-juliet-shapes.test.js test/catalog-cs-sard-p2.test.js test/sard-cwe-key-merge.test.js test/parser-php-backtick.test.js test/parser-php-include.test.js test/php-include-merge.test.js test/parser-php-array-field-taint.test.js test/parser-php-cond-assign.test.js test/parser-rust-redos.test.js test/multi-sink-taint-chain.test.js test/static-field-cross-class-call-string.test.js test/regex-guard-narrowing.test.js test/object-instance-field-taint.test.js test/param-type-inference.test.js test/smt-path-feasibility.test.js test/cross-service-taint.test.js test/dataflow-expr-taint-scaling.test.js test/evaluation/guard-dominance.test.js test/evaluation/engine-mechanisms.test.js test/rx-exec-receiver.test.js test/incremental-dependency.test.js test/incremental-integrity.test.js test/demand-query.test.js test/ir-cache.test.js test/canonicalize-parity.test.js test/dataflow-source-attribution.test.js",
|
|
91
91
|
"test:mcp": "node --test test/mcp.test.js test/mcp-apply-fix-multifile.test.js test/mcp-protocol-smoke.test.js test/mcp-audit.test.js test/audit-cli.test.js test/mcp-scratchpad.test.js test/mcp-offload.test.js test/sca-upgrade.test.js test/lsp-server.test.js test/mcp-dataflow-tools.test.js test/cli/governance-propose-edit.test.js test/cli/remediation-open-update.test.js test/cli/remediation-verify-reopen.test.js test/cli/dataflow-observations.test.js test/cli/federate-declare-list.test.js test/capabilities/tools.test.js",
|
|
92
92
|
"test:report": "node --test test/report-scan-invariants.test.js test/junit.test.js test/ci.test.js test/poc-generator.test.js test/verifier.test.js test/verifier-target.test.js test/annotator-errors.test.js test/git-history-batch.test.js test/default-scan-drift.test.js test/bundle-optional-deps.test.js test/scan-health.test.js test/finding-schema.test.js test/pipeline/finding-schema-provenance.test.js test/evidence-provenance.test.js test/report/provenance-output.test.js test/report/provenance-format-parity.test.js test/legacy-compat.test.js test/annotator-runner.test.js test/detector-runner.test.js test/detector-errors.test.js test/analyzer-supervisor.test.js test/cascade-worker-pool.test.js test/cascade-pool-wiring.test.js test/coverage-ledger.test.js test/coverage-ledger-completeness.test.js test/assurance-mode.test.js test/artifact-registry.test.js test/artifact-registry-completeness.test.js test/retention-policy.test.js test/state-lifecycle-report.test.js test/legal-hold.test.js test/production-feedback.test.js test/calibration-feedback.test.js test/encryption-provider.test.js test/grader-calibration.test.js test/pr-delta-gate.test.js test/vex.test.js test/report-render.test.js test/oscal-conformance.test.js test/cli-fix-apply.test.js test/apply-fix-service.test.js test/high-impact-approval-gate.test.js test/approver-registry.test.js test/suppression-exceptions.test.js test/fix-history.test.js test/producer-registry.test.js test/producer-collector.test.js test/enrichment-completion.test.js",
|
|
93
93
|
"test:lineage": "node --test test/lineage/analysis-completion.test.js test/lineage/schema.test.js test/lineage/ids.test.js test/lineage/protection.test.js test/lineage/classification.test.js test/lineage/validate.test.js test/lineage/json-schema-parity.test.js test/lineage/flagship-fixture.test.js test/lineage/flagship-fixture-semantics.test.js test/lineage/field-identity.test.js test/lineage/engine-expr-resolver.test.js test/lineage/engine-walker.test.js test/lineage/engine-integration.test.js test/lineage/engine-receiver-identity.test.js test/lineage/summaries.test.js test/lineage/driver.test.js test/lineage/engine-provenance.test.js test/lineage/engine-provenance-interprocedural.test.js test/lineage/path-store.test.js test/lineage/path-query.test.js test/lineage/flow-grade.test.js test/lineage/source-registry.test.js test/lineage/sink-registry.test.js test/lineage/transform-catalog.test.js test/lineage/handling-analyzer.test.js test/lineage/registry-real-code.test.js test/lineage/source-seeding.test.js test/lineage/graph-builder.test.js test/lineage/coverage.test.js test/lineage/resolve-destination.test.js test/lineage/queue-detail.test.js test/lineage/index.test.js test/lineage/obligation-mapping.test.js test/lineage/obligation-predicates.test.js test/lineage/obligation-predicates-walkthrough.test.js test/lineage/transit-protection.test.js test/lineage/at-rest-protection.test.js test/lineage/protection-summary.test.js test/lineage/ac01-multi-sink.test.js test/lineage/policy-verdict.test.js test/lineage/governance-refs.test.js test/lineage/export-privacy.test.js test/lineage/export-json.test.js test/lineage/export-csv.test.js test/lineage/decision-story.test.js test/lineage/export-briefing.test.js test/lineage/graph-snapshot.test.js test/lineage/graph-diff.test.js test/lineage/drift-policy.test.js test/lineage/recipient-profile.test.js test/lineage/recipient-registry.test.js test/lineage/recipient-wiring.test.js test/lineage/redact-graph.test.js test/lineage-scan-wiring.test.js test/lineage-artifact-write.test.js test/bench-data-lineage-runner.test.js test/bundle-frontend.test.js test/bundle-frontend-golden.test.js test/generate-html-report.test.js test/export-image.test.js test/lineage/scenario.test.js test/lineage/scenario-engine.test.js test/lineage/scenario-diff.test.js test/lineage/scenario-no-obligation-wiring.test.js test/lineage/impact-assessment.test.js test/lineage/impact-engine.test.js test/lineage/impact-no-obligation-wiring.test.js test/lineage/governance-edit.test.js test/lineage/remediation.test.js test/lineage/runtime-observation.test.js test/lineage/observation-correlation.test.js test/lineage/observation-adapters.test.js test/lineage/observation-store.test.js test/lineage/runtime-corroboration-wiring.test.js test/lineage/cross-repo-link.test.js test/lineage/federation-loader.test.js test/lineage/cross-repo-link-wiring.test.js test/lineage/runtime-assurance.test.js test/lineage/runtime-edge-states.test.js test/lineage/runtime-explorer-view.test.js test/cli/runtime-explorer-cli.test.js test/cli/runtime-identity-cli.test.js test/cli/runtime-twin-cli.test.js test/lineage/cut-planner.test.js test/lineage/scc.test.js test/lineage/scc-solver.test.js test/graph/graph-views.test.js test/lineage/dag07-completion.test.js test/lineage/owned-build.test.js test/dataflow/boundary-propagation.test.js test/lineage/boundary-contract.test.js test/lineage/correlation-v2.test.js test/lineage/path-control-evidence.test.js test/lineage/smt-z3-backend.test.js test/cli/dag-commands.test.js",
|
|
94
94
|
"test:bench-modules": "node --test test/phase4-harness.test.js test/pipeline.test.js test/proof-corpus-lib.test.js test/proof-corpus-runner.test.js",
|
|
95
95
|
"test:server": "node --test test/server/graph-loader.test.js test/server/security.test.js test/server/routes.test.js test/server/http-server.test.js test/server/cmd-explore.test.js test/server/cmd-dataflow-export.test.js test/server/static-assets.test.js test/server/dataflow-scenario-cli.test.js test/server/dataflow-impact-cli.test.js",
|
|
96
|
-
"test:haskell": "node --test test/haskell/haskell-weak-hash-names.test.js test/haskell/haskell-models-extended.test.js test/haskell/haskell-rules-extended.test.js test/haskell/haskell-injection.test.js test/haskell/haskell-ir.test.js test/haskell/haskell-manifests.test.js test/haskell/haskell-parser.test.js test/haskell/haskell-remediation.test.js test/haskell/haskell-resolved-graph.test.js test/haskell/haskell-sca.test.js test/haskell/haskell-sca-severity.test.js test/haskell/haskell-web-guards.test.js test/haskell/haskell-advisory-feed.test.js test/haskell/haskell-security-rules.test.js test/haskell/haskell-taint.test.js test/haskell/haskell-boundaries.test.js test/haskell/haskell-live-feed-scan.test.js test/haskell/haskell-supply-bounds.test.js test/haskell/haskell-ir-scaling.test.js test/haskell/haskell-boundary-propagation.test.js",
|
|
96
|
+
"test:haskell": "node --test test/haskell/haskell-alias-taint.test.js test/haskell/haskell-weak-hash-names.test.js test/haskell/haskell-models-extended.test.js test/haskell/haskell-rules-extended.test.js test/haskell/haskell-injection.test.js test/haskell/haskell-ir.test.js test/haskell/haskell-manifests.test.js test/haskell/haskell-parser.test.js test/haskell/haskell-remediation.test.js test/haskell/haskell-resolved-graph.test.js test/haskell/haskell-sca.test.js test/haskell/haskell-sca-severity.test.js test/haskell/haskell-web-guards.test.js test/haskell/haskell-advisory-feed.test.js test/haskell/haskell-security-rules.test.js test/haskell/haskell-taint.test.js test/haskell/haskell-boundaries.test.js test/haskell/haskell-live-feed-scan.test.js test/haskell/haskell-supply-bounds.test.js test/haskell/haskell-ir-scaling.test.js test/haskell/haskell-boundary-propagation.test.js test/haskell/haskell-generalization.test.js test/haskell/haskell-trust-boundary.test.js test/haskell/haskell-comment-invariance.test.js test/haskell/haskell-remediation-classes.test.js test/haskell/haskell-trust-boundary-frameworks.test.js test/haskell/haskell-generic-detectors.test.js",
|
|
97
97
|
"test:nix": "node --test test/nix/nix-option-types.test.js test/nix/nixos-hardening-daemon.test.js test/nix/nixos-hardening-extended.test.js test/nix/nix-build-trust.test.js test/nix/nix-eval-isolation.test.js test/nix/nix-input-inventory.test.js test/nix/nix-parser-ir.test.js test/nix/nix-remediation.test.js test/nix/nix-resolved-closure.test.js test/nix/nix-sca-patches.test.js test/nix/nix-sca-severity.test.js test/nix/nix-haskell-closure-names.test.js test/nix/nix-script-taint.test.js test/nix/nix-secrets-store.test.js test/nix/nixos-hardening.test.js test/nix/nixos-module-resolution.test.js test/nix/nix-fix-multifile.test.js test/nix/nixos-evaluator-forms.test.js test/nix/nix-advisory-feed.test.js test/nix/nix-fix-prewrite.test.js test/nix/nix-boundary-scope.test.js",
|
|
98
|
-
"test:language": "node --test test/language/capability-ledger.test.js test/language/language-accuracy-regression.test.js test/language/language-aibom.test.js test/language/language-assurance.test.js test/language/language-bom.test.js test/language/language-compliance.test.js test/language/language-contracts.test.js test/language/language-corpora-integrity.test.js test/language/language-discovery.test.js test/language/language-doc-coverage.test.js test/language/language-evidence-posture.test.js test/language/language-explorer.test.js test/language/language-gap-fixes.test.js test/language/language-gap-fixes-2.test.js test/language/language-governance.test.js test/language/language-integrations.test.js test/language/language-llm-agent.test.js test/language/language-local-ai.test.js test/language/language-polyglot-bridges.test.js test/language/language-privacy-lineage.test.js test/language/language-proof-remediation.test.js test/language/language-report-formats.test.js test/language/language-secrets.test.js test/language/language-trust-boundary.test.js",
|
|
98
|
+
"test:language": "node --test test/language/capability-ledger.test.js test/language/language-accuracy-regression.test.js test/language/language-aibom.test.js test/language/language-assurance.test.js test/language/language-bom.test.js test/language/language-compliance.test.js test/language/language-contracts.test.js test/language/language-corpora-integrity.test.js test/language/language-discovery.test.js test/language/language-doc-coverage.test.js test/language/language-evidence-posture.test.js test/language/language-explorer.test.js test/language/language-gap-fixes.test.js test/language/language-gap-fixes-2.test.js test/language/language-governance.test.js test/language/language-integrations.test.js test/language/language-llm-agent.test.js test/language/language-local-ai.test.js test/language/language-parity-haskell.test.js test/language/language-polyglot-bridges.test.js test/language/language-privacy-lineage.test.js test/language/language-proof-remediation.test.js test/language/language-report-formats.test.js test/language/language-secrets.test.js test/language/language-trust-boundary.test.js",
|
|
99
99
|
"test:language-stress": "node --test --test-concurrency=1 test/language/language-stress-offline.test.js",
|
|
100
100
|
"test:language-tools": "node --test test/haskell/haskell-web-auth.test.js test/haskell/haskell-support-gate.test.js",
|
|
101
101
|
"bench:language-support:check": "node ../bench/language-support/check.mjs",
|