CVSS vs OWASP contextual scoring¶
Who this is for: anyone who wants to understand why Vens scores differ from their scanner. By the end of this page: you know what the OWASP score represents and why it moves.
The one-sentence answer¶
A CVSS base score describes the vulnerability. OWASP Risk Rating describes the risk to your system.
The base score your scanner prints is the same wherever that component runs. A CVE has as many OWASP scores as there are systems running it.
CVSS does have environmental metrics for exactly this, and they are the right idea. They also arrive empty: filling them takes a judgment per CVE and per asset that nobody produces at scale. That gap is what Vens fills.
A concrete example¶
The CVE id used below is illustrative, not a real published CVE.
Two services both contain libfoo-1.2.3 with a hypothetical CVE CVE-XXXX-YYYY. The CVE is a denial-of-service in a CSV parsing function.
CVSS says: 8.8 HIGH. That is the base score, and it is the same wherever the component runs.
Vens says, for service A (internal dashboard, no CSV parsing in production):
OWASP score: 8 / 81
Severity: low
Reason: The vulnerable CSV parser is not reachable in production.
Internal exposure limits threat actors. Business impact is low.
Vens says, for service B (public checkout, parses uploaded CSVs, GDPR):
OWASP score: 56 / 81
Severity: high
Reason: CSV upload is a direct user input. Internet exposure means high
threat agent. DoS affects availability of a revenue-critical
service. Compliance impact under GDPR breach reporting.
Same CVE, same base score, two completely different risks. Vens quantifies that.
The OWASP Risk Rating formula¶
Risk = Likelihood × Impact (0 to 81)
Likelihood = (Threat Agent + Vulnerability Factors) / 2
Impact = (Technical Impact + Business Impact) / 2
Each of the four factors is a number from 0 to 9. Multiply the two averages together and you get a risk score from 0 to 81.
Vens maps the raw OWASP score onto the CycloneDX severity field like this:
| Score | Severity (ratings[].severity) |
|---|---|
| 0–4 | info |
| 5–19 | low |
| 20–39 | medium |
| 40–59 | high |
| 60–81 | critical |
Full OWASP methodology: owasp.org/www-community/OWASP_Risk_Rating_Methodology.
The four factors, plain English¶
1. Threat Agent — "who would attack this?"¶
internetexposure → many attackers, easy access → highinternalexposure → few attackers, need a foothold → low
Fed by your exposure field.
2. Vulnerability Factors — "how easy is it to exploit?"¶
- Public exploit available, no auth needed → high
- Requires specific config, authenticated access, WAF in front → low
Fed by the CVE metadata and your controls (WAF, segmentation, etc.).
3. Technical Impact — "what breaks if this is exploited?"¶
- Confidentiality loss on PII → high
- Availability loss on a dev sandbox → low
Fed by your data_sensitivity, availability_requirement, audit_requirement.
4. Business Impact — "what does it cost the business?"¶
- Revenue-critical + compliance fines → high
- Internal tooling outage → low
Fed by your business_criticality and compliance_requirements.
Why scores go down from CVSS¶
The most common case. A CVE has a base score of 8.8 but:
- The vulnerable code path is not used in your build (LLM infers from CVE description + your
notes) - You have compensating controls (WAF, segmentation)
- The affected data is public
- The service has low business criticality
A generic 8.8 becomes, say, 10 out of 81. You should not patch it urgently.
Why scores go up from CVSS¶
Less common but critical. A CVE has a base score of 5.3, "medium", but:
- It leaks the exact type of data your system handles (PII)
- You are under GDPR / PCI-DSS — one breach triggers disclosure obligations
- The service is publicly exposed with no WAF
- The business impact of a disclosed breach exceeds normal scoring bounds
A generic 5.3 becomes, say, 52 out of 81. This is the CVE you patch first, and it was buried in your scanner report.
When to trust the Vens score¶
✅ You've described your context honestly and precisely in config.yaml
✅ Your controls reflect reality (no wishful thinking)
✅ You've added architectural detail in notes for non-obvious systems
✅ You've reviewed the LLM reasoning for the top 10 scores via --debug-dir
When to be cautious¶
⚠️ Generic or sparse config.yaml → scores will be generic
⚠️ You lie about controls → optimistic scores that miss real risk
⚠️ The LLM has no information about a very recent CVE (< 2 weeks) → score may regress to the generic CVSS interpretation
⚠️ Deeply custom internal CVEs → the LLM may not know the specifics; review manually
So what do I do with CVSS?¶
The base score still matters as the input that puts the CVE in your report at all. Vens does not read the number: the model gets the CVE title, description and the vendor severity label, then scores your context. You don't have to choose between the two, Vens is CVSS plus context, not CVSS replaced.
Next¶
- Put this into practice: Prioritize a CVE backlog
- Refine your context: Describe your system context