ACVE advisory
An ACVE advisory is a JSON document in the OSV 1.6 format with a configuration-aware database_specific.acve extension. The normal OSV fields remain useful to package scanners; ACVE adds the condition under which a configuration is vulnerable. Entries in OSV ecosystems (npm, PyPI, Go, crates.io and the others OSV lists) match in ordinary OSV tools. The ACVE ecosystems below and the ACVE- id prefix are not registered with OSV, so strict OSV schema validation rejects records that use them.
Lifecycle
draft is local work, candidate is reviewable and may produce an unverified finding, published has passed its publication tier's review gates, and withdrawn remains in the registry with a reason. Files are never deleted to hide history. A published record requires structured affected ranges and the evidence for its publication route. A behaviour record is published by one of two routes: a reproduced evaluation (see Behavioural evidence) or, for an incident, incident review (see Incident publication). Incident review replaces OSV grounding and the ADVISORY/FIX reference requirement for behaviour records with occurrence.basis real-use or attempted; every other published record still needs them. The four kinds of rogue or malicious agent event ACVE records, and the CVE and KEV re-posts it leaves out, are defined in [GOVERNANCE.md](../GOVERNANCE.md#editorial-policy).
acve advisory publish <ACVE-ID> [dir] [--tier reported] [--apply] [--json] checks the publication gates before changing a candidate to published. acve advisory withdraw <ACVE-ID> [dir] --reason <text> [--apply] [--json] withdraws a draft, candidate or published record with a timestamp and a ## Withdrawn section in its details. Both commands are dry runs without --apply. The withdrawal reason is 20 to 600 characters, states facts rather than instructions, and contains no control, bidirectional or invisible characters. An already withdrawn record is left unchanged.
Identifiers
ACVE-YYYY-NNNN ids are assigned in sequence within the year and carry no meaning. The number blocks used before 2026-09-25 (02xx evaluations, 03xx model artifacts, 04xx supply chain, 05xx incidents) are historical; a new record takes the next unused number after the highest id of its year, whatever its kind. Ids are never reassigned or renumbered.
Required evidence
Every record has an ACVE id, summary, modified date, affected package/range data, severity, vulnerability classes, a typed fix, and a matcher. The summary is one sentence of at most 200 characters that leads with the harm and its outcome; feed consumers truncate longer text, so anything after 200 characters is lost. CVE/GHSA aliases are optional for ACVE-native weaknesses, but an alias must use its canonical syntax. validatedBy identifies who checked the claim, when, how, and where the evidence lives.
Exposure and reproducibility
database_specific.acve.exposure describes the agent configuration that produces the harm; threat remains for compatibility but is deprecated. harness: product and version range, with any, status, and optional source. model: model name or any, with any, status, and optional source. goal: source-stated task or a general Any ... goal, with stated, status, and optional source. tools: tools, settings, files, and flags, with status and optional source. approval: approval mode and description, with mode, status, and optional source. reach: what the agent could touch, with free-text value, non-empty enumerated kinds, status, and optional source. condition: the one-sentence circumstance under which the behaviour fired, with value, status, and optional source. scale: an optional source-counted scale with a non-empty statement, enumerated unit, non-negative value or null, and HTTPS source. recovery: optional; whether the harm was undone, with value (one sentence: who undid what, and how long it took), outcome (recovered, partially-recovered, unrecovered, or unknown), status, and optional source. Recovery describes the incident, not the configuration, so it never changes severity. inputControl: the party controlling the input, from the enumerated input-control values. agentAction: the one-sentence action the agent takes. harm: the resulting harm category. divergence: whether pursuing the goal diverged, or none when the harm needs no misbehaviour. Every axis has status confirmed, detected, or unconfirmed; confirmed and detected axes require an HTTPS source, and exposure strings are hardened as record data.
harm also permits financial-loss, meaning the agent spent or moved funds, and intrusion, meaning the agent got into a system, account or data store it had no right to reach, such as a real target attacked from an evaluation. Optional firstReported records the first source report as {date, url, publisher}; its date is the date part of published.
Records split into behaviour records when exposure.divergence is present and not none, and flaw records otherwise; in-scope flaw records describe configurations containing known-malicious components. database_specific.acve.occurrence is optional on the schema but required for behaviour records; it states the strength and origin of the account and may record responses from parties that control the harm. real-use = the harmful action reached a real operator, real users, or a real third party's systems, accounts or data outside a test. This includes an agent that was itself running in training or evaluation when it reached a real outside party; inputControl: evaluation shows that origin. attempted = a harmful instruction reached real users but the sources say it did not run. demonstrated = shown by a researcher, vendor or evaluation, with the harm contained in the test environment or falling only on the party running the test. reportedBy = who first gave the account. responses = what the product's maker, or another party that controls the harm such as an infrastructure provider, said or did, from a cited source. Each response has a short party, a status, an optional short statement, and an HTTPS source; real-use also requires top-level firstReported. primary = the first-hand documents behind the account, as {url, kind, party}, where kind is operator-account, agent-transcript, issue-report, vendor-report, provider-statement, registry-statement, or researcher-report, and party names who wrote it. A news article is never a primary; it belongs in references.
A worked exposure, for a Codex CLI configuration:
{
"harness": { "value": "Codex CLI < 0.24.0", "any": false, "status": "confirmed", "source": "https://cveawg.mitre.org/api/cve/CVE-2025-0007" },
"model": { "value": "any", "any": true, "status": "confirmed", "source": "https://cveawg.mitre.org/api/cve/CVE-2025-0007" },
"goal": { "value": "Any task started with codex inside the repository", "stated": false, "status": "detected", "source": "https://cveawg.mitre.org/api/cve/CVE-2025-0007" },
"tools": { "value": ".env setting CODEX_HOME=./.codex and .codex/config.toml mcp_servers", "status": "confirmed", "source": "https://cveawg.mitre.org/api/cve/CVE-2025-0007" },
"approval": { "value": "The configured MCP server runs without a prompt", "mode": "no-prompt-by-design", "status": "confirmed", "source": "https://cveawg.mitre.org/api/cve/CVE-2025-0007" },
"inputControl": "repo-author",
"agentAction": "The agent loads the repository-controlled configuration and runs the configured MCP command.",
"harm": "arbitrary-command",
"divergence": "none"
}
database_specific.acve.reproducibility is written by acve advisory verify and records whether the public configuration, components, trigger, and observable action are sufficient to reproduce the case. It travels in database_specific in the feed alongside exposure.
Incident publication
database_specific.acve.tier is optional, with values confirmed and reported. Absent means confirmed: all existing publication rules remain unchanged. reported is valid only on an incident-route record (behaviour with occurrence.basis real-use or attempted); any other route emits ETIER. A published Reported record is labelled Reported, unverified.
A behaviour record with occurrence.basis real-use or attempted may be published when a reviewer has matched it to first-hand sources. Incident review replaces OSV grounding and the ADVISORY/FIX reference requirement for these records; every other published record still needs them. The rule is:
occurrence.primarycontains the first-hand account of the party inreportedBy: an
operator-account, agent-transcript or issue-report for an operator; a vendor-report, provider-statement or registry-statement for a vendor; a researcher-report for a researcher.
- Every exposure axis present (
harness,model,goal,tools,approval,reach,
condition, recovery) is confirmed, and its source is one of the occurrence.primary URLs. An axis that claims nothing is exempt and may stay unconfirmed: harness or model with any: true, goal with stated: false, and recovery with outcome unknown.
recoveryis present.validatedByhas areviewentry whoseevidenceis one of theoccurrence.primaryURLs.
A response from the product's maker or another party is recorded when one exists, but is not required: a party that stays silent cannot keep a record unpublished. Incident publication means the record matches its first-hand sources. It does not mean anyone reproduced the behaviour.
Reported incidents
A press-sourced incident can publish with tier: "reported" after a person's review, without claiming first-hand confirmation. The following replace EINCIDENT_PRIMARY, EINCIDENT_AXIS and EINCIDENT_REVIEW for this tier:
ERPT_SOURCES: references include URLs from at least two different registrable domains,
using the public suffix list (ICANN section). www and syndication subdomains of one domain count as one publisher; different articles on the same domain also count as one.
ERPT_AXIS: every present exposure axis listed above cites a URL inreferencesor
occurrence.primary, with the same exemptions for any harness/model, an unstated goal, and unknown recovery. Press-sourced axes remain detected or unconfirmed. An axis can be confirmed only when its source is an occurrence.primary URL.
ERPT_REVIEW:validatedByincludesmethod: "review"withevidenceequal to a reference URL.
Recovery remains required (EINCIDENT_RECOVERY), and all other validation rules still apply. News is never a primary source. Party responses, including disputes, remain visible.
acve advisory publish <ACVE-ID> [dir] --tier reported previews this route; --apply writes it. The command adds a review citing the first reference, or a reference selected with --evidence. advisory readiness offers the Reported route for blocked incident candidates, with remaining codes; its JSON adds reported: {tier, ready, blockers, evidence} on those records (and on reported-tier candidates). Readiness anticipates the review entry added by the publish command; it does not itself review or change any record. Nothing is published automatically. advisory readiness [dir] --tier reported selects the Reported gates for its main readiness result and counts, with tier: "reported" in each JSON row; non-incident records return ETIER.
A Reported record moves to confirmed through a reviewed record update: a first-hand account is added to occurrence.primary, the non-exempt axes are confirmed against primary URLs, and a validatedBy review cites a primary URL. Setting tier to confirmed (or removing it) then subjects the published record to every normal incident publication gate above. Adding a report alone does not promote the record; a person reviews every record and tier change.
Claims
database_specific.acve.claims[] records short, checkable statements. Each claim has a kind, statement, status, and method; sourced claims also carry an HTTPS source, and confirmed claims carry checkedAt. confirmed = matches the primary source (CVE record, vendor or GitHub advisory, package registry, or the original researcher's write-up); detected = taken from public reporting with a source link, not yet matched to a primary source; unconfirmed = stated without a source that contains it. A verifier may add result (match, mismatch, unavailable, or unchecked) and observed source text. unavailable means the claim matches its primary source, but the claimed version is not present on the package registry; it is allowed for candidates but a published fixed-version claim must not be unavailable. Published records must confirm their identifier, affected range, fixed version, and severity claims.
Confirmed means the statement matches the cited primary source. Nothing on this page has been reproduced.
installable claims report whether the highest affected npm or PyPI version named by the record is still available from that registry. When an affected range has only a fixed event, verification derives the highest registry version strictly below that fixed version (semver-aware for npm and PEP 440-aware for PyPI), records that version in the claim, and checks it per-version. npm verification confirms the package at /latest and then reads abbreviated metadata with Accept: application/vnd.npm.install-v1+json; PyPI verification reads the releases keys from its JSON metadata. A 200 Hugging Face model response counts only when disabled and gated are absent or false; disabled/gated models and 401/403/404 responses are unobtainable, while 429, 5xx, and transport failures are unknown. For behavioural/configuration records, a discoverable, unbounded harness is obtainable; a named model without a registry reference remains unknown. Unknown components yield partial, not not-reproducible. A reproducible status also requires an EXPLOIT, ARTIFACT, or EVIDENCE reference or a quoted trigger; naming a file in exposure.tools alone is not a published trigger. These claims are informative and never block validation.
spec/known-failures.json lists existing records and structural error codes that are intentionally known while they are corrected. Strict validation still reports those failures; they do not fail CI, but a new failure or a stale entry does.
Record kinds are code, behavioural, and artifact. Artifact model references must be pinned to a Hugging Face revision, Ollama manifest digest, or file SHA-256; an unpinned name is rejected. The exploitation block records exploited-itw, weaponised-poc, demonstrated, or none-known and is shown separately from publication status.
Behavioural evidence
kind defaults to code for legacy records. Behavioural advisories add a threat classification and evidence[]; evaluation evidence carries benchmark version, attack, defence, model identity, harness, permission mode, k, seeds, runner, and an inspectable artefactUrl. Candidate records need an eval or incident with a primary URL. Publication by evaluation needs linked reproduced-eval evidence with at least three seeds (or n >= 3), ci95, a pinned revision/digest, and an artefact URL. Incidents publish by incident review instead.
advisory ground --eval verifies evidence URLs and artefacts, records hashes up to 5 MiB, and never executes an evidence command.
Severity
database_specific.severity has one of three bases, recorded in database_specific.acve.severityBasis:
cvss: the record carries a CVSS vector inseverity[]; severity follows the CNA or OSV score.eval-asr: derived from attacker-budget ASR: CRITICAL at 0.50 or above, HIGH at 0.20,
MODERATE at 0.05, and LOW below 0.05. k=1 values are called out in details.
harm-reach: every other behaviour record. Severity describes what the configuration put
at risk, from exposure.harm and exposure.reach.kinds:
| Severity | Rule | | --- | --- | | CRITICAL | a severe harm and a wide reach | | HIGH | a severe harm, or another harm with a wide reach | | MODERATE | file-read, file-write or harmful-action | | LOW | harm none |
Severe harms are data-loss, financial-loss, credential-theft, data-exfiltration, arbitrary-command, persistence and intrusion. Wide reach kinds are root, production-database, backups, cloud-credentials, payment-method, funds and wallet; network is not wide, because nearly every agent has it. An attempted record, whose harmful instruction did not run, is one level lower (never below LOW). Recovery is shown beside severity and never lowers it: a production database restored from the provider's backups was still deleted.
Framework mappings and control owners
database_specific.acve.taxonomy optionally maps a record to external frameworks: owasp_asi lists OWASP Top 10 for Agentic Applications ids (ASI01 to ASI10), atlas lists MITRE ATLAS technique ids (AML.T0051, AML.T0051.000), and owasp_llm lists OWASP Top 10 for LLM Applications ids (LLM01 to LLM10). Each fix.actions[] entry may name the owner who controls that fix: operator, harness-vendor, model-provider, infra-provider, tool-provider, or package-registry.
Matching
Matchers use explicit element scoping (some or every) for arrays. A condition can inspect a field, compare equality or versions, test membership, a regex, or a hash. Missing values evaluate to unknown, so incomplete lockfiles produce possible findings, never a false clean result. A record without a matcher is informational and is not an automatic audit finding.
Package identities
Use a real OSV ecosystem whenever a component comes from a package manager: npm, PyPI, Go, crates.io or any other ecosystem OSV lists (spec/osv-ecosystems.json), with the package's normal name. VS Code extensions use OSV's VSCode ecosystem with <publisher>.<name>, and VSCode:https://open-vsx.org for Open VSX. Ordinary OSV consumers can then match the component without understanding ACVE.
In the all.zip OSV export, affected entries whose package ecosystem is not listed by OSV (such as AgentHarness, MCP, AgentPlugin, AgentSkill, or Model) move unchanged to database_specific.acve.nonOsvAffected so each exported record validates; the per-record JSON and feed.json keep them in affected.
Use an ACVE ecosystem only when OSV has no package identity:
| Ecosystem | Name rule | | --- | --- | | AgentHarness | Canonical harness id, such as claude-code | | MCP | Official MCP registry name or a stable pkg: identity | | AgentPlugin | <name>@<marketplace>, for plugin marketplaces OSV does not list | | AgentSkill | Stable published skill name | | Model | A family such as llama-3.2, qwen3 or claude-opus-4; Hugging Face pins use hf:<org>/<repo>@<sha> and local pins ollama:<ns>/<model>:<tag>@sha256:… |
An advisory may carry twin npm and MCP affected entries with identical ranges. Ecosystem names are case-sensitive where OSV defines them. ACVE does not change OSV range semantics: SEMVER ranges use their events arrays, ECOSYSTEM uses the ecosystem's rules, and GIT identifies repository history. Model family ranges use ECOSYSTEM events over the family's numeric version tuple; exact pins use versions[].