The most dangerous field in a VEX document is the one filled in by a default.
When you generate VEX at scale, most findings are genuinely undecided. The scanner flags a CVE in a transitive dependency, and nobody has yet traced whether the vulnerable code path is reachable from your entry points. That is not a bug in the process. That is the normal state of a queue that is longer than the day.
The temptation is to make it disappear. Unknown reachability becomes not_affected, the document goes green, and the pipeline stops complaining.
But not_affected is an assertion. It says a human or a tool examined this and concluded the vulnerable function is never called. If nobody did that, the document is now carrying a judgement that does not exist anywhere in your organisation. The consumer downstream cannot tell the difference between analysis and a default value. That is how a compliance artifact turns into a liability.
I built vexdesk (github.com/polycratia/vexdesk) around the opposite rule: an undecided finding is emitted as under_investigation, never quietly resolved. The status is uncomfortable to look at, and that is the point. It puts real work on a real queue instead of hiding it behind a green field.
I have made the same trade before in payment reconciliation. When an incoming payment cannot be matched to an obligation with confidence, you do not attach it to the closest plausible account. You flag it as unmatched and let a human decide. The unmatched pile is ugly, it is visible, and it is honest. Every system I have seen that auto-guessed instead ended up with balances that were silently wrong for months.
The general principle: a system should never manufacture certainty it was not given. "I do not know yet" is a legitimate output, and an artifact that cannot express it will lie by omission.
For anyone generating VEX or SBOM attestations in CI — how do you keep the under_investigation pile from becoming a permanent parking lot?