attackmap 0.2.0__tar.gz → 0.3.1__tar.gz
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.
- {attackmap-0.2.0/src/attackmap.egg-info → attackmap-0.3.1}/PKG-INFO +244 -11
- attackmap-0.3.1/README.md +545 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/pyproject.toml +1 -1
- {attackmap-0.2.0 → attackmap-0.3.1}/src/attackmap/__init__.py +1 -1
- {attackmap-0.2.0 → attackmap-0.3.1}/src/attackmap/analyzers.py +32 -9
- attackmap-0.3.1/src/attackmap/anomalies.py +385 -0
- attackmap-0.3.1/src/attackmap/authz.py +196 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/src/attackmap/cli.py +75 -1
- attackmap-0.3.1/src/attackmap/crypto.py +188 -0
- attackmap-0.3.1/src/attackmap/exploitability.py +275 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/src/attackmap/llm_review.py +9 -5
- {attackmap-0.2.0 → attackmap-0.3.1}/src/attackmap/merge.py +20 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/src/attackmap/models.py +163 -0
- attackmap-0.3.1/src/attackmap/progress.py +155 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/src/attackmap/report.py +54 -2
- {attackmap-0.2.0 → attackmap-0.3.1}/src/attackmap/review_prompts.py +102 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/src/attackmap/scanner.py +58 -5
- attackmap-0.3.1/src/attackmap/srcpaths.py +83 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/src/attackmap/taint.py +181 -2
- {attackmap-0.2.0 → attackmap-0.3.1}/src/attackmap/threat_model.py +544 -26
- attackmap-0.3.1/src/attackmap/weaknesses.py +188 -0
- attackmap-0.3.1/src/attackmap/webhardening.py +142 -0
- {attackmap-0.2.0 → attackmap-0.3.1/src/attackmap.egg-info}/PKG-INFO +244 -11
- {attackmap-0.2.0 → attackmap-0.3.1}/src/attackmap.egg-info/SOURCES.txt +19 -1
- attackmap-0.3.1/tests/test_anomalies.py +371 -0
- attackmap-0.3.1/tests/test_authz.py +241 -0
- attackmap-0.3.1/tests/test_crypto.py +256 -0
- attackmap-0.3.1/tests/test_exploitability.py +199 -0
- attackmap-0.3.1/tests/test_hunt.py +170 -0
- attackmap-0.3.1/tests/test_injection_sinks.py +247 -0
- attackmap-0.3.1/tests/test_progress.py +97 -0
- attackmap-0.3.1/tests/test_srcpaths.py +120 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/tests/test_taint.py +122 -7
- attackmap-0.3.1/tests/test_weaknesses.py +255 -0
- attackmap-0.3.1/tests/test_webhardening.py +208 -0
- attackmap-0.2.0/README.md +0 -312
- {attackmap-0.2.0 → attackmap-0.3.1}/LICENSE +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/setup.cfg +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/src/attackmap/analyzer.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/src/attackmap/analyzer_contracts.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/src/attackmap/asset_model.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/src/attackmap/attack_taxonomy.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/src/attackmap/config_scanner.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/src/attackmap/context_pack.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/src/attackmap/control_model.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/src/attackmap/cve.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/src/attackmap/defensive_review.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/src/attackmap/detection_opportunities.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/src/attackmap/diagrams.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/src/attackmap/diff.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/src/attackmap/graph.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/src/attackmap/insights.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/src/attackmap/recon_models.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/src/attackmap/recon_to_analysis.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/src/attackmap/review_eval.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/src/attackmap/review_json.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/src/attackmap/sarif.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/src/attackmap/sbom.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/src/attackmap/sdk/__init__.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/src/attackmap/sdk/contracts.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/src/attackmap/sdk/models.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/src/attackmap/security_overlay.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/src/attackmap/suggest.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/src/attackmap/topology.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/src/attackmap.egg-info/dependency_links.txt +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/src/attackmap.egg-info/entry_points.txt +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/src/attackmap.egg-info/requires.txt +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/src/attackmap.egg-info/top_level.txt +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/tests/test_analyzer.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/tests/test_analyzer_metadata_schema.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/tests/test_analyzers.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/tests/test_artifact_schemas.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/tests/test_config_scanner.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/tests/test_context_pack.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/tests/test_cve.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/tests/test_defensive_review.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/tests/test_diagrams.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/tests/test_diff.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/tests/test_graph.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/tests/test_llm_review.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/tests/test_merge.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/tests/test_provenance.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/tests/test_recon_to_analysis.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/tests/test_report.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/tests/test_review_eval.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/tests/test_review_json.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/tests/test_review_prompts.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/tests/test_sarif.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/tests/test_sbom.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/tests/test_scanner.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/tests/test_security_overlay.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/tests/test_shared_contract_imports.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/tests/test_signal_v2.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/tests/test_suggest.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/tests/test_threat_intel.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/tests/test_threat_model.py +0 -0
- {attackmap-0.2.0 → attackmap-0.3.1}/tests/test_topology.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: attackmap
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Summary: AI-assisted defensive security analyzer for codebases — scans a repository, models assets and controls, finds cross-cutting weaknesses, and generates an evidence-grounded review with MITRE ATT&CK mappings and detection-engineering hints.
|
|
5
5
|
Author: AttackMap Contributors
|
|
6
6
|
Author-email: Matthew Davis <matthewd@matthewd.xyz>
|
|
@@ -60,9 +60,11 @@ Dynamic: license-file
|
|
|
60
60
|
# AttackMap
|
|
61
61
|
|
|
62
62
|
**AI-assisted defensive security analysis for codebases.** AttackMap reads your
|
|
63
|
-
repository, models its assets and defensive controls,
|
|
64
|
-
|
|
65
|
-
security review with MITRE ATT&CK mappings and
|
|
63
|
+
repository, models its assets and defensive controls, traces request-to-sink
|
|
64
|
+
data flow, inventories dependencies and their known CVEs, and produces an
|
|
65
|
+
evidence-grounded security review with MITRE ATT&CK mappings and
|
|
66
|
+
detection-engineering hints — finding the cross-cutting weaknesses that
|
|
67
|
+
single-file scanners miss.
|
|
66
68
|
|
|
67
69
|
Built for AppSec engineers, SOC and detection-engineering teams, and engineering
|
|
68
70
|
managers who need to triage an unfamiliar codebase.
|
|
@@ -71,6 +73,13 @@ managers who need to triage an unfamiliar codebase.
|
|
|
71
73
|
|
|
72
74
|
[](LICENSE)
|
|
73
75
|
[](https://www.python.org/)
|
|
76
|
+
[](https://pypi.org/project/attackmap/)
|
|
77
|
+
|
|
78
|
+
> **Status: beta (v0.3.1).** Core engine and 14 analyzer plugins are published
|
|
79
|
+
> to PyPI, Homebrew, and GHCR and validated against real-world codebases.
|
|
80
|
+
> AttackMap is heuristic by design — findings are confidence-tiered evidence,
|
|
81
|
+
> not proof. See [Project status](#project-status) for what's solid and what's
|
|
82
|
+
> still maturing.
|
|
74
83
|
|
|
75
84
|
---
|
|
76
85
|
|
|
@@ -108,7 +117,7 @@ Read `reports/defensive-review.md` (heuristic) and `reports/defensive-review-llm
|
|
|
108
117
|
```bash
|
|
109
118
|
pip install attackmap # core only
|
|
110
119
|
pip install "attackmap[llm]" # add LLM narrative support
|
|
111
|
-
pip install "attackmap[all]" # core + LLM + all
|
|
120
|
+
pip install "attackmap[all]" # core + LLM + all 14 analyzer plugins
|
|
112
121
|
```
|
|
113
122
|
|
|
114
123
|
You can also install individual analyzer plugins on demand:
|
|
@@ -166,8 +175,10 @@ Every `attackmap analyze` run writes:
|
|
|
166
175
|
| `attackmap-paths.md` | Mermaid flowcharts of each attack path — renders inline on GitHub |
|
|
167
176
|
| `attackmap-topology.md` | Mermaid graph of the service topology, with edge kinds styled per relationship type |
|
|
168
177
|
| `attackmap-paths.dot` / `attackmap-topology.dot` | Graphviz DOT versions of the two diagrams — feed into `dot -Tsvg` for slide-quality graphics |
|
|
178
|
+
| `attackmap-exploitability.md` | "Most exploitable now" — route→sink paths ranked by fused 0–100 score, each with its factors |
|
|
169
179
|
| `defensive-review-llm.md` *(with `--llm`)* | Claude-narrated review |
|
|
170
180
|
| `defensive-review-llm.meta.json` *(with `--llm`)* | Backend, model, token usage |
|
|
181
|
+
| `vulnerability-hypotheses.md` *(with `--hunt`)* | LLM-generated, evidence-cited exploit-chain **hypotheses** to confirm (leads, not detections) |
|
|
171
182
|
|
|
172
183
|
### GitHub Code Scanning integration
|
|
173
184
|
|
|
@@ -213,6 +224,151 @@ on unrelated commits, so a finding that persists across scans has the same id
|
|
|
213
224
|
in both. The diff has three sections — **New**, **Persisted**, **Resolved** —
|
|
214
225
|
which drop cleanly into a PR comment.
|
|
215
226
|
|
|
227
|
+
### Data-flow / injection detection
|
|
228
|
+
|
|
229
|
+
A lightweight taint pass (Python + JS/TS) walks the import graph up to two hops
|
|
230
|
+
from each route handler and flags dangerous sinks reachable from an entry point.
|
|
231
|
+
Each sink kind that a route can reach produces a dedicated finding with an
|
|
232
|
+
ATT&CK mapping:
|
|
233
|
+
|
|
234
|
+
| Sink kind | What it catches | Severity |
|
|
235
|
+
|---|---|---|
|
|
236
|
+
| `eval` / `exec` | Request-reachable code execution | HIGH |
|
|
237
|
+
| `subprocess_shell` | OS command execution (`shell=True`, `child_process.exec`) | HIGH |
|
|
238
|
+
| `unsafe_deserialization` | `pickle.loads`, `yaml.load` (no SafeLoader), `marshal`, `node-serialize` | HIGH |
|
|
239
|
+
| `ssti` | Server-side template injection (`render_template_string`, `Template(req…)`) | HIGH |
|
|
240
|
+
| `ssrf` | Request-derived URL into `requests`/`httpx`/`urlopen`/`axios`/`fetch` | MEDIUM |
|
|
241
|
+
| `nosql_injection` | Request object as a Mongo filter, or `$where` | MEDIUM |
|
|
242
|
+
| `sql_execute` | Cursor/session `.execute`/`.query` reachable from a route | (feeds attack paths) |
|
|
243
|
+
| `dynamic_open` | `open()` with request-shaped path | (feeds attack paths) |
|
|
244
|
+
|
|
245
|
+
| `open_redirect` | Request-derived URL into `redirect()`/`res.redirect()` | MEDIUM |
|
|
246
|
+
|
|
247
|
+
Beyond the taint sinks, a per-file pass flags additional undisclosed-vuln
|
|
248
|
+
classes (`scan.code_weaknesses`): **prototype pollution** (`__proto__` writes,
|
|
249
|
+
deep-merge of a request object), **mass assignment** (a whole request body bound
|
|
250
|
+
to a model), **JWT weaknesses** (`alg=none`, signature verification off), **XXE**
|
|
251
|
+
(XML parsers with external entities enabled), **ReDoS** (regexes with
|
|
252
|
+
catastrophic backtracking), **insecure upload** (a file saved under a
|
|
253
|
+
client-controlled name/path), and **GraphQL exposure** (introspection/playground
|
|
254
|
+
left on).
|
|
255
|
+
|
|
256
|
+
Sinks that are only dangerous with attacker-controlled input (SSRF, SSTI, NoSQL,
|
|
257
|
+
open redirect, `open`) are gated on a request-shaped identifier in the call — a constant URL or
|
|
258
|
+
template is not flagged. It's a heuristic (import-edge ≠ call-edge), so findings
|
|
259
|
+
are evidence, not proof; confidence tapers with hop distance. Chains appear in
|
|
260
|
+
`attackmap-report.json` under `scan.taint_chains`.
|
|
261
|
+
|
|
262
|
+
Test and spec files (`tests/`, `__tests__/`, `*.test.*`, `test_*.py`, …) are
|
|
263
|
+
excluded from all the heuristic passes above by default, since dangerous
|
|
264
|
+
patterns in test scaffolding are rarely real exposure. Set
|
|
265
|
+
`ATTACKMAP_INCLUDE_TESTS=1` to scan them too (e.g. for test-quality reviews).
|
|
266
|
+
|
|
267
|
+
### Web hardening gaps
|
|
268
|
+
|
|
269
|
+
Route- and config-level checks for common web misconfigurations, each an
|
|
270
|
+
ATT&CK-mapped finding:
|
|
271
|
+
|
|
272
|
+
| Kind | Catches | Severity |
|
|
273
|
+
|---|---|---|
|
|
274
|
+
| `cors_wildcard_credentials` | wildcard/reflected CORS origin **with** credentials | HIGH |
|
|
275
|
+
| `csrf_disabled` | CSRF explicitly disabled / exempted | MEDIUM |
|
|
276
|
+
| `insecure_cookie` | `httpOnly:false`, `secure:false`, `SameSite=None` without `Secure` | MEDIUM |
|
|
277
|
+
| `weak_csp` | CSP allowing `'unsafe-inline'` / `'unsafe-eval'` | MEDIUM |
|
|
278
|
+
| `debug_enabled` | debug mode / actuator wildcard exposure shipped on | MEDIUM |
|
|
279
|
+
|
|
280
|
+
These detect *positively-present* misconfigurations rather than hard-to-judge
|
|
281
|
+
absences (a wildcard CORS origin alone is fine — it's the pairing with
|
|
282
|
+
credentials that's flagged). Results appear under `scan.web_hardening_issues`.
|
|
283
|
+
|
|
284
|
+
### Insecure cryptography & weak randomness
|
|
285
|
+
|
|
286
|
+
A cheap per-file pass flags crypto misuse, each as a finding with an ATT&CK
|
|
287
|
+
mapping:
|
|
288
|
+
|
|
289
|
+
| Kind | Catches | Severity |
|
|
290
|
+
|---|---|---|
|
|
291
|
+
| `weak_password_hash` | MD5/SHA-1 over a password-shaped value | HIGH |
|
|
292
|
+
| `weak_cipher` | DES / 3DES / RC4 / Blowfish | HIGH |
|
|
293
|
+
| `ecb_mode` | ECB block-cipher mode (incl. Java's `Cipher.getInstance("AES")` default) | MEDIUM |
|
|
294
|
+
| `static_iv_salt` | hard-coded IV or salt literal | MEDIUM |
|
|
295
|
+
| `insecure_random` | `Math.random`/`random`/`rand`/`mt_rand` for a token/key/salt/nonce | MEDIUM |
|
|
296
|
+
| `insecure_tls` | `verify=False`, `rejectUnauthorized:false`, `InsecureSkipVerify:true`, deprecated TLS | HIGH |
|
|
297
|
+
|
|
298
|
+
The noisy families (weak hash, insecure RNG) are gated on a security-context
|
|
299
|
+
identifier; cipher/ECB tokens are matched case-sensitively so algorithm names
|
|
300
|
+
aren't confused with prose (e.g. the French word "des"). Results appear under
|
|
301
|
+
`scan.crypto_weaknesses`.
|
|
302
|
+
|
|
303
|
+
### Broken object-level authorization (BOLA / IDOR)
|
|
304
|
+
|
|
305
|
+
OWASP API Security #1. AttackMap flags a route as a BOLA/IDOR candidate when it
|
|
306
|
+
composes three signals it already has:
|
|
307
|
+
|
|
308
|
+
1. the route takes a **resource id** in the path (`/users/{id}`,
|
|
309
|
+
`/orders/:orderId`, `/docs/<int:doc_id>`), and
|
|
310
|
+
2. it **reaches a datastore** — a DB hint in the same file/module, or a taint
|
|
311
|
+
chain from the route to a SQL execute sink, and
|
|
312
|
+
3. **no ownership/authorization check** is visible near the handler
|
|
313
|
+
(`current_user`, `request.user`, `authorize`, a policy/guard, or a
|
|
314
|
+
`filter_by(user_id=…)`-style scoped query).
|
|
315
|
+
|
|
316
|
+
Write routes (POST/PUT/PATCH/DELETE) are HIGH, reads MEDIUM. Candidates appear
|
|
317
|
+
under `scan.authz_candidates`; the ownership-marker scan is the main
|
|
318
|
+
false-positive reducer, so a well-scoped handler is not flagged. Path-template
|
|
319
|
+
routes today; query-parameter and RPC-method ids are future work.
|
|
320
|
+
|
|
321
|
+
### Anomaly / outlier detection
|
|
322
|
+
|
|
323
|
+
The closest honest thing to "surface the unknown": instead of matching a
|
|
324
|
+
known-bad signature, AttackMap flags a route that deviates from the norm its own
|
|
325
|
+
siblings establish. Routes are bucketed into resource cohorts by path prefix
|
|
326
|
+
(`/api/users`, `/api/users/{id}` and `/api/users/export` all share `api/users`;
|
|
327
|
+
`api`/version scaffolding is stripped so versioned resources still separate), and
|
|
328
|
+
within each cohort the odd-one-out is reported:
|
|
329
|
+
|
|
330
|
+
| Kind | Catches | Severity |
|
|
331
|
+
|---|---|---|
|
|
332
|
+
| `auth_outlier` | siblings carry an auth/authorization signal near the handler; this route doesn't | HIGH |
|
|
333
|
+
| `validation_outlier` | among a cohort's state-changing handlers, peers validate input and this one shows no validation marker | LOW |
|
|
334
|
+
| `method_outlier` | a lone state-changing method in an otherwise read-only cohort | MEDIUM |
|
|
335
|
+
|
|
336
|
+
Everything is peer-relative and **confidence scales with how consistent the
|
|
337
|
+
cohort is** — a lone deviation among many agreeing siblings is likelier a mistake
|
|
338
|
+
than the same deviation in a split group. Outliers are only flagged when they're a
|
|
339
|
+
strict minority (a genuinely 50/50 surface isn't nagged), the cohort must have
|
|
340
|
+
real route structure (distinct paths with parameters/sub-paths, not repeated
|
|
341
|
+
method-call strings), and per-route signal detection is scoped to each handler's
|
|
342
|
+
own span so a sibling's guard is never miscredited. Results appear under
|
|
343
|
+
`scan.anomalies`, each finding naming the peer group and the deviation. This is
|
|
344
|
+
the scan-level, route-cohort counterpart to the layered engine's
|
|
345
|
+
`asymmetric_protection` insight.
|
|
346
|
+
|
|
347
|
+
### Exploitability fusion ("Most exploitable now")
|
|
348
|
+
|
|
349
|
+
Every signal AttackMap has about a route→sink path is fused into a single
|
|
350
|
+
**0–100 exploitability score** so the highest-risk *combinations* rise to the
|
|
351
|
+
top — the public, unauthenticated route whose request reaches a SQL sink next to
|
|
352
|
+
a secret is a different animal from an internal, authed route that reaches the
|
|
353
|
+
same sink two hops away. The score is:
|
|
354
|
+
|
|
355
|
+
- **Deterministic** — the same scan always yields the same number; no
|
|
356
|
+
randomness, no clock.
|
|
357
|
+
- **Explainable** — the score is the clamped sum of named factors, and every one
|
|
358
|
+
is shown. Contributing factors: sink danger (SQLi/RCE/deserialization highest),
|
|
359
|
+
exposure (public/internal/unknown), auth at the entry route, reachability
|
|
360
|
+
(fewer hops = higher), and data sensitivity at the sink (a co-located secret or
|
|
361
|
+
datastore), plus insecure-crypto / web-hardening gaps on the path as
|
|
362
|
+
amplifiers.
|
|
363
|
+
|
|
364
|
+
Scores land on the relevant taint findings (`exploitability` + `exploitability_tier`)
|
|
365
|
+
and in a ranked **`attackmap-exploitability.md`** report plus the `exploitability`
|
|
366
|
+
array in `attackmap-report.json`; the console summary leads with the top few. For
|
|
367
|
+
example, `public + no-auth + taint-to-eval (0 hops)` scores 90/100 (CRITICAL).
|
|
368
|
+
(Dependency CVEs are manifest-level, not attributable to a specific source path,
|
|
369
|
+
so they inform the report but aren't folded into a path's score — path-attributed
|
|
370
|
+
CVE fusion is future work.)
|
|
371
|
+
|
|
216
372
|
### SBOM inventory
|
|
217
373
|
|
|
218
374
|
Every scan also produces a lightweight SBOM by parsing direct dependencies out
|
|
@@ -268,7 +424,10 @@ AttackMap is built as four layers, each grounded in the layer below.
|
|
|
268
424
|
databases, external calls, auth signals, secrets, frameworks, and entrypoints.
|
|
269
425
|
Every signal carries a `file:line` citation, an evidence-text snippet, and a
|
|
270
426
|
confidence score. Plugins are auto-discovered through the `attackmap.analyzers`
|
|
271
|
-
entry-point group.
|
|
427
|
+
entry-point group. Alongside recon, three cross-file passes run in core: a
|
|
428
|
+
**taint / data-flow** walk (request-to-sink reachability across imports), a
|
|
429
|
+
**BOLA/IDOR** authorization check, and an **SBOM** dependency inventory
|
|
430
|
+
(optionally cross-referenced against OSV.dev with `--cve`).
|
|
272
431
|
|
|
273
432
|
**2. Asset and control overlay.** Identifies *what's at risk* (credentials,
|
|
274
433
|
sessions, PII, payment records, internal secrets — with criticality tiers) and
|
|
@@ -285,6 +444,18 @@ trust-boundary violations, and more.
|
|
|
285
444
|
from the structured evidence pack. The model is forced to cite real
|
|
286
445
|
surface/asset/control IDs, so it can't invent findings.
|
|
287
446
|
|
|
447
|
+
**5. Vulnerability-hypothesis hunting (`--hunt`).** The honest core of the
|
|
448
|
+
"find the unknown" ask. `attackmap analyze . --hunt` has Claude reason over the
|
|
449
|
+
full evidence pack (surfaces, assets, controls, taint chains, exploitability
|
|
450
|
+
scores, anomalies) as a red-team analyst and propose **ranked, human-verifiable
|
|
451
|
+
exploit-chain hypotheses** — candidate weaknesses a static rule wouldn't catch,
|
|
452
|
+
especially novel cross-signal combinations. Output goes to
|
|
453
|
+
`vulnerability-hypotheses.md` under an unmissable banner: **these are hypotheses
|
|
454
|
+
to confirm, not detections.** The same grounding contract as the review applies
|
|
455
|
+
(every hypothesis cites real evidence IDs), plus honesty guardrails: no CVE
|
|
456
|
+
assignment, no exploit code, confidence-tiered, and each lead lists exactly what
|
|
457
|
+
a human must verify. Uses the same auth/backend resolution as `--llm`.
|
|
458
|
+
|
|
288
459
|
Layered on top: **MITRE ATT&CK technique mappings** on every insight and
|
|
289
460
|
**detection opportunities** (Sigma/KQL/Splunk-style hints) for each weakness.
|
|
290
461
|
|
|
@@ -292,7 +463,7 @@ Layered on top: **MITRE ATT&CK technique mappings** on every insight and
|
|
|
292
463
|
|
|
293
464
|
## Supported ecosystems
|
|
294
465
|
|
|
295
|
-
|
|
466
|
+
Fourteen official analyzer plugins, each distributable as a separate package:
|
|
296
467
|
|
|
297
468
|
| Plugin | Coverage |
|
|
298
469
|
|---|---|
|
|
@@ -302,13 +473,15 @@ Thirteen official analyzer plugins, each distributable as a separate package:
|
|
|
302
473
|
| `attackmap-analyzer-java-spring` | Java/Kotlin Spring Boot, JAX-RS, Ktor; Spring Data; Spring Security; jjwt |
|
|
303
474
|
| `attackmap-analyzer-dotnet` | ASP.NET Core minimal APIs and attribute routing, EF Core, Identity, JwtBearer |
|
|
304
475
|
| `attackmap-analyzer-terraform` | AWS, Azure, GCP resources; IAM wildcards; open SGs; secrets |
|
|
476
|
+
| `attackmap-analyzer-iac` | Dockerfile hardening, docker-compose service graphs, GitHub Actions workflows, `.env` templates, shell installers |
|
|
305
477
|
| `attackmap-analyzer-c` | libmicrohttpd, civetweb, mongoose; libcurl; OpenSSL/libsodium; sqlite3/libpq/mysql |
|
|
306
478
|
| `attackmap-analyzer-cpp` | Crow, Pistache, Drogon, cpprestsdk; libcurl/cpr; OpenSSL/Botan/libsodium; libpqxx/mongocxx |
|
|
307
479
|
| `attackmap-analyzer-node-service` | Node.js / TypeScript service ecosystems |
|
|
308
480
|
| `attackmap-analyzer-atproto` | AT Protocol (Bluesky) services |
|
|
309
481
|
| `attackmap-analyzer-php-web` / `-php-laminas` / `-omeka-s` | Generic PHP web, Laminas/Zend MVC, Omeka-S |
|
|
310
482
|
|
|
311
|
-
`pip install "attackmap[all]"` installs every official plugin.
|
|
483
|
+
`pip install "attackmap[all]"` installs every official plugin. Not sure which
|
|
484
|
+
you need? `attackmap suggest ./repo` recommends the right set for a repo's shape.
|
|
312
485
|
|
|
313
486
|
### Building your own analyzer
|
|
314
487
|
|
|
@@ -324,16 +497,28 @@ scaffolding, testing, and publishing instructions is in
|
|
|
324
497
|
```bash
|
|
325
498
|
attackmap analyze <path> # run a review on a repository
|
|
326
499
|
attackmap analyze <path> --output dir # write outputs to `dir/`
|
|
500
|
+
attackmap analyze <path> --format json # json | markdown | all (default)
|
|
327
501
|
attackmap analyze <path> --module python --module rust # only these analyzers
|
|
502
|
+
attackmap analyze <path> --cve # cross-reference SBOM against OSV.dev
|
|
328
503
|
attackmap analyze <path> --llm # add LLM narrative (auto-resolve auth)
|
|
329
504
|
attackmap analyze <path> --llm --llm-backend cli # force Claude CLI
|
|
505
|
+
attackmap analyze <path> --hunt # LLM vulnerability-hypothesis hunt (leads to confirm)
|
|
506
|
+
|
|
507
|
+
# CI / PR diff gating
|
|
508
|
+
attackmap analyze <path> --baseline prev/attackmap-report.json \
|
|
509
|
+
--diff-output reports/attackmap-diff.md --fail-on-new-high
|
|
510
|
+
|
|
511
|
+
# Plugin discovery
|
|
330
512
|
attackmap suggest ./repo # recommend plugins for a repo shape
|
|
331
513
|
attackmap suggest ./repo --install # and pip-install the missing ones
|
|
332
514
|
attackmap modules # list installed analyzers
|
|
333
515
|
```
|
|
334
516
|
|
|
335
517
|
`--module` is repeatable. Missing requested external analyzers can be
|
|
336
|
-
auto-installed (when possible) from the `mlaify` GitHub organization.
|
|
518
|
+
auto-installed (when possible) from the `mlaify` GitHub organization. `--cve`
|
|
519
|
+
does network I/O (cached under `~/.attackmap/cache/osv/`, 24h TTL);
|
|
520
|
+
`--fail-on-new-high` requires `--baseline` and exits non-zero when the diff
|
|
521
|
+
introduces a new HIGH finding.
|
|
337
522
|
|
|
338
523
|
---
|
|
339
524
|
|
|
@@ -341,13 +526,61 @@ auto-installed (when possible) from the `mlaify` GitHub organization.
|
|
|
341
526
|
|
|
342
527
|
- **A runtime detector.** AttackMap is static. The detection opportunities it
|
|
343
528
|
emits are *hints* for your SIEM team — they are not deployable rules.
|
|
344
|
-
- **A
|
|
345
|
-
|
|
529
|
+
- **A replacement for dedicated SCA.** AttackMap does inventory dependencies and
|
|
530
|
+
cross-reference OSV.dev with `--cve`, but tools like Trivy, Grype, and
|
|
531
|
+
Dependabot go deeper on transitive resolution and lockfiles. AttackMap's
|
|
532
|
+
value is folding the CVE signal into an architecture-aware narrative
|
|
533
|
+
("this public route reaches this vulnerable ORM").
|
|
534
|
+
- **A true taint engine.** The data-flow pass is a heuristic import-graph walk
|
|
535
|
+
(import-edge ≈ call-edge), not sound interprocedural taint analysis. It
|
|
536
|
+
favors precision over recall; findings are evidence, not proof.
|
|
346
537
|
- **Exhaustive.** AttackMap is heuristic by design. Findings are confidence-tiered
|
|
347
538
|
with explicit guardrails for stale signals.
|
|
348
539
|
|
|
349
540
|
---
|
|
350
541
|
|
|
542
|
+
## Project status
|
|
543
|
+
|
|
544
|
+
AttackMap is **beta** (v0.3.1) — published and validated on real codebases, but
|
|
545
|
+
pre-1.0 and heuristic.
|
|
546
|
+
|
|
547
|
+
**Solid today:**
|
|
548
|
+
|
|
549
|
+
- Modular analyzer execution with entry-point discovery; 14 official plugins on PyPI.
|
|
550
|
+
- Framework-aware route extraction (FastAPI/Flask/Express/Spring/axum/chi/…).
|
|
551
|
+
- Asset + control modeling, cross-cutting insight engine, chain-aware threat model.
|
|
552
|
+
- Injection / data-flow detection: SSRF, SSTI, NoSQL, unsafe deserialization,
|
|
553
|
+
eval/exec/shell, SQL, dynamic file open, open redirect — request-container-gated
|
|
554
|
+
for precision.
|
|
555
|
+
- Novel vuln-class detectors: prototype pollution, mass assignment, JWT weakness,
|
|
556
|
+
XXE, ReDoS, insecure upload, GraphQL exposure.
|
|
557
|
+
- BOLA/IDOR authorization detection on path-template routes.
|
|
558
|
+
- Insecure-crypto / weak-randomness and web-hardening (CORS/CSRF/cookies/CSP/debug)
|
|
559
|
+
detection.
|
|
560
|
+
- Anomaly / outlier detection (the odd-one-out among sibling routes) and
|
|
561
|
+
**exploitability fusion** — a deterministic, explainable 0–100 "exploitable now"
|
|
562
|
+
score that ranks route→sink combinations.
|
|
563
|
+
- **`--hunt`**: LLM vulnerability-hypothesis mode — evidence-cited, human-verifiable
|
|
564
|
+
exploit-chain leads (not detections).
|
|
565
|
+
- SBOM inventory (5 ecosystems) + OSV.dev CVE cross-reference (`--cve`).
|
|
566
|
+
- Output: Markdown + JSON + **SARIF 2.1.0** (GitHub Code Scanning) + **Mermaid /
|
|
567
|
+
Graphviz** diagrams; **diff/baseline** mode for PR gating; optional LLM narrative.
|
|
568
|
+
- Live scan progress bar + ETA; test/spec files excluded from heuristic passes.
|
|
569
|
+
- Distribution: `pip install attackmap[all]`, `brew install mlaify/tap/attackmap`,
|
|
570
|
+
`docker pull ghcr.io/mlaify/attackmap`.
|
|
571
|
+
|
|
572
|
+
**Still maturing:**
|
|
573
|
+
|
|
574
|
+
- Taint + BOLA are Python + JS/TS and path-template scoped; query-param / RPC-method
|
|
575
|
+
authorization and more languages are planned.
|
|
576
|
+
- The import-graph taint walk approximates call-edges with import-edges — precision
|
|
577
|
+
over recall; findings are evidence, not proof.
|
|
578
|
+
- CVE lookup resolves a best-effort concrete version, not full lockfile ranges, and
|
|
579
|
+
isn't yet fused into per-path exploitability scores.
|
|
580
|
+
- Anomaly / exploitability reasoning is route-cohort and taint-chain scoped.
|
|
581
|
+
|
|
582
|
+
---
|
|
583
|
+
|
|
351
584
|
## Documentation
|
|
352
585
|
|
|
353
586
|
- [`CHANGELOG.md`](CHANGELOG.md) — release notes
|