How precise should an advisory's affected range be when the flaw needs an optional feature enabled?
answer
- the range describes code, not exposure
- no version number encodes a config flag
- precondition goes in the text
- introduced zero condemns everything
- one entry per package coordinate
basics
~20 sA version range answers 'which builds contain the vulnerable code', not 'who can be hurt by it'. Keep it accurate to the code, and put the configuration precondition in the advisory text and structured fields beside the range.
solid answer
~50 sDo not narrow the range to exclude consumers who never enabled the feature - a range is a statement about shipped code, and there is no version number that means 'only if you registered the optional handler'. Trimming it hides the flaw from exactly the consumers who did enable it. The correct shape is a range that starts at the release where the vulnerable path first shipped and ends at the first patched release on each line, plus an explicit, prominent precondition: which setting, which handler, which non-default mode. Ecosystem-specific fields and the detail text are where that lives. The opposite error costs as much: `introduced: 0` with no fixed version buries every consumer in findings they cannot act on and teaches them to ignore you. Give an accurate range plus a precise precondition, and let each consumer decide whether their deployment is exposed.
code
json · 17 lines{
"package": {
"ecosystem": "NuGet",
"name": "Example.Auth",
"purl": "pkg:nuget/Example.Auth"
},
"ranges": [
{ "type": "ECOSYSTEM",
"events": [ { "introduced": "3.1.0" }, { "fixed": "3.4.2" } ] }
],
"ecosystem_specific": {
"precondition": "reachable only when the optional passthrough handler is registered"
},
"severity": [ { "type": "CVSS_V3",
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N" } ]
...
}go deeper
Know that the affected range is about which released versions contain the vulnerable code, and that a configuration condition cannot be expressed as a version number - it has to be written out for the reader.
Explain both failure directions: a trimmed range silently misses exposed consumers, and an over-broad one floods everyone with findings they cannot act on. Say where the precondition actually goes in an advisory entry.
Demonstrate that you weigh downstream triage cost as a real cost - holding a publication to bisect the introduced version, closing an open range promptly, splitting entries when the package ships under two coordinates.
Own the credibility economics: an ecosystem's willingness to act on your advisories is a finite asset, and every over-broad range spends it. Decide what review your advisories get before they leave the building.
## Two different questions, one field Consider a NuGet authentication library whose flaw only bites consumers who registered one optional request handler. The default configuration never reaches the vulnerable code. Roughly ninety per cent of your users are, in practice, fine. What do you write in the affected range? The temptation is to narrow it - to somehow encode 'affected only if configured this way'. You cannot. A version range is an interval over version numbers, and there is no version number that means 'and you switched the handler on'. Anything you do to the range to represent the configuration ends up excluding real versions, which means excluding real, exposed consumers. The consumer who did enable the handler - the one person whose credentials are actually at risk - gets no alert. So the rule is: the range is a claim about the code your artifact contains. It runs from the release where the vulnerable path first shipped to the first release on each maintained line that no longer contains it. The precondition is a separate claim, and it belongs in separate fields. ## Where the precondition goes Advisory formats give you places to put it. There is free-form detail text, which is where a human reads 'only when the optional passthrough handler is registered'. There are ecosystem-specific and database-specific objects for structured qualifiers. Some formats let you name the affected symbols or entry points, which is the machine-readable form of the same claim. And the severity vector, published as a vector rather than a number, lets a reader see the conditions you scored under. Put the precondition in the first sentence of the summary, not in paragraph four. The consumer's first contact with your advisory is usually a one-line finding in a report, and whether they can rule themselves out in ten seconds decides whether they act on the rest of it. What you are not doing is deciding on the consumer's behalf that they are safe. You are giving them the fact they need - 'the vulnerable path is only reachable with X enabled' - and their own inventory tells them whether X is enabled. That division of labour is the whole point: you know the code, they know their deployment. ## The cost of the over-broad range The mirror-image mistake is the defensive over-claim. Two versions of it show up constantly. The first is `introduced: 0`. It is technically safe - if you do not know when the bug appeared, claiming it was always there cannot under-alert. But it condemns years of releases that never carried the code, and it makes the advisory useless as a decision input: nobody can tell from it whether upgrading a minor version helps. If you genuinely do not know yet, it is usually better to hold the advisory a day and bisect than to publish a range you will have to correct. The second is publishing an affected range with no fixed version while the patch is still being prepared. Every consumer gets an alert with no remedy, and alerts with no remedy are how you train an ecosystem to ignore you. Sometimes you must - the flaw is public and people need to mitigate - but then say so explicitly and update the entry the moment the fix ships. Both errors have the same downstream effect: they inflate the number of findings a consumer must triage, and triage capacity is finite. An advisory that costs a hundred teams an hour each of pointless investigation has done real damage, even though it looks conservative from where you are standing. ## Identity precision, not just version precision The same discipline applies to which package the range hangs off. If your module changed its import path at a major version - a common pattern where the major version becomes part of the module path - then one vulnerability spans two package coordinates. Consumers on the old path and consumers on the new path resolve different names, and a tool matches only the name it resolved. One advisory, two affected entries, each with its own package identity and its own ranges. Miss one and half the ecosystem is never told. The same is true for renames, scoped and unscoped publications of the same code, and platform-specific distribution names. ## The test Before publishing, ask two questions of your draft. Is there a consumer running vulnerable code whose installed version falls outside my ranges? Is there a consumer running code that was never vulnerable whose version falls inside them? The first is a miss; the second is noise. Both are yours to prevent, and the precondition prose is what lets you keep the range honest without drowning the ninety per cent who are fine.
- Your module's import path changed at the major version and both paths still get patches. How does that change the advisory?It becomes two affected entries under one advisory - one per package coordinate, each with its own ranges. A consumer's tool matches the coordinate it actually resolved, so an entry that only names the new path leaves every consumer still on the old path unalerted. Same flaw, same identifier, two identities.
- Should the rarity of the vulnerable configuration lower the severity you publish?No. How many people enabled the feature is prevalence, not an intrinsic property of the flaw, and a base score does not have a metric for it. Score the vulnerable configuration honestly and state the precondition in the text. Discounting scores because a bug is embarrassing is how a vendor's numbers stop being believed.
- Is it ever right to publish an affected range with no fixed version?Yes - when the flaw is already public or actively abused and consumers need to mitigate now. Say plainly that no fix exists yet, give the workaround, and update the entry the moment the patch ships. What you should not do is leave an open-ended range sitting there because nobody remembered to close it.
saying these in an interview costs you the question
- Narrowing the version range to exclude unaffected configurations
- Marking every version ever released affected to be safe
- Burying the precondition below the fold of the advisory text
- Leaving the range open after the fixed release shipped
- Publishing one entry when the package ships under two coordinates