CVSS (Common Vulnerability Scoring System) library for Erlang.
Supports all CVSS versions:
- CVSS 1.0 — Specification
- CVSS 2.0 — Specification
- CVSS 3.0 — Specification
- CVSS 3.1 — Specification
- CVSS 4.0 — Specification
Minimum supported Erlang/OTP version is OTP 26.
Add cvss to your dependencies in rebar.config:
{deps, [cvss]}.Add cvss to your dependencies in mix.exs:
{:cvss, "~> 0.1"}Use the cvss module when the version is not known ahead of time:
%% Parse a vector of any version
{ok, Cvss} = cvss:parse(<<"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H">>).
%% Calculate the overall score
9.8 = cvss:score(Cvss).
%% Get the severity rating (v3.0+)
critical = cvss:rating(Cvss).
%% Compose back to a vector string
<<"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H">> = iolist_to_binary(cvss:compose(Cvss)).
%% Check if a vector is valid
true = cvss:valid(<<"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H">>).# Parse a vector of any version
{:ok, cvss} = :cvss.parse("CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H")
# Calculate the overall score
9.8 = :cvss.score(cvss)
# Get the severity rating (v3.0+)
:critical = :cvss.rating(cvss)
# Compose back to a vector string
"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H" =
:cvss.compose(cvss) |> IO.iodata_to_binary()
# Check if a vector is valid
true = :cvss.valid("CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H")For direct access to version-specific features and detailed score types, use
:cvss_v1, :cvss_v2, :cvss_v3, or :cvss_v4 directly.
These versions share the same score types: Base, Temporal, and Environmental. Each score builds on the previous one.
{ok, Cvss} = cvss_v3:parse(<<"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H/E:F/RL:W/RC:R">>).
9.8 = cvss_v3:base_score(Cvss).
9.1 = cvss_v3:temporal_score(Cvss).
9.1 = cvss_v3:environmental_score(Cvss).
9.1 = cvss_v3:score(Cvss). %% Returns the most specific score available{:ok, cvss} = :cvss_v3.parse("CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H/E:F/RL:W/RC:R")
9.8 = :cvss_v3.base_score(cvss)
9.1 = :cvss_v3.temporal_score(cvss)
9.1 = :cvss_v3.environmental_score(cvss)
9.1 = :cvss_v3.score(cvss) # Returns the most specific score availableCVSS 4.0 uses a unified scoring formula. The score functions control which metric groups are considered, matching the CVSS 4.0 nomenclature:
| Function | Nomenclature | Metrics Used |
|---|---|---|
base_score/1 |
CVSS-B | Base only |
threat_score/1 |
CVSS-BT | Base + Threat |
environmental_score/1 |
CVSS-BE | Base + Environmental |
score/1 |
CVSS-BTE | Base + Threat + Environmental |
{ok, Cvss} = cvss_v4:parse(
<<"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H/E:P">>
).
cvss_v4:base_score(Cvss). %% CVSS-B: ignores threat & environmental
cvss_v4:threat_score(Cvss). %% CVSS-BT: ignores environmental
cvss_v4:environmental_score(Cvss). %% CVSS-BE: ignores threat
cvss_v4:score(Cvss). %% CVSS-BTE: uses all present metrics{:ok, cvss} = :cvss_v4.parse(
"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H/E:P"
)
:cvss_v4.base_score(cvss) # CVSS-B: ignores threat & environmental
:cvss_v4.threat_score(cvss) # CVSS-BT: ignores environmental
:cvss_v4.environmental_score(cvss) # CVSS-BE: ignores threat
:cvss_v4.score(cvss) # CVSS-BTE: uses all present metricsThe parsed CVSS values are Erlang records. To pattern match or construct them
in Elixir, use Record.defrecord/2:
import Record
defrecord :cvss_v3, Record.extract(:cvss_v3, from_lib: "cvss/include/cvss_v3.hrl")
defrecord :cvss_v4, Record.extract(:cvss_v4, from_lib: "cvss/include/cvss_v4.hrl")
# Pattern match on parsed results
{:ok, cvss} = :cvss_v3.parse("CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H")
cvss_v3(av: :network, c: confidentiality) = cvssQualitative severity ratings are defined by the CVSS v3.0, v3.1, and v4.0
specifications. The cvss:rating/1 function applies these thresholds:
| Rating | Score Range |
|---|---|
none |
0.0 |
low |
0.1 – 3.9 |
medium |
4.0 – 6.9 |
high |
7.0 – 8.9 |
critical |
9.0 – 10.0 |
CVSS v1.0 and v2.0 do not define severity ratings in their specifications. The same thresholds are applied as a convenience but are not spec-mandated for those versions.