Skip to content

Decision Point Groups

Decision Point groups provide collections of related Decision Points for some specific purpose.

With the introduction of Decision Tables, Decision Point groups are less important than they once were, and may be removed in a future release. However, they can still be useful for documentation and for some programmatic uses.

Provides a DecisionPointGroup object for use in SSVC.

ssvc.dp_groups is deprecated

This module is deprecated. New development should focus on ssvc.decision_tables.

DecisionPointGroup

Bases: _Base, _SchemaVersioned, _Versioned, BaseModel, MutableMapping

DEPRECATED: DecisionPointGroup has been superseded by DecisionTable. New development should use DecisionTable instead. We are keeping this class around for backward compatibility, but it may be removed in future releases.

Models a group of decision points as a dictionary, keyed by their ID.

Source code in src/ssvc/dp_groups/base.py
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
class DecisionPointGroup(
    _Base, _SchemaVersioned, _Versioned, BaseModel, MutableMapping
):
    """
    **DEPRECATED:** `DecisionPointGroup` has been superseded by `DecisionTable`.
    New development should use `DecisionTable` instead.
    We are keeping this class around for backward compatibility, but it may be removed in future releases.

    Models a group of decision points as a dictionary, keyed by their ID.
    """

    decision_points: dict[str, DecisionPoint]
    _schema_version: ClassVar[str] = SCHEMA_VERSION
    schemaVersion: Literal[SCHEMA_VERSION]

    def __init__(self, *args, **kwargs):
        warnings.warn(
            f"{self.__class__.__name__} is deprecated; use `DecisionTable` instead.",
            DeprecationWarning,
            stacklevel=2,
        )
        super().__init__(*args, **kwargs)

    @model_validator(mode="before")
    @classmethod
    def transform_decision_points(cls, data):
        if isinstance(data, dict) and "decision_points" in data:
            # If decision_points is a list/tuple, convert to dictionary
            # this allows us to handle the older way of defining decision point groups
            dp_value = data["decision_points"]
            if isinstance(dp_value, (list, tuple)):
                data["decision_points"] = {dp.id: dp for dp in dp_value}
        return data

    # dunder methods to allow dict-like access in conjunction with MutableMapping abstract base class
    def __getitem__(self, key):
        return self.decision_points[key]

    def __setitem__(self, key, value):
        if not isinstance(value, DecisionPoint):
            raise TypeError("Value must be a DecisionPoint")
        self.decision_points[key] = value

    def __delitem__(self, key):
        del self.decision_points[key]

    def __iter__(self):
        return iter(self.decision_points)

    def __len__(self):
        return len(self.decision_points)

    def add(self, decision_point: DecisionPoint) -> None:
        """
        Add a decision point to the group.
        """
        if decision_point.id in self.decision_points:
            # are they the same?
            existing_dp = self.decision_points[decision_point.id]
            if existing_dp == decision_point:
                # this is a no-op, they are the same
                return
            # otherwise, raise an error
            raise ValueError(
                f"Decision point {decision_point.id} already exists in the group."
            )

        # set the decision point in the dictionary
        self.decision_points[decision_point.id] = decision_point

    @classmethod
    def model_json_schema(cls, **kwargs):
        """
        Overrides schema generation to ensure it's the way we want it
        """
        schema = super().model_json_schema(**kwargs)

        deprecation_warning = f"**DEPRECATED:** `{cls.__name__}` has been superseded by `DecisionTable`.\nNew development should use `DecisionTable` instead.\nWe are keeping this class around for backward compatibility, but it may be removed in future releases.\n\n"

        # append a deprecation warning to the description
        if "description" in schema:
            schema["description"] = (
                deprecation_warning + schema["description"].strip()
            )
        else:
            schema["description"] = deprecation_warning.strip()

        return schema

add(decision_point)

Add a decision point to the group.

