This repository maintains canonical conda-forge package identity mappings. Each mapping record is keyed by conda-forge package name and carries identifiers that downstream security tooling can use:
- a primary Package URL (PURL) and optional alternative PURLs
- optional CPE 2.3 vendor/product prefixes for NVD matching
- package context such as latest observed version, recipe/source URLs, summary, and download counts
CVE assignment, OpenVEX review state, AI CVE drafts, and SBOM-derived findings are intentionally out of scope. A downstream CVE project should consume the identity mapping payload produced here, enumerate conda-forge versions there, and join those versions with OSV/NVD affected-version data there.
The core object is a conda-forge package identity record:
{
"name": "ncurses",
"version": "6.5",
"purl": "pkg:github/ThomasDickey/ncurses-snapshots",
"type": "github",
"namespace": "ThomasDickey",
"pkg_name": "ncurses-snapshots",
"alternative_purls": [],
"cpes": [
"cpe:2.3:a:gnu:ncurses",
"cpe:2.3:a:invisible-island:ncurses"
],
"status": "verified",
"identities": [
{
"kind": "purl",
"role": "primary",
"value": "pkg:github/ThomasDickey/ncurses-snapshots",
"provenance": {
"availability": "available",
"source": "manual",
"review": {
"status": "verified",
"reviewer": "nichmor",
"reviewed_at": "2026-05-25T00:00:00Z"
}
}
},
{
"kind": "cpe",
"role": "associated",
"value": "cpe:2.3:a:gnu:ncurses",
"provenance": { "availability": "unavailable" }
}
]
}PURLs identify source/package ecosystem coordinates. CPEs identify NVD vendor/product coordinates. CPE strings stored here are identity-level prefixes; this repository does not store CVE affected ranges or per-CVE version decisions.
The generated payload's identities array is the authoritative per-identity
view for downstream consumers:
kind: "purl", role: "primary"identifies the primary PURL. Its provenance contains a required reviewstatus, a nullablereviewer, and an optionalreviewed_at. Automatic primary identities additionally retain their available confidence and source evidence.kind: "purl", role: "alternative"identifies an alternative PURL. Detailed alternatives retain their ownsourceandconfidence; bare string alternatives useavailability: "unavailable". They never inherit the primary PURL's review object.kind: "cpe", role: "associated"identifies a CPE prefix. The current source model does not retain CPE-level attribution, so its provenance is explicitlyunavailableand never inferred from primary review state.
Identity order is deterministic: primary PURL, alternatives in source order,
then CPEs in source order. A missing primary PURL produces no primary identity.
Every published confidence is a finite JSON number; NaN and infinities are
rejected. Contribution precedence compares timezone-aware timestamps as UTC
instants, with the on-disk filename as the deterministic tie-breaker.
| Path | Purpose |
|---|---|
mappings/auto.json |
automatically inferred PURL mappings |
mappings/manual.json |
legacy/manual reviewed overrides |
mappings/contributions/*.json |
PR-submitted mapping contributions, including CPE pipeline output |
mappings/cpe_candidates/*.json |
audit output from CPE discovery |
mappings/cpe_vet/*.json |
optional AI tiebreaker output for ambiguous CPE candidates |
web/public/mappings.json |
generated full mapping bundle |
web/public/mappings-index.json |
generated compact index for the web app |
web/public/mapping_packages/*.json |
generated sharded package detail payloads |
PFX-1826 advances mappings.json from schema 1 to 2,
mappings-index.json from schema 2 to 3, and mapping detail shards from
schema 1 to 2. These versions add identities without removing or changing
legacy purl, alternative_purls, cpes, status, or attribution fields.
This additive compatibility window lets existing clients continue reading the
legacy fields while provenance-aware clients migrate to identities. New
clients should reject unknown future schema versions rather than guessing.
The validator accepts the immediately preceding schemas during this window but
requires and validates the per-identity contract on current schemas.
The payload deployed by the Pages workflow is canonical. The checked-in
mappings-index.json and shard files are build inputs/cache for the app, not a
supported raw-consumer contract on their own: a source change can leave them
stale until mappings:merge regenerates the bundle, index, and all shards
atomically. Consumers should use the deployed Pages payload rather than mixing
checked-in generations. Routine changes should not commit the 257-file shard
churn unless repository policy explicitly requires an atomic generated-data
refresh.
flowchart TD
A[conda-forge metadata] --> B[scripts.automap]
B --> C[mappings/auto.json]
C --> D[scripts.merge_mappings]
E[mappings/manual.json] --> D
F[mappings/contributions/*.json] --> D
D --> G[web/public/mappings*.json]
G --> H[PURL editing UI]
H --> I[Worker POST /api/submit]
I --> F
Useful commands:
pixi run purl:automap --only numpy,ripgrep,pandas
pixi run -e lite mappings:merge
pixi run -e lite mappings:validate
pixi run purl:testCPE discovery is part of identity mapping, not CVE assignment. The retained CPE
pipeline proposes NVD vendor/product prefixes and promotes accepted mappings as
normal contribution files. Those CPEs then flow through scripts.merge_mappings
into the public mapping payload.
CPE list behavior is intentionally unchanged: a contribution containing cpes
replaces the prior list. Changing that to union semantics could make explicit
UI/pipeline removals impossible, so PFX-1826 does not silently change it. A
separate follow-up should decide whether CPE contributions need an explicit
replace/union operation before any union behavior is introduced.
flowchart TD
A[mappings/auto.json + reviewed mappings] --> B[scripts.cpe_discover]
B --> C[mappings/cpe_candidates/*.json]
C --> D[scripts.cpe_vet optional]
D --> E[mappings/cpe_vet/*.json]
C --> F[scripts.cpe_promote]
E --> F
F --> G[mappings/contributions/*--cpe-pipeline--*.json]
G --> H[scripts.merge_mappings]
Useful commands:
pixi run cpe:discover --top 50
pixi run cpe:vet --dry-run
pixi run cpe:promote --dry-run
pixi run -e lite mappings:merge
pixi run -e lite mappings:validateThe GitHub Pages app is a PURL editing UI:
- users can review, edit, approve, or mark PURL mappings as unmapped
- staged PURL edits are saved locally until submitted
- submitted edits open PRs containing one new file under
mappings/contributions/ - CPEs are displayed read-only as package identity metadata
- no CVE dashboard, OpenVEX review, AI CVE queue, or deep-inspection routes are served from this repository
The Worker exposes only:
POST /exchangefor GitHub OAuth code exchangePOST /api/submitfor PURL mapping contribution PRs
A downstream CVE project should consume web/public/mappings.json or the split
mappings-index.json + mapping_packages/*.json payload. It should then:
- enumerate conda-forge package versions independently,
- use PURLs for OSV/package-ecosystem matching,
- use CPE prefixes for NVD matching,
- apply OSV/NVD affected-version logic in that downstream project, and
- store CVE assignment/review state outside this repository.
Run these checks before opening a PR:
pixi run -e lite mappings:merge
pixi run -e lite mappings:test
pixi run -e lite mappings:validate
pixi run app:checkFor frontend/Worker-only checks:
cd web && npm run build
cd worker && npm run typecheck