Publish every advisory as a readable web page and in the machine-readable formats your customers' tools consume. Get a CVE ID from the CNA whose scope covers the product, and publish the CVE record with affected and fixed versions, a CWE and a CVSS vector. For enterprise customers, publish a CSAF 2.0 document, using the VEX profile to state which products are affected, fixed or not affected and why, and list it through provider-metadata.json and security.txt. For open-source packages, publish a GitHub security advisory or an OSV record so package scanners match it. CSAF 2.1 was still a committee draft in October 2026, so emit 2.0.
- Do give exact affected and fixed versions per product and branch; vague ranges cause both missed patches and false alarms.
- Do publish CSAF 2.0 and validate every document with the schema and the mandatory tests before release; 2.1 is not final.
- Do back every
known_not_affectedstatus with a flag or an impact statement, and everyknown_affectedstatus with a remediation. - Do put a CWE and a CVSS vector in the CVE record, and publish the record within 72 hours of disclosing the ID, as the CNA rules require.
- Don't hand-edit advisories in three places: generate the web page, CVE record, CSAF and OSV from one case record.
| Setting | Value | Note | Source |
|---|---|---|---|
| CSAF version to emit | 2.0 | CSAF 2.1 is at Committee Specification Draft 03 (11 September 2026), not an OASIS Standard. | OASIS CSAF TC |
| CSAF 2.0 score types | cvss_v2 and cvss_v3 (3.0 and 3.1) | CSAF 2.0 cannot carry a CVSS 4.0 score; the 2.1 draft adds it, with EPSS and SSVC. | — |
| VEX profile category | csaf_vex | — | CSAF 2.0, section 4.5 |
| Provider metadata location | /.well-known/csaf/provider-metadata.json, and a CSAF: line in security.txt | — | CSAF 2.0, requirements 8 and 9 |
| CVE record after disclosure | Should within 24 hours; must within 72 hours | — | CNA Operational Rules 4.2.0 |
| CVE Record Format | 5.2.0 (released 29 October 2025) | — | CVEProject/cve-schema |
| OSV schema | 1.9.1 (24 September 2026) | IDs need a registered database prefix such as GHSA, or x_ for a local database. | OSV schema |
- Validate each CSAF document against the OASIS schema and run the mandatory tests (for example with csaf-validator-lib or the gocsaf
csaf_validator) in CI before publishing. - Run the gocsaf
csaf_checkeragainst your domain to confirmprovider-metadata.json, thesecurity.txtCSAF line and the directory or ROLIE feed are found. - Fetch your last three CVE records from the CVE Services API and check affected and fixed versions, CWE and CVSS vector against the advisory.
- Scan a vulnerable and a fixed version of your open-source package with OSV-Scanner and confirm only the vulnerable one is reported.
- Pick a
known_not_affectedstatement and confirm the flag or impact statement still holds for the current build.
- Applies to
- CSAF 2.0 OASIS Standard (18 November 2022); 2.1 at Committee Specification Draft 03 (11 September 2026)
- CVE Record Format 5.2.0
- OSV schema 1.9.1
- Validation Ajv 8 with the OASIS and FIRST schemas; @secvisogram/csaf-validator-lib 3.0.0 mandatory and optional tests (all passed)
Vendors and open-source maintainers who publish vulnerability information about their own products. For consuming and judging VEX from suppliers, see the VEX decisions guide.
- Part of
- Workflow: Respond to a vulnerability
Tested fixes: the vulnerable code, the fix, a plausible fix that still fails, and the regression tests that tell them apart.
Learning goals and prerequisites
What you will learn
- List what an advisory must say and which format each audience reads.
- Write and validate a CSAF 2.0 VEX document with correct statuses, flags and remediations.
- Publish CSAF provider metadata so tools can find your documents.
- Get CVE IDs through a CNA and publish OSV records for open-source packages.
Before you start
PSIRT members, product security engineers and open-source maintainers who publish vulnerability information
- Know your products, supported versions and how fixes are released.
- Read a JSON document and a CVSS vector.
- For validation: Node.js with Ajv or csaf-validator-lib.
Refresh first: Run coordinated vulnerability disclosure from report to advisory
Go to the guided practiceA customer reading an advisory needs to answer three questions quickly: am I affected, what do I do, and how urgent is it. The FIRST PSIRT Services Framework's advisory template lists title, summary, CVE IDs, supported product impact and status, acknowledgement, references and revision history. Add the details that make the answer unambiguous.
- Affected products and exact version ranges per branch, and the first fixed version on each branch.
- Products and versions confirmed not affected, with the reason, so customers stop asking.
- Severity as a CVSS vector with its version, not only a number or a word.
- Whether exploitation is known, and since when.
- The fix, any workaround or mitigation, and how to tell whether a system has been attacked if you know.
- Identifiers (CVE, your advisory ID, related GHSA or vendor IDs), the CWE, credit to the finder, and a revision history with dates.
Publish the human page and the formats each audience's tools read. Generate them all from one case record, such as the one in /domains/appsec/vulnerability-response/psirt-operating-model/, so versions and statuses cannot drift between them.
| Format | Who reads it | Where it goes |
|---|---|---|
| Web advisory | People: customers, support, press | Your security advisories page |
| CVE record | Every scanner and vulnerability database, NVD, CISA ADP enrichment | The CVE List, through your CNA |
| CSAF 2.0 advisory or VEX document | Enterprise customers, CERTs, vendor-management and asset tools that read CSAF | Your CSAF provider directory or ROLIE feed |
| OSV record or GitHub security advisory | Package scanners (OSV-Scanner, Dependabot and others) for open-source packages | GitHub Advisory Database or the ecosystem's OSV database |
| OpenVEX or CycloneDX VEX | Container and SBOM scanners that consume VEX | Alongside images or SBOMs; see /domains/supply-chain/vex/producer-and-consumer-decisions/ |
The Common Security Advisory Framework is an OASIS standard JSON format for security advisories. CSAF 2.0 became an OASIS Standard on 18 November 2022. A document has three parts: document (publisher, tracking, notes, references, distribution), product_tree (the products, usually as vendor, product name and version branches, each with a product ID) and vulnerabilities (identifiers, CWE, notes, product statuses, remediations, scores and flags). Five profiles set extra rules by document.category: csaf_base, csaf_security_incident_response, csaf_informational_advisory, csaf_security_advisory and csaf_vex.
CSAF 2.1 is not final. Its latest stage on docs.oasis-open.org is Committee Specification Draft 03, dated 11 September 2026, after drafts in May 2025 and February 2026. The draft adds, among other things, CVSS 4.0 scores, EPSS and SSVC data, and profiles for withdrawn and superseded documents. Publish 2.0 documents now, and test 2.1 support in tooling such as csaf-validator-lib, whose 2.1 checks are marked experimental. A practical consequence: CSAF 2.0 can carry CVSS 2.0, 3.0 and 3.1 scores but not CVSS 4.0, so put the 4.0 vector, which /tools/cvss-calculator/ can score, in the CVE record and the web advisory.
CSAF's product_status lists products by their relation to the vulnerability. The VEX profile requires at least one of fixed, known_affected, known_not_affected or under_investigation, a CVE or other ID, and notes. It adds two rules that make the document actionable: every known_not_affected product needs a machine-readable flag or an impact statement explaining why it cannot be exploited, and every known_affected product needs a remediation as an action statement, where no_fix_planned and none_available are allowed.
- CSAF 2.0 flag labels for not-affected products:
component_not_present,vulnerable_code_not_present,vulnerable_code_cannot_be_controlled_by_adversary,vulnerable_code_not_in_execute_pathandinline_mitigations_already_exist. - OpenVEX uses the same five justifications; CycloneDX has its own nine. Keep the original label when converting.
- A not-affected claim is a statement about one product version and build; re-check it when the build changes.
| Status | Use it when | What CSAF requires with it |
|---|---|---|
known_affected | The product version contains the vulnerability and it can be exploited | A remediation: vendor_fix, workaround, mitigation, no_fix_planned or none_available |
fixed | The version contains the fix | Nothing more; name the fixed version precisely |
known_not_affected | The version is not exploitable | A flag (below) or a threats entry of category impact explaining why |
under_investigation | You do not know yet | Update the document when you do; customers will treat it as possibly affected |
The document below describes a fictional missing-authentication flaw in Kestrel Agent 5.2.2 and 5.2.3, fixed in 5.2.4, and states that Kestrel Console is not affected because it does not contain the component. It uses the csaf_vex profile, the ids field for the vendor's own advisory ID (add "cve" once a CVE ID is assigned), a CPE for each product, a CVSS 3.1 vector with its computed score, a vendor fix and a workaround, and a canonical self reference whose file name follows CSAF's naming rule (lower-case tracking ID plus .json). Keys are sorted, as CSAF's optional test 6.2.13 recommends.
Validation: the document passes the OASIS CSAF 2.0 JSON schema with the referenced FIRST CVSS schemas under Ajv 8, and passes all mandatory tests and all optional tests in @secvisogram/csaf-validator-lib 3.0.0 with no errors or warnings.
{
"document": {
"category": "csaf_vex",
"csaf_version": "2.0",
"distribution": {
"tlp": {
"label": "WHITE"
}
},
"lang": "en",
"notes": [
{
"category": "summary",
"text": "The Kestrel Agent management API accepts configuration changes without authentication in versions 5.2.2 and 5.2.3. Version 5.2.4 fixes it. Kestrel Console does not include the agent and is not affected."
}
],
"publisher": {
"category": "vendor",
"name": "Kestrel (example)",
"namespace": "https://kestrel.example"
},
"references": [
{
"category": "self",
"summary": "Canonical URL",
"url": "https://kestrel.example/.well-known/csaf/white/2026/ksa-2026-007.json"
},
{
"category": "self",
"summary": "Human-readable advisory",
"url": "https://kestrel.example/security/advisories/KSA-2026-007"
}
],
"title": "Kestrel Agent: unauthenticated configuration change",
"tracking": {
"current_release_date": "2026-10-10T09:00:00.000Z",
"id": "KSA-2026-007",
"initial_release_date": "2026-10-10T09:00:00.000Z",
"revision_history": [
{
"date": "2026-10-10T09:00:00.000Z",
"number": "1",
"summary": "Initial release."
}
],
"status": "final",
"version": "1"
}
},
"product_tree": {
"branches": [
{
"branches": [
{
"branches": [
{
"category": "product_version",
"name": "5.2.2",
"product": {
"name": "Kestrel Agent 5.2.2",
"product_id": "CSAFPID-0001",
"product_identification_helper": {
"cpe": "cpe:2.3:a:kestrel:agent:5.2.2:*:*:*:*:*:*:*"
}
}
},
{
"category": "product_version",
"name": "5.2.3",
"product": {
"name": "Kestrel Agent 5.2.3",
"product_id": "CSAFPID-0002",
"product_identification_helper": {
"cpe": "cpe:2.3:a:kestrel:agent:5.2.3:*:*:*:*:*:*:*"
}
}
},
{
"category": "product_version",
"name": "5.2.4",
"product": {
"name": "Kestrel Agent 5.2.4",
"product_id": "CSAFPID-0003",
"product_identification_helper": {
"cpe": "cpe:2.3:a:kestrel:agent:5.2.4:*:*:*:*:*:*:*"
}
}
}
],
"category": "product_name",
"name": "Kestrel Agent"
},
{
"branches": [
{
"category": "product_version",
"name": "2026.10",
"product": {
"name": "Kestrel Console 2026.10",
"product_id": "CSAFPID-0004",
"product_identification_helper": {
"cpe": "cpe:2.3:a:kestrel:console:2026.10:*:*:*:*:*:*:*"
}
}
}
],
"category": "product_name",
"name": "Kestrel Console"
}
],
"category": "vendor",
"name": "Kestrel"
}
]
},
"vulnerabilities": [
{
"cwe": {
"id": "CWE-306",
"name": "Missing Authentication for Critical Function"
},
"flags": [
{
"label": "component_not_present",
"product_ids": [
"CSAFPID-0004"
]
}
],
"ids": [
{
"system_name": "Kestrel PSIRT",
"text": "KSA-2026-007"
}
],
"notes": [
{
"category": "description",
"text": "The agent's local management API on port 9443 did not require a token for PUT /config, so any host that could reach the port could change the agent's configuration."
}
],
"product_status": {
"fixed": [
"CSAFPID-0003"
],
"known_affected": [
"CSAFPID-0001",
"CSAFPID-0002"
],
"known_not_affected": [
"CSAFPID-0004"
]
},
"remediations": [
{
"category": "vendor_fix",
"details": "Upgrade to Kestrel Agent 5.2.4 or later.",
"product_ids": [
"CSAFPID-0001",
"CSAFPID-0002"
],
"url": "https://kestrel.example/downloads/agent/5.2.4"
},
{
"category": "workaround",
"details": "Until you upgrade, block inbound connections to port 9443 except from localhost.",
"product_ids": [
"CSAFPID-0001",
"CSAFPID-0002"
]
}
],
"scores": [
{
"cvss_v3": {
"baseScore": 9.8,
"baseSeverity": "CRITICAL",
"vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
"version": "3.1"
},
"products": [
"CSAFPID-0001",
"CSAFPID-0002"
]
}
]
}
]
}CSAF 2.0 defines distribution roles. A CSAF publisher makes valid documents available over TLS with the right file names. A CSAF provider also publishes a provider-metadata.json file, advertises it through at least one of a CSAF: line in security.txt, the well-known path /.well-known/csaf/provider-metadata.json or a DNS name, and offers either a directory layout with one folder per year, index.txt and changes.csv, or ROLIE feeds. A CSAF trusted provider adds hashes, OpenPGP signatures and a published public key. Aggregators and listers collect documents from many providers.
Start as a provider with the directory layout; it is static files. Add CSAF: https://kestrel.example/.well-known/csaf/provider-metadata.json to your security.txt (see /domains/appsec/vulnerability-response/vdp-bug-bounty-pentest/). The gocsaf project's csaf_checker tests a domain against these requirements, and its csaf_provider and csaf_aggregator tools implement the roles. The metadata file below validates against the OASIS provider schema.
{
"canonical_url": "https://kestrel.example/.well-known/csaf/provider-metadata.json",
"distributions": [
{"directory_url": "https://kestrel.example/.well-known/csaf/white/"}
],
"last_updated": "2026-10-10T09:00:00.000Z",
"list_on_CSAF_aggregators": true,
"metadata_version": "2.0",
"mirror_on_CSAF_aggregators": true,
"publisher": {
"category": "vendor",
"name": "Kestrel (example)",
"namespace": "https://kestrel.example"
},
"role": "csaf_provider"
}Ask the CVE Numbering Authority whose scope covers the product. If your organization is a CNA, assign it yourself; if a vendor whose product you build on is a CNA, it may own the ID; for open-source projects on GitHub, GitHub is a CNA and assigns IDs from a repository security advisory unless another CNA covers the project; otherwise use a CNA of last resort. /domains/appsec/vulnerability-response/psirt-operating-model/ covers becoming a CNA.
Under CNA Operational Rules 4.2.0, a record must name at least one affected product, state a problem type (preferably a CWE), include a description and at least one public reference, and should list fixed versions. Records use the CVE Record Format, version 5.2.0 since October 2025, and CISA may add SSVC, KEV and other data through its ADP container. The CVSS 4.0 vector you put in the CNA container is what downstream tools read now that NVD no longer scores every CVE; see /frameworks/vulnerability-prioritization/.
Package scanners match vulnerabilities by ecosystem, package name and version, which is what OSV records describe. The simplest route for a GitHub-hosted project is a repository security advisory, which gets a GHSA ID; GitHub reviews published advisories for supported ecosystems for the GitHub Advisory Database, which OSV.dev imports. Some ecosystems run their own OSV databases, such as the Go vulnerability database, the PyPA advisory database and RustSec. If you publish OSV yourself outside those databases, the schema requires a registered ID prefix or x_ for a local database.
The record below validates against OSV schema 1.9.1. Unlike CSAF 2.0, OSV can carry a CVSS 4.0 vector; the vector shown scores 8.7. The ranges events say every version from 3.1.0 up to, but not including, 3.4.2 is affected.
{
"schema_version": "1.9.1",
"id": "x_KESTREL-2026-0001",
"modified": "2026-10-10T09:00:00Z",
"published": "2026-10-10T09:00:00Z",
"summary": "Signature check skipped for webhook payloads with an empty signature header",
"details": "In @kestrel-example/sdk 3.1.0 to 3.4.1, `verifyWebhook()` returned true when the `Kestrel-Signature` header was present but empty. Upgrade to 3.4.2.",
"severity": [
{
"type": "CVSS_V4",
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N"
}
],
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "@kestrel-example/sdk",
"purl": "pkg:npm/%40kestrel-example/sdk"
},
"ranges": [
{
"type": "SEMVER",
"events": [{"introduced": "3.1.0"}, {"fixed": "3.4.2"}]
}
]
}
],
"references": [
{"type": "ADVISORY", "url": "https://kestrel.example/security/advisories/KSA-2026-008"},
{"type": "FIX", "url": "https://github.com/kestrel-example/sdk/commit/0000000000000000000000000000000000000000"}
],
"database_specific": {"cwe_ids": ["CWE-347"]}
}- Keep one case record per vulnerability with products, versions, statuses, CWE, vectors and dates.
- Generate the web page, CVE record, CSAF document and OSV record from it in CI.
- Validate: CSAF schema plus mandatory tests, OSV schema, CVE record schema; fail the build on any error.
- Publish the CVE record and the advisory together, and in any case within the CNA rules' 72 hours of disclosing the ID.
- On any change, bump the CSAF
tracking.version, add a revision history entry and updatemodifiedin OSV. - Re-run
csaf_checkeragainst your domain after each release of the provider files.
- Writing "versions before 5.3" when 5.2.4 on a maintenance branch is already fixed: scanners flag patched systems.
- Marking products
known_not_affectedwith no flag or impact statement, which breaks the VEX profile and leaves customers guessing. - Emitting CSAF 2.1 drafts to customers whose tools only read 2.0.
- Publishing CVSS numbers without vectors, or a CVSS 4.0 score where the format expects 3.1.
- Leaving the CVE record reserved but unpublished after the advisory is out.
- Fixing a mistake in the web page but not in the CSAF, CVE and OSV records.
Guided practice
Kestrel (fictional) fixed a path traversal in its log export API. Review the draft advisory data, decide each product's VEX status, and list what must change before the CSAF document and CVE record can be published.
Supplied scenario material
Draft advisory data (fictional):
Title: "Log export path traversal"
Products: Kestrel Agent 5.2.4 and 5.2.5 (vulnerable), 5.2.6 (fixed); Agent 4.9.x LTS branch: "probably not affected"; Kestrel Console 2026.10: export API not shipped in Console
Severity: "9.1 critical" (no vector)
CWE: none recorded
Planned CSAF: csaf_version "2.1", category "csaf_vex", score cvss_v4 "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N"
CVE: reserved by Kestrel's CNA on 2026-10-01; advisory planned for 2026-10-14; CVE record publication "when we have time"
security.txt: no CSAF line1. Assign statuses
Give each product a CSAF status and what it needs.
Expected result and reasoning
Agent 5.2.4 and 5.2.5:
known_affectedwith avendor_fixremediation pointing to 5.2.6. Agent 5.2.6:fixed. Console 2026.10:known_not_affectedwith flagcomponent_not_present. Agent 4.9.x:under_investigationuntil someone checks; "probably" is not a status.2. Fix the version choice
What is wrong with
csaf_version"2.1"andcvss_v4?Expected result and reasoning
CSAF 2.1 is a committee draft, so publish 2.0. CSAF 2.0 has no
cvss_v4; include a CVSS 3.1 vector in the CSAF document if you have one, and put the 4.0 vector in the CVE record and the web advisory.3. Complete the record
What must the CVE record contain, and when must it be published?
Expected result and reasoning
At least one affected product with versions, the CWE (CWE-22 for path traversal), a description and a public reference; fixed versions should be listed. Publish it with the advisory on 2026-10-14, and in any case within 72 hours of disclosing the ID.
4. Make it findable
What do customers' tools need to discover the CSAF document?
Expected result and reasoning
A
provider-metadata.jsonat/.well-known/csaf/, aCSAF:line insecurity.txtpointing to it, the document under the year folder with a lower-case file name from the tracking ID, andindex.txtandchanges.csvupdated; then runcsaf_checker.5. Validate before release
Which checks run in CI?
Expected result and reasoning
The CSAF 2.0 schema with CVSS schemas, the mandatory tests (6.1.x), the CVE record schema, and a diff of versions and statuses between the case record and every generated format.
Kestrel and its products are fictional. CSAF 2.1 may become final after October 2026; check docs.oasis-open.org before choosing a version.
Save a draft on this device to resume later. Automatic saving begins after you choose Save. Drafts are never sent by this application; use synthetic data.
No draft saved on this device yet.
Sources & further reading
The standards, specifications and documentation behind the guidance above. Each is the evidence for a claim on this page; consult it for detail beyond the defaults and versions listed here.
- OASIS: Common Security Advisory Framework Version 2.0 (OASIS Standard). 18 November 2022.
- OASIS: CSAF Version 2.1, latest stage (Committee Specification Draft 03). 11 September 2026.
- OASIS: CSAF 2.0 JSON schemas
- secvisogram/csaf-validator-lib
- gocsaf/csaf: provider, checker, validator and aggregator tools
- CVE Program: CNA Operational Rules 4.2.0. Effective 25 August 2026.
- CVEProject/cve-schema: CVE Record Format 5.2.0. 29 October 2025.
- Open Source Vulnerability format (OSV schema). Version 1.9.1 (24 September 2026).
- GitHub Docs: repository security advisories
- CISA: Minimum Requirements for Vulnerability Exploitability eXchange (VEX). 21 April 2023.