@clear-capabilities/agentic-security-scanner 0.77.0 → 0.78.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 (83) hide show
  1. package/bin/.agentic-security/findings.json +1907 -0
  2. package/bin/.agentic-security/last-scan.json +1907 -0
  3. package/bin/.agentic-security/last-scan.json.sig +1 -0
  4. package/bin/.agentic-security/scan-history.json +115 -0
  5. package/bin/.agentic-security/streak.json +20 -0
  6. package/bin/agentic-security.js +33 -2
  7. package/dist/178.index.js +1 -1
  8. package/dist/384.index.js +1 -1
  9. package/dist/637.index.js +1 -1
  10. package/dist/718.index.js +106 -0
  11. package/dist/824.index.js +126 -0
  12. package/dist/838.index.js +1 -1
  13. package/dist/agentic-security.mjs +32 -32
  14. package/dist/agentic-security.mjs.sha256 +1 -1
  15. package/package.json +3 -3
  16. package/src/.agentic-security/findings.json +82642 -0
  17. package/src/.agentic-security/last-scan.json +82642 -0
  18. package/src/.agentic-security/last-scan.json.sig +1 -0
  19. package/src/.agentic-security/scan-history.json +10054 -0
  20. package/src/.agentic-security/streak.json +21 -0
  21. package/src/dataflow/.agentic-security/findings.json +3515 -0
  22. package/src/dataflow/.agentic-security/last-scan.json +3515 -0
  23. package/src/dataflow/.agentic-security/last-scan.json.sig +1 -0
  24. package/src/dataflow/.agentic-security/scan-history.json +702 -0
  25. package/src/dataflow/.agentic-security/streak.json +22 -0
  26. package/src/dataflow/async-sequencing.js +16 -7
  27. package/src/dataflow/builtin-summaries.js +131 -0
  28. package/src/dataflow/catalog.js +107 -0
  29. package/src/dataflow/cross-repo.js +75 -1
  30. package/src/dataflow/engine.js +129 -0
  31. package/src/dataflow/implicit-flow.js +24 -6
  32. package/src/dataflow/stub-aware-filter.js +69 -11
  33. package/src/dataflow/summaries.js +28 -3
  34. package/src/engine-parallel.js +70 -0
  35. package/src/engine.js +165 -15
  36. package/src/ir/.agentic-security/findings.json +3777 -0
  37. package/src/ir/.agentic-security/last-scan.json +3777 -0
  38. package/src/ir/.agentic-security/last-scan.json.sig +1 -0
  39. package/src/ir/.agentic-security/scan-history.json +771 -0
  40. package/src/ir/.agentic-security/streak.json +21 -0
  41. package/src/ir/index.js +22 -1
  42. package/src/ir/parser-go.js +403 -0
  43. package/src/ir/parser-js.js +2 -0
  44. package/src/ir/parser-php.js +330 -0
  45. package/src/ir/parser-py.helper.py +137 -11
  46. package/src/ir/parser-rb.js +309 -0
  47. package/src/posture/.agentic-security/findings.json +51562 -0
  48. package/src/posture/.agentic-security/last-scan.json +51562 -0
  49. package/src/posture/.agentic-security/last-scan.json.sig +1 -0
  50. package/src/posture/.agentic-security/scan-history.json +650 -0
  51. package/src/posture/.agentic-security/streak.json +20 -0
  52. package/src/posture/calibration.js +14 -0
  53. package/src/posture/triage.js +13 -0
  54. package/src/report/.agentic-security/findings.json +80 -0
  55. package/src/report/.agentic-security/last-scan.json +80 -0
  56. package/src/report/.agentic-security/last-scan.json.sig +1 -0
  57. package/src/report/.agentic-security/scan-history.json +35 -0
  58. package/src/report/.agentic-security/streak.json +22 -0
  59. package/src/report/index.js +23 -2
  60. package/src/sast/.agentic-security/findings.json +5190 -0
  61. package/src/sast/.agentic-security/last-scan.json +5190 -0
  62. package/src/sast/.agentic-security/last-scan.json.sig +1 -0
  63. package/src/sast/.agentic-security/scan-history.json +408 -0
  64. package/src/sast/.agentic-security/streak.json +20 -0
  65. package/src/sast/cache-poisoning.js +77 -0
  66. package/src/sast/comparison-safety.js +73 -0
  67. package/src/sast/db-taint.js +54 -0
  68. package/src/sast/graphql.js +127 -0
  69. package/src/sast/llm-stored-prompt.js +57 -0
  70. package/src/sast/mutation-xss.js +43 -0
  71. package/src/sast/nosql-injection.js +5 -0
  72. package/src/sast/null-byte-injection.js +76 -0
  73. package/src/sast/redos-nfa.js +338 -0
  74. package/src/sast/sensitive-data-logging.js +73 -0
  75. package/src/sast/weak-password-hash.js +77 -0
  76. package/src/sast/weak-randomness.js +100 -0
  77. package/src/sca/.agentic-security/findings.json +1587 -0
  78. package/src/sca/.agentic-security/last-scan.json +1587 -0
  79. package/src/sca/.agentic-security/last-scan.json.sig +1 -0
  80. package/src/sca/.agentic-security/scan-history.json +36 -0
  81. package/src/sca/.agentic-security/streak.json +21 -0
  82. package/src/sca/llm-function-extract.js +107 -0
  83. package/src/sca/vendor-detect.js +91 -0
