@clear-capabilities/agentic-security-scanner 0.78.0 → 0.80.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.
Files changed (126) hide show
  1. package/bin/.agentic-security/findings.json +16 -16
  2. package/bin/.agentic-security/last-scan.json +16 -16
  3. package/bin/.agentic-security/last-scan.json.sig +1 -1
  4. package/bin/.agentic-security/scan-history.json +51 -0
  5. package/bin/.agentic-security/streak.json +5 -5
  6. package/bin/agentic-security.js +22 -7
  7. package/dist/178.index.js +1 -1
  8. package/dist/333.index.js +283 -0
  9. package/dist/384.index.js +1 -1
  10. package/dist/476.index.js +5 -5
  11. package/dist/637.index.js +1 -1
  12. package/dist/700.index.js +138 -0
  13. package/dist/718.index.js +53 -0
  14. package/dist/838.index.js +1 -1
  15. package/dist/985.index.js +95 -1
  16. package/dist/agentic-security.mjs +83 -83
  17. package/dist/agentic-security.mjs.sha256 +1 -1
  18. package/package.json +6 -4
  19. package/src/.agentic-security/findings.json +29799 -7803
  20. package/src/.agentic-security/last-scan.json +29799 -7803
  21. package/src/.agentic-security/last-scan.json.sig +1 -1
  22. package/src/.agentic-security/scan-history.json +5119 -2611
  23. package/src/.agentic-security/streak.json +6 -6
  24. package/src/dataflow/.agentic-security/findings.json +2879 -308
  25. package/src/dataflow/.agentic-security/last-scan.json +2879 -308
  26. package/src/dataflow/.agentic-security/last-scan.json.sig +1 -1
  27. package/src/dataflow/.agentic-security/scan-history.json +68 -520
  28. package/src/dataflow/.agentic-security/streak.json +6 -7
  29. package/src/dataflow/cross-service-taint.js +201 -0
  30. package/src/dataflow/engine.js +52 -8
  31. package/src/dataflow/formal-verify.js +204 -0
  32. package/src/dataflow/ifds-precise.js +222 -0
  33. package/src/dataflow/k2-summary-cache.js +153 -0
  34. package/src/dataflow/lib-taint-summaries.js +198 -0
  35. package/src/dataflow/privacy-taint.js +205 -0
  36. package/src/dataflow/smt-feasibility.js +189 -0
  37. package/src/engine.js +890 -132
  38. package/src/integrations/index.js +2 -1
  39. package/src/ir/.agentic-security/findings.json +240 -6
  40. package/src/ir/.agentic-security/last-scan.json +240 -6
  41. package/src/ir/.agentic-security/last-scan.json.sig +1 -1
  42. package/src/ir/.agentic-security/scan-history.json +16 -594
  43. package/src/ir/.agentic-security/streak.json +8 -9
  44. package/src/ir/callgraph.js +27 -7
  45. package/src/ir/cpp-preprocessor.js +142 -0
  46. package/src/ir/csharp-ir.js +604 -0
  47. package/src/ir/universal-ir.js +403 -0
  48. package/src/llm-validator/index.js +7 -5
  49. package/src/mcp/.agentic-security/findings.json +8632 -0
  50. package/src/mcp/.agentic-security/last-scan.json +8632 -0
  51. package/src/mcp/.agentic-security/last-scan.json.sig +1 -0
  52. package/src/mcp/.agentic-security/scan-history.json +143 -0
  53. package/src/mcp/.agentic-security/streak.json +20 -0
  54. package/src/mcp/audit.js +5 -0
  55. package/src/mcp/tools.js +90 -1
  56. package/src/posture/.agentic-security/findings.json +16809 -4367
  57. package/src/posture/.agentic-security/last-scan.json +16809 -4367
  58. package/src/posture/.agentic-security/last-scan.json.sig +1 -1
  59. package/src/posture/.agentic-security/scan-history.json +6689 -177
  60. package/src/posture/.agentic-security/streak.json +8 -7
  61. package/src/posture/api-contract.js +193 -0
  62. package/src/posture/attack-taxonomy.js +227 -0
  63. package/src/posture/calibration-drift.js +2 -1
  64. package/src/posture/calibration.js +3 -2
  65. package/src/posture/compliance-policy.js +218 -0
  66. package/src/posture/composite-risk.js +122 -0
  67. package/src/posture/csharp-analysis.js +330 -0
  68. package/src/posture/exploit-bundle.js +210 -0
  69. package/src/posture/federated-learning.js +172 -0
  70. package/src/posture/fix-history.js +8 -2
  71. package/src/posture/license-attributions.js +94 -0
  72. package/src/posture/license-graph.js +238 -0
  73. package/src/posture/pqc-migration-plan.js +158 -0
  74. package/src/posture/profile.js +4 -5
  75. package/src/posture/reachability-filter.js +33 -2
  76. package/src/posture/realtime-cve-monitor.js +214 -0
  77. package/src/posture/rule-overrides.js +2 -3
  78. package/src/posture/rule-pack-signing.js +2 -3
  79. package/src/posture/rule-synthesis.js +5 -6
  80. package/src/posture/runtime-correlation.js +174 -0
  81. package/src/posture/sbom-diff.js +171 -0
  82. package/src/posture/sca-policy.js +235 -0
  83. package/src/posture/sca-upgrade.js +259 -0
  84. package/src/posture/security-trend.js +4 -7
  85. package/src/posture/state-dir.js +124 -0
  86. package/src/posture/streak.js +3 -0
  87. package/src/posture/suppressions.js +5 -8
  88. package/src/posture/threat-model-auto.js +268 -0
  89. package/src/posture/triage-learning.js +170 -0
  90. package/src/posture/triage.js +29 -6
  91. package/src/posture/validator-metrics.js +3 -6
  92. package/src/sast/.agentic-security/findings.json +996 -32
  93. package/src/sast/.agentic-security/last-scan.json +996 -32
  94. package/src/sast/.agentic-security/last-scan.json.sig +1 -1
  95. package/src/sast/.agentic-security/scan-history.json +565 -32
  96. package/src/sast/.agentic-security/streak.json +10 -8
  97. package/src/sast/_secret-entropy.js +145 -0
  98. package/src/sast/cloud-iam.js +312 -0
  99. package/src/sast/cpp.js +138 -4
  100. package/src/sast/crypto-protocol.js +388 -0
  101. package/src/sast/csharp-tokenizer.js +392 -0
  102. package/src/sast/csharp.js +924 -138
  103. package/src/sast/dapp-frontend.js +200 -0
  104. package/src/sast/db-taint.js +24 -0
  105. package/src/sast/k8s-admission.js +271 -0
  106. package/src/sast/llm-app.js +272 -0
  107. package/src/sast/ml-supply-chain.js +259 -0
  108. package/src/sast/mobile.js +224 -0
  109. package/src/sast/post-quantum-crypto.js +348 -0
  110. package/src/sast/rust.js +26 -0
  111. package/src/sast/web3-advanced.js +375 -0
  112. package/src/sca/.agentic-security/findings.json +6044 -171
  113. package/src/sca/.agentic-security/last-scan.json +6044 -171
  114. package/src/sca/.agentic-security/last-scan.json.sig +1 -1
  115. package/src/sca/.agentic-security/scan-history.json +83 -6
  116. package/src/sca/.agentic-security/streak.json +9 -9
  117. package/src/sca/CLAUDE.md +161 -0
  118. package/src/sca/binary-metadata.js +146 -0
  119. package/src/sca/py-package-functions.js +118 -0
  120. package/src/sca/sigstore-verify.js +215 -0
  121. package/src/sca/vendor-detect.js +53 -0
  122. package/src/report/.agentic-security/findings.json +0 -80
  123. package/src/report/.agentic-security/last-scan.json +0 -80
  124. package/src/report/.agentic-security/last-scan.json.sig +0 -1
  125. package/src/report/.agentic-security/scan-history.json +0 -35
  126. package/src/report/.agentic-security/streak.json +0 -22
