crowbar-cli 0.1.0__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.
- crowbar_cli-0.1.0/.gitignore +39 -0
- crowbar_cli-0.1.0/AGENTS.md +386 -0
- crowbar_cli-0.1.0/LICENSE +21 -0
- crowbar_cli-0.1.0/Makefile +62 -0
- crowbar_cli-0.1.0/PKG-INFO +287 -0
- crowbar_cli-0.1.0/README.md +266 -0
- crowbar_cli-0.1.0/bin/crowbar +11 -0
- crowbar_cli-0.1.0/crowbar/__init__.py +3 -0
- crowbar_cli-0.1.0/crowbar/catalog.py +174 -0
- crowbar_cli-0.1.0/crowbar/cli.py +1417 -0
- crowbar_cli-0.1.0/crowbar/datasets.py +584 -0
- crowbar_cli-0.1.0/crowbar/db.py +47 -0
- crowbar_cli-0.1.0/crowbar/indexer.py +985 -0
- crowbar_cli-0.1.0/crowbar/intel.py +562 -0
- crowbar_cli-0.1.0/crowbar/loaders.py +382 -0
- crowbar_cli-0.1.0/crowbar/mcp.py +387 -0
- crowbar_cli-0.1.0/crowbar/paths.py +54 -0
- crowbar_cli-0.1.0/crowbar/query.py +551 -0
- crowbar_cli-0.1.0/docs/DATASETS.md +147 -0
- crowbar_cli-0.1.0/docs/INTEL.md +89 -0
- crowbar_cli-0.1.0/docs/INTEL_RESEARCH_PROMPT.md +114 -0
- crowbar_cli-0.1.0/docs/LAUNCH.md +83 -0
- crowbar_cli-0.1.0/docs/MAP.md +178 -0
- crowbar_cli-0.1.0/docs/NIX.md +68 -0
- crowbar_cli-0.1.0/docs/assets/agent-session.gif +0 -0
- crowbar_cli-0.1.0/docs/assets/demo.gif +0 -0
- crowbar_cli-0.1.0/docs/assets/flow.svg +18 -0
- crowbar_cli-0.1.0/mcp/server.py +11 -0
- crowbar_cli-0.1.0/pyproject.toml +50 -0
- crowbar_cli-0.1.0/scripts/age_index.py +20 -0
- crowbar_cli-0.1.0/scripts/check.py +140 -0
- crowbar_cli-0.1.0/scripts/fetch_intel.py +373 -0
- crowbar_cli-0.1.0/scripts/install.mjs +309 -0
- crowbar_cli-0.1.0/scripts/install.test.mjs +93 -0
- crowbar_cli-0.1.0/scripts/make_fixture.py +44 -0
- crowbar_cli-0.1.0/scripts/merge_p0.py +161 -0
- crowbar_cli-0.1.0/scripts/rollback_index.sh +41 -0
- crowbar_cli-0.1.0/scripts/selftest.py +122 -0
- crowbar_cli-0.1.0/scripts/smoke.py +81 -0
- crowbar_cli-0.1.0/skills/crowbar/SKILL.md +68 -0
- crowbar_cli-0.1.0/tests/__init__.py +0 -0
- crowbar_cli-0.1.0/tests/support.py +229 -0
- crowbar_cli-0.1.0/tests/test_corpus.py +750 -0
- crowbar_cli-0.1.0/tests/test_unit.py +813 -0
- crowbar_cli-0.1.0/tests/test_v3.py +280 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Corpus and build output - never committed (see docs/DATASETS.md)
|
|
2
|
+
data/
|
|
3
|
+
index/
|
|
4
|
+
*.db
|
|
5
|
+
*.db.*
|
|
6
|
+
*.sha256
|
|
7
|
+
|
|
8
|
+
# Python
|
|
9
|
+
__pycache__/
|
|
10
|
+
*.py[cod]
|
|
11
|
+
.venv/
|
|
12
|
+
venv/
|
|
13
|
+
*.egg-info/
|
|
14
|
+
dist/
|
|
15
|
+
build/
|
|
16
|
+
|
|
17
|
+
# Agent/editor local config
|
|
18
|
+
opencode.json
|
|
19
|
+
.opencode/
|
|
20
|
+
.crowbar
|
|
21
|
+
.DS_Store
|
|
22
|
+
|
|
23
|
+
# Experiments / non-public working dirs
|
|
24
|
+
ganith/
|
|
25
|
+
Exploits/
|
|
26
|
+
notes/
|
|
27
|
+
skills/hacker-skill/
|
|
28
|
+
_publish/
|
|
29
|
+
|
|
30
|
+
# Docusaurus
|
|
31
|
+
website/node_modules/
|
|
32
|
+
website/build/
|
|
33
|
+
website/.docusaurus/
|
|
34
|
+
assets/demo.mp4
|
|
35
|
+
assets/demo.webm
|
|
36
|
+
|
|
37
|
+
# nix build output
|
|
38
|
+
result
|
|
39
|
+
result-*
|
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
# AGENTS.md - crowbar traversal manual
|
|
2
|
+
|
|
3
|
+
Offline vulnerability intelligence at the repo root (or `.crowbar/` in a linked
|
|
4
|
+
project). One SQLite+FTS5 database, one CLI, one MCP server.
|
|
5
|
+
|
|
6
|
+
**Three ways in, in order of preference:**
|
|
7
|
+
|
|
8
|
+
1. MCP tools (`cb_*`) when the server is connected.
|
|
9
|
+
2. `bin/crowbar <cmd> --json` - stable JSON, no parsing needed.
|
|
10
|
+
3. Read-only SQL on `index/crowbar.db` via `crowbar sql` (never write).
|
|
11
|
+
|
|
12
|
+
Never answer CVE facts from memory. If a fact is not in the DB, say so.
|
|
13
|
+
|
|
14
|
+
## Product and authority
|
|
15
|
+
|
|
16
|
+
crowbar is a local, read-only vulnerability-intelligence index with shared
|
|
17
|
+
CLI and MCP workflows. It grounds answers in indexed upstream data - it is not
|
|
18
|
+
a scanner and not authorization. Only test systems the user owns or may test.
|
|
19
|
+
Rank threat by **KEV / SSVC active > EPSS > CVSS**, never CVSS alone. KEV and
|
|
20
|
+
SSVC describe exploitation observed elsewhere; EPSS is a model estimate; a
|
|
21
|
+
missing row is not proof of "not affected".
|
|
22
|
+
|
|
23
|
+
## Performance (agent tokens first)
|
|
24
|
+
|
|
25
|
+
Return the smallest sufficient answer. `cb_cve` caps the large per-CVE arrays
|
|
26
|
+
(`affects`, `references`, `products`, `exploits`) at 50 rows each and reports an
|
|
27
|
+
`affects_total` / `references_total` / `products_total` count; use `crowbar sql` or
|
|
28
|
+
the CLI for the full list. Any tool response over the hard ceiling comes back as
|
|
29
|
+
a valid-JSON `result_too_large` notice, never a sliced payload - so narrow the
|
|
30
|
+
query or lower `limit` rather than parsing a truncated blob.
|
|
31
|
+
|
|
32
|
+
Contributing to the repo itself: see [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## 0. Orient (do this first, every session)
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
.crowbar/bin/crowbar doctor # built? schema? stale? (exit 1 = needs work)
|
|
40
|
+
.crowbar/bin/crowbar stats --json # row counts + freshness
|
|
41
|
+
.crowbar/bin/crowbar map # dataset -> path -> tables -> command
|
|
42
|
+
.crowbar/bin/crowbar map --tables # what every table means
|
|
43
|
+
.crowbar/bin/crowbar where --json # absolute paths
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
If the index is missing: `crowbar sync && crowbar build` (minutes - tell the user).
|
|
47
|
+
`crowbar update` is the cheap refresh (≈10 s). `crowbar update --deep` reindexes the
|
|
48
|
+
intel tables.
|
|
49
|
+
|
|
50
|
+
Freshness: the CLI and the MCP server start a background `crowbar update` once
|
|
51
|
+
the index is a day old (at most hourly; `CROWBAR_NO_AUTO_UPDATE=1` turns it off,
|
|
52
|
+
log in `index/update.log`). `cb_stats` → `index.age_days` / `index.stale`; stale
|
|
53
|
+
means older than NVD's 8-day change window, so say recent CVEs may be missing.
|
|
54
|
+
An installed package keeps its index in `~/.crowbar` (`CROWBAR_HOME` overrides).
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## 1. Repo map
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
crowbar/
|
|
62
|
+
├── bin/crowbar CLI shim (works through symlinks)
|
|
63
|
+
├── mcp/server.py MCP stdio shim -> crowbar.mcp
|
|
64
|
+
├── crowbar/
|
|
65
|
+
│ ├── paths.py root resolution, YEARS, SCHEMA_VERSION
|
|
66
|
+
│ ├── datasets.py registry + downloader + manifest/freshness
|
|
67
|
+
│ ├── indexer.py schema, NVD/KEV/intel loaders, build(), update()
|
|
68
|
+
│ ├── loaders.py bulk loaders: OSV, Debian, MSRC, Apple, toolkit,
|
|
69
|
+
│ │ Exploit-DB source code, Metasploit sources
|
|
70
|
+
│ ├── catalog.py static dataset -> table -> command map (crowbar map)
|
|
71
|
+
│ ├── query.py read layer; every function returns dicts
|
|
72
|
+
│ ├── cli.py terminal commands (single source of truth)
|
|
73
|
+
│ └── mcp.py MCP tool definitions (calls query.py directly)
|
|
74
|
+
├── scripts/
|
|
75
|
+
│ ├── selftest.py end-to-end corpus checks
|
|
76
|
+
│ ├── check.py static checks (schema/catalog/docs/style)
|
|
77
|
+
│ └── make_fixture.py tiny synthetic index for CI
|
|
78
|
+
├── tests/
|
|
79
|
+
│ ├── test_unit.py 111 fixture tests (CI, no corpus needed)
|
|
80
|
+
│ └── test_corpus.py generated tests against index/crowbar.db
|
|
81
|
+
├── docs/
|
|
82
|
+
│ ├── DATASETS.md per-source license, shape, caveats
|
|
83
|
+
│ ├── MAP.md full tree + data flow
|
|
84
|
+
│ └── NIX.md scheduling via home-manager (no launchctl)
|
|
85
|
+
├── data/ raw upstream corpora (git-ignored, ~3.3 GB)
|
|
86
|
+
├── index/
|
|
87
|
+
│ ├── crowbar.db the index (query this)
|
|
88
|
+
│ ├── manifest.json url/bytes/sha256/fetched_at per dataset
|
|
89
|
+
│ ├── state.json schema, built_at, updated_at
|
|
90
|
+
│ └── stats.json last build/update summary
|
|
91
|
+
├── AGENTS.md this file
|
|
92
|
+
├── README.md user docs
|
|
93
|
+
├── TODO.md known gaps
|
|
94
|
+
└── Makefile sync / build / update / test / doctor
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Raw data is grouped by source; `crowbar map` is authoritative for the mapping:
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
data/nvd/ NVD year + recent/modified feeds (gzip)
|
|
101
|
+
data/kev/ CISA KEV
|
|
102
|
+
data/epss/ EPSS scores
|
|
103
|
+
data/cwe/ capec/ MITRE taxonomies
|
|
104
|
+
data/attack/ ATT&CK enterprise/mobile/ics
|
|
105
|
+
data/vulnrichment/ CISA SSVC (per-CVE JSON)
|
|
106
|
+
data/exploitdb/ index CSVs + full/ source tree
|
|
107
|
+
data/nuclei/ template YAML
|
|
108
|
+
data/metasploit/ tree.json + source/modules/
|
|
109
|
+
data/osv/ per-ecosystem advisory zips
|
|
110
|
+
data/debian/ tracker.json
|
|
111
|
+
data/msrc/ Microsoft Security Update Guide (sug.json)
|
|
112
|
+
data/apple/ security release index + advisory pages
|
|
113
|
+
data/toolkit/ gtfobins, lolbas, payloads
|
|
114
|
+
data/models/ models.dev catalog
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## 2. Tables
|
|
120
|
+
|
|
121
|
+
```sql
|
|
122
|
+
-- core
|
|
123
|
+
cve(id PK, published, modified, status, description,
|
|
124
|
+
cvss, cvss_version, cvss_vector, severity,
|
|
125
|
+
kev INT, epss REAL, epss_pct REAL,
|
|
126
|
+
has_exploit INT, has_nuclei INT, has_msf INT, year INT)
|
|
127
|
+
cve_cwe(cve_id, cwe)
|
|
128
|
+
cve_product(cve_id, vendor, product)
|
|
129
|
+
cpe_match(cve_id, part, vendor, product, version,
|
|
130
|
+
v_start_incl, v_start_excl, v_end_incl, v_end_excl)
|
|
131
|
+
cve_ref(cve_id, url, tags)
|
|
132
|
+
cve_exploit(cve_id, exploit_id)
|
|
133
|
+
cve_nuclei(cve_id, template_id)
|
|
134
|
+
cve_msf(cve_id, module_path)
|
|
135
|
+
|
|
136
|
+
-- intel
|
|
137
|
+
kev(cve PK, vendor, product, name, date_added, ransomware, action, due, notes,
|
|
138
|
+
epss, epss_pct) -- EPSS on every KEV row, even CVEs outside the tier's NVD years
|
|
139
|
+
exploit(id PK, file, description, date, author, type, platform,
|
|
140
|
+
verified, codes, tags, url, raw)
|
|
141
|
+
shellcode(id PK, file, description, date, platform, url)
|
|
142
|
+
nuclei(id PK, name, severity, tags, cve, path, description, domain)
|
|
143
|
+
msf(path PK, type, name, platform, privileged, disclosure_date,
|
|
144
|
+
description, cves)
|
|
145
|
+
attack(id, domain, name, tactics, platforms, description, url) -- PK(id,domain)
|
|
146
|
+
cwe(id PK, name, abstraction, status, description)
|
|
147
|
+
capec(id PK, name, severity, likelihood, cwe, description)
|
|
148
|
+
model(provider, provider_name, id, name, context, output_limit,
|
|
149
|
+
input_cost, output_cost, released, reasoning, tool_call, vision)
|
|
150
|
+
ssvc(cve_id PK, exploitation, automatable, technical_impact, timestamp, source)
|
|
151
|
+
|
|
152
|
+
-- bulk / ecosystem / vendor
|
|
153
|
+
advisory(source, id, ecosystem, package, cve, summary, severity,
|
|
154
|
+
published, modified, url, aliases, affected_count)
|
|
155
|
+
package_range(advisory_id, ecosystem, package, introduced, fixed,
|
|
156
|
+
last_affected, versions)
|
|
157
|
+
debian(package, release, cve, status, fixed, urgency, description)
|
|
158
|
+
os_advisory(source, cve, platform, product, version, title, severity,
|
|
159
|
+
impact, exploited, released, url)
|
|
160
|
+
toolkit(source, name, path, description, tags)
|
|
161
|
+
|
|
162
|
+
-- full-text
|
|
163
|
+
cve_fts(id, description, products)
|
|
164
|
+
exploit_fts(id, description, tags, codes)
|
|
165
|
+
nuclei_fts(id, name, tags, cve)
|
|
166
|
+
model_fts(provider, id, name)
|
|
167
|
+
exploit_code_fts(exploit_id, path, content) -- Exploit-DB source code
|
|
168
|
+
toolkit_fts(source, name, description, tags)
|
|
169
|
+
|
|
170
|
+
-- schema v3: CNA + public PoC + provenance
|
|
171
|
+
cve_cna(cve_id PK, assigner, state, published, updated, title, description,
|
|
172
|
+
cvss, cvss_version, cvss_vector, severity, record_path, source,
|
|
173
|
+
source_url, source_sha256, fetched_at)
|
|
174
|
+
cve_cna_ref(cve_id, url, tags) -- CNA references, kept apart from NVD
|
|
175
|
+
cve_cna_product(cve_id, vendor, product) -- CNA affected products
|
|
176
|
+
cve_meta(cve_id PK, published_year, cve_year, has_poc, poc_count)
|
|
177
|
+
poc(source, cve_id, repo, url, repo_id, stars, language,
|
|
178
|
+
created_at, pushed_at, description, fetched_at)
|
|
179
|
+
poc_orphan(cve_id PK, count) -- PoCs for CVEs the index does not carry
|
|
180
|
+
cve_alias(cve_id, alias, source)
|
|
181
|
+
source_state(source PK, url, path, license, sha256, fetched_at, loaded_at,
|
|
182
|
+
record_count, status, note)
|
|
183
|
+
|
|
184
|
+
meta(key, value)
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
`cve_cna` holds the **CNA-authored** record (CVE List v5) beside the NVD row;
|
|
188
|
+
it never replaces `cve.description` or `cve.cvss`. `cve_meta.published_year` is
|
|
189
|
+
the publication year, `cve_meta.cve_year` the year in the CVE ID - they differ
|
|
190
|
+
for ~85k records. `poc` holds repository metadata only; no PoC is ever cloned
|
|
191
|
+
or executed.
|
|
192
|
+
|
|
193
|
+
`os_advisory.platform` is `windows` (MSRC) or `ios` / `macos` / `apple`
|
|
194
|
+
(Apple). `impact` is normalized: `RCE`, `EoP`, `DoS`, `InfoDisclosure`,
|
|
195
|
+
`Spoofing`, `Bypass`, `Tampering`.
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## 3. Which path answers which question
|
|
200
|
+
|
|
201
|
+
| question | use | not this |
|
|
202
|
+
|---|---|---|
|
|
203
|
+
| is product X version Y affected? | `crowbar product X --version Y` (`cpe_match`) | `crowbar search --product` |
|
|
204
|
+
| what does CVE-X mean? | `crowbar cve CVE-X` | search |
|
|
205
|
+
| CVE in an npm/PyPI/Go package | `crowbar advisory --package pkg` or `crowbar cve` → `advisories` | CVE search |
|
|
206
|
+
| Windows / iOS / macOS advisory | `crowbar os` (`--platform`, `--impact RCE`) | vendor CVE title grep |
|
|
207
|
+
| Debian fixed version | `crowbar debian pkg` | NVD |
|
|
208
|
+
| public PoC repository for a CVE | `crowbar poc --cve CVE-X` | `crowbar cve` → `pocs` |
|
|
209
|
+
| CNA-authored description / refs | `crowbar cve CVE-X` → `cna` | NVD description |
|
|
210
|
+
| which source filled a table | `crowbar sources` | - |
|
|
211
|
+
| PoC code, not just a title | `crowbar code "<snippet>"` | `crowbar exploit` |
|
|
212
|
+
| living-off-the-land binary | `crowbar bin <name>` | ATT&CK |
|
|
213
|
+
| technique for an actor/behavior | `crowbar attack <q>` | CWE |
|
|
214
|
+
| weakness class | `crowbar cwe <n>` / `crowbar capec <q>` | CVE |
|
|
215
|
+
| model pricing/context | `crowbar models` | - |
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## 4. Recipes
|
|
220
|
+
|
|
221
|
+
### Triage one CVE
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
.crowbar/bin/crowbar cve CVE-2021-44228 --json | jq \
|
|
225
|
+
'{id,severity,cvss,epss,kev,cwe,ssvc,
|
|
226
|
+
exploits:(.exploits|length), nuclei:(.nuclei|length),
|
|
227
|
+
os:.os, advisories:.advisories, ranges:[.affects[].label]}'
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
Interpretation order:
|
|
231
|
+
|
|
232
|
+
1. `kev == 1` → confirmed exploitation somewhere in the wild.
|
|
233
|
+
2. `ssvc.exploitation` → `active` / `poc` / `none`.
|
|
234
|
+
3. `epss` (30-day probability) and `epss_pct`.
|
|
235
|
+
4. `cvss` / `severity` → impact if triggered.
|
|
236
|
+
5. `exploits` / `nuclei` / `metasploit` → working or near-working PoC.
|
|
237
|
+
6. `os` / `advisories` / `debian` → vendor and distro applicability.
|
|
238
|
+
7. `cwe` / `capec` → bug class → mitigations and detection.
|
|
239
|
+
|
|
240
|
+
Never present CVSS alone as "risk". KEV ≫ SSVC ≫ EPSS ≫ CVSS.
|
|
241
|
+
|
|
242
|
+
### "We run <product> <version> - what's exploitable?"
|
|
243
|
+
|
|
244
|
+
```bash
|
|
245
|
+
crowbar product nginx --version 1.18.0 --json
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
Tests every `cpe_match` row against the version (exact or start/end bounds) and
|
|
249
|
+
returns only real hits plus the matched range. Rank by `kev`, `epss`,
|
|
250
|
+
`has_exploit`. NVD CPE data is incomplete for some vendors (notably Apple);
|
|
251
|
+
cross-check `crowbar os`.
|
|
252
|
+
|
|
253
|
+
### Ecosystem package
|
|
254
|
+
|
|
255
|
+
```bash
|
|
256
|
+
crowbar advisory --package lodash --ecosystem npm --json
|
|
257
|
+
crowbar advisory "prototype pollution" --limit 20
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
Each result carries `ranges[]` with `introduced` / `fixed` / `last_affected`.
|
|
261
|
+
`crowbar cve` also lists advisory ids and Debian fixed versions.
|
|
262
|
+
|
|
263
|
+
### Windows / iOS / macOS
|
|
264
|
+
|
|
265
|
+
```bash
|
|
266
|
+
crowbar os --platform windows --impact RCE --since 2025-01-01
|
|
267
|
+
crowbar os "Windows 11" --json
|
|
268
|
+
crowbar os --platform ios
|
|
269
|
+
crowbar os --platform macos --limit 100
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
MSRC rows carry `severity` and normalized `impact`; Apple rows carry the
|
|
273
|
+
product/version title and the CVEs extracted from each advisory page.
|
|
274
|
+
|
|
275
|
+
### PoC / exploit code
|
|
276
|
+
|
|
277
|
+
```bash
|
|
278
|
+
crowbar exploit "log4j jndi" --json # Exploit-DB index
|
|
279
|
+
crowbar exploit 50592 # download source, prints local path
|
|
280
|
+
crowbar code "jndi lookup ldap" # search inside the sources, returns snippet
|
|
281
|
+
crowbar nuclei "cve-2021-44228" --json # template path
|
|
282
|
+
crowbar msf ms17 --json
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
Nuclei YAML is at `data/nuclei/templates/<path>`; Exploit-DB sources at
|
|
286
|
+
`data/exploitdb/full/<path>`. Neither is executed.
|
|
287
|
+
|
|
288
|
+
### Search
|
|
289
|
+
|
|
290
|
+
```bash
|
|
291
|
+
crowbar search "remote code execution" --limit 50 --json
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
AND over FTS5 tokens (prefix ≥4 chars), falling back to the longest term.
|
|
295
|
+
Filters: `--kev --exploit --epss N --cvss N --severity A,B --year Y --since DATE
|
|
296
|
+
--cwe CWE-N --product P --vendor V --ssvc active`.
|
|
297
|
+
|
|
298
|
+
Ranking: `10·normalized_bm25 + 4·KEV + 5·EPSS + 1.5·min(exploits,3)`.
|
|
299
|
+
`--sort newest|cvss|epss` overrides.
|
|
300
|
+
|
|
301
|
+
### SQL escape hatch
|
|
302
|
+
|
|
303
|
+
```bash
|
|
304
|
+
crowbar sql "select cve, vendor, product, name, date_added from kev
|
|
305
|
+
where date_added >= date('now','-90 day') order by date_added desc" --json
|
|
306
|
+
|
|
307
|
+
crowbar sql "select c.id, c.epss, c.cvss from cve c
|
|
308
|
+
where c.epss > 0.5 and c.kev = 0 and c.has_exploit = 1
|
|
309
|
+
order by c.epss desc limit 50" --json
|
|
310
|
+
|
|
311
|
+
crowbar sql "select advisory_id, ecosystem, package, fixed from package_range
|
|
312
|
+
where package='log4j-core'" --json
|
|
313
|
+
|
|
314
|
+
crowbar sql "select cve, product, version, impact from os_advisory
|
|
315
|
+
where platform='windows' and impact='RCE'
|
|
316
|
+
and released >= '2026-01-01' order by released desc" --json
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
`crowbar sql` is `PRAGMA query_only=ON`: no writes, no DDL.
|
|
320
|
+
|
|
321
|
+
### ATT&CK / CWE / CAPEC / models
|
|
322
|
+
|
|
323
|
+
```bash
|
|
324
|
+
crowbar attack T1059 --json
|
|
325
|
+
crowbar attack "credential dumping" --domain enterprise --json
|
|
326
|
+
crowbar attack plc --domain ics --json
|
|
327
|
+
crowbar cwe 79
|
|
328
|
+
crowbar capec 66
|
|
329
|
+
crowbar models --json | jq '[.[]|{provider,id,context,input_cost}]|sort_by(.input_cost)[:10]'
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
---
|
|
333
|
+
|
|
334
|
+
## 5. Project linking
|
|
335
|
+
|
|
336
|
+
```bash
|
|
337
|
+
crowbar link /path/to/project # .crowbar -> corpus, .opencode/skills/crowbar -> skill
|
|
338
|
+
crowbar unlink /path/to/project
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
Inside a linked project use `.crowbar/bin/crowbar`. Unlinking removes only the
|
|
342
|
+
symlinks. The MCP server works in every project whether or not it is linked.
|
|
343
|
+
|
|
344
|
+
---
|
|
345
|
+
|
|
346
|
+
## 6. Guardrails
|
|
347
|
+
|
|
348
|
+
- **Authorization first.** Only test hosts you own or are permitted to test.
|
|
349
|
+
- Exploits are untrusted code. Run in a disposable VM/container.
|
|
350
|
+
`crowbar exploit <id>` downloads source; it never executes it.
|
|
351
|
+
- KEV/SSVC describe observed exploitation elsewhere, not your host.
|
|
352
|
+
- EPSS is model output, not a verdict.
|
|
353
|
+
- `cpe_match` keeps NVD's `vulnerable=true` rows; wildcard vendors/products are
|
|
354
|
+
dropped. If a CVE has no CPE data, read the raw NVD JSON.
|
|
355
|
+
- OSV/Apple/MSRC coverage is advisory-driven, not exhaustive. Absence of a row
|
|
356
|
+
is not proof of "not affected".
|
|
357
|
+
|
|
358
|
+
---
|
|
359
|
+
|
|
360
|
+
## 7. Maintenance
|
|
361
|
+
|
|
362
|
+
```bash
|
|
363
|
+
crowbar sync # fetch changed datasets (sha256 + HTTP 304)
|
|
364
|
+
crowbar sync --bulk # + OSV zips, Debian tracker, full Exploit-DB, toolkit
|
|
365
|
+
crowbar build # full rebuild, atomic swap (heavy with bulk data)
|
|
366
|
+
crowbar update # in-place incremental (~10 s)
|
|
367
|
+
crowbar update --deep # + Nuclei / MSF / ATT&CK / vendor + toolkit tables
|
|
368
|
+
crowbar verify # SQLite integrity + sha256 of every dataset
|
|
369
|
+
crowbar stats # coverage + freshness
|
|
370
|
+
python3 scripts/selftest.py # corpus health checks
|
|
371
|
+
python3 scripts/check.py # schema/catalog/docs/style consistency
|
|
372
|
+
python3 -m tests.test_unit # 111 fixture tests (also runs in CI)
|
|
373
|
+
python3 -m tests.test_corpus # generated corpus tests
|
|
374
|
+
pre-commit run --all-files # check + unit + corpus + gitleaks
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
CI (`.github/workflows/`): `ci.yml` runs lint (ruff, shellcheck, actionlint),
|
|
378
|
+
check + fixture tests on Linux/macOS × Python 3.11–3.14, wheel/sdist/uvx/nix/docker
|
|
379
|
+
installs through `scripts/smoke.py`, npm pack contents, and plugin/skill/MCP
|
|
380
|
+
manifest validation. `upstream.yml` builds a real lite index nightly, checks what
|
|
381
|
+
lite promises, and runs the auto-update end to end. Plus CodeQL, scorecard, PR title,
|
|
382
|
+
dependency review and link checks.
|
|
383
|
+
|
|
384
|
+
Build needs ~2× the DB size in free space (writes `crowbar.db.tmp`, then swaps).
|
|
385
|
+
Do not kill an update mid-write on removable media; `crowbar verify` repairs a hot
|
|
386
|
+
journal.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 kushvinth
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
SHELL := /bin/bash
|
|
2
|
+
PY ?= python3
|
|
3
|
+
HV := ./bin/crowbar
|
|
4
|
+
|
|
5
|
+
.PHONY: all sync build update test test-unit test-corpus check selftest precommit \
|
|
6
|
+
doctor stats map verify link unlink clean demo
|
|
7
|
+
|
|
8
|
+
all: sync build
|
|
9
|
+
|
|
10
|
+
sync:
|
|
11
|
+
$(PY) -m crowbar.cli sync
|
|
12
|
+
|
|
13
|
+
build:
|
|
14
|
+
$(PY) -m crowbar.cli build
|
|
15
|
+
|
|
16
|
+
update:
|
|
17
|
+
$(PY) -m crowbar.cli update --deep
|
|
18
|
+
|
|
19
|
+
test: test-unit test-corpus
|
|
20
|
+
|
|
21
|
+
test-unit:
|
|
22
|
+
$(PY) -m tests.test_unit
|
|
23
|
+
|
|
24
|
+
test-corpus:
|
|
25
|
+
$(PY) -m tests.test_corpus
|
|
26
|
+
|
|
27
|
+
check:
|
|
28
|
+
$(PY) scripts/check.py
|
|
29
|
+
|
|
30
|
+
selftest:
|
|
31
|
+
$(PY) scripts/selftest.py
|
|
32
|
+
|
|
33
|
+
precommit:
|
|
34
|
+
pre-commit run --all-files
|
|
35
|
+
|
|
36
|
+
doctor:
|
|
37
|
+
$(HV) doctor
|
|
38
|
+
|
|
39
|
+
stats:
|
|
40
|
+
$(HV) stats
|
|
41
|
+
|
|
42
|
+
map:
|
|
43
|
+
$(HV) map --tables
|
|
44
|
+
|
|
45
|
+
verify:
|
|
46
|
+
$(HV) verify
|
|
47
|
+
|
|
48
|
+
link:
|
|
49
|
+
$(HV) link $(PWD)
|
|
50
|
+
|
|
51
|
+
unlink:
|
|
52
|
+
$(HV) unlink $(PWD)
|
|
53
|
+
|
|
54
|
+
clean:
|
|
55
|
+
rm -rf data index/crowbar.db index/crowbar.db.tmp index/manifest.json index/state.json
|
|
56
|
+
find . -name __pycache__ -type d -prune -exec rm -rf {} +
|
|
57
|
+
|
|
58
|
+
# README GIFs from the asciinema casts (needs agg: nix run nixpkgs#asciinema-agg)
|
|
59
|
+
AGG ?= agg --theme monokai --font-size 16 --idle-time-limit 2 --last-frame-duration 4
|
|
60
|
+
demo:
|
|
61
|
+
$(AGG) website/demo.cast docs/assets/demo.gif
|
|
62
|
+
$(AGG) assets/agent-session.cast docs/assets/agent-session.gif
|