Source code in src/ssvc/dp_groups/base.py
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
def add(self, decision_point: DecisionPoint) -> None:
    """
    Add a decision point to the group.
    """
    if decision_point.id in self.decision_points:
        # are they the same?
        existing_dp = self.decision_points[decision_point.id]
        if existing_dp == decision_point:
            # this is a no-op, they are the same
            return
        # otherwise, raise an error
        raise ValueError(
            f"Decision point {decision_point.id} already exists in the group."
        )

    # set the decision point in the dictionary
    self.decision_points[decision_point.id] = decision_point

model_json_schema(**kwargs) classmethod

Overrides schema generation to ensure it's the way we want it

Source code in src/ssvc/dp_groups/base.py
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
@classmethod
def model_json_schema(cls, **kwargs):
    """
    Overrides schema generation to ensure it's the way we want it
    """
    schema = super().model_json_schema(**kwargs)

    deprecation_warning = f"**DEPRECATED:** `{cls.__name__}` has been superseded by `DecisionTable`.\nNew development should use `DecisionTable` instead.\nWe are keeping this class around for backward compatibility, but it may be removed in future releases.\n\n"

    # append a deprecation warning to the description
    if "description" in schema:
        schema["description"] = (
            deprecation_warning + schema["description"].strip()
        )
    else:
        schema["description"] = deprecation_warning.strip()

    return schema

get_all_decision_points_from(*groups)

Given a list of DecisionPointGroup objects, return a list of all the unique DecisionPoint objects contained in those groups.

Parameters:

Name Type Description Default
groups list

A list of SsvcDecisionPointGroup objects.

()

Returns:

Name Type Description
list list[DecisionPoint]

A list of unique SsvcDecisionPoint objects.

Source code in src/ssvc/dp_groups/base.py
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
def get_all_decision_points_from(
    *groups: list[DecisionPointGroup],
) -> list[DecisionPoint]:
    """
    Given a list of DecisionPointGroup objects, return a list of all
    the unique DecisionPoint objects contained in those groups.

    Args:
        groups (list): A list of SsvcDecisionPointGroup objects.

    Returns:
        list: A list of unique SsvcDecisionPoint objects.
    """

    # each group has a decision_points dict, we need to collect all the decision points
    new_dict = {}
    for group in groups:
        # we could have just done a dict update, but want to ensure uniqueness
        # even if the decision point groups use non-standard keys for their
        # decision points dict. So we'll build a new dict with known consistent keys.
        for dp in group.decision_points.values():
            new_dict[dp.id] = dp
    # now we have a dictionary of all decision points, we can return them as a tuple
    return list(new_dict.values())

SSVC Decision Point Groups

Provides collections of decision points for each version of the SSVC.

SSVCv1 = DecisionPointGroup(name='SSVCv1', definition='The first version of the SSVC.', version='1.0.0', decision_points=(get_all_decision_points_from(PATCH_APPLIER_1, PATCH_DEVELOPER_1))) module-attribute

SSVC version 1 decision point group.

SSVCv2 = DecisionPointGroup(name='SSVCv2', definition='The second version of the SSVC.', version='2.0.0', decision_points=(get_all_decision_points_from(COORDINATOR_PUBLICATION_1, COORDINATOR_TRIAGE_1, DEPLOYER_2, SUPPLIER_2))) module-attribute

SSVC version 2 decision point group.

SSVCv2_1 = DecisionPointGroup(name='SSVCv2.1', definition='The second version of the SSVC.', version='2.1.0', decision_points=(get_all_decision_points_from(COORDINATOR_PUBLICATION_1, COORDINATOR_TRIAGE_1, DEPLOYER_3, SUPPLIER_2))) module-attribute

SSVC version 2.1 decision point group.

CVSS Decision Point Groups

Models CVSS vectors as SSVC decision point groups

BASE_1 = [ACCESS_VECTOR_1, ACCESS_COMPLEXITY_1, AUTHENTICATION_1, CONFIDENTIALITY_IMPACT_1, INTEGRITY_IMPACT_1, AVAILABILITY_IMPACT_1, IMPACT_BIAS_1] module-attribute

List of CVSS v1 Base decision points

