When reachability analysis finds no call path to a vulnerable function, you can record that in a VEX statement with status not_affected and the justification vulnerable_code_not_in_execute_path. The OpenVEX specification requires either a justification label or an impact statement for every not_affected claim, so the reason always travels with the result.
What a VEX statement is
VEX stands for Vulnerability Exploitability eXchange. It lets a supplier tell consumers whether a listed vulnerability actually affects a product. CISA published baseline elements for VEX documents in April 2023. OpenVEX is one format.
The OpenVEX status values are not_affected, affected, fixed and under_investigation.
The five justification labels
For not_affected, the specification lists these labels:
- component_not_present
- vulnerable_code_not_present
- vulnerable_code_not_in_execute_path
- vulnerable_code_cannot_be_controlled_by_adversary
- inline_mitigations_already_exist
Which label fits which reachability result
| Result | Label |
|---|---|
| Package not in the shipped build | component_not_present |
| Package present but the affected function was stripped or never compiled in | vulnerable_code_not_present |
| Function present, no call path found | vulnerable_code_not_in_execute_path |
| Path exists but input cannot be attacker controlled | vulnerable_code_cannot_be_controlled_by_adversary |
| Path exists and a guard blocks the trigger | inline_mitigations_already_exist |
Choosing carefully matters. Writing not in the execute path when the real reason is a guard misleads a consumer.
An example statement shape
{
"vulnerability": { "name": "CVE-0000-00000" },
"products": [ { "@id": "pkg:example/app@1.0.0" } ],
"status": "not_affected",
"justification": "vulnerable_code_not_in_execute_path"
}
The identifiers above are placeholders. Replace them with your real vulnerability and product identifiers, and check the current specification for required fields.
Habits that make VEX trustworthy
- Tie each statement to a dated analysis of a specific build.
- Use under_investigation honestly while you check.
- Revise the statement when the code changes, since it describes one version.
- Do not use not_affected for anything you only suspect.
For the limits of the underlying analysis, see what reachability cannot tell you.
Mistakes to avoid
Do not publish a statement for a product version you did not analyze. Do not copy a justification from an older statement after the code changed. Do not mark everything not affected to clear a customer scan, because the claim carries your name. If you are unsure, under_investigation is the honest status, and you can update it when the analysis is done. A VEX feed with a few careful statements is worth more than a large one nobody trusts.
Quick check
Can I write not_affected without a justification?
The specification says a not_affected statement needs either a justification label or an impact statement, and recommends the label.
Is unreachable the same as not present?
No. Not present means the code is absent from the build. Not in execute path means present but never called.
Safeguard supports dependency scanning and reachability analysis that feed this kind of statement. You can start with a free scan.
Sources
Last reviewed: 19 October 2026.