@@ -0,0 +1,20 @@
1
+ {
2
+ "firstScanDate": "2026-05-27T11:16:44.741Z",
3
+ "lastScanDate": "2026-05-27T11:19:53.871Z",
4
+ "totalScans": 3,
5
+ "daysCleanCritical": 0,
6
+ "lastCleanDate": null,
7
+ "lastCriticalDate": "2026-05-27",
8
+ "hasEverHadCritical": true,
9
+ "bestDaysCleanCritical": 0,
10
+ "totalFindingsAtFirstScan": 257,
11
+ "totalFindingsAtLastScan": 257,
12
+ "totalFixesInferred": 0,
13
+ "lastGrade": "C",
14
+ "bestGrade": "C",
15
+ "launchCheckPassedAt": null,
16
+ "achievements": [
17
+ "first-scan"
18
+ ],
19
+ "previousGrade": "C"
20
+ }
@@ -120,6 +120,20 @@ export function loadCalibrationHistory(scanRoot) {
120
120
  };
121
121
  if (seed) merge(seed);
122
122
  if (customer) merge(customer);
123
+ // Merge triage-derived TP/FP counts (auto-feedback loop)
124
+ try {
125
+ const triage = _readJsonMaybe(path.join(scanRoot || process.cwd(), '.agentic-security', 'triage.json'));
126
+ if (triage && triage.findings) {
127
+ const triageFams = {};
128
+ for (const f of Object.values(triage.findings)) {
129
+ const fam = f.family || 'unknown';
130
+ if (!triageFams[fam]) triageFams[fam] = { tp: 0, fp: 0 };
131
+ if (f.state === 'fixed' || f.state === 'open' || f.state === 'in-progress') triageFams[fam].tp++;
132
+ else if (f.state === 'false-positive') triageFams[fam].fp++;
133
+ }
134
+ merge({ families: triageFams });
135
+ }
136
+ } catch { /* triage file optional */ }
123
137
  return { families };
124
138
  }
125
139
 
@@ -144,3 +144,16 @@ export function trend(scanRoot, sinceDays = 30) {
144
144
  totalOpen: findings.filter(f => f.state === 'open' || f.state === 'in-progress').length,
145
145
  };
146
146
  }
