Only exploitability facts map to OpenVEX justifications, such as vulnerable code not present or not in the execute path. Risk decisions, like "no fix yet" or "business deferral", are not VEX facts and belong in your exception register, not in a not affected statement.
Two different questions
An exception answers: "do we allow this risk for now?" A VEX statement answers: "is this product affected by this vulnerability?" They overlap only when the reason for the exception is a fact about exploitability. For the wider comparison, see risk acceptance vs VEX not affected.
The OpenVEX specification says a statement with a not affected status must include either a status justification or a free form impact statement. It defines a fixed set of justification labels:
component_not_presentvulnerable_code_not_presentvulnerable_code_cannot_be_controlled_by_adversaryvulnerable_code_not_in_execute_pathinline_mitigations_already_exist
Mapping table
| Internal exception reason | VEX status | Justification label |
|---|---|---|
| Package is not in the shipped artefact | not_affected | component_not_present |
| Affected function removed or patched in a fork | not_affected | vulnerable_code_not_present |
| Input never attacker controlled | not_affected | vulnerable_code_cannot_be_controlled_by_adversary |
| Reachability analysis shows no call path | not_affected | vulnerable_code_not_in_execute_path |
| Built in mitigation prevents exploitation | not_affected | inline_mitigations_already_exist |
| No upstream fix yet | affected, with action statement | none |
| Business deferral | not a VEX fact | keep in the register |
| Compensating control outside the product | not a VEX fact in most cases | keep in the register |
The last two matter. A network control around a product does not change whether the product itself is affected. Calling it not affected misleads the reader.
Where each record lives
Keep the full approval, owner and expiry in the exception register. Publish only the facts others need in a VEX statement. The register may also point to the statement as evidence.
Keep the two in sync
When a not affected statement is published because of reachability, the exception record should reference it. When code changes and the claim is no longer true, both must change. A VEX statement that outlives its evidence is worse than none.
Use timestamps and versions on both, so a consumer can tell which build the claim applies to. The related guide on how to build a VEX document for consumers covers construction.
Pitfalls
- Mapping "accepted risk" to not affected
- Using the free form impact statement when a fixed label fits, which hinders automation
- Leaving a VEX statement in place after upgrading
- Publishing claims for products you have not analysed
Safeguard's reachability analysis produces the kind of evidence behind a not in execute path claim, and its SBOM tooling gives you the component inventory to publish alongside.
Try it yourself
Click through it at your own pace, or open it full screen.
Look at how the check arrives at a verdict, since a VEX justification should rest on the same kind of reasoning.
Quick check
Can I publish a not affected statement for an accepted risk?
No. Accepting a risk means the product is affected and you tolerate it. Keep that in the register.
Is the impact statement a substitute for a label?
It is allowed, but the specification notes it is free form, not machine readable. Prefer a label when one fits.
Sources
Last reviewed: 19 October 2026.