Backpatch VEX feed

Your scanner still flags
a patched CVE.

A backpatch carries the upstream security fix onto the exact release you already run, published as +backpatch.NNN. Your scanner reads the version number, sees the old release, and flags the CVE anyway. This feed is the proof it's already patched.

OpenVEXGrype · Trivy
vex.backpatch.moderne.io/openvex/all.json
CycloneDXXray · Dependency-Track
vex.backpatch.moderne.io/cyclonedx/backpatch-vex.cdx.json

Configure your scanner

Every statement matches by exact package URL. Fetch the feed, wire it in, findings move to suppressed.

Grype

OpenVEX

Also the engine in Anchore Enterprise

Reads local OpenVEX. Fetch the feed, pass it with --vex.

grype
curl -fsSLO https://vex.backpatch.moderne.io/openvex/all.json &&
grype sbom:my-app.cdx.json --vex all.json --show-suppressed

Trivy

OpenVEX

Also the engine in Harbor and GitLab

Point --vex at the file; matching PURLs move to suppressed.

trivy
curl -fsSLO https://vex.backpatch.moderne.io/openvex/all.json &&
trivy sbom my-app.cdx.json --vex ./all.json

JFrog Xray

CycloneDX

Advanced Security (3.136+) ingests external CycloneDX VEX. Enable Skip Not Applicable CVEs, plus one scoped ignore rule per (component, CVE).

jfrog-xray
curl -fsSLO https://vex.backpatch.moderne.io/cyclonedx/backpatch-vex.cdx.json
# Import as an external CycloneDX VEX source, then enable
# the "Skip Not Applicable CVEs" contextual-analysis rule.

Sonatype

CycloneDX

Matches by binary hash — rebuilt backpatches often clear on their own. For a waiver, POST the CycloneDX to the experimental Analysis API.

sonatype-iq
curl -fsSLO https://vex.backpatch.moderne.io/cyclonedx/backpatch-vex.cdx.json &&
curl -u "$IQ_USER:$IQ_TOKEN" -X POST \
  "$IQ_URL/api/experimental/vex/application/$APP_ID/report/$SCAN_ID" \
  --data-binary @backpatch-vex.cdx.json

OWASP Dependency-Track

CycloneDX

Ingests CycloneDX VEX per project. Re-apply after each SBOM upload — or do both in one CI step.

dependency-track
curl -fsSLO https://vex.backpatch.moderne.io/cyclonedx/backpatch-vex.cdx.json &&
curl -X POST https://dtrack.example.com/api/v1/vex \
  -H "X-Api-Key: $DT_API_KEY" \
  -F "project=$PROJECT_UUID" -F "vex=@backpatch-vex.cdx.json"

Verify the feed

Regenerated on every publish, served without caching.

verify
# how many statements are live?
curl -fsS https://vex.backpatch.moderne.io/openvex/all.json | jq '.statements | length'

# confirm a backpatched artifact is cleared
grype my-app.cdx.json --vex all.json --show-suppressed | grep 'suppressed by VEX'

Anatomy of a statement

New to VEX? Here's what these documents say, and why the feed ships two formats.

A scanner reads your SBOM and flags every CVE ever filed against the versions it finds. VEX (Vulnerability Exploitability eXchange) is the other half: a machine-readable statement of whether a CVE actually affects a specific artifact, and what was done about it. Statements in this feed carry one of two statuses: fixed, where we shipped a patch, and not_affected, where the CVE is filed against the baseline but the vulnerable code is not in the artifact we ship.

OpenVEX

OpenSSF · for Grype and Trivy

A minimal, standalone VEX format. Each document is a small JSON file of statements, so CLI scanners read it directly with --vex.

Read the spec →

CycloneDX

OWASP · for Xray, Dependency-Track, auditors

A full SBOM standard that also carries vulnerability and analysis data, and can embed pedigree linking the upstream fix commit as evidence.

VEX in CycloneDX →

A single OpenVEX statement looks like this:

gson-2.8.8+backpatch.001.json
{
  "@context": "https://openvex.dev/ns/v0.2.0",
  "@id": "https://vex.backpatch.moderne.io/openvex/gson-2.8.8+backpatch.001.json",
  "author": "Moderne Backpatch Alliance <support@moderne.io>",
  "timestamp": "2026-07-05T06:53:21Z",
  "version": 1,
  "statements": [
    {
      "vulnerability": { "name": "CVE-2022-25647", "aliases": ["GHSA-4jrv-ppp4-jm57"] },
      "products": [
        {
          "@id": "pkg:maven/com.google.code.gson/gson@2.8.8%2Bbackpatch.001",
          "identifiers": { "purl": "pkg:maven/com.google.code.gson/gson@2.8.8%2Bbackpatch.001" },
          "hashes": { "sha-256": "2575baa2fd678a378998e9c3f238d68bdffe327303c00192401eff3ee570be17" }
        }
      ],
      "status": "fixed",
      "action_statement": "CVE-2022-25647 fixed by backporting the upstream fix onto the 2.8.8 baseline."
    }
  ]
}
vulnerability
The CVE plus its aliases, including the GHSA that Grype keys Java findings on.
products
The exact patched coordinate as a package URL (purl), plus the SHA-256 of the built jar.
status
fixed means a patch for it ships in that baseline. not_affected means it never applied to what we ship.
action_statement
On a fixed statement, a plain-language note on what was done.
justification
On a not_affected statement, the OpenVEX label saying why it does not apply, usually vulnerable_code_not_present. An optional impact_statement spells the same reason out in prose.