BASE_2 = [ACCESS_VECTOR_2, ACCESS_COMPLEXITY_2, AUTHENTICATION_2, CONFIDENTIALITY_IMPACT_1, INTEGRITY_IMPACT_1, AVAILABILITY_IMPACT_1] module-attribute

List of CVSS v2 Base decision points

BASE_3 = [ATTACK_VECTOR_3, ATTACK_COMPLEXITY_3, PRIVILEGES_REQUIRED_1, USER_INTERACTION_1, SCOPE, CONFIDENTIALITY_IMPACT_2, INTEGRITY_IMPACT_2, AVAILABILITY_IMPACT_2] module-attribute

List of CVSS v3 Base decision points

BASE_4 = EXPLOITABILITY_4 + IMPACT_4 module-attribute

List of CVSS v4 Base decision points

CVSSv1_B = DecisionPointGroup(name='CVSS', version='1.0.0', definition='CVSS v1 decision points', decision_points=(tuple(BASE_1))) module-attribute

CVSS v1 Base Metrics

CVSSv1_BT = DecisionPointGroup(name='CVSS', version='1.0.0', definition='CVSS v1 decision points', decision_points=(tuple(BASE_1 + TEMPORAL_1))) module-attribute

CVSS v1 Base and Temporal Metrics

CVSSv1_BTE = DecisionPointGroup(name='CVSS', version='1.0.0', definition='CVSS v1 decision points', decision_points=(tuple(BASE_1 + TEMPORAL_1 + ENVIRONMENTAL_1))) module-attribute

CVSS v1 Base, Temporal, and Environmental Metrics

CVSSv2_B = DecisionPointGroup(name='CVSS Version 2 Base Metrics', definition='Base metrics for CVSS v2', version='2.0.0', decision_points=(tuple(BASE_2))) module-attribute

CVSS v2 Base Metrics

CVSSv2_BT = DecisionPointGroup(name='CVSS Version 2 Base and Temporal Metrics', definition='Base and Temporal metrics for CVSS v2', version='2.0.0', decision_points=(tuple(BASE_2 + TEMPORAL_2))) module-attribute

CVSS v2 Base and Temporal Metrics

CVSSv2_BTE = DecisionPointGroup(name='CVSS Version 2 Base, Temporal, and Environmental Metrics', definition='Base, Temporal, and Environmental metrics for CVSS v2', version='2.0.0', decision_points=(tuple(BASE_2 + TEMPORAL_2 + ENVIRONMENTAL_2))) module-attribute

CVSS v2 Base, Temporal, and Environmental Metrics

CVSSv3_B = DecisionPointGroup(name='CVSS Version 3 Base Metrics', definition='Base metrics for CVSS v3', version='3.0.0', decision_points=(tuple(BASE_3))) module-attribute

CVSS v3 Base Metrics

CVSSv3_BT = DecisionPointGroup(name='CVSS Version 3 Base and Temporal Metrics', definition='Base and Temporal metrics for CVSS v3', version='3.0.0', decision_points=(tuple(BASE_3 + TEMPORAL_3))) module-attribute

CVSS v3 Base and Temporal Metrics

CVSSv3_BTE = DecisionPointGroup(name='CVSS Version 3 Base, Temporal, and Environmental Metrics', definition='Base, Temporal, and Environmental metrics for CVSS v3', version='3.0.0', decision_points=(tuple(BASE_3 + TEMPORAL_3 + ENVIRONMENTAL_3))) module-attribute

CVSS v3 Base, Temporal, and Environmental Metrics

CVSSv4 = DecisionPointGroup(name='CVSSv4', definition='All decision points for CVSS v4 (including supplemental metrics)', version='4.0.0', decision_points=(tuple(BASE_4 + THREAT_4 + ENVIRONMENTAL_4 + SUPPLEMENTAL_4))) module-attribute

CVSS v4 All Metrics

CVSSv4_B = DecisionPointGroup(name='CVSSv4 Base Metrics', definition='Base metrics for CVSS v4', version='4.0.0', decision_points=(tuple(BASE_4))) module-attribute

CVSS v4 Base Metrics