147
+
148
+ export function exportTriageMetrics(scanRoot) {
149
+ const triage = loadTriage(scanRoot);
150
+ const findings = Object.values(triage.findings || {});
151
+ const families = {};
152
+ for (const f of findings) {
153
+ const fam = f.family || 'unknown';
154
+ if (!families[fam]) families[fam] = { tp: 0, fp: 0 };
155
+ if (f.state === 'fixed' || f.state === 'open' || f.state === 'in-progress') families[fam].tp++;
156
+ else if (f.state === 'false-positive') families[fam].fp++;
157
+ }
158
+ return { families };
159
+ }
@@ -0,0 +1,80 @@
1
+ {
2
+ "scanId": "db8e3115-87e6-4e90-8041-31f9921c7b54",
3
+ "startedAt": "2026-05-27T11:09:28.873Z",
4
+ "durationMs": 183,
5
+ "scanned": {
6
+ "files": 2,
7
+ "lines": 0
8
+ },
9
+ "findings": [],
10
+ "bundles": [],
11
+ "routes": [],
12
+ "components": [],
13
+ "suppressedCount": 0,
14
+ "blastRadiusSignals": {
15
+ "industry": "generic",
16
+ "industryConfidence": "low",
17
+ "jurisdictions": [],
18
+ "controls": [],
19
+ "estimatedUsers": 50,
20
+ "revenueIndicator": "pre-revenue",
21
+ "hasStripe": false,
22
+ "hasAuth": false,
23
+ "hasUserTable": false,
24
+ "hasPII": false,
25
+ "hasPHI": false,
26
+ "hasS3": false
27
+ },
28
+ "_v3": {
29
+ "counterfactual": {
30
+ "spofControls": [],
31
+ "controlsDetected": 174
32
+ },
33
+ "threatModel": {
34
+ "summary": {
35
+ "assetCount": 0,
36
+ "boundaryCount": 0,
37
+ "strideCounts": {
38
+ "spoofing": 0,
39
+ "tampering": 0,
40
+ "repudiation": 0,
41
+ "informationDisclosure": 0,
42
+ "denialOfService": 0,
43
+ "elevationOfPrivilege": 0
44
+ }
45
+ },
46
+ "assets": [],
47
+ "trustBoundaries": [],
48
+ "stride": {
49
+ "spoofing": [],
50
+ "tampering": [],
51
+ "repudiation": [],
52
+ "informationDisclosure": [],
53
+ "denialOfService": [],
54
+ "elevationOfPrivilege": []
55
+ }
56
+ },
57
+ "trustBoundaryDiagram": {
58
+ "mermaid": "flowchart LR\n INTERNET((Internet))\n APP[\"Application\"]\n classDef sev_critical fill:#ffcccc,stroke:#a00,stroke-width:2px;\n classDef sev_high fill:#ffe0b2,stroke:#c60,stroke-width:2px;\n classDef sev_medium fill:#fff3cd,stroke:#a80;\n classDef sev_low fill:#e8eaf6,stroke:#557;",
59
+ "nodes": [
60
+ {
61
+ "id": "INTERNET",
62
+ "kind": "external",
63
+ "label": "Internet"
64
+ },
65
+ {
66
+ "id": "APP",
67
+ "kind": "app",
68
+ "label": "Application"
69
+ }
70
+ ],
71
+ "edges": [],
72
+ "decorations": []
73
+ },
74
+ "calibrationDrift": {
75
+ "alarms": [],
76
+ "note": "no-feedback-data"
77
+ }
78
+ },
79
+ "annotatorErrors": []
80
+ }
@@ -0,0 +1,80 @@
1
+ {
2
+ "scanId": "db8e3115-87e6-4e90-8041-31f9921c7b54",
3
+ "startedAt": "2026-05-27T11:09:28.873Z",
4
+ "durationMs": 183,
5
+ "scanned": {
6
+ "files": 2,
7
+ "lines": 0
8
+ },
9
+ "findings": [],
10
+ "bundles": [],
11
+ "routes": [],
12
+ "components": [],
13
+ "suppressedCount": 0,
14
+ "blastRadiusSignals": {
15
+ "industry": "generic",
16
+ "industryConfidence": "low",
17
+ "jurisdictions": [],
18
+ "controls": [],
19
+ "estimatedUsers": 50,
20
+ "revenueIndicator": "pre-revenue",
21
+ "hasStripe": false,
22
+ "hasAuth": false,
23
+ "hasUserTable": false,
24
+ "hasPII": false,
25
+ "hasPHI": false,
26
+ "hasS3": false
27
+ },
28
+ "_v3": {
29
+ "counterfactual": {
30
+ "spofControls": [],
31
+ "controlsDetected": 174
32
+ },
33
+ "threatModel": {
34
+ "summary": {
35
+ "assetCount": 0,
36
+ "boundaryCount": 0,
37
+ "strideCounts": {
38
+ "spoofing": 0,
39
+ "tampering": 0,
40
+ "repudiation": 0,
41
+ "informationDisclosure": 0,
42
+ "denialOfService": 0,
43
+ "elevationOfPrivilege": 0
44
+ }
45
+ },
46
+ "assets": [],
47
+ "trustBoundaries": [],
48
+ "stride": {
49
+ "spoofing": [],
50
+ "tampering": [],
51
+ "repudiation": [],
52
+ "informationDisclosure": [],
53
+ "denialOfService": [],
54
+ "elevationOfPrivilege": []
55
+ }
56
+ },
57
+ "trustBoundaryDiagram": {
58
+ "mermaid": "flowchart LR\n INTERNET((Internet))\n APP[\"Application\"]\n classDef sev_critical fill:#ffcccc,stroke:#a00,stroke-width:2px;\n classDef sev_high fill:#ffe0b2,stroke:#c60,stroke-width:2px;\n classDef sev_medium fill:#fff3cd,stroke:#a80;\n classDef sev_low fill:#e8eaf6,stroke:#557;",
59
+ "nodes": [
60
+ {
61
+ "id": "INTERNET",
62
+ "kind": "external",
63
+ "label": "Internet"
64
+ },
65
+ {
66
+ "id": "APP",
67
+ "kind": "app",
68
+ "label": "Application"
69
+ }
70
+ ],
71
+ "edges": [],
72
+ "decorations": []
73
+ },
74
+ "calibrationDrift": {
75
+ "alarms": [],
76
+ "note": "no-feedback-data"
77
+ }
78
+ },
79
+ "annotatorErrors": []
80
+ }
@@ -0,0 +1 @@
1
+ e3726a5fd5c2a4b763554484c083d9136dbb026f1f913a0c9b35e3455711b303
@@ -0,0 +1,35 @@
1
+ [
2
+ {
3
+ "timestamp": "2026-05-27T11:06:13.261Z",
4
+ "label": "scan",
5
+ "total": 0,
6
+ "critical": 0,
7
+ "high": 0,
8
+ "medium": 0,
9
+ "low": 0,
10
+ "kev": 0,
11
+ "ids": []
12
+ },
13
+ {
14
+ "timestamp": "2026-05-27T11:07:38.301Z",
15
+ "label": "scan",
16
+ "total": 0,
17
+ "critical": 0,
18
+ "high": 0,
19
+ "medium": 0,
20
+ "low": 0,
21
+ "kev": 0,
22
+ "ids": []
23
+ },
24
+ {
25
+ "timestamp": "2026-05-27T11:09:29.055Z",
26
+ "label": "scan",
27
+ "total": 0,
28
+ "critical": 0,
29
+ "high": 0,
30
+ "medium": 0,
31
+ "low": 0,
32
+ "kev": 0,
33
+ "ids": []
34
+ }
35
+ ]
@@ -0,0 +1,22 @@
1
+ {
2
+ "firstScanDate": "2026-05-27T11:06:13.266Z",
3
+ "lastScanDate": "2026-05-27T11:09:29.061Z",
4
+ "totalScans": 3,
5
+ "daysCleanCritical": 1,
6
+ "lastCleanDate": "2026-05-27",
7
+ "lastCriticalDate": null,
8
+ "hasEverHadCritical": false,
9
+ "bestDaysCleanCritical": 1,
10
+ "totalFindingsAtFirstScan": 0,
11
+ "totalFindingsAtLastScan": 0,
12
+ "totalFixesInferred": 0,
13
+ "lastGrade": "A+",
14
+ "bestGrade": "A+",
15
+ "launchCheckPassedAt": null,
16
+ "achievements": [
17
+ "first-scan",
18
+ "grade-a",
19
+ "grade-a-plus"
20
+ ],
21
+ "previousGrade": "A+"
22
+ }
@@ -322,6 +322,7 @@ export function toJSON(scan, meta={}, opts={}){
322
322
  // threw and were skipped. The findings still ship; downstream consumers
323
323
  // see the gap.
324
324
  annotatorErrors: Array.isArray(scan.annotatorErrors) ? scan.annotatorErrors : [],
325
+ _scanMeta: scan._scanMeta || null,
325
326
  };
