Safeguard
Supply Chain•

Using VEX not_affected justifications for unreachable code

How to record a reachability result in an OpenVEX statement: the five not_affected justification labels and which one fits code that is never called.

Safeguard Security Team
3 min read

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:

  1. component_not_present
  2. vulnerable_code_not_present
  3. vulnerable_code_not_in_execute_path
  4. vulnerable_code_cannot_be_controlled_by_adversary
  5. inline_mitigations_already_exist

Which label fits which reachability result

ResultLabel
Package not in the shipped buildcomponent_not_present
Package present but the affected function was stripped or never compiled invulnerable_code_not_present
Function present, no call path foundvulnerable_code_not_in_execute_path
Path exists but input cannot be attacker controlledvulnerable_code_cannot_be_controlled_by_adversary
Path exists and a guard blocks the triggerinline_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.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.