@clear-capabilities/agentic-security-scanner 0.78.0 → 0.79.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/bin/.agentic-security/findings.json +16 -16
- package/bin/.agentic-security/last-scan.json +16 -16
- package/bin/.agentic-security/last-scan.json.sig +1 -1
- package/bin/.agentic-security/scan-history.json +51 -0
- package/bin/.agentic-security/streak.json +5 -5
- package/bin/agentic-security.js +22 -7
- package/dist/178.index.js +1 -1
- package/dist/384.index.js +1 -1
- package/dist/476.index.js +5 -5
- package/dist/637.index.js +1 -1
- package/dist/700.index.js +138 -0
- package/dist/718.index.js +53 -0
- package/dist/838.index.js +1 -1
- package/dist/985.index.js +5 -0
- package/dist/agentic-security.mjs +1 -1
- package/dist/agentic-security.mjs.sha256 +1 -1
- package/package.json +2 -2
- package/src/dataflow/engine.js +52 -8
- package/src/engine.js +107 -6
- package/src/integrations/index.js +2 -1
- package/src/ir/callgraph.js +27 -7
- package/src/llm-validator/index.js +7 -5
- package/src/mcp/audit.js +5 -0
- package/src/posture/calibration-drift.js +2 -1
- package/src/posture/calibration.js +3 -2
- package/src/posture/fix-history.js +8 -2
- package/src/posture/profile.js +4 -5
- package/src/posture/rule-overrides.js +2 -3
- package/src/posture/rule-pack-signing.js +2 -3
- package/src/posture/rule-synthesis.js +5 -6
- package/src/posture/security-trend.js +4 -7
- package/src/posture/state-dir.js +124 -0
- package/src/posture/streak.js +3 -0
- package/src/posture/suppressions.js +5 -8
- package/src/posture/triage.js +3 -5
- package/src/posture/validator-metrics.js +3 -6
- package/src/sast/db-taint.js +24 -0
- package/src/sast/rust.js +26 -0
- package/src/sca/binary-metadata.js +124 -0
- package/src/sca/py-package-functions.js +118 -0
- package/src/sca/vendor-detect.js +53 -0
- package/src/.agentic-security/findings.json +0 -82642
- package/src/.agentic-security/last-scan.json +0 -82642
- package/src/.agentic-security/last-scan.json.sig +0 -1
- package/src/.agentic-security/scan-history.json +0 -10054
- package/src/.agentic-security/streak.json +0 -21
- package/src/dataflow/.agentic-security/findings.json +0 -3515
- package/src/dataflow/.agentic-security/last-scan.json +0 -3515
- package/src/dataflow/.agentic-security/last-scan.json.sig +0 -1
- package/src/dataflow/.agentic-security/scan-history.json +0 -702
- package/src/dataflow/.agentic-security/streak.json +0 -22
- package/src/ir/.agentic-security/findings.json +0 -3777
- package/src/ir/.agentic-security/last-scan.json +0 -3777
- package/src/ir/.agentic-security/last-scan.json.sig +0 -1
- package/src/ir/.agentic-security/scan-history.json +0 -771
- package/src/ir/.agentic-security/streak.json +0 -21
- package/src/posture/.agentic-security/findings.json +0 -51562
- package/src/posture/.agentic-security/last-scan.json +0 -51562
- package/src/posture/.agentic-security/last-scan.json.sig +0 -1
- package/src/posture/.agentic-security/scan-history.json +0 -650
- package/src/posture/.agentic-security/streak.json +0 -20
- package/src/report/.agentic-security/findings.json +0 -80
- package/src/report/.agentic-security/last-scan.json +0 -80
- package/src/report/.agentic-security/last-scan.json.sig +0 -1
- package/src/report/.agentic-security/scan-history.json +0 -35
- package/src/report/.agentic-security/streak.json +0 -22
- package/src/sast/.agentic-security/findings.json +0 -5190
- package/src/sast/.agentic-security/last-scan.json +0 -5190
- package/src/sast/.agentic-security/last-scan.json.sig +0 -1
- package/src/sast/.agentic-security/scan-history.json +0 -408
- package/src/sast/.agentic-security/streak.json +0 -20
- package/src/sca/.agentic-security/findings.json +0 -1587
- package/src/sca/.agentic-security/last-scan.json +0 -1587
- package/src/sca/.agentic-security/last-scan.json.sig +0 -1
- package/src/sca/.agentic-security/scan-history.json +0 -36
- package/src/sca/.agentic-security/streak.json +0 -21
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
|
-
"scanId": "
|
|
3
|
-
"startedAt": "2026-05-
|
|
4
|
-
"durationMs":
|
|
2
|
+
"scanId": "bb8f9491-46eb-4ec6-a21b-df7b0a436001",
|
|
3
|
+
"startedAt": "2026-05-28T14:16:52.841Z",
|
|
4
|
+
"durationMs": 320,
|
|
5
5
|
"scanned": {
|
|
6
6
|
"files": 7,
|
|
7
7
|
"lines": 0
|
|
@@ -759,7 +759,7 @@
|
|
|
759
759
|
"attackPlaybook": null
|
|
760
760
|
},
|
|
761
761
|
{
|
|
762
|
-
"id": "toctou-fs:agentic-security.js:
|
|
762
|
+
"id": "toctou-fs:agentic-security.js:367",
|
|
763
763
|
"kind": "sast",
|
|
764
764
|
"severity": "medium",
|
|
765
765
|
"vuln": "TOCTOU: file existence/permission check before open",
|
|
@@ -767,7 +767,7 @@
|
|
|
767
767
|
"owaspLlm": null,
|
|
768
768
|
"stride": "Tampering",
|
|
769
769
|
"file": "agentic-security.js",
|
|
770
|
-
"line":
|
|
770
|
+
"line": 367,
|
|
771
771
|
"snippet": "if (args.flags['since-baseline'] && fs.existsSync(baselinePath)) {",
|
|
772
772
|
"fix": null,
|
|
773
773
|
"reachable": false,
|
|
@@ -848,7 +848,7 @@
|
|
|
848
848
|
"dominantDriver": "legal counsel",
|
|
849
849
|
"comparable": "Generic finding — likely cost driven by user count + jurisdiction stack",
|
|
850
850
|
"confidence": "low",
|
|
851
|
-
"narrative": "TOCTOU: file existence/permission check before open on `agentic-security.js:
|
|
851
|
+
"narrative": "TOCTOU: file existence/permission check before open on `agentic-security.js:367` could expose configuration / internal data. Context: general SaaS / no specific regulatory exposure. Estimated cost: best $23k · likely $136k · worst $775k. Dominant driver: legal counsel. Comparable: Generic finding — likely cost driven by user count + jurisdiction stack."
|
|
852
852
|
},
|
|
853
853
|
"stableId": "ba3080b44d262d10",
|
|
854
854
|
"confidenceTier": "medium",
|
|
@@ -981,7 +981,7 @@
|
|
|
981
981
|
"attackPlaybook": null
|
|
982
982
|
},
|
|
983
983
|
{
|
|
984
|
-
"id": "toctou-fs:agentic-security.js:
|
|
984
|
+
"id": "toctou-fs:agentic-security.js:1151",
|
|
985
985
|
"kind": "sast",
|
|
986
986
|
"severity": "medium",
|
|
987
987
|
"vuln": "TOCTOU: file existence/permission check before open",
|
|
@@ -989,7 +989,7 @@
|
|
|
989
989
|
"owaspLlm": null,
|
|
990
990
|
"stride": "Tampering",
|
|
991
991
|
"file": "agentic-security.js",
|
|
992
|
-
"line":
|
|
992
|
+
"line": 1151,
|
|
993
993
|
"snippet": "const st = fs.statSync(abs);",
|
|
994
994
|
"fix": null,
|
|
995
995
|
"reachable": false,
|
|
@@ -1070,7 +1070,7 @@
|
|
|
1070
1070
|
"dominantDriver": "legal counsel",
|
|
1071
1071
|
"comparable": "Generic finding — likely cost driven by user count + jurisdiction stack",
|
|
1072
1072
|
"confidence": "low",
|
|
1073
|
-
"narrative": "TOCTOU: file existence/permission check before open on `agentic-security.js:
|
|
1073
|
+
"narrative": "TOCTOU: file existence/permission check before open on `agentic-security.js:1151` could expose configuration / internal data. Context: general SaaS / no specific regulatory exposure. Estimated cost: best $23k · likely $136k · worst $775k. Dominant driver: legal counsel. Comparable: Generic finding — likely cost driven by user count + jurisdiction stack."
|
|
1074
1074
|
},
|
|
1075
1075
|
"stableId": "17f63a600e3a68b4",
|
|
1076
1076
|
"confidenceTier": "medium",
|
|
@@ -1701,14 +1701,14 @@
|
|
|
1701
1701
|
"family": null
|
|
1702
1702
|
},
|
|
1703
1703
|
{
|
|
1704
|
-
"id": "logic:agentic-security.js:
|
|
1704
|
+
"id": "logic:agentic-security.js:367:TOCTOU:_existsSync_followed_by_file_op",
|
|
1705
1705
|
"kind": "logic",
|
|
1706
1706
|
"severity": "medium",
|
|
1707
1707
|
"vuln": "TOCTOU: existsSync followed by file op",
|
|
1708
1708
|
"cwe": "CWE-367",
|
|
1709
1709
|
"stride": "Tampering",
|
|
1710
1710
|
"file": "agentic-security.js",
|
|
1711
|
-
"line":
|
|
1711
|
+
"line": 367,
|
|
1712
1712
|
"snippet": "if (args.flags['since-baseline'] && fs.existsSync(baselinePath)) {",
|
|
1713
1713
|
"fix": {
|
|
1714
1714
|
"description": "Replace the check-then-act sequence with a single atomic operation (e.g., `fs.open` with appropriate flags). Between `existsSync` and the file op the file can be replaced by a symlink or removed.",
|
|
@@ -1778,7 +1778,7 @@
|
|
|
1778
1778
|
"dominantDriver": "legal counsel",
|
|
1779
1779
|
"comparable": "Generic finding — likely cost driven by user count + jurisdiction stack",
|
|
1780
1780
|
"confidence": "low",
|
|
1781
|
-
"narrative": "TOCTOU: existsSync followed by file op on `agentic-security.js:
|
|
1781
|
+
"narrative": "TOCTOU: existsSync followed by file op on `agentic-security.js:367` could expose configuration / internal data. Context: general SaaS / no specific regulatory exposure. Estimated cost: best $23k · likely $136k · worst $775k. Dominant driver: legal counsel. Comparable: Generic finding — likely cost driven by user count + jurisdiction stack."
|
|
1782
1782
|
},
|
|
1783
1783
|
"parser": "LOGIC",
|
|
1784
1784
|
"family": null
|
|
@@ -1787,7 +1787,7 @@
|
|
|
1787
1787
|
"bundles": [],
|
|
1788
1788
|
"routes": [],
|
|
1789
1789
|
"components": [],
|
|
1790
|
-
"suppressedCount":
|
|
1790
|
+
"suppressedCount": 42,
|
|
1791
1791
|
"blastRadiusSignals": {
|
|
1792
1792
|
"industry": "generic",
|
|
1793
1793
|
"industryConfidence": "low",
|
|
@@ -1805,7 +1805,7 @@
|
|
|
1805
1805
|
"_v3": {
|
|
1806
1806
|
"counterfactual": {
|
|
1807
1807
|
"spofControls": [],
|
|
1808
|
-
"controlsDetected":
|
|
1808
|
+
"controlsDetected": 119
|
|
1809
1809
|
},
|
|
1810
1810
|
"threatModel": {
|
|
1811
1811
|
"summary": {
|
|
@@ -1854,13 +1854,13 @@
|
|
|
1854
1854
|
{
|
|
1855
1855
|
"vuln": "TOCTOU: file existence/permission check before open",
|
|
1856
1856
|
"file": "agentic-security.js",
|
|
1857
|
-
"line":
|
|
1857
|
+
"line": 367,
|
|
1858
1858
|
"severity": "medium"
|
|
1859
1859
|
},
|
|
1860
1860
|
{
|
|
1861
1861
|
"vuln": "TOCTOU: file existence/permission check before open",
|
|
1862
1862
|
"file": "agentic-security.js",
|
|
1863
|
-
"line":
|
|
1863
|
+
"line": 1151,
|
|
1864
1864
|
"severity": "medium"
|
|
1865
1865
|
}
|
|
1866
1866
|
],
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
|
-
"scanId": "
|
|
3
|
-
"startedAt": "2026-05-
|
|
4
|
-
"durationMs":
|
|
2
|
+
"scanId": "bb8f9491-46eb-4ec6-a21b-df7b0a436001",
|
|
3
|
+
"startedAt": "2026-05-28T14:16:52.841Z",
|
|
4
|
+
"durationMs": 320,
|
|
5
5
|
"scanned": {
|
|
6
6
|
"files": 7,
|
|
7
7
|
"lines": 0
|
|
@@ -759,7 +759,7 @@
|
|
|
759
759
|
"attackPlaybook": null
|
|
760
760
|
},
|
|
761
761
|
{
|
|
762
|
-
"id": "toctou-fs:agentic-security.js:
|
|
762
|
+
"id": "toctou-fs:agentic-security.js:367",
|
|
763
763
|
"kind": "sast",
|
|
764
764
|
"severity": "medium",
|
|
765
765
|
"vuln": "TOCTOU: file existence/permission check before open",
|
|
@@ -767,7 +767,7 @@
|
|
|
767
767
|
"owaspLlm": null,
|
|
768
768
|
"stride": "Tampering",
|
|
769
769
|
"file": "agentic-security.js",
|
|
770
|
-
"line":
|
|
770
|
+
"line": 367,
|
|
771
771
|
"snippet": "if (args.flags['since-baseline'] && fs.existsSync(baselinePath)) {",
|
|
772
772
|
"fix": null,
|
|
773
773
|
"reachable": false,
|
|
@@ -848,7 +848,7 @@
|
|
|
848
848
|
"dominantDriver": "legal counsel",
|
|
849
849
|
"comparable": "Generic finding — likely cost driven by user count + jurisdiction stack",
|
|
850
850
|
"confidence": "low",
|
|
851
|
-
"narrative": "TOCTOU: file existence/permission check before open on `agentic-security.js:
|
|
851
|
+
"narrative": "TOCTOU: file existence/permission check before open on `agentic-security.js:367` could expose configuration / internal data. Context: general SaaS / no specific regulatory exposure. Estimated cost: best $23k · likely $136k · worst $775k. Dominant driver: legal counsel. Comparable: Generic finding — likely cost driven by user count + jurisdiction stack."
|
|
852
852
|
},
|
|
853
853
|
"stableId": "ba3080b44d262d10",
|
|
854
854
|
"confidenceTier": "medium",
|
|
@@ -981,7 +981,7 @@
|
|
|
981
981
|
"attackPlaybook": null
|
|
982
982
|
},
|
|
983
983
|
{
|
|
984
|
-
"id": "toctou-fs:agentic-security.js:
|
|
984
|
+
"id": "toctou-fs:agentic-security.js:1151",
|
|
985
985
|
"kind": "sast",
|
|
986
986
|
"severity": "medium",
|
|
987
987
|
"vuln": "TOCTOU: file existence/permission check before open",
|
|
@@ -989,7 +989,7 @@
|
|
|
989
989
|
"owaspLlm": null,
|
|
990
990
|
"stride": "Tampering",
|
|
991
991
|
"file": "agentic-security.js",
|
|
992
|
-
"line":
|
|
992
|
+
"line": 1151,
|
|
993
993
|
"snippet": "const st = fs.statSync(abs);",
|
|
994
994
|
"fix": null,
|
|
995
995
|
"reachable": false,
|
|
@@ -1070,7 +1070,7 @@
|
|
|
1070
1070
|
"dominantDriver": "legal counsel",
|
|
1071
1071
|
"comparable": "Generic finding — likely cost driven by user count + jurisdiction stack",
|
|
1072
1072
|
"confidence": "low",
|
|
1073
|
-
"narrative": "TOCTOU: file existence/permission check before open on `agentic-security.js:
|
|
1073
|
+
"narrative": "TOCTOU: file existence/permission check before open on `agentic-security.js:1151` could expose configuration / internal data. Context: general SaaS / no specific regulatory exposure. Estimated cost: best $23k · likely $136k · worst $775k. Dominant driver: legal counsel. Comparable: Generic finding — likely cost driven by user count + jurisdiction stack."
|
|
1074
1074
|
},
|
|
1075
1075
|
"stableId": "17f63a600e3a68b4",
|
|
1076
1076
|
"confidenceTier": "medium",
|
|
@@ -1701,14 +1701,14 @@
|
|
|
1701
1701
|
"family": null
|
|
1702
1702
|
},
|
|
1703
1703
|
{
|
|
1704
|
-
"id": "logic:agentic-security.js:
|
|
1704
|
+
"id": "logic:agentic-security.js:367:TOCTOU:_existsSync_followed_by_file_op",
|
|
1705
1705
|
"kind": "logic",
|
|
1706
1706
|
"severity": "medium",
|
|
1707
1707
|
"vuln": "TOCTOU: existsSync followed by file op",
|
|
1708
1708
|
"cwe": "CWE-367",
|
|
1709
1709
|
"stride": "Tampering",
|
|
1710
1710
|
"file": "agentic-security.js",
|
|
1711
|
-
"line":
|
|
1711
|
+
"line": 367,
|
|
1712
1712
|
"snippet": "if (args.flags['since-baseline'] && fs.existsSync(baselinePath)) {",
|
|
1713
1713
|
"fix": {
|
|
1714
1714
|
"description": "Replace the check-then-act sequence with a single atomic operation (e.g., `fs.open` with appropriate flags). Between `existsSync` and the file op the file can be replaced by a symlink or removed.",
|
|
@@ -1778,7 +1778,7 @@
|
|
|
1778
1778
|
"dominantDriver": "legal counsel",
|
|
1779
1779
|
"comparable": "Generic finding — likely cost driven by user count + jurisdiction stack",
|
|
1780
1780
|
"confidence": "low",
|
|
1781
|
-
"narrative": "TOCTOU: existsSync followed by file op on `agentic-security.js:
|
|
1781
|
+
"narrative": "TOCTOU: existsSync followed by file op on `agentic-security.js:367` could expose configuration / internal data. Context: general SaaS / no specific regulatory exposure. Estimated cost: best $23k · likely $136k · worst $775k. Dominant driver: legal counsel. Comparable: Generic finding — likely cost driven by user count + jurisdiction stack."
|
|
1782
1782
|
},
|
|
1783
1783
|
"parser": "LOGIC",
|
|
1784
1784
|
"family": null
|
|
@@ -1787,7 +1787,7 @@
|
|
|
1787
1787
|
"bundles": [],
|
|
1788
1788
|
"routes": [],
|
|
1789
1789
|
"components": [],
|
|
1790
|
-
"suppressedCount":
|
|
1790
|
+
"suppressedCount": 42,
|
|
1791
1791
|
"blastRadiusSignals": {
|
|
1792
1792
|
"industry": "generic",
|
|
1793
1793
|
"industryConfidence": "low",
|
|
@@ -1805,7 +1805,7 @@
|
|
|
1805
1805
|
"_v3": {
|
|
1806
1806
|
"counterfactual": {
|
|
1807
1807
|
"spofControls": [],
|
|
1808
|
-
"controlsDetected":
|
|
1808
|
+
"controlsDetected": 119
|
|
1809
1809
|
},
|
|
1810
1810
|
"threatModel": {
|
|
1811
1811
|
"summary": {
|
|
@@ -1854,13 +1854,13 @@
|
|
|
1854
1854
|
{
|
|
1855
1855
|
"vuln": "TOCTOU: file existence/permission check before open",
|
|
1856
1856
|
"file": "agentic-security.js",
|
|
1857
|
-
"line":
|
|
1857
|
+
"line": 367,
|
|
1858
1858
|
"severity": "medium"
|
|
1859
1859
|
},
|
|
1860
1860
|
{
|
|
1861
1861
|
"vuln": "TOCTOU: file existence/permission check before open",
|
|
1862
1862
|
"file": "agentic-security.js",
|
|
1863
|
-
"line":
|
|
1863
|
+
"line": 1151,
|
|
1864
1864
|
"severity": "medium"
|
|
1865
1865
|
}
|
|
1866
1866
|
],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
5bb921912d508574fede241a7e16cd7ac261f415b200e9eff04093fa70426dd1
|
|
@@ -111,5 +111,56 @@
|
|
|
111
111
|
"toctou-fs:agentic-security.js:1136",
|
|
112
112
|
"toctou-fs:agentic-security.js:362"
|
|
113
113
|
]
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"timestamp": "2026-05-28T14:13:54.951Z",
|
|
117
|
+
"label": "scan",
|
|
118
|
+
"total": 5,
|
|
119
|
+
"critical": 0,
|
|
120
|
+
"high": 0,
|
|
121
|
+
"medium": 5,
|
|
122
|
+
"low": 0,
|
|
123
|
+
"kev": 0,
|
|
124
|
+
"ids": [
|
|
125
|
+
"toctou-fs:agentic-security-audit.js:55",
|
|
126
|
+
"toctou-fs:agentic-security-consistency.js:44",
|
|
127
|
+
"toctou-fs:agentic-security-consistency.js:66",
|
|
128
|
+
"toctou-fs:agentic-security.js:1141",
|
|
129
|
+
"toctou-fs:agentic-security.js:362"
|
|
130
|
+
]
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
"timestamp": "2026-05-28T14:16:39.437Z",
|
|
134
|
+
"label": "scan",
|
|
135
|
+
"total": 5,
|
|
136
|
+
"critical": 0,
|
|
137
|
+
"high": 0,
|
|
138
|
+
"medium": 5,
|
|
139
|
+
"low": 0,
|
|
140
|
+
"kev": 0,
|
|
141
|
+
"ids": [
|
|
142
|
+
"toctou-fs:agentic-security-audit.js:55",
|
|
143
|
+
"toctou-fs:agentic-security-consistency.js:44",
|
|
144
|
+
"toctou-fs:agentic-security-consistency.js:66",
|
|
145
|
+
"toctou-fs:agentic-security.js:1146",
|
|
146
|
+
"toctou-fs:agentic-security.js:367"
|
|
147
|
+
]
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
"timestamp": "2026-05-28T14:16:53.162Z",
|
|
151
|
+
"label": "scan",
|
|
152
|
+
"total": 5,
|
|
153
|
+
"critical": 0,
|
|
154
|
+
"high": 0,
|
|
155
|
+
"medium": 5,
|
|
156
|
+
"low": 0,
|
|
157
|
+
"kev": 0,
|
|
158
|
+
"ids": [
|
|
159
|
+
"toctou-fs:agentic-security-audit.js:55",
|
|
160
|
+
"toctou-fs:agentic-security-consistency.js:44",
|
|
161
|
+
"toctou-fs:agentic-security-consistency.js:66",
|
|
162
|
+
"toctou-fs:agentic-security.js:1151",
|
|
163
|
+
"toctou-fs:agentic-security.js:367"
|
|
164
|
+
]
|
|
114
165
|
}
|
|
115
166
|
]
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"firstScanDate": "2026-05-26T04:00:10.482Z",
|
|
3
|
-
"lastScanDate": "2026-05-
|
|
4
|
-
"totalScans":
|
|
5
|
-
"daysCleanCritical":
|
|
6
|
-
"lastCleanDate": "2026-05-
|
|
3
|
+
"lastScanDate": "2026-05-28T14:16:53.192Z",
|
|
4
|
+
"totalScans": 10,
|
|
5
|
+
"daysCleanCritical": 3,
|
|
6
|
+
"lastCleanDate": "2026-05-28",
|
|
7
7
|
"lastCriticalDate": null,
|
|
8
8
|
"hasEverHadCritical": false,
|
|
9
|
-
"bestDaysCleanCritical":
|
|
9
|
+
"bestDaysCleanCritical": 3,
|
|
10
10
|
"totalFindingsAtFirstScan": 11,
|
|
11
11
|
"totalFindingsAtLastScan": 13,
|
|
12
12
|
"totalFixesInferred": 0,
|
package/bin/agentic-security.js
CHANGED
|
@@ -269,6 +269,11 @@ function renderV3Blocks(scan, flags) {
|
|
|
269
269
|
// Always-on machine output (R2). Vibecoder gets JSON only; pro gets JSON+SARIF+CSV.
|
|
270
270
|
async function writeMachineOutput(targetAbs, scan, meta, profile) {
|
|
271
271
|
const stateDir = path.join(targetAbs, '.agentic-security');
|
|
272
|
+
const { isSafeStateDir: _isSafe } = await import('../src/posture/state-dir.js');
|
|
273
|
+
if (!_isSafe(stateDir)) {
|
|
274
|
+
if (process.env.AGENTIC_SECURITY_DEBUG === '1') process.stderr.write(`[agentic-security] refusing to write machine output at ${stateDir} — no project marker\n`);
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
272
277
|
await fsp.mkdir(stateDir, { recursive: true });
|
|
273
278
|
// Always JSON (used by /security-fix and /security-report).
|
|
274
279
|
await fsp.writeFile(path.join(stateDir, 'findings.json'),
|
|
@@ -495,14 +500,19 @@ async function cmdScan(args) {
|
|
|
495
500
|
else process.stdout.write(body + '\n');
|
|
496
501
|
|
|
497
502
|
// Persist last scan for /security-fix and /security-report
|
|
503
|
+
const { isSafeStateDir: _isSafeStateDir } = await import('../src/posture/state-dir.js');
|
|
498
504
|
const stateDir = path.join(path.resolve(target), '.agentic-security');
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
505
|
+
if (_isSafeStateDir(stateDir)) {
|
|
506
|
+
await fsp.mkdir(stateDir, { recursive: true });
|
|
507
|
+
const persistedScan = toJSON(scan, meta);
|
|
508
|
+
const lastScanBody = JSON.stringify(persistedScan, null, 2);
|
|
509
|
+
await fsp.writeFile(path.join(stateDir, 'last-scan.json'), lastScanBody);
|
|
510
|
+
try {
|
|
511
|
+
await fsp.writeFile(path.join(stateDir, 'last-scan.json.sig'), _signLastScan(lastScanBody));
|
|
512
|
+
} catch { /* non-fatal — sig file is best-effort */ }
|
|
513
|
+
} else {
|
|
514
|
+
if (process.env.AGENTIC_SECURITY_DEBUG === '1') process.stderr.write(`[agentic-security] refusing to write state at ${stateDir} — no project marker in ${path.resolve(target)}\n`);
|
|
515
|
+
}
|
|
506
516
|
|
|
507
517
|
// 0.14.0 — update streak / achievements after every full scan. Suppress
|
|
508
518
|
// streak side effects when the user only wants raw JSON output (CI piping).
|
|
@@ -587,6 +597,11 @@ async function cmdCi(args) {
|
|
|
587
597
|
|
|
588
598
|
// Persist the three CI artifacts.
|
|
589
599
|
const stateDir = path.join(targetAbs, '.agentic-security');
|
|
600
|
+
const { isSafeStateDir: _isSafeCi } = await import('../src/posture/state-dir.js');
|
|
601
|
+
if (!_isSafeCi(stateDir)) {
|
|
602
|
+
if (process.env.AGENTIC_SECURITY_DEBUG === '1') process.stderr.write(`[agentic-security] refusing to write CI artifacts at ${stateDir} — no project marker\n`);
|
|
603
|
+
return;
|
|
604
|
+
}
|
|
590
605
|
await fsp.mkdir(stateDir, { recursive: true });
|
|
591
606
|
await fsp.writeFile(path.join(stateDir, 'findings.json'),
|
|
592
607
|
JSON.stringify(toJSON(scan, meta), null, 2));
|
package/dist/178.index.js
CHANGED
|
@@ -13,7 +13,7 @@ export const modules = {
|
|
|
13
13
|
/* harmony import */ var node_child_process__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1421);
|
|
14
14
|
/* harmony import */ var node_fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3024);
|
|
15
15
|
/* harmony import */ var node_path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6760);
|
|
16
|
-
/* harmony import */ var _engine_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(
|
|
16
|
+
/* harmony import */ var _engine_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(6048);
|
|
17
17
|
// Time-travel + counterfactual scanning (v0.68).
|
|
18
18
|
//
|
|
19
19
|
// Two new modes that exploit the pure-input shape of runFullScan:
|
package/dist/384.index.js
CHANGED
|
@@ -8,7 +8,7 @@ export const modules = {
|
|
|
8
8
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
9
9
|
/* harmony export */ scanCredentials: () => (/* reexport safe */ _engine_js__WEBPACK_IMPORTED_MODULE_0__.Sv)
|
|
10
10
|
/* harmony export */ });
|
|
11
|
-
/* harmony import */ var _engine_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(
|
|
11
|
+
/* harmony import */ var _engine_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6048);
|
|
12
12
|
// Secrets submodule view of the engine — credential + entropy + TODO scanning.
|
|
13
13
|
|
|
14
14
|
|
package/dist/476.index.js
CHANGED
|
@@ -11,6 +11,7 @@ export const modules = {
|
|
|
11
11
|
/* unused harmony export _internals */
|
|
12
12
|
/* harmony import */ var node_fs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3024);
|
|
13
13
|
/* harmony import */ var node_path__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6760);
|
|
14
|
+
/* harmony import */ var _state_dir_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(1174);
|
|
14
15
|
// Auto-rule synthesis from repeated FPs (FR-LEARN-6).
|
|
15
16
|
//
|
|
16
17
|
// Reads `.agentic-security/triage-feedback.json` (populated by the /triage
|
|
@@ -27,13 +28,11 @@ export const modules = {
|
|
|
27
28
|
|
|
28
29
|
|
|
29
30
|
|
|
30
|
-
const TRIAGE_PATH = node_path__WEBPACK_IMPORTED_MODULE_1__.join('.agentic-security', 'triage-feedback.json');
|
|
31
|
-
const PROPOSED_DIR = node_path__WEBPACK_IMPORTED_MODULE_1__.join('.agentic-security', 'rules-proposed');
|
|
32
31
|
|
|
33
32
|
const DEFAULT_FP_THRESHOLD = 5;
|
|
34
33
|
|
|
35
34
|
function _readTriage(scanRoot) {
|
|
36
|
-
const fp =
|
|
35
|
+
const fp = (0,_state_dir_js__WEBPACK_IMPORTED_MODULE_2__/* .statePath */ .BQ)(scanRoot, 'triage-feedback.json');
|
|
37
36
|
if (!node_fs__WEBPACK_IMPORTED_MODULE_0__.existsSync(fp)) return null;
|
|
38
37
|
try { return JSON.parse(node_fs__WEBPACK_IMPORTED_MODULE_0__.readFileSync(fp, 'utf8')); } catch { return null; }
|
|
39
38
|
}
|
|
@@ -100,7 +99,8 @@ function synthesizeRules(scanRoot, opts = {}) {
|
|
|
100
99
|
groups.get(k).push(e);
|
|
101
100
|
}
|
|
102
101
|
const proposals = [];
|
|
103
|
-
const dir =
|
|
102
|
+
const dir = (0,_state_dir_js__WEBPACK_IMPORTED_MODULE_2__/* .statePath */ .BQ)(scanRoot, 'rules-proposed');
|
|
103
|
+
if (!opts.dryRun && !(0,_state_dir_js__WEBPACK_IMPORTED_MODULE_2__.isSafeStateDir)(node_path__WEBPACK_IMPORTED_MODULE_1__.dirname(dir))) return [];
|
|
104
104
|
for (const [, group] of groups) {
|
|
105
105
|
if (group.length < threshold) continue;
|
|
106
106
|
const summary = _summarizeGroup(group);
|
|
@@ -118,7 +118,7 @@ function synthesizeRules(scanRoot, opts = {}) {
|
|
|
118
118
|
return proposals;
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
-
const _internals = { DEFAULT_FP_THRESHOLD
|
|
121
|
+
const _internals = { DEFAULT_FP_THRESHOLD };
|
|
122
122
|
|
|
123
123
|
|
|
124
124
|
/***/ })
|
package/dist/637.index.js
CHANGED
|
@@ -10,7 +10,7 @@ export const modules = {
|
|
|
10
10
|
/* harmony export */ renderPrDeltaText: () => (/* binding */ renderPrDeltaText)
|
|
11
11
|
/* harmony export */ });
|
|
12
12
|
/* harmony import */ var node_child_process__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1421);
|
|
13
|
-
/* harmony import */ var _engine_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(
|
|
13
|
+
/* harmony import */ var _engine_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6048);
|
|
14
14
|
// Shadowscan / security-DELTA on PR (v0.72).
|
|
15
15
|
//
|
|
16
16
|
// Most SAST PR-comment integrations show absolute counts — "12 findings
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
export const id = 700;
|
|
2
|
+
export const ids = [700];
|
|
3
|
+
export const modules = {
|
|
4
|
+
|
|
5
|
+
/***/ 1700:
|
|
6
|
+
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
|
7
|
+
|
|
8
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
9
|
+
/* harmony export */ validateOsvFunctionsExist: () => (/* binding */ validateOsvFunctionsExist)
|
|
10
|
+
/* harmony export */ });
|
|
11
|
+
/* unused harmony export extractPythonPackageFunctions */
|
|
12
|
+
/* harmony import */ var node_fs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3024);
|
|
13
|
+
/* harmony import */ var node_path__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6760);
|
|
14
|
+
/* harmony import */ var node_child_process__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(1421);
|
|
15
|
+
/* harmony import */ var _ir_parser_py_cst_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(682);
|
|
16
|
+
// Python package function extraction via the CST parser.
|
|
17
|
+
//
|
|
18
|
+
// Locates an installed Python package in site-packages or .venv,
|
|
19
|
+
// parses its source files via the Python CST parser, and returns
|
|
20
|
+
// a map of exported function names. Used by markUsedVulnFunctions
|
|
21
|
+
// to validate that OSV-named vulnerable functions actually exist
|
|
22
|
+
// in the installed version.
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
const VENV_DIRS = ['.venv', 'venv', '.env', 'env'];
|
|
30
|
+
|
|
31
|
+
function _findSitePackages(scanRoot) {
|
|
32
|
+
for (const vdir of VENV_DIRS) {
|
|
33
|
+
const base = node_path__WEBPACK_IMPORTED_MODULE_1__.join(scanRoot || '.', vdir);
|
|
34
|
+
if (!node_fs__WEBPACK_IMPORTED_MODULE_0__.existsSync(base)) continue;
|
|
35
|
+
const lib = node_path__WEBPACK_IMPORTED_MODULE_1__.join(base, 'lib');
|
|
36
|
+
if (!node_fs__WEBPACK_IMPORTED_MODULE_0__.existsSync(lib)) continue;
|
|
37
|
+
const pydirs = node_fs__WEBPACK_IMPORTED_MODULE_0__.readdirSync(lib).filter(d => d.startsWith('python'));
|
|
38
|
+
for (const pydir of pydirs) {
|
|
39
|
+
const sp = node_path__WEBPACK_IMPORTED_MODULE_1__.join(lib, pydir, 'site-packages');
|
|
40
|
+
if (node_fs__WEBPACK_IMPORTED_MODULE_0__.existsSync(sp)) return sp;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// Fallback: ask python3 directly
|
|
44
|
+
try {
|
|
45
|
+
const out = (0,node_child_process__WEBPACK_IMPORTED_MODULE_2__.execFileSync)('python3', ['-c', 'import site; print(site.getsitepackages()[0])'], {
|
|
46
|
+
encoding: 'utf8', timeout: 5000,
|
|
47
|
+
}).trim();
|
|
48
|
+
if (out && node_fs__WEBPACK_IMPORTED_MODULE_0__.existsSync(out)) return out;
|
|
49
|
+
} catch { /* no python3 or no site-packages */ }
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function _findPackageDir(sitePackages, packageName) {
|
|
54
|
+
if (!sitePackages) return null;
|
|
55
|
+
const normalized = packageName.replace(/-/g, '_').toLowerCase();
|
|
56
|
+
const candidates = [
|
|
57
|
+
normalized,
|
|
58
|
+
packageName.toLowerCase(),
|
|
59
|
+
packageName,
|
|
60
|
+
];
|
|
61
|
+
for (const name of candidates) {
|
|
62
|
+
const dir = node_path__WEBPACK_IMPORTED_MODULE_1__.join(sitePackages, name);
|
|
63
|
+
if (node_fs__WEBPACK_IMPORTED_MODULE_0__.existsSync(dir) && node_fs__WEBPACK_IMPORTED_MODULE_0__.statSync(dir).isDirectory()) return dir;
|
|
64
|
+
}
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function _readPyFilesFromDir(dir, maxFiles = 50) {
|
|
69
|
+
const entries = [];
|
|
70
|
+
try {
|
|
71
|
+
const files = node_fs__WEBPACK_IMPORTED_MODULE_0__.readdirSync(dir, { recursive: true })
|
|
72
|
+
.filter(f => f.endsWith('.py'))
|
|
73
|
+
.slice(0, maxFiles);
|
|
74
|
+
for (const f of files) {
|
|
75
|
+
const fp = node_path__WEBPACK_IMPORTED_MODULE_1__.join(dir, f);
|
|
76
|
+
try {
|
|
77
|
+
const content = node_fs__WEBPACK_IMPORTED_MODULE_0__.readFileSync(fp, 'utf8');
|
|
78
|
+
if (content.length < 1_000_000) {
|
|
79
|
+
entries.push({ file: f, content });
|
|
80
|
+
}
|
|
81
|
+
} catch { /* skip unreadable files */ }
|
|
82
|
+
}
|
|
83
|
+
} catch { /* dir not readable */ }
|
|
84
|
+
return entries;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function extractPythonPackageFunctions(packageName, scanRoot) {
|
|
88
|
+
const cap = (0,_ir_parser_py_cst_js__WEBPACK_IMPORTED_MODULE_3__/* .probePythonAvailable */ .w4)();
|
|
89
|
+
if (!cap.ok) return null;
|
|
90
|
+
|
|
91
|
+
const sitePackages = _findSitePackages(scanRoot);
|
|
92
|
+
const pkgDir = _findPackageDir(sitePackages, packageName);
|
|
93
|
+
if (!pkgDir) return null;
|
|
94
|
+
|
|
95
|
+
const pyFiles = _readPyFilesFromDir(pkgDir);
|
|
96
|
+
if (!pyFiles.length) return null;
|
|
97
|
+
|
|
98
|
+
const batch = (0,_ir_parser_py_cst_js__WEBPACK_IMPORTED_MODULE_3__/* .parsePythonFilesBatch */ .H2)(pyFiles);
|
|
99
|
+
if (!batch || !Array.isArray(batch)) return null;
|
|
100
|
+
|
|
101
|
+
const functionMap = new Map();
|
|
102
|
+
for (const fileIR of batch) {
|
|
103
|
+
if (!fileIR || !fileIR.functions) continue;
|
|
104
|
+
for (const fn of fileIR.functions) {
|
|
105
|
+
if (fn.name && !fn.name.startsWith('_')) {
|
|
106
|
+
functionMap.set(fn.name, {
|
|
107
|
+
file: fileIR.file,
|
|
108
|
+
line: fn.line,
|
|
109
|
+
qid: fn.qid,
|
|
110
|
+
params: fn.params,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return functionMap;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function validateOsvFunctionsExist(packageName, osvFunctions, scanRoot) {
|
|
119
|
+
if (!osvFunctions || !osvFunctions.length) return { validated: [], missing: [] };
|
|
120
|
+
const fnMap = extractPythonPackageFunctions(packageName, scanRoot);
|
|
121
|
+
if (!fnMap) return { validated: osvFunctions, missing: [] };
|
|
122
|
+
const validated = [];
|
|
123
|
+
const missing = [];
|
|
124
|
+
for (const fn of osvFunctions) {
|
|
125
|
+
const shortFn = fn.includes('.') ? fn.split('.').pop() : fn;
|
|
126
|
+
if (fnMap.has(shortFn) || fnMap.has(fn)) {
|
|
127
|
+
validated.push(shortFn);
|
|
128
|
+
} else {
|
|
129
|
+
missing.push(fn);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return { validated, missing };
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
/***/ })
|
|
137
|
+
|
|
138
|
+
};
|
package/dist/718.index.js
CHANGED
|
@@ -97,6 +97,59 @@ function detectVendoredLibraries(fileContents) {
|
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
99
|
}
|
|
100
|
+
// Pass 2: Function-body structural matching for minified/forked copies
|
|
101
|
+
const FUNCTION_BODY_SIGS = [
|
|
102
|
+
{ pkg: 'lodash', ecosystem: 'npm', fn: 'merge', paramMin: 1,
|
|
103
|
+
bodyContains: ['assignValue', 'baseFor', 'isObject', 'baseMerge'] },
|
|
104
|
+
{ pkg: 'lodash', ecosystem: 'npm', fn: 'template', paramMin: 1,
|
|
105
|
+
bodyContains: ['sourceURL', 'interpolate', 'evaluate', 'escape'] },
|
|
106
|
+
{ pkg: 'lodash', ecosystem: 'npm', fn: 'defaultsDeep', paramMin: 1,
|
|
107
|
+
bodyContains: ['baseMerge', 'isMergeableObject', 'customDefaultsMerge'] },
|
|
108
|
+
{ pkg: 'jquery', ecosystem: 'npm', fn: 'ajax', paramMin: 1,
|
|
109
|
+
bodyContains: ['XMLHttpRequest', 'ajaxSettings', 'crossDomain', 'responseFields'] },
|
|
110
|
+
{ pkg: 'handlebars', ecosystem: 'npm', fn: 'compile', paramMin: 1,
|
|
111
|
+
bodyContains: ['templateSpec', 'container', 'invokePartial', 'blockParams'] },
|
|
112
|
+
{ pkg: 'marked', ecosystem: 'npm', fn: 'parse', paramMin: 1,
|
|
113
|
+
bodyContains: ['Lexer', 'Parser', 'blockTokens', 'walkTokens'] },
|
|
114
|
+
{ pkg: 'ejs', ecosystem: 'npm', fn: 'render', paramMin: 1,
|
|
115
|
+
bodyContains: ['includeFile', 'resolveInclude', 'rethrow', 'escapeFn'] },
|
|
116
|
+
{ pkg: 'moment', ecosystem: 'npm', fn: 'format', paramMin: 0,
|
|
117
|
+
bodyContains: ['formatMoment', 'expandFormat', 'makeFormatFunction', 'localFormattingTokens'] },
|
|
118
|
+
{ pkg: 'underscore', ecosystem: 'npm', fn: 'template', paramMin: 1,
|
|
119
|
+
bodyContains: ['interpolate', 'evaluate', 'escape', 'templateSettings'] },
|
|
120
|
+
{ pkg: 'minimist', ecosystem: 'npm', fn: 'parse', paramMin: 1,
|
|
121
|
+
bodyContains: ['boolean', 'alias', 'default', 'stopEarly', 'unknown'] },
|
|
122
|
+
];
|
|
123
|
+
|
|
124
|
+
for (const [fp, content] of Object.entries(fileContents)) {
|
|
125
|
+
if (!content || typeof content !== 'string') continue;
|
|
126
|
+
if (SKIP_DIRS.test(fp)) continue;
|
|
127
|
+
if (!/\.(?:js|mjs|cjs)$/i.test(fp)) continue;
|
|
128
|
+
if (content.length < 200 || content.length > 500_000) continue;
|
|
129
|
+
|
|
130
|
+
for (const sig of FUNCTION_BODY_SIGS) {
|
|
131
|
+
const key = `${sig.pkg}:${fp}`;
|
|
132
|
+
if (seen.has(key)) continue;
|
|
133
|
+
const fnRe = new RegExp(`(?:function\\s+${sig.fn}|(?:const|let|var)\\s+${sig.fn}\\s*=|${sig.fn}\\s*[:=]\\s*function)\\s*\\(`, 'g');
|
|
134
|
+
const m = fnRe.exec(content);
|
|
135
|
+
if (!m) continue;
|
|
136
|
+
const bodyWindow = content.slice(m.index, m.index + 2000);
|
|
137
|
+
const matchCount = sig.bodyContains.filter(kw => bodyWindow.includes(kw)).length;
|
|
138
|
+
if (matchCount < Math.ceil(sig.bodyContains.length * 0.6)) continue;
|
|
139
|
+
seen.add(key);
|
|
140
|
+
detected.push({
|
|
141
|
+
name: sig.pkg,
|
|
142
|
+
version: 'unknown',
|
|
143
|
+
ecosystem: sig.ecosystem,
|
|
144
|
+
file: fp,
|
|
145
|
+
scope: 'vendored',
|
|
146
|
+
isVendored: true,
|
|
147
|
+
_detectionMethod: 'function-body-signature',
|
|
148
|
+
_matchedKeywords: matchCount,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
100
153
|
return detected;
|
|
101
154
|
}
|
|
102
155
|
|