@@ -1,21 +1,20 @@
1
1
  {
2
- "firstScanDate": "2026-05-26T15:14:23.942Z",
3
- "lastScanDate": "2026-05-27T02:22:42.227Z",
4
- "totalScans": 30,
2
+ "firstScanDate": "2026-05-28T18:59:26.568Z",
3
+ "lastScanDate": "2026-05-29T06:24:38.574Z",
4
+ "totalScans": 7,
5
5
  "daysCleanCritical": 2,
6
- "lastCleanDate": "2026-05-27",
6
+ "lastCleanDate": "2026-05-29",
7
7
  "lastCriticalDate": null,
8
8
  "hasEverHadCritical": false,
9
9
  "bestDaysCleanCritical": 2,
10
- "totalFindingsAtFirstScan": 13,
11
- "totalFindingsAtLastScan": 16,
10
+ "totalFindingsAtFirstScan": 16,
11
+ "totalFindingsAtLastScan": 17,
12
12
  "totalFixesInferred": 0,
13
13
  "lastGrade": "B",
14
- "bestGrade": "A-",
14
+ "bestGrade": "B",
15
15
  "launchCheckPassedAt": null,
16
16
  "achievements": [
17
- "first-scan",
18
- "scan-veteran-25"
17
+ "first-scan"
19
18
  ],
20
19
  "previousGrade": "B"
21
20
  }
