A CVE record in the CVE Record Format is JSON with a cveMetadata block and a containers block. The CNA container holds what the assigning organization published. ADP containers hold enrichment added by other authorized parties. A severity score may sit in an ADP container, so tools that read only the CNA part can miss it.
The shape of a record
The format is defined by a JSON schema maintained in the CVE Project's cve-schema repository, which was formerly called the CVE Schema. The main branch is described as the current production version used by CVE Services.
To see a real record, I fetched one from the public CVE Services API for CVE-2021-44228, a well known Apache Log4j2 issue. The top level held a data type of CVE_RECORD and a data version of 5.1. The metadata block listed state, cveId, assigner organization ID, assigner short name, and date fields for reserved, published and updated.
The two kinds of container
| Container | Written by | Typical contents |
|---|---|---|
| cna | The CVE Numbering Authority that assigned the ID | Title, descriptions, affected products, references, credits, problem types |
| adp | An Authorized Data Publisher | Added metrics, references, timeline, and other enrichment |
In the record I fetched, the cna container had affected, credits, descriptions, metrics, problemTypes, providerMetadata, references, source, title and an x_generator field. There were two ADP containers. One came from the CVE program itself and added a title and references. The other came from CISA and added metrics, references and a timeline.
Where the severity was
This is the lesson for tool builders. In that record the CNA metrics entry was a generic other metric holding the text critical, not a CVSS vector. The CVSS 3.1 vector, with a base score of 10 and the vector string, was in the CISA ADP container. The CISA container also carried an SSVC decision entry.
So a parser that read only the CNA container would see no CVSS score for this well known record. A parser that merged all containers would find one. Always read every container and keep the provider name with each metric, so you can explain where a number came from.
How affected versions are written
The affected entry names a vendor, a product, and a list of versions. Each version has a status, and can have a lessThan field and a list of changes that mark where status flips between affected and unaffected. In the fetched record, the changes list moved from unaffected to affected and back across several release lines before ending at the fixed release.
That is more detailed than a simple range, and it is why you should not collapse it to one number. Keep the changes list and evaluate it in order.
A checklist for ingesting CVE records
- Read dataVersion, and fail clearly on a version you do not support.
- Read the state. Do not process a record whose state is not published without a reason.
- Loop over the cna container and every adp container.
- Store the provider short name with each metric.
- Prefer a vector string over a bare score so you can recompute and audit it.
- Keep the affected changes list intact.
- Treat missing metrics as unknown, not as zero.
Try it yourself
Click through it at your own pace, or open it full screen. Watch how a new record appears first and how details can arrive later from other sources.
Where this fits
Records change after publication, which is why scoring and enrichment can lag. See CISA's CVE record quality push. Safeguard offers zero day discovery and dependency scanning, and the free scan is a way to see matches on a real project.
Quick check
Is the CVSS score always in the CNA container?
No. In the record I fetched for CVE-2021-44228, the CVSS vector came from an ADP container. Read all containers.
What is an ADP?
An Authorized Data Publisher, an organization that adds enrichment to a record without being the assigning CNA.
Sources
Last reviewed: 19 October 2026.