CVSSv4_BE = DecisionPointGroup(name='CVSSv4 Base and Environmental Metrics', definition='Base and Environmental metrics for CVSS v4', version='4.0.0', decision_points=(tuple(BASE_4 + ENVIRONMENTAL_4))) module-attribute

CVSS v4 Base and Environmental Metrics

CVSSv4_BT = DecisionPointGroup(name='CVSSv4 Base and Threat Metrics', definition='Base and Threat metrics for CVSS v4', version='4.0.0', decision_points=(tuple(BASE_4 + THREAT_4))) module-attribute

CVSS v4 Base and Threat Metrics

CVSSv4_BTE = DecisionPointGroup(name='CVSSv4 Base, Threat, and Environmental Metrics', definition='Base, Threat, and Environmental metrics for CVSS v4', version='4.0.0', decision_points=(tuple(BASE_4 + THREAT_4 + ENVIRONMENTAL_4))) module-attribute

CVSS v4 Base, Threat, and Environmental Metrics

ENVIRONMENTAL_1 = [COLLATERAL_DAMAGE_POTENTIAL_1, TARGET_DISTRIBUTION_1] module-attribute

List of CVSS v1 Environmental decision points

ENVIRONMENTAL_2 = [COLLATERAL_DAMAGE_POTENTIAL_2, TARGET_DISTRIBUTION_1_1, CONFIDENTIALITY_REQUIREMENT_1, INTEGRITY_REQUIREMENT_1, AVAILABILITY_REQUIREMENT_1] module-attribute

List of CVSS v2 Environmental decision points

ENVIRONMENTAL_3 = [(modify_3(dp)) for dp in BASE_3] + [CONFIDENTIALITY_REQUIREMENT_1_1, INTEGRITY_REQUIREMENT_1_1, AVAILABILITY_REQUIREMENT_1_1] module-attribute

List of CVSS v3 Environmental decision points

ENVIRONMENTAL_4 = [(modify_4(dp)) for dp in BASE_4] + [CONFIDENTIALITY_REQUIREMENT_1_1_1, INTEGRITY_REQUIREMENT_1_1_1, AVAILABILITY_REQUIREMENT_1_1_1] module-attribute

List of CVSS v4 Environmental decision points

EXPLOITABILITY_4 = [ATTACK_VECTOR_3_0_1, ATTACK_COMPLEXITY_3_0_1, ATTACK_REQUIREMENTS_1, PRIVILEGES_REQUIRED_1_0_1, USER_INTERACTION_2] module-attribute

List of CVSS v4 Exploitability decision points

IMPACT_4 = [CONFIDENTIALITY_IMPACT_3_0_0, INTEGRITY_IMPACT_3_0_0, AVAILABILITY_IMPACT_3_0_0, SUBSEQUENT_CONFIDENTIALITY_IMPACT_1, SUBSEQUENT_INTEGRITY_IMPACT_1, SUBSEQUENT_AVAILABILITY_IMPACT_1] module-attribute

List of CVSS v4 Impact decision points

SUPPLEMENTAL_4 = [SAFETY_1, AUTOMATABLE_1, PROVIDER_URGENCY_1, RECOVERY_1, VALUE_DENSITY_1, VULNERABILITY_RESPONSE_EFFORT_1] module-attribute

List of CVSS v4 Supplemental decision points

TEMPORAL_1 = [EXPLOITABILITY_1, REMEDIATION_LEVEL_1, REPORT_CONFIDENCE_1] module-attribute

List of CVSS v1 Temporal decision points

TEMPORAL_2 = [EXPLOITABILITY_1_1, REMEDIATION_LEVEL_1_1, REPORT_CONFIDENCE_1_1] module-attribute

List of CVSS v2 Temporal decision points

TEMPORAL_3 = [EXPLOIT_CODE_MATURITY_1_2, REMEDIATION_LEVEL_1_1, REPORT_CONFIDENCE_2] module-attribute

List of CVSS v3 Temporal decision points

THREAT_4 = [EXPLOIT_MATURITY_2] module-attribute

List of CVSS v4 Threat decision points