Reporting

CVSS in practice: the scoring mistakes that make a report arguable

Most disputed findings are disputed on the score, not the facts. What changed in CVSS v4.0, the errors that survive peer review, and how to score so the conversation stays on the fix.

Pental13 min read

A finding with a shaky score invites a conversation about the score instead of the fix. That is the practical cost of getting CVSS wrong: a remediation call spent arguing about a number while the vulnerability stays open, and a client who starts checking your other numbers.

Two things make this harder than it should be. Scoring is genuinely subtle in places, and the industry is currently running two versions of the standard at once.

Know which version you are speaking

CVSS v3.1 is still what most vulnerability databases, scanners and client tooling report. CVSS v4.0 is the current specification, and it changed enough that a vector from one is not a vector from the other.

The differences that matter day to day:

  • Scope is gone. v3.1 had a single Scope flag and one set of impact metrics. v4.0 splits impact into the Vulnerable System (VC, VI, VA) and Subsequent Systems (SC, SI, SA), which is a much better fit for container escapes, sandbox breaks and injection that reaches a separate backend.
  • Attack Requirements (AT) is new. Conditions outside the attacker's control that must hold, a race that has to be won, a specific deployment state, now live in their own metric instead of being crushed into Attack Complexity.
  • User Interaction is graded. v4.0 distinguishes Passive from Active interaction rather than treating any user involvement as one value.
  • The naming is explicit. CVSS-B, CVSS-BT and CVSS-BTE tell a reader whether Threat and Environmental metrics were applied. Publishing a base-only score and calling it "the CVSS score" is exactly what that naming exists to stop.

Whichever you use, say so in the report, in the methodology section, once. A vector string without a version is ambiguous, and a client with a scanner speaking the other version will find the ambiguity before you do.

Score the observed case, not the worst case

Base metrics describe the vulnerability as it exists. If you achieved read access to one table, the impact metrics describe that. The chain to full compromise belongs in the narrative, and if you actually walked the chain, it belongs in its own finding with its own vector.

The temptation runs the other way when a client is unresponsive: score it high enough and someone will pay attention. It works once. Afterwards every score you publish is discounted by the reader, including the accurate ones.

Complexity is not effort

Attack Complexity describes conditions the attacker cannot control. It is not a measure of how long the exploit took you or how much skill it needed. A fiddly but reliable exploit is low complexity however long the afternoon felt, and in v4.0 the "there has to be a race, and you have to win it" case has its own metric in Attack Requirements.

Privileges Required is about the attacker, not the interface

Privileges Required describes what the attacker needs before the attack starts, not what the application asks a legitimate user for. If the endpoint answers unauthenticated requests, the fact that the button is hidden behind a login is irrelevant. Client-side gating is a finding in itself, not a mitigating factor in someone else's score.

Base scores do not answer "is this urgent for us"

Base metrics are deliberately environment-blind, which is what makes them portable and what makes them a poor answer to the only question your client actually has. Environmental metrics exist for this: if you know the asset is internet-facing and holds cardholder data, say so, adjust, and show both numbers.

This is the single highest-value thing a testing firm can do with CVSS, and most reports skip it. A client can get a base score from a scanner for free. Contextualised severity is the part they are paying a human for.

Label and vector must agree

If your report carries both a severity word and a numeric vector, they must never disagree. A finding labelled Critical with a 6.4 vector reads as carelessness even when the label is the more accurate of the two, and it is the first thing a technically literate reviewer will pick at. Where your professional judgement genuinely overrides the arithmetic, say so explicitly in the finding: "scored Medium by CVSS, raised to High because this system authenticates every other system in the estate" is defensible. Silence is not.

Write the vector before the prose

Fixing a vector after the narrative is written creates pressure to leave the narrative alone, and the two drift. Vector first, then describe what the vector says, and they cannot contradict each other.

A useful peer-review question for any finding: could a competent reader reconstruct your vector from your description alone? If not, one of the two is wrong.

A short review checklist

  • Version stated, and the same version used throughout the report.
  • Vector matches the described access, impact and preconditions.
  • Impact reflects what was demonstrated, with chains scored separately.
  • Environmental adjustment applied where you know enough to apply it, and its reasoning stated.
  • Severity label and score agree, or the divergence is argued in the finding.

Scoring consistently across a team

Everything above is about one person scoring one finding. The harder problem is five people scoring forty findings across a quarter and arriving somewhere consistent, because inconsistency between testers is what a returning client notices first.

Three things move the needle more than training does.

  • Write the house position down. Not the specification, which already exists, but the calls your firm makes: how you treat an unauthenticated endpoint hidden behind a client-side check, when a chain gets its own finding, whether you apply environmental metrics by default. One page, agreed once.
  • Score in review, not only in writing. The reviewer checks the vector against the description as a matter of course. It takes seconds and it catches the drift early, while the finding is still cheap to change.
  • Reuse the wording, not just the score. A weakness your firm has described well once should be described that way every time, with the vector attached to the description rather than re-derived from memory.

Findings carry the vector as structured data rather than as text in a document, so severity, score and label cannot drift apart between the editor, the client portal and the rendered report. Saving a finding to the Library keeps its scoring alongside its wording, so the next instance starts from the version your firm already agreed.


Pental Is Built by the People Writing This

Engagement management for testing firms, on a database you own, under your brand, with the AI running on your key.

Related reading

Reporting · 5 min read
What a Penetration Test Report Should Contain
Section by section, what belongs in a report, what it is for, and the six things reports leave out that make them harder to act on than they need to be.
Reporting · 5 min read min read
Writing Remediation a Developer Will Actually Action
"Implement input validation" is not remediation, it is a category. What a developer needs from your finding, how specific to be without writing their code for them, and what to do when there is no clean fix.
Reporting · 12 min read min read
Writing an Attestation Letter an Auditor Will Actually Accept
The one-page letter your client forwards to their auditor, their insurer and their biggest customer. What has to be on it, what quietly gets it rejected, and why it outlives the report it summarises.

Setup guide

See the product set up, end to end

The whole setup in 8:15, with chapters you can jump to: registering, your own domain, your own database, your own mail server, branding, the first sign-in, and keeping the database updated.

  • 0:00 · Registering, signing in, and the free trial
  • 0:51 · Your name and your firm’s name
  • 0:57 · Custom domain
  • +5 more