Imported from ferralon-ai/vulnerability-corpus (
AGENTS.md). Install upstream withnpx skills add ferralon-ai/vulnerability-corpus. Copyright stays with the author.
AGENTS.md — orientation for an agent working in this repository
The Ferralon Vulnerability Corpus is 106,913 advisories as one structured JSON record each, and what makes it different from a package-name feed is what those records carry: code-level detail — the vulnerable symbols, the fixing commit, and a sink and root-cause classification. An SBOM match says a vulnerable package is present; it cannot say whether the code calls the vulnerable path. These records carry the evidence that second question needs, and that is what you are here to use.
Keyed by canonical identifier (CVE / GHSA / other OSV-family ids), partitioned by publication
year, published under the Business Source License 1.1 (SPDX BUSL-1.1) — production use is
granted, competing commercially is not, and each version converts to Apache-2.0 after four years.
Read LICENSE before you build on it; it is not an Open Source licence.
Try this first — it is what the corpus is for
"I depend on
github.com/opencontainers/runc. Which advisories here name it, which of those carry the vulnerable symbols and the fixing commit, and what do those symbols let me claim about my own code?"
Answer it with the answering-a-dependency-question-with-the-ferralon-corpus skill, which walks
it end to end, or over the MCP server in mcp/ — one dependency-free Go binary, ten tools, no
clone required. Two more worth running: "I'm on next 14.2.3 — which advisories cover that
version, and which can you not decide?" and "this record has no fix field; does that mean it
isn't fixed?" (the answer to the last one is the rule at the bottom of this file).
What is actually in the records
Counted by the publish that built this tree, over 106,913 advisories:
| Field | Carried by | Share |
|---|---|---|
rejection_status |
106,913 | 100.0% |
root_cause |
104,342 | 97.6% |
poc_signal |
96,783 | 90.5% |
cwes |
75,818 | 70.9% |
sink_kind |
30,137 | 28.2% |
affected |
31,208 | 29.2% |
fix.upstream_commit |
6,719 | 6.3% |
symbols |
2,537 | 2.4% |
Quote these as counts, not as shares. 104,342 advisories carry a structured root-cause classification, 96,783 a public-exploit signal sourced in both directions, 75,818 a weakness class, 30,137 a sink classification and 31,208 a package coordinate with version ranges. 6,719 are anchored to the exact fixing commit and 2,537 name the vulnerable functions.
Those last two are the deepest fields and the smallest populations — enrichment is depth-first,
so say so when you answer, and read LIMITATIONS.md before you promise a user symbol-level detail.
The share column divides by every advisory here, including the many whose upstream sources will
never support a symbol; give the count and the share together, never a share alone. The live
figures are in coverage.json; do not hand-write a count into any answer you cannot source from
it.
What you can query, and how
- MCP server —
mcp/.ferralon-corpus-mcp, one dependency-free Go binary, ten tools. Build:cd mcp && go build -o ferralon-corpus-mcp ./cmd/ferralon-corpus-mcp. Then{ "mcpServers": { "ferralon-corpus": { "command": "ferralon-corpus-mcp" } } }in your client. The default mode fetches records over HTTPS and needs no clone;-mode local -root <path>reads a checkout;-self-checkproves the wiring before you rely on it. Every answer carries an explicitabsent_fieldslist, which is the mechanism behind the rule below. Detail:mcp/README.md. - Records —
manifest.json+<YYYY>/<MM>/<ID>.json. Resolve through the manifest, then verify each file's SHA-256 against itsoutput_digestbefore decoding — part of the protocol, not an option.CONSUMING.mdis the protocol;FIELDS.mddefines every key. - Reverse indexes —
package-index.jsonl,symbol-index.jsonl,fix-commit-index.jsonl. From a Package URL, a vulnerable symbol, or a 40-hex fixing commit to the advisories that name it. Each is built only from records that sourced that field, so a missing key is not sourced. - Scope —
selection-index.jsonl,policies/,feed.json,signals.json. What to scan, prebaked selections, a delta cursor, and the KEV/EPSS sidecar; theselecting-from-the-ferralon-corpusskill covers all four. - Skills —
skills/. Seven, BSL 1.1 like the rest of the tree, already installed at.claude/skillsand.agents/skillsand loaded automatically. Start atskills/README.md.
The rule that decides whether your answer is right
An absent field means "not sourced". It never means false, none, zero, empty, or
not-applicable. Nothing here carries a placeholder for a value we could not establish first-hand,
so concluding "unfixed" from a missing fix is a confident wrong conclusion drawn from correct
data. A sourced negative looks different and is present on the wire:
poc_signal: {"available": false}.
This corpus underwrites no verdict. Not exploitable, not affected, not safe, not reachable. An assertion built on a field nobody sourced is the failure the honest-absent discipline exists to prevent. Report what is sourced, name what is absent, point at the upstream authority for the rest.