Skip to content

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?"

  • internet exposure → many attackers, easy access → high
  • internal exposure → 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