@clear-capabilities/agentic-security-scanner 0.79.0 → 0.84.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/178.index.js +1 -1
- package/dist/333.index.js +283 -0
- package/dist/384.index.js +1 -1
- package/dist/637.index.js +1 -1
- package/dist/838.index.js +1 -1
- package/dist/839.index.js +170 -0
- package/dist/985.index.js +140 -1
- package/dist/agentic-security.mjs +10 -10
- package/dist/agentic-security.mjs.sha256 +1 -1
- package/package.json +7 -5
- package/src/.agentic-security/findings.json +117732 -0
- package/src/.agentic-security/last-scan.json +117732 -0
- package/src/.agentic-security/last-scan.json.sig +1 -0
- package/src/.agentic-security/scan-history.json +12946 -0
- package/src/.agentic-security/streak.json +21 -0
- package/src/dataflow/.agentic-security/findings.json +6086 -0
- package/src/dataflow/.agentic-security/last-scan.json +6086 -0
- package/src/dataflow/.agentic-security/last-scan.json.sig +1 -0
- package/src/dataflow/.agentic-security/scan-history.json +250 -0
- package/src/dataflow/.agentic-security/streak.json +21 -0
- package/src/dataflow/cross-service-taint.js +201 -0
- package/src/dataflow/formal-verify.js +204 -0
- package/src/dataflow/ifds-precise.js +222 -0
- package/src/dataflow/k2-summary-cache.js +153 -0
- package/src/dataflow/lib-taint-summaries.js +198 -0
- package/src/dataflow/privacy-taint.js +205 -0
- package/src/dataflow/smt-feasibility.js +189 -0
- package/src/engine.js +825 -127
- package/src/ir/.agentic-security/findings.json +4011 -0
- package/src/ir/.agentic-security/last-scan.json +4011 -0
- package/src/ir/.agentic-security/last-scan.json.sig +1 -0
- package/src/ir/.agentic-security/scan-history.json +193 -0
- package/src/ir/.agentic-security/streak.json +20 -0
- package/src/ir/cpp-preprocessor.js +142 -0
- package/src/ir/csharp-ir.js +604 -0
- package/src/ir/universal-ir.js +403 -0
- package/src/mcp/.agentic-security/findings.json +8632 -0
- package/src/mcp/.agentic-security/last-scan.json +8632 -0
- package/src/mcp/.agentic-security/last-scan.json.sig +1 -0
- package/src/mcp/.agentic-security/scan-history.json +331 -0
- package/src/mcp/.agentic-security/streak.json +20 -0
- package/src/mcp/tools.js +140 -1
- package/src/posture/.agentic-security/findings.json +77181 -0
- package/src/posture/.agentic-security/last-scan.json +77181 -0
- package/src/posture/.agentic-security/last-scan.json.sig +1 -0
- package/src/posture/.agentic-security/scan-history.json +8904 -0
- package/src/posture/.agentic-security/streak.json +21 -0
- package/src/posture/api-contract.js +193 -0
- package/src/posture/attack-taxonomy.js +227 -0
- package/src/posture/auditor-walkthrough.js +252 -0
- package/src/posture/claude-authorship.js +197 -0
- package/src/posture/compliance-frameworks/.agentic-security/findings.json +80 -0
- package/src/posture/compliance-frameworks/.agentic-security/last-scan.json +80 -0
- package/src/posture/compliance-frameworks/.agentic-security/last-scan.json.sig +1 -0
- package/src/posture/compliance-frameworks/.agentic-security/scan-history.json +90 -0
- package/src/posture/compliance-frameworks/.agentic-security/streak.json +22 -0
- package/src/posture/compliance-frameworks/ccpa.json +32 -0
- package/src/posture/compliance-frameworks/eu-ai-act.json +51 -0
- package/src/posture/compliance-frameworks/gdpr.json +45 -0
- package/src/posture/compliance-frameworks/hipaa-security-rule.json +56 -0
- package/src/posture/compliance-frameworks/nist-ai-600-1.json +51 -0
- package/src/posture/compliance-frameworks/nist-csf-2.json +73 -0
- package/src/posture/compliance-frameworks/owasp-asvs-5.json +79 -0
- package/src/posture/compliance-frameworks/owasp-llm-top-10.json +69 -0
- package/src/posture/compliance-policy.js +218 -0
- package/src/posture/composite-risk.js +122 -0
- package/src/posture/cross-repo-memory.js +180 -0
- package/src/posture/csharp-analysis.js +330 -0
- package/src/posture/dep-add-guard.js +197 -0
- package/src/posture/exploit-bundle.js +210 -0
- package/src/posture/federated-learning.js +172 -0
- package/src/posture/findings-memory.js +152 -0
- package/src/posture/fix-style-mirror.js +118 -0
- package/src/posture/git-history.js +141 -0
- package/src/posture/intent-context.js +175 -0
- package/src/posture/license-attributions.js +94 -0
- package/src/posture/license-graph.js +238 -0
- package/src/posture/model-rescan.js +76 -0
- package/src/posture/pattern-propagation.js +39 -0
- package/src/posture/pqc-migration-plan.js +158 -0
- package/src/posture/pr-augment.js +234 -0
- package/src/posture/reachability-filter.js +33 -2
- package/src/posture/realtime-cve-monitor.js +214 -0
- package/src/posture/risk-dollars.js +158 -0
- package/src/posture/runtime-correlation.js +174 -0
- package/src/posture/sbom-diff.js +171 -0
- package/src/posture/sca-policy.js +235 -0
- package/src/posture/sca-upgrade.js +259 -0
- package/src/posture/threat-model-auto.js +268 -0
- package/src/posture/threat-model-grounding.js +169 -0
- package/src/posture/time-to-fix.js +129 -0
- package/src/posture/triage-learning.js +170 -0
- package/src/posture/triage-memory.js +151 -0
- package/src/posture/triage.js +40 -1
- package/src/posture/watch-mode.js +171 -0
- package/src/posture/workflow-installer.js +231 -0
- package/src/sast/.agentic-security/findings.json +6154 -0
- package/src/sast/.agentic-security/last-scan.json +6154 -0
- package/src/sast/.agentic-security/last-scan.json.sig +1 -0
- package/src/sast/.agentic-security/scan-history.json +941 -0
- package/src/sast/.agentic-security/streak.json +22 -0
- package/src/sast/_secret-entropy.js +145 -0
- package/src/sast/cloud-iam.js +312 -0
- package/src/sast/cpp.js +138 -4
- package/src/sast/crypto-protocol.js +388 -0
- package/src/sast/csharp-tokenizer.js +392 -0
- package/src/sast/csharp.js +924 -138
- package/src/sast/dapp-frontend.js +200 -0
- package/src/sast/k8s-admission.js +271 -0
- package/src/sast/llm-app.js +272 -0
- package/src/sast/ml-supply-chain.js +259 -0
- package/src/sast/mobile.js +224 -0
- package/src/sast/post-quantum-crypto.js +348 -0
- package/src/sast/web3-advanced.js +375 -0
- package/src/sca/.agentic-security/findings.json +7460 -0
- package/src/sca/.agentic-security/last-scan.json +7460 -0
- package/src/sca/.agentic-security/last-scan.json.sig +1 -0
- package/src/sca/.agentic-security/scan-history.json +113 -0
- package/src/sca/.agentic-security/streak.json +21 -0
- package/src/sca/CLAUDE.md +161 -0
- package/src/sca/binary-metadata.js +37 -15
- package/src/sca/sigstore-verify.js +215 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
c5c255f3078afcb3abb37615903b8ab5c7f13f82bd33a5089398909530ab25e9
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"timestamp": "2026-05-28T21:51:05.438Z",
|
|
4
|
+
"label": "scan",
|
|
5
|
+
"total": 13,
|
|
6
|
+
"critical": 0,
|
|
7
|
+
"high": 0,
|
|
8
|
+
"medium": 13,
|
|
9
|
+
"low": 0,
|
|
10
|
+
"kev": 0,
|
|
11
|
+
"ids": [
|
|
12
|
+
"ssrf-meta-hardcoded:catalog.js:538",
|
|
13
|
+
"ssrf-meta-hardcoded:exploit-prover.js:33",
|
|
14
|
+
"struct:incremental.js:203:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
15
|
+
"struct:incremental.js:204:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
16
|
+
"struct:incremental.js:209:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
17
|
+
"struct:incremental.js:220:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
18
|
+
"struct:incremental.js:223:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
19
|
+
"struct:incremental.js:50:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
20
|
+
"struct:incremental.js:51:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
21
|
+
"struct:incremental.js:68:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
22
|
+
"struct:incremental.js:69:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
23
|
+
"toctou-fs:incremental.js:50",
|
|
24
|
+
"toctou-fs:incremental.js:68"
|
|
25
|
+
]
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"timestamp": "2026-05-28T21:58:02.385Z",
|
|
29
|
+
"label": "scan",
|
|
30
|
+
"total": 13,
|
|
31
|
+
"critical": 0,
|
|
32
|
+
"high": 0,
|
|
33
|
+
"medium": 13,
|
|
34
|
+
"low": 0,
|
|
35
|
+
"kev": 0,
|
|
36
|
+
"ids": [
|
|
37
|
+
"ssrf-meta-hardcoded:catalog.js:538",
|
|
38
|
+
"ssrf-meta-hardcoded:exploit-prover.js:33",
|
|
39
|
+
"struct:incremental.js:203:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
40
|
+
"struct:incremental.js:204:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
41
|
+
"struct:incremental.js:209:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
42
|
+
"struct:incremental.js:220:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
43
|
+
"struct:incremental.js:223:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
44
|
+
"struct:incremental.js:50:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
45
|
+
"struct:incremental.js:51:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
46
|
+
"struct:incremental.js:68:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
47
|
+
"struct:incremental.js:69:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
48
|
+
"toctou-fs:incremental.js:50",
|
|
49
|
+
"toctou-fs:incremental.js:68"
|
|
50
|
+
]
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"timestamp": "2026-05-29T06:25:27.255Z",
|
|
54
|
+
"label": "scan",
|
|
55
|
+
"total": 17,
|
|
56
|
+
"critical": 0,
|
|
57
|
+
"high": 0,
|
|
58
|
+
"medium": 17,
|
|
59
|
+
"low": 0,
|
|
60
|
+
"kev": 0,
|
|
61
|
+
"ids": [
|
|
62
|
+
"ssrf-meta-hardcoded:catalog.js:538",
|
|
63
|
+
"ssrf-meta-hardcoded:exploit-prover.js:33",
|
|
64
|
+
"struct:ifds-precise.js:177:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
65
|
+
"struct:ifds-precise.js:179:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
66
|
+
"struct:ifds-precise.js:206:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
67
|
+
"struct:incremental.js:203:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
68
|
+
"struct:incremental.js:204:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
69
|
+
"struct:incremental.js:209:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
70
|
+
"struct:incremental.js:220:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
71
|
+
"struct:incremental.js:223:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
72
|
+
"struct:incremental.js:50:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
73
|
+
"struct:incremental.js:51:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
74
|
+
"struct:incremental.js:68:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
75
|
+
"struct:incremental.js:69:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
76
|
+
"toctou-fs:ifds-precise.js:177",
|
|
77
|
+
"toctou-fs:incremental.js:50",
|
|
78
|
+
"toctou-fs:incremental.js:68"
|
|
79
|
+
]
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
"timestamp": "2026-05-29T06:26:15.864Z",
|
|
83
|
+
"label": "scan",
|
|
84
|
+
"total": 17,
|
|
85
|
+
"critical": 0,
|
|
86
|
+
"high": 0,
|
|
87
|
+
"medium": 17,
|
|
88
|
+
"low": 0,
|
|
89
|
+
"kev": 0,
|
|
90
|
+
"ids": [
|
|
91
|
+
"ssrf-meta-hardcoded:catalog.js:538",
|
|
92
|
+
"ssrf-meta-hardcoded:exploit-prover.js:33",
|
|
93
|
+
"struct:ifds-precise.js:177:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
94
|
+
"struct:ifds-precise.js:179:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
95
|
+
"struct:ifds-precise.js:206:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
96
|
+
"struct:incremental.js:203:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
97
|
+
"struct:incremental.js:204:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
98
|
+
"struct:incremental.js:209:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
99
|
+
"struct:incremental.js:220:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
100
|
+
"struct:incremental.js:223:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
101
|
+
"struct:incremental.js:50:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
102
|
+
"struct:incremental.js:51:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
103
|
+
"struct:incremental.js:68:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
104
|
+
"struct:incremental.js:69:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
105
|
+
"toctou-fs:ifds-precise.js:177",
|
|
106
|
+
"toctou-fs:incremental.js:50",
|
|
107
|
+
"toctou-fs:incremental.js:68"
|
|
108
|
+
]
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"timestamp": "2026-05-29T06:26:55.369Z",
|
|
112
|
+
"label": "scan",
|
|
113
|
+
"total": 23,
|
|
114
|
+
"critical": 0,
|
|
115
|
+
"high": 0,
|
|
116
|
+
"medium": 23,
|
|
117
|
+
"low": 0,
|
|
118
|
+
"kev": 0,
|
|
119
|
+
"ids": [
|
|
120
|
+
"ssrf-meta-hardcoded:catalog.js:538",
|
|
121
|
+
"ssrf-meta-hardcoded:exploit-prover.js:33",
|
|
122
|
+
"struct:cross-service-taint.js:53:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
123
|
+
"struct:cross-service-taint.js:55:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
124
|
+
"struct:cross-service-taint.js:97:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
125
|
+
"struct:cross-service-taint.js:98:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
126
|
+
"struct:ifds-precise.js:177:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
127
|
+
"struct:ifds-precise.js:179:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
128
|
+
"struct:ifds-precise.js:206:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
129
|
+
"struct:incremental.js:203:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
130
|
+
"struct:incremental.js:204:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
131
|
+
"struct:incremental.js:209:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
132
|
+
"struct:incremental.js:220:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
133
|
+
"struct:incremental.js:223:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
134
|
+
"struct:incremental.js:50:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
135
|
+
"struct:incremental.js:51:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
136
|
+
"struct:incremental.js:68:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
137
|
+
"struct:incremental.js:69:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
138
|
+
"toctou-fs:cross-service-taint.js:53",
|
|
139
|
+
"toctou-fs:cross-service-taint.js:97",
|
|
140
|
+
"toctou-fs:ifds-precise.js:177",
|
|
141
|
+
"toctou-fs:incremental.js:50",
|
|
142
|
+
"toctou-fs:incremental.js:68"
|
|
143
|
+
]
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
"timestamp": "2026-05-29T06:31:00.224Z",
|
|
147
|
+
"label": "scan",
|
|
148
|
+
"total": 23,
|
|
149
|
+
"critical": 0,
|
|
150
|
+
"high": 0,
|
|
151
|
+
"medium": 23,
|
|
152
|
+
"low": 0,
|
|
153
|
+
"kev": 0,
|
|
154
|
+
"ids": [
|
|
155
|
+
"ssrf-meta-hardcoded:catalog.js:538",
|
|
156
|
+
"ssrf-meta-hardcoded:exploit-prover.js:33",
|
|
157
|
+
"struct:cross-service-taint.js:53:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
158
|
+
"struct:cross-service-taint.js:55:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
159
|
+
"struct:cross-service-taint.js:97:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
160
|
+
"struct:cross-service-taint.js:98:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
161
|
+
"struct:ifds-precise.js:177:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
162
|
+
"struct:ifds-precise.js:179:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
163
|
+
"struct:ifds-precise.js:206:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
164
|
+
"struct:incremental.js:203:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
165
|
+
"struct:incremental.js:204:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
166
|
+
"struct:incremental.js:209:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
167
|
+
"struct:incremental.js:220:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
168
|
+
"struct:incremental.js:223:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
169
|
+
"struct:incremental.js:50:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
170
|
+
"struct:incremental.js:51:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
171
|
+
"struct:incremental.js:68:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
172
|
+
"struct:incremental.js:69:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
173
|
+
"toctou-fs:cross-service-taint.js:53",
|
|
174
|
+
"toctou-fs:cross-service-taint.js:97",
|
|
175
|
+
"toctou-fs:ifds-precise.js:177",
|
|
176
|
+
"toctou-fs:incremental.js:50",
|
|
177
|
+
"toctou-fs:incremental.js:68"
|
|
178
|
+
]
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
"timestamp": "2026-05-29T06:32:47.791Z",
|
|
182
|
+
"label": "scan",
|
|
183
|
+
"total": 23,
|
|
184
|
+
"critical": 0,
|
|
185
|
+
"high": 0,
|
|
186
|
+
"medium": 23,
|
|
187
|
+
"low": 0,
|
|
188
|
+
"kev": 0,
|
|
189
|
+
"ids": [
|
|
190
|
+
"ssrf-meta-hardcoded:catalog.js:538",
|
|
191
|
+
"ssrf-meta-hardcoded:exploit-prover.js:33",
|
|
192
|
+
"struct:cross-service-taint.js:53:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
193
|
+
"struct:cross-service-taint.js:55:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
194
|
+
"struct:cross-service-taint.js:97:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
195
|
+
"struct:cross-service-taint.js:98:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
196
|
+
"struct:ifds-precise.js:177:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
197
|
+
"struct:ifds-precise.js:179:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
198
|
+
"struct:ifds-precise.js:206:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
199
|
+
"struct:incremental.js:203:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
200
|
+
"struct:incremental.js:204:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
201
|
+
"struct:incremental.js:209:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
202
|
+
"struct:incremental.js:220:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
203
|
+
"struct:incremental.js:223:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
204
|
+
"struct:incremental.js:50:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
205
|
+
"struct:incremental.js:51:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
206
|
+
"struct:incremental.js:68:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
207
|
+
"struct:incremental.js:69:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
208
|
+
"toctou-fs:cross-service-taint.js:53",
|
|
209
|
+
"toctou-fs:cross-service-taint.js:97",
|
|
210
|
+
"toctou-fs:ifds-precise.js:177",
|
|
211
|
+
"toctou-fs:incremental.js:50",
|
|
212
|
+
"toctou-fs:incremental.js:68"
|
|
213
|
+
]
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
"timestamp": "2026-05-29T06:49:36.287Z",
|
|
217
|
+
"label": "scan",
|
|
218
|
+
"total": 23,
|
|
219
|
+
"critical": 0,
|
|
220
|
+
"high": 0,
|
|
221
|
+
"medium": 23,
|
|
222
|
+
"low": 0,
|
|
223
|
+
"kev": 0,
|
|
224
|
+
"ids": [
|
|
225
|
+
"ssrf-meta-hardcoded:catalog.js:538",
|
|
226
|
+
"ssrf-meta-hardcoded:exploit-prover.js:33",
|
|
227
|
+
"struct:cross-service-taint.js:53:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
228
|
+
"struct:cross-service-taint.js:55:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
229
|
+
"struct:cross-service-taint.js:97:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
230
|
+
"struct:cross-service-taint.js:98:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
231
|
+
"struct:ifds-precise.js:177:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
232
|
+
"struct:ifds-precise.js:179:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
233
|
+
"struct:ifds-precise.js:206:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
234
|
+
"struct:incremental.js:203:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
235
|
+
"struct:incremental.js:204:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
236
|
+
"struct:incremental.js:209:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
237
|
+
"struct:incremental.js:220:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
238
|
+
"struct:incremental.js:223:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
239
|
+
"struct:incremental.js:50:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
240
|
+
"struct:incremental.js:51:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
241
|
+
"struct:incremental.js:68:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
242
|
+
"struct:incremental.js:69:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
243
|
+
"toctou-fs:cross-service-taint.js:53",
|
|
244
|
+
"toctou-fs:cross-service-taint.js:97",
|
|
245
|
+
"toctou-fs:ifds-precise.js:177",
|
|
246
|
+
"toctou-fs:incremental.js:50",
|
|
247
|
+
"toctou-fs:incremental.js:68"
|
|
248
|
+
]
|
|
249
|
+
}
|
|
250
|
+
]
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"firstScanDate": "2026-05-28T21:51:05.470Z",
|
|
3
|
+
"lastScanDate": "2026-05-29T06:49:36.319Z",
|
|
4
|
+
"totalScans": 8,
|
|
5
|
+
"daysCleanCritical": 2,
|
|
6
|
+
"lastCleanDate": "2026-05-29",
|
|
7
|
+
"lastCriticalDate": null,
|
|
8
|
+
"hasEverHadCritical": false,
|
|
9
|
+
"bestDaysCleanCritical": 2,
|
|
10
|
+
"totalFindingsAtFirstScan": 17,
|
|
11
|
+
"totalFindingsAtLastScan": 30,
|
|
12
|
+
"totalFixesInferred": 0,
|
|
13
|
+
"lastGrade": "A",
|
|
14
|
+
"bestGrade": "A",
|
|
15
|
+
"launchCheckPassedAt": null,
|
|
16
|
+
"achievements": [
|
|
17
|
+
"first-scan",
|
|
18
|
+
"grade-a"
|
|
19
|
+
],
|
|
20
|
+
"previousGrade": "A"
|
|
21
|
+
}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
// Cross-repo / cross-service taint — Recommendation #4 of the world-class
|
|
2
|
+
// roadmap.
|
|
3
|
+
//
|
|
4
|
+
// Discovers vulnerabilities that no single-repo scan can find: tainted
|
|
5
|
+
// data flowing from service A's HTTP request body, through A's response,
|
|
6
|
+
// into service B's consumer, then to a sink inside B. The "trust this
|
|
7
|
+
// because the upstream team owns it" assumption is what kills companies;
|
|
8
|
+
// the scanner catches it by reading a per-project service-graph file and
|
|
9
|
+
// propagating taint across service boundaries.
|
|
10
|
+
//
|
|
11
|
+
// Inputs:
|
|
12
|
+
// .agentic-security/services.yml — declares service-to-service edges:
|
|
13
|
+
//
|
|
14
|
+
// services:
|
|
15
|
+
// payments:
|
|
16
|
+
// repo: github.com/acme/payments
|
|
17
|
+
// exposes:
|
|
18
|
+
// - { route: "POST /charges", taints: ["request.amount", "request.cardToken"] }
|
|
19
|
+
// consumes:
|
|
20
|
+
// - { source: "events.charge_created", fields: ["amount", "cardToken"] }
|
|
21
|
+
// ledger:
|
|
22
|
+
// repo: github.com/acme/ledger
|
|
23
|
+
// exposes:
|
|
24
|
+
// - { route: "GET /balances/:userId", taints: ["pathParam.userId"] }
|
|
25
|
+
//
|
|
26
|
+
// edges:
|
|
27
|
+
// - { from: "payments", to: "ledger", via: "http", path: "/balances/{userId}" }
|
|
28
|
+
// - { from: "payments", to: "fraud", via: "kafka", topic: "events.charge_created" }
|
|
29
|
+
//
|
|
30
|
+
// The scanner uses this graph to:
|
|
31
|
+
// 1. Mark every "consumes" entry-point in each service as tainted-by-default
|
|
32
|
+
// 2. Walk the call graph from those entry points to any sink
|
|
33
|
+
// 3. When a finding's sink is reachable from a cross-service edge, emit a
|
|
34
|
+
// `crossService: { from, to, via, path }` annotation
|
|
35
|
+
// 4. Bump severity by one tier because cross-service taint is by definition
|
|
36
|
+
// reaching across a trust boundary
|
|
37
|
+
//
|
|
38
|
+
// In v1 we don't run BOTH services in one scan — that would require
|
|
39
|
+
// either a monorepo or a federated-scan API. We DO emit cross-service
|
|
40
|
+
// findings when the local service is on the receiving end of an edge,
|
|
41
|
+
// based on the declared upstream taint contract.
|
|
42
|
+
|
|
43
|
+
import * as fs from 'node:fs';
|
|
44
|
+
import * as path from 'node:path';
|
|
45
|
+
import * as yaml from 'js-yaml';
|
|
46
|
+
|
|
47
|
+
const SERVICES_FILE_NAMES = ['services.yml', 'services.yaml'];
|
|
48
|
+
|
|
49
|
+
export function loadServiceGraph(scanRoot) {
|
|
50
|
+
if (!scanRoot) return null;
|
|
51
|
+
for (const name of SERVICES_FILE_NAMES) {
|
|
52
|
+
const fp = path.join(scanRoot, '.agentic-security', name);
|
|
53
|
+
if (!fs.existsSync(fp)) continue;
|
|
54
|
+
try {
|
|
55
|
+
const raw = fs.readFileSync(fp, 'utf8');
|
|
56
|
+
const doc = yaml.load(raw);
|
|
57
|
+
return _normalizeGraph(doc);
|
|
58
|
+
} catch (e) {
|
|
59
|
+
return { _error: `Failed to parse ${fp}: ${e.message}` };
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function _normalizeGraph(doc) {
|
|
66
|
+
if (!doc || typeof doc !== 'object') return null;
|
|
67
|
+
const services = {};
|
|
68
|
+
for (const [name, def] of Object.entries(doc.services || {})) {
|
|
69
|
+
services[name] = {
|
|
70
|
+
name,
|
|
71
|
+
repo: def.repo || null,
|
|
72
|
+
exposes: Array.isArray(def.exposes) ? def.exposes : [],
|
|
73
|
+
consumes: Array.isArray(def.consumes) ? def.consumes : [],
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
const edges = Array.isArray(doc.edges) ? doc.edges.map(e => ({
|
|
77
|
+
from: e.from, to: e.to,
|
|
78
|
+
via: e.via || 'http',
|
|
79
|
+
path: e.path || null,
|
|
80
|
+
topic: e.topic || null,
|
|
81
|
+
})) : [];
|
|
82
|
+
return { services, edges };
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Identify the "current service" by name. Two heuristics:
|
|
87
|
+
* 1. If the scanRoot's package.json / pyproject.toml / etc. name matches
|
|
88
|
+
* a service in the graph, that's us.
|
|
89
|
+
* 2. Otherwise fall back to the basename of the scanRoot.
|
|
90
|
+
*/
|
|
91
|
+
export function identifyCurrentService(graph, scanRoot) {
|
|
92
|
+
if (!graph || !graph.services) return null;
|
|
93
|
+
// Try package.json / pyproject.toml name field.
|
|
94
|
+
let projectName = null;
|
|
95
|
+
try {
|
|
96
|
+
const pkg = path.join(scanRoot, 'package.json');
|
|
97
|
+
if (fs.existsSync(pkg)) {
|
|
98
|
+
const j = JSON.parse(fs.readFileSync(pkg, 'utf8'));
|
|
99
|
+
projectName = j.name;
|
|
100
|
+
}
|
|
101
|
+
} catch {}
|
|
102
|
+
if (projectName && graph.services[projectName]) return graph.services[projectName];
|
|
103
|
+
const base = path.basename(scanRoot);
|
|
104
|
+
if (graph.services[base]) return graph.services[base];
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Compute the list of incoming "edges" terminating at the current
|
|
110
|
+
* service. Each edge identifies which upstream service is the source of
|
|
111
|
+
* taint into this service.
|
|
112
|
+
*/
|
|
113
|
+
export function incomingEdges(graph, currentService) {
|
|
114
|
+
if (!graph || !currentService) return [];
|
|
115
|
+
return (graph.edges || []).filter(e => e.to === currentService.name);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* For each consume entry on the current service, locate the upstream
|
|
120
|
+
* `exposes` entry that produces it (matched by path/topic) and return
|
|
121
|
+
* the upstream-declared tainted fields. This is the data we use to
|
|
122
|
+
* mark code entry points as tainted-by-default during scanning.
|
|
123
|
+
*/
|
|
124
|
+
export function upstreamTaintContract(graph, currentService) {
|
|
125
|
+
if (!graph || !currentService) return [];
|
|
126
|
+
const contracts = [];
|
|
127
|
+
for (const consume of currentService.consumes || []) {
|
|
128
|
+
for (const edge of (graph.edges || [])) {
|
|
129
|
+
if (edge.to !== currentService.name) continue;
|
|
130
|
+
const upstream = graph.services[edge.from];
|
|
131
|
+
if (!upstream) continue;
|
|
132
|
+
for (const expose of upstream.exposes || []) {
|
|
133
|
+
const matches = (edge.via === 'http' && edge.path && expose.route && expose.route.includes(edge.path.split('?')[0]))
|
|
134
|
+
|| (edge.via === 'kafka' && edge.topic && consume.source === edge.topic);
|
|
135
|
+
if (matches) {
|
|
136
|
+
contracts.push({
|
|
137
|
+
upstreamService: upstream.name,
|
|
138
|
+
via: edge.via,
|
|
139
|
+
taintedFields: [...(consume.fields || []), ...(expose.taints || [])],
|
|
140
|
+
consume,
|
|
141
|
+
expose,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return contracts;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Annotate findings whose source matches a cross-service taint contract.
|
|
152
|
+
* Adds `crossService: { from, via, path, taintedFields }` and bumps
|
|
153
|
+
* severity by one tier (medium → high, high → critical).
|
|
154
|
+
*/
|
|
155
|
+
export function annotateCrossServiceFindings(findings, graph, currentService) {
|
|
156
|
+
if (!Array.isArray(findings) || !graph || !currentService) return { annotated: 0, bumped: 0 };
|
|
157
|
+
const contracts = upstreamTaintContract(graph, currentService);
|
|
158
|
+
if (!contracts.length) return { annotated: 0, bumped: 0 };
|
|
159
|
+
let annotated = 0, bumped = 0;
|
|
160
|
+
for (const f of findings) {
|
|
161
|
+
const sourceExpr = (f.source && (f.source.snippet || f.source.expr)) || f.snippet || '';
|
|
162
|
+
for (const contract of contracts) {
|
|
163
|
+
const matches = contract.taintedFields.some(field => {
|
|
164
|
+
const pat = new RegExp(`\\b${field.replace('.', '\\.')}\\b`);
|
|
165
|
+
return pat.test(sourceExpr);
|
|
166
|
+
});
|
|
167
|
+
if (!matches) continue;
|
|
168
|
+
f.crossService = {
|
|
169
|
+
from: contract.upstreamService,
|
|
170
|
+
to: currentService.name,
|
|
171
|
+
via: contract.via,
|
|
172
|
+
taintedField: contract.taintedFields.find(field => new RegExp(`\\b${field.replace('.', '\\.')}\\b`).test(sourceExpr)),
|
|
173
|
+
};
|
|
174
|
+
annotated++;
|
|
175
|
+
// Severity bump.
|
|
176
|
+
const ladder = ['info', 'low', 'medium', 'high', 'critical'];
|
|
177
|
+
const cur = ladder.indexOf(f.severity);
|
|
178
|
+
if (cur > 0 && cur < ladder.length - 1) {
|
|
179
|
+
f._severityBumpReason = `cross-service-from:${contract.upstreamService}`;
|
|
180
|
+
f.severity = ladder[cur + 1];
|
|
181
|
+
bumped++;
|
|
182
|
+
}
|
|
183
|
+
break;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return { annotated, bumped };
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Run the cross-service annotation pass — convenience entry point called
|
|
191
|
+
* from the engine after the normal scan completes.
|
|
192
|
+
*/
|
|
193
|
+
export function runCrossServiceTaint(scanRoot, findings) {
|
|
194
|
+
const graph = loadServiceGraph(scanRoot);
|
|
195
|
+
if (!graph || graph._error) return { error: graph?._error, annotated: 0 };
|
|
196
|
+
const current = identifyCurrentService(graph, scanRoot);
|
|
197
|
+
if (!current) return { error: 'no-current-service-identified', annotated: 0 };
|
|
198
|
+
return annotateCrossServiceFindings(findings, graph, current);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export const _internals = { _normalizeGraph, SERVICES_FILE_NAMES };
|