@@ -8,11 +8,25 @@
8
8
  // 4. Anything else → unresolved; the dataflow engine treats the callee as
9
9
  // an opaque sink for taint.
10
10
 
11
- export function buildCallGraph(perFileIR) {
12
- // perFileIR is { [file]: parseJsFile output }
13
- const functions = new Map(); // qid → FunctionIR
14
- const byNameInFile = new Map(); // file → Map<name, qid>
15
- const classMethods = new Map(); // 'ClassName.method' qid
11
+ export function buildCallGraph(perFileIR, fileContents) {
12
+ const functions = new Map();
13
+ const byNameInFile = new Map();
14
+ const classMethods = new Map();
15
+ // Re-export resolution: track `export { x } from './y'` and `module.exports = require('./y')`
16
+ const reexportMap = new Map();
17
+ if (fileContents) {
18
+ for (const [file, code] of Object.entries(fileContents)) {
19
+ if (!code || typeof code !== 'string') continue;
20
+ for (const m of code.matchAll(/export\s*\{\s*([^}]+)\s*\}\s*from\s*['"]([^'"]+)['"]/g)) {
21
+ const names = m[1].split(',').map(n => n.trim().split(/\s+as\s+/));
22
+ for (const [orig, alias] of names) {
23
+ reexportMap.set(`${file}::${alias || orig}`, { sourceFile: m[2], sourceName: orig.trim() });
24
+ }
25
+ }
26
+ const cjsReexport = code.match(/module\.exports\s*=\s*require\s*\(\s*['"]([^'"]+)['"]\s*\)/);
27
+ if (cjsReexport) reexportMap.set(`${file}::*`, { sourceFile: cjsReexport[1], sourceName: '*' });
28
+ }
29
+ }
16
30
 
17
31
  for (const file of Object.keys(perFileIR || {})) {
18
32
  const ir = perFileIR[file];
@@ -21,7 +35,6 @@ export function buildCallGraph(perFileIR) {
21
35
  for (const fn of ir.functions) {
22
36
  functions.set(fn.qid, fn);
23
37
  byNameInFile.get(file).set(fn.name, fn.qid);
24
- // Class methods: qid carries the class name as the scope.
25
38
  const m = fn.qid.match(/::([A-Z]\w*)::(\w+)@/);
26
39
  if (m) classMethods.set(`${m[1]}.${m[2]}`, fn.qid);
27
40
  }
@@ -56,7 +69,6 @@ export function buildCallGraph(perFileIR) {
56
69
  // ClassName.method falls back).
57
70
  function resolve(name) {
58
71
  if (!name || typeof name !== 'string') return null;
59
- // Direct ident match — search every file's same-file map.
60
72
  for (const m of byNameInFile.values()) {
61
73
  if (m.has(name)) return m.get(name);
62
74
  }
@@ -67,6 +79,14 @@ export function buildCallGraph(perFileIR) {
67
79
  if (m.has(tail)) return m.get(tail);
68
80
  }
69
81
  }
82
+ // Follow re-exports: if name was re-exported from another file, resolve there
83
+ for (const [key, { sourceName }] of reexportMap) {
84
+ if (key.endsWith(`::${name}`) || (sourceName === name)) {
85
+ for (const m of byNameInFile.values()) {
86
+ if (m.has(sourceName)) return m.get(sourceName);
87
+ }
88
+ }
89
+ }
70
90
  return null;
71
91
  }
72
92
  return { functions, edges, callersOf, resolve };
@@ -0,0 +1,142 @@
1
+ // Lightweight C/C++ preprocessor — Recommendation #8 of the SCA/SAST plan.
2
+ //
3
+ // Resolves `#include` + `#define BUF[N]` patterns across header files so
4
+ // the strcpy-destination-size guard (cpp.js#_classifyDestBuffer) can find
5
+ // buffer-size declarations declared in a sibling .h.
6
+ //
7
+ // Scope (v1, intentionally narrow):
8
+ // - `#include "local.h"` resolved relative to the source file
9
+ // (`#include <…>` system headers NOT resolved — they're too noisy
10
+ // and don't carry security signal at this layer)
11
+ // - `#define IDENT VALUE` — single-line object-like macros only;
12
+ // function-like macros (`#define X(a,b) ...`) ignored in v1
13
+ // - `typedef char BufT[N];` — alias expansion when N is literal
14
+ //
15
+ // What's intentionally OUT of scope:
16
+ // - Multi-step macro expansion (cascade of #define A B / #define B C / use A)
17
+ // - Conditional compilation (#ifdef / #if / #else): we union all branches
18
+ // - Token-pasting (##) and stringification (#)
19
+ // - Compiler -D flags (would require build-system integration)
20
+ //
21
+ // The goal is not to be a complete preprocessor; it's to recover the
22
+ // 80% of fixed-buffer-size context that Juliet C/C++ tests scatter across
23
+ // `header.h` (with `#define BUFSIZE 1024`) and `source.c` (with
24
+ // `char buf[BUFSIZE]; strcpy(buf, src);`).
25
+ //
26
+ // Output: { defines: Map<name, value>, typedefs: Map<name, {kind,size}>,
27
+ // includes: string[] }
28
+ // where size is a literal integer when resolvable, null otherwise.
29
+
30
+ import * as fs from 'node:fs';
31
+ import * as path from 'node:path';
32
+
33
+ const _MAX_INCLUDE_DEPTH = 4; // refuse pathological recursion
34
+ const _MAX_LINES_PER_FILE = 10_000; // skip auto-generated huge headers
35
+
36
+ function _parseDefines(content) {
37
+ const defines = new Map();
38
+ for (const m of content.matchAll(/^\s*#\s*define\s+([A-Za-z_]\w*)\s+(.+?)(?:$|\/\*|\/\/)/gm)) {
39
+ const name = m[1];
40
+ let val = m[2].trim();
41
+ // Strip trailing line continuation backslashes.
42
+ val = val.replace(/\\\s*$/, '').trim();
43
+ // Skip function-like macros for v1.
44
+ if (val.startsWith('(') && /\b[A-Za-z_]\w*\s*\(/.test(val)) continue;
45
+ defines.set(name, val);
46
+ }
47
+ return defines;
48
+ }
49
+
50
+ function _parseTypedefs(content) {
51
+ const typedefs = new Map();
52
+ // typedef char BufT[1024]; / typedef unsigned char Bytes[256];
53
+ for (const m of content.matchAll(/typedef\s+(?:unsigned\s+|signed\s+)?(?:char|wchar_t|int8_t|uint8_t)\s+([A-Za-z_]\w*)\s*\[\s*([A-Za-z_]\w*|\d+)\s*\]\s*;/g)) {
54
+ const name = m[1];
55
+ const sizeTxt = m[2];
56
+ let size = null;
57
+ if (/^\d+$/.test(sizeTxt)) size = parseInt(sizeTxt, 10);
58
+ typedefs.set(name, { kind: 'char-array', size, sizeExpr: sizeTxt });
59
+ }
60
+ return typedefs;
61
+ }
62
+
63
+ function _parseIncludes(content) {
64
+ const includes = [];
65
+ for (const m of content.matchAll(/^\s*#\s*include\s+"([^"]+)"/gm)) {
66
+ includes.push(m[1]);
67
+ }
68
+ return includes;
69
+ }
70
+
71
+ function _resolveSize(sizeExpr, defines) {
72
+ if (/^\d+$/.test(sizeExpr)) return parseInt(sizeExpr, 10);
73
+ const macro = defines.get(sizeExpr);
74
+ if (macro && /^\d+$/.test(macro)) return parseInt(macro, 10);
75
+ return null;
76
+ }
77
+
78
+ /**
79
+ * Recursively preprocess a single source file by walking its #includes.
80
+ * Returns the merged define table + typedef table + flat list of resolved
81
+ * include paths. Cycles are detected via the `visited` set.
82
+ */
83
+ export function preprocessFile(sourcePath, opts = {}) {
84
+ const visited = opts.visited || new Set();
85
+ const depth = opts.depth || 0;
86
+ const result = { defines: new Map(), typedefs: new Map(), includes: [] };
87
+
88
+ const abs = path.resolve(sourcePath);
89
+ if (visited.has(abs)) return result;
90
+ visited.add(abs);
91
+ if (depth > _MAX_INCLUDE_DEPTH) return result;
92
+
93
+ let content;
94
+ try { content = fs.readFileSync(abs, 'utf8'); }
95
+ catch { return result; }
96
+ if (content.split('\n').length > _MAX_LINES_PER_FILE) return result;
97
+
98
+ // First pass on this file's own contents.
99
+ const localDefines = _parseDefines(content);
100
+ const localTypedefs = _parseTypedefs(content);
101
+ const includes = _parseIncludes(content);
102
+
103
+ // Recursive merge — header values are merged BEFORE local ones so that
104
+ // a local #undef + redefine could in principle override (we don't model
105
+ // #undef, but this ordering is the correct future-extension point).
106
+ const dir = path.dirname(abs);
107
+ for (const inc of includes) {
108
+ const child = preprocessFile(path.join(dir, inc), { visited, depth: depth + 1 });
109
+ for (const [k, v] of child.defines) if (!result.defines.has(k)) result.defines.set(k, v);
110
+ for (const [k, v] of child.typedefs) if (!result.typedefs.has(k)) result.typedefs.set(k, v);
111
+ result.includes.push(...child.includes, inc);
112
+ }
113
+ for (const [k, v] of localDefines) result.defines.set(k, v);
114
+ for (const [k, v] of localTypedefs) result.typedefs.set(k, v);
115
+
116
+ // Final pass — resolve typedef sizes that referenced a macro.
117
+ for (const [name, td] of result.typedefs) {
118
+ if (td.size === null && td.sizeExpr) {
119
+ const resolved = _resolveSize(td.sizeExpr, result.defines);
120
+ if (resolved !== null) result.typedefs.set(name, { ...td, size: resolved });
121
+ }
122
+ }
123
+ return result;
124
+ }
125
+
126
+ /**
127
+ * Resolve a buffer-size expression in the context of a preprocessed file.
128
+ * Accepts either a literal integer string or a macro name. Returns the
129
+ * integer size, or null if unresolvable.
130
+ */
131
+ export function resolveSize(sizeExpr, preprocessed) {
132
+ return _resolveSize(sizeExpr, preprocessed.defines || new Map());
133
+ }
134
+
135
+ /**
136
+ * Resolve a typedef name to its size, if it's a char-array typedef.
137
+ */
138
+ export function resolveTypedef(name, preprocessed) {
139
+ return preprocessed.typedefs.get(name) || null;
140
+ }
141
+
142
+ export const _internals = { _parseDefines, _parseTypedefs, _parseIncludes };