A VEX not_affected statement says a vulnerability is present in a component but cannot be exploited in your product. A risk acceptance says the vulnerability can be exploited, and a named person has decided to live with it for a limited time. One is a technical claim. The other is a business decision.
Why teams mix them up
Both end with a finding that stays open in the scanner and does not get a fix right away. That is where the similarity stops. Mixing them up causes two problems. A risk acceptance dressed up as "not affected" tells customers something false. A real not_affected case handled as a risk acceptance burns approver time and creates paperwork that never needed to exist.
Definitions
| Question | VEX not_affected | Risk acceptance |
|---|---|---|
| What does it claim? | The flaw cannot be exploited here | The flaw can be exploited, we accept that |
| Who decides? | Whoever can show the technical facts | A person with authority over the risk |
| What backs it? | A justification, such as code not in the execute path | Impact analysis, compensating controls, a plan |
| Does it expire? | Only when the facts change | Yes, it should have an end date |
| Who sees it? | Often shared with customers | Usually internal, plus auditors |
The OpenVEX specification lists the status values not_affected, affected, fixed and under_investigation. For a not_affected statement it requires either a status justification or an impact statement. The defined justifications are component_not_present, vulnerable_code_not_present, vulnerable_code_not_in_execute_path, vulnerable_code_cannot_be_controlled_by_adversary and inline_mitigations_already_exist.
How to choose
Ask one question first: can an attacker reach the vulnerable behavior in this product, as configured?
- If no, and you can say why in one of the justification forms, write a VEX not_affected statement. Keep the evidence, such as a call graph result or a build configuration.
- If yes, but a fix is not possible yet, you are in risk acceptance territory. Record the impact, the compensating controls, the approver and an expiry date.
- If yes and a fix exists, the default answer is to fix it. Acceptance is for cases where fixing costs more than the risk or cannot happen yet.
The third option in the OpenVEX list, inline_mitigations_already_exist, sits near the boundary. It is still a statement that the flaw cannot be exploited, so it needs evidence that the mitigation is part of the shipped product. A mitigation that lives only in someone's deployment is a compensating control, which belongs in a risk acceptance.
Keep the facts fresh
A not_affected claim can go stale when code changes and the vulnerable function becomes reachable. Tie it to a version of the product and re-check it on each release. A risk acceptance goes stale on a calendar date, so give it one. See how long a vulnerability exception should last for ways to pick it.
Where Safeguard fits
Safeguard runs reachability analysis on dependency findings, which supplies evidence for not_affected decisions, and its policies and gates let you require an approver and expiry when a finding is accepted instead.
Try it yourself
Click through it at your own pace, or open it full screen. Look for the point where a finding turns out to be unreachable, which is the case for not_affected rather than acceptance.
Quick check
Can I use not_affected to hide a vulnerability I just do not want to fix?
No. A not_affected statement is a factual claim that customers and auditors may rely on. If the flaw is exploitable, record a risk acceptance instead.
Does a risk acceptance remove the finding from the scanner?
It should not. The finding stays visible with its status, owner and expiry, so the decision can be reviewed and reversed.
Sources
Last reviewed: 19 October 2026.