326
327
  if (opts.includeSuppressed) out.suppressed = scan.suppressions||[];
327
328
  return out;
@@ -560,11 +561,31 @@ export function toSARIF(scan, meta={}){
560
561
  ...(scan && scan._rulesetVersionMismatch ? { rulesetVersionMismatch: scan._rulesetVersionMismatch } : {}),
561
562
  },
562
563
  }],
563
- results: findings.map(f => ({
564
+ results: findings.map(f => {
565
+ const chain = Array.isArray(f.chain) ? f.chain : [];
566
+ const codeFlows = chain.length >= 2 ? [{
567
+ threadFlows: [{
568
+ locations: chain.map((hop, idx) => ({
569
+ location: {
570
+ physicalLocation: {
571
+ artifactLocation: { uri: hop.file || f.file },
572
+ region: { startLine: Math.max(1, hop.line || 1) },
573
+ },
574
+ message: { text: hop.label || (idx === 0 ? 'source' : idx === chain.length - 1 ? 'sink' : 'propagation') },
575
+ },
576
+ })),
577
+ }],
578
+ }] : undefined;
579
+ const fixes = f.remediation ? [{
580
+ description: { text: f.remediation.slice(0, 500) },
581
+ }] : undefined;
582
+ return {
564
583
  ruleId: f.vuln ? f.vuln.replace(/[^a-zA-Z0-9]/g, '_') : 'unknown',
565
584
  level: SEV_TO_SARIF[f.severity] || 'warning',
566
585
  message: { text: f.fix?.description || f.vuln || 'Security finding' },
567
586
  locations: [{ physicalLocation: { artifactLocation: { uri: f.file }, region: { startLine: Math.max(1, f.line||1) } } }],
587
+ ...(codeFlows ? { codeFlows } : {}),
588
+ ...(fixes ? { fixes } : {}),
568
589
  // Phase-1 (Sentinel-parity) fingerprint: stableId persists across
569
590
  // refactors. Keep partialFingerprints intact for tools that key on
570
591
  // the line-hash; add a 'stableId' fingerprint for tools that respect
@@ -595,7 +616,7 @@ export function toSARIF(scan, meta={}){
595
616
  ...(f._unsigned ? { unsigned: true } : {}),
596
617
  ...(f._passThroughSigning ? { passThroughSigning: true } : {}),
597
618
  },
598
- })),
619
+ };}),
599
620
  }],
600
621
  };
601
622
  }