This script calculates the CVSS Base Score, Temporal Score, and Environmental Score using either the CVSS 3.0 or CVSS 3.1 calculator according to https://www.first.org/cvss/ calculation documentation.
import math
from typing import Any
import demistomock as demisto
from CommonServerPython import *
def round_up(n):
if n is None:
return None
int_input = int(n * 100000)
if (int_input % 10000) == 00:
return int_input / 100000.0
else:
return math.floor((int_input / 10000) + 1) / 10.0
def main():
args = demisto.args()
version = args.get("version", "3.1")
vector_string = f"CVSS:{version}/"
values_map_options: dict[str, dict[str, dict[str, Any]]] = {
"3.0": {
"AV": {
"X": None,
"N": 0.85,
"A": 0.62,
"L": 0.55,
"P": 0.2,
},
"AC": {"X": None, "L": 0.77, "H": 0.44},
"PR": {"X": None, "N": 0.85, "L": {"C": 0.68, "U": 0.62}, "H": {"C": 0.5, "U": 0.27}},
"UI": {"X": None, "N": 0.85, "R": 0.62},
"CIA": {
"X": None,
"N": 0,
"H": 0.56,
"L": 0.22,
},
"E": {"X": 1, "H": 1, "F": 0.97, "P": 0.94, "U": 0.91},
"RL": {"X": 1, "U": 1, "W": 0.97, "T": 0.96, "O": 0.95},
"RC": {"X": 1, "C": 1, "R": 0.96, "U": 0.92},
"CIAR": {"X": 1, "H": 1.5, "M": 1, "L": 0.5},
},
"3.1": {
"AV": {
"X": None,
"N": 0.85,
"A": 0.62,
"L": 0.55,
"P": 0.2,
},
"AC": {"X": None, "L": 0.77, "H": 0.44},
"PR": {"X": None, "N": 0.85, "L": {"C": 0.68, "U": 0.62}, "H": {"C": 0.5, "U": 0.27}},
"UI": {"X": None, "N": 0.85, "R": 0.56},
"CIA": {
"X": None,
"N": 0,
"H": 0.56,
"L": 0.22,
},
"E": {"X": 1, "H": 1, "F": 0.97, "P": 0.94, "U": 0.91},
"RL": {"X": 1, "U": 1, "W": 0.97, "T": 0.96, "O": 0.95},
"RC": {"X": 1, "C": 1, "R": 0.96, "U": 0.92},
"CIAR": {"X": 1, "H": 1.5, "M": 1, "L": 0.5},
},
}
version = args.get("version")
values_map = values_map_options[version]
value_list = []
for k, v in args.items():
if v != "X" and k != "version":
value_list.append(f"{k}:{v}")
vector_string += "/".join(value_list)
###########################################
# Get all required values for calculations
###########################################
confidentiality = values_map["CIA"][args.get("C")]
modified_confidentiality = args.get("MC", "X")
modified_confidentiality = confidentiality if modified_confidentiality == "X" else values_map["CIA"][modified_confidentiality]
integrity = values_map["CIA"][args.get("I")]
modified_integrity = args.get("MI", "X")
modified_integrity = integrity if modified_integrity == "X" else values_map["CIA"][modified_integrity]
availability = values_map["CIA"][args.get("A")]
modified_availability = args.get("MA", "X")
modified_availability = availability if modified_availability == "X" else values_map["CIA"][modified_availability]
exploit_code_maturity = values_map["E"].get(args.get("E"), "X")
scope_changed = args.get("S") == "C"
modified_scope_changed = args.get("MS") == "C"
atack_vector = values_map["AV"].get(args.get("AV"), 0)
modified_attack_vector = args.get("MAV", "X")
modified_attack_vector = atack_vector if modified_attack_vector == "X" else values_map["AV"].get(modified_attack_vector, 0)
attack_complexity = values_map["AC"][args.get("AC")]
modified_attack_complexity = args.get("MAC", "X")
modified_attack_complexity = (
attack_complexity if modified_attack_complexity == "X" else values_map["AC"][modified_attack_complexity]
)
privileges_required = values_map["PR"][args.get("PR")]
if type(privileges_required) is dict:
privileges_required = (
privileges_required.get("C") if scope_changed or modified_scope_changed else privileges_required["U"]
)
modified_privileges_required = args.get("MPR", "X")
if modified_privileges_required == "X":
modified_privileges_required = privileges_required
elif type(modified_privileges_required) is dict:
modified_privileges_required = (
modified_privileges_required["C"] if scope_changed or modified_scope_changed else modified_privileges_required["U"]
)
else:
modified_privileges_required = values_map["PR"][modified_privileges_required]
user_interaction = values_map["UI"][args.get("UI")]
modified_user_interaction = args.get("MUI", "X")
modified_user_interaction = (
user_interaction if modified_user_interaction == "X" else values_map["UI"][modified_user_interaction]
)
remediation_level = values_map["RL"][args.get("RL", "X")]
report_confidence = values_map["RC"][args.get("RC", "X")]
confidentiality_requirement = values_map["CIAR"][args.get("CR", "X")]
integrity_requirement = values_map["CIAR"][args.get("IR", "X")]
availability_requirement = values_map["CIAR"][args.get("AR", "X")]
###########################################
# Base Metric Equation calculations
###########################################
# Impact Sub-Score
iss = 0
if version in ["3.0", "3.1"]:
iss = 1 - ((1 - confidentiality) * (1 - integrity) * (1 - availability))
# Impact
impact = 0.0
if version in ["3.0", "3.1"]:
if not scope_changed:
impact = 6.42 * iss
else:
impact = 7.52 * (iss - 0.029) - 3.25 * (iss - 0.02) ** 15
# Exploitability
exploitability = 0.0
if version in ["3.0", "3.1"]:
exploitability = 8.22 * atack_vector * attack_complexity * privileges_required * user_interaction
# Base Score
base_score = 0.0
if version in ["3.0", "3.1"]:
base_score = 0
if impact > 0:
multiplier = 1.0
if scope_changed:
multiplier = 1.08
calculated_value = multiplier * (impact + exploitability)
base_score = min(10.0, calculated_value)
base_score = round_up(base_score)
###########################################
# Temporal Metric calculations
###########################################
temporal_score_roundup = 0.0
if version in ["3.0", "3.1"]:
temporal_score_roundup = base_score * exploit_code_maturity * remediation_level * report_confidence
# Environmental Metrics
modified_impact_sub_score = 0.0
modified_impact = 0.0
modified_exploitability = 0.0
if version in ["3.0", "3.1"]:
calculatedmodified_impact_sub_score = 1 - (
(1 - confidentiality_requirement * modified_confidentiality)
* (1 - integrity_requirement * modified_integrity)
* (1 - availability_requirement * modified_availability)
)
modified_impact_sub_score = min(0.915, calculatedmodified_impact_sub_score)
if version in ["3.0", "3.1"]:
if modified_scope_changed:
if version == "3.0":
modified_impact = (
7.52 * (modified_impact_sub_score - 0.029) - 3.25 * (modified_impact_sub_score * 0.9731 - 0.02) ** 15
)
elif version == "3.1":
modified_impact = (
7.52 * (modified_impact_sub_score - 0.029) - 3.25 * (modified_impact_sub_score * 0.9731 - 0.02) ** 13
)
else:
modified_impact = 6.42 * modified_impact_sub_score
modified_exploitability = (
8.22 * modified_attack_vector * modified_attack_complexity * modified_privileges_required * modified_user_interaction
)
# Environmental Score
environmental_score = 0.0
if version in ["3.0", "3.1"]:
environmental_score = 0
if modified_impact > 0:
exponential = 1.0
if modified_scope_changed:
exponential = 1.08
calculated_value = exponential * (modified_impact + modified_exploitability)
calculated_value = min(10, calculated_value)
calculated_value = round_up(calculated_value)
environmental_score = calculated_value * exploit_code_maturity * remediation_level * report_confidence
environmental_score = round_up(environmental_score)
# Round values
iss = round_up(iss)
impact = round_up(impact)
exploitability = round_up(exploitability)
base_score = round_up(base_score)
temporal_score_roundup = round_up(temporal_score_roundup)
modified_impact_sub_score = round_up(modified_impact_sub_score)
modified_impact = round_up(modified_impact)
modified_exploitability = round_up(modified_exploitability)
environmental_score = round_up(environmental_score)
entry = {
"VectorString": vector_string,
"Version": version,
"ImpactSubScore": iss,
"Impact": impact,
"Exploitability": exploitability,
"BaseScore": base_score,
"TemporalScore": temporal_score_roundup,
"ModifiedImpactSubScore": modified_impact_sub_score,
"ModifiedImpact": modified_impact,
"ModifiedExploitability": modified_exploitability,
"EnvironmentalScore": environmental_score,
}
hrentry = {k: v for k, v in entry.items() if v}
markdown = tableToMarkdown("CVSS Score:", hrentry)
results = CommandResults(
readable_output=markdown,
outputs_prefix="",
outputs_key_field="",
outputs={"CVSS(val.VectorString === obj.VectorString && val.Version === obj.Version)": entry},
)
return results
if __name__ in ["__main__", "builtin", "builtins"]:
res = main()
return_results(res)
README
This script calculates the CVSS Base Score, Temporal Score, and Environmental Score using either the CVSS 3.0 or CVSS 3.1 calculator according to https://www.first.org/cvss/ calculation documentation.
Script Data
Name
Description
Script Type
python3
Cortex XSOAR Version
5.0.0
Inputs
Argument Name
Description
version
The CVSS version to use for scoring. Can be “3.1” or “3.0”. Default is “3.1”.
AV
Attack Vector. Can be “N”, “A”, “L”, or “P”.
AC
Attack Complexity. Can be “L” or “H”.
PR
Privileges Required. Can be “N”, “L”, or “H”.
UI
User Interaction. Can be “N” or “R”.
S
Scope. Can be “U” or “C”.
C
Confidentiality. Can be “H”, “L”, or “N”.
I
Integrity. Can be “H”, “L”, or “N”.
A
Availability. Can be “H”, “L”, or “N”.
E
Exploit Code Maturity. Can be “X”, “H”, “F”, “P”, or “U”. Default is “X”.
RL
Remediation Level. Can be “X”, “U”, “W”, “T”, or “O”. Default is “X”.
RC
Report Confidence. Can be “X”, “C”, “R”, or “U”. Default is “X”.
CR
Confidentiality Requirement. Can be “X”, “H”, “M”, or “L”. Default is “X”.
IR
Integrity Requirement. Can be “X”, “H”, “M”, or “L”. Default is “X”.
AR
Availability Requirement. Can be “X”, “H”, “M”, or “L”. Default is “X”.
MAV
Modified Attack Vector. Can be “X”, “N”, “A”, “L”, or “P”. Default is “X”.
MAC
Modified Attack Complexity. Can be “X”, “L”, or “N”. Default is “X”.
MPR
Modified Privileges Required. Can be “X”, “N”, “L”, or “H”. Default is “X”.
MUI
Modified User Interaction. Can be “X”, “N”, or “R”. Default is “X”.
MS
Modified Scope. Can be “X”, “U”, or “C”. Default is “X”.
MC
Modified Confidentiality. Can be “X”, “N”, “L”, or “H”. Default is “X”.
MI
Modified Integrity. Can be “X”, “N”, “L”, or “H”. Default is “X”.
MA
Modified Availability. Can be “X”, “N”, “L”, or “H”. Default is “X”.