Why CVSS Doesn't Fit Smart Contract Bugs, and What We Use Instead
Security Wiz team3 min read
Every audit report has to answer the same question: how bad is this? In traditional software security the answer usually comes from CVSS, the Common Vulnerability Scoring System. It's a good system, for the problems it was designed for. Smart contracts aren't one of them.
Where CVSS runs out of road
CVSS measures harm to a computer system's confidentiality, integrity and availability. Most smart contract harm looks different:
- Money moves. The key question is whose funds can be stolen or frozen, and how much. CVSS has no metric for that.
- It can't be undone. A stolen token rarely comes back. CVSS doesn't ask whether the damage is reversible.
- Capital is part of the attack. Flash loans let an attacker borrow millions for a single transaction, so attack cost matters more than network access.
- Every contract is public. CVSS's attack-vector metric (network, adjacent, local, physical) is almost always "network" onchain, so it tells you nothing.
The result is that two very different bugs can land on the same CVSS number, and the number can't be traced back to the things a protocol team actually cares about.
OVSS: the same shape, different questions
OVSS, the Onchain Vulnerability Scoring System, keeps what works in CVSS: a short vector string records a reviewer's judgments, a fixed public formula turns it into a score from 0.0 to 10.0, and the familiar Critical / High / Medium / Low bands apply. What changes are the metrics. There are ten, in three groups:
| Group | Metrics |
|---|---|
| Impact | F Funds, C Control, A Availability, D Data integrity |
| Modifiers | R Reversibility, S Scope |
| Exploitability | PR Privileges required, AC Attack cost, PC Preconditions, UI User interaction |
The highest of the four impact metrics sets the base impact. Reversibility and scope adjust it. Exploitability multiplies it. A vector looks like this:
OVSS:1.0/F:T/C:N/A:N/D:N/R:N/S:U/PR:N/AC:L/PC:N/UI:N → 10.0 Critical
That reads: total loss of funds, can't be undone, anyone can do it, cheap or flash-loanable, no special conditions, no victim action needed. Anyone holding the vector can recompute the score and check it, which is the point.
Two bugs, two scores
Take the classic first-depositor share inflation bug in a vault. It can steal later deposits, but only if the attacker is first in an empty vault, which is a rare state, and it needs some capital held across transactions:
OVSS:1.0/F:P/C:N/A:N/D:N/R:N/S:U/PR:N/AC:M/PC:R/UI:N → 5.4 Medium
Now compare an admin with no timelock who can withdraw everything. The loss is total, but it requires a privileged role:
OVSS:1.0/F:T/C:N/A:N/D:N/R:N/S:U/PR:H/AC:L/PC:N/UI:N → 5.0 Medium
Both land in Medium, for very different reasons, and the vector shows exactly why. That's something a single CVSS number can't do for a smart contract.
How it relates to Immunefi
Immunefi's severity classification is the scale most of web3 already knows, because most bug bounty programs use it. It assigns a level from the impact alone: direct theft of user funds is Critical, however hard the attack is. OVSS starts from the same impact categories, then adjusts for how likely and how easy the attack is. So the two can differ, and a theft that only works in a rare market state may be Immunefi Critical and OVSS Medium. We show both in our reports, and explain any large gap.
Try it
OVSS is open. The specification is licensed CC BY 4.0 and the reference code is MIT, so you can use it in your own reports with credit. You can score a finding yourself with the OVSS calculator, which shows the full math and gives you a vector to paste into a report.
We use OVSS for every on-chain finding we report. Web2 findings (websites, APIs, servers) still use CVSS 4.0, where it fits.
Shipping something onchain?
Send us your repo and we’ll return a quote within 24 hours.