Skip to content

Vultron ActivityStreams Vocabulary Objects

vultron.as_vocab.objects.base

Provides a base class for all Vultron ActivityStreams Objects.

VultronObject dataclass

Bases: as_Object

Base class for all Vultron ActivityStreams Objects

Source code in vultron/as_vocab/objects/base.py
25
26
27
28
29
30
@dataclass_json
@dataclass(kw_only=True)
class VultronObject(as_Object):
    """
    Base class for all Vultron ActivityStreams Objects
    """

vultron.as_vocab.objects.case_participant

Provides various CaseParticipant objects for the Vultron ActivityStreams Vocabulary.

CaseParticipant dataclass

Bases: VultronObject

A CaseParticipant is a wrapper around an Actor in a VulnerabilityCase. It is used to track the status of the participant within the context of a specific case, as well as the roles they play in the case.

Several subclasses of CaseParticipant are provided for convenience, including:

  • FinderParticipant
  • ReporterParticipant
  • FinderReporterParticipant
  • VendorParticipant
  • DeployerParticipant
  • CoordinatorParticipant
  • OtherParticipant

But you can also create your own CaseParticipant objects if you need to.

Examples:

The following example creates a case participant and adds the VENDOR and DEPLOYER roles to it.

actor = as_Actor(name="Actor Name")
cp = CaseParticipant(actor=actor, context="case_id_foo")
cp.add_role(CVDRole.VENDOR)
cp.add_role(CVDRole.DEPLOYER)
Source code in vultron/as_vocab/objects/case_participant.py
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 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
@activitystreams_object
@dataclass_json(letter_case=LetterCase.CAMEL)
@dataclass(kw_only=True)
class CaseParticipant(VultronObject):
    """
    A CaseParticipant is a wrapper around an Actor in a VulnerabilityCase.
    It is used to track the status of the participant within the context of a specific case, as well as the roles they
    play in the case.

    Several subclasses of CaseParticipant are provided for convenience, including:

    - FinderParticipant
    - ReporterParticipant
    - FinderReporterParticipant
    - VendorParticipant
    - DeployerParticipant
    - CoordinatorParticipant
    - OtherParticipant

    But you can also create your own CaseParticipant objects if you need to.

    Examples:
        The following example creates a case participant and adds the VENDOR and DEPLOYER roles to it.

        ```python
        actor = as_Actor(name="Actor Name")
        cp = CaseParticipant(actor=actor, context="case_id_foo")
        cp.add_role(CVDRole.VENDOR)
        cp.add_role(CVDRole.DEPLOYER)
        ```
    """

    actor: as_Actor
    name: str
    case_roles: list[CVDRole] = field(
        default_factory=list,
        metadata=config(
            encoder=lambda x: [CVDRole(value).name for value in x],
            decoder=lambda x: [CVDRole[name] for name in x],
        ),
    )
    participant_status: list[ParticipantStatus] = field(default_factory=list)
    participant_case_name: str = field(
        default=None, metadata=config(exclude=exclude_if_none)
    )
    context: "VulnerabilityCase" | as_Link | str = field(
        default=None, repr=True
    )

    def __post_init__(self):
        super().__post_init__()
        if len(self.case_roles) == 0:
            # if they didn't specify a role, put NO_ROLE here
            self.case_roles.append(CVDRole.NO_ROLE)

        if self.name is None:
            if self.actor is not None:
                if hasattr(self.actor, "name"):
                    self.name = self.actor.name
                else:
                    self.name = self.actor

        if len(self.participant_status) == 0:
            self.participant_status.append(
                ParticipantStatus(
                    context=self.context,
                    actor=self.actor,
                )
            )

        if len(self.case_roles) == 0:
            self.case_roles.append(CVDRole.NO_ROLE)

    def add_role(self, role, reset=False):
        if reset:
            self.case_roles = []
        self.case_roles.append(role)

CoordinatorParticipant dataclass

Bases: CaseParticipant

A CoordinatorParticipant is a CaseParticipant that has the COORDINATOR role in a VulnerabilityCase.

Source code in vultron/as_vocab/objects/case_participant.py
205
206
207
208
209
210
211
212
213
214
215
216
217
@activitystreams_object
@dataclass_json(letter_case=LetterCase.CAMEL)
@dataclass(kw_only=True)
class CoordinatorParticipant(CaseParticipant):
    """
    A CoordinatorParticipant is a CaseParticipant that has the COORDINATOR role in a VulnerabilityCase.
    """

    as_type = "CaseParticipant"

    def __post_init__(self):
        super().__post_init__()
        self.add_role(CVDRole.COORDINATOR, reset=True)

DeployerParticipant dataclass

Bases: CaseParticipant

A DeployerParticipant is a CaseParticipant that has the DEPLOYER role in a VulnerabilityCase.

Source code in vultron/as_vocab/objects/case_participant.py
190
191
192
193
194
195
196
197
198
199
200
201
202
@activitystreams_object
@dataclass_json(letter_case=LetterCase.CAMEL)
@dataclass(kw_only=True)
class DeployerParticipant(CaseParticipant):
    """
    A DeployerParticipant is a CaseParticipant that has the DEPLOYER role in a VulnerabilityCase.
    """

    as_type = "CaseParticipant"

    def __post_init__(self):
        super().__post_init__()
        self.add_role(CVDRole.DEPLOYER, reset=True)

FinderParticipant dataclass

Bases: CaseParticipant

A FinderParticipant is a CaseParticipant that has the FINDER role in a VulnerabilityCase.

Source code in vultron/as_vocab/objects/case_participant.py
113
114
115
116
117
118
119
120
121
122
123
124
125
@activitystreams_object
@dataclass_json(letter_case=LetterCase.CAMEL)
@dataclass(kw_only=True)
class FinderParticipant(CaseParticipant):
    """
    A FinderParticipant is a CaseParticipant that has the FINDER role in a VulnerabilityCase.
    """

    as_type = "CaseParticipant"

    def __post_init__(self):
        super().__post_init__()
        self.add_role(CVDRole.FINDER, reset=True)

FinderReporterParticipant dataclass

Bases: CaseParticipant

A FinderReporterParticipant is a CaseParticipant that has both the FINDER and REPORTER roles in a VulnerabilityCase.

Source code in vultron/as_vocab/objects/case_participant.py
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
@activitystreams_object
@dataclass_json(letter_case=LetterCase.CAMEL)
@dataclass(kw_only=True)
class FinderReporterParticipant(CaseParticipant):
    """
    A FinderReporterParticipant is a CaseParticipant that has both the FINDER and REPORTER roles in a
    VulnerabilityCase.
    """

    as_type = "CaseParticipant"

    def __post_init__(self):
        super().__post_init__()
        self.add_role(CVDRole.FINDER, reset=True)
        self.add_role(CVDRole.REPORTER, reset=False)

        # by definition, to be a reporter, you must have accepted the report
        pstatus = ParticipantStatus(
            context=self.context,
            actor=self.actor,
            rm_state=RM.ACCEPTED,
        )
        self.participant_status = [pstatus]

OtherParticipant dataclass

Bases: CaseParticipant

An OtherParticipant is a CaseParticipant that has the OTHER role in a VulnerabilityCase.

Source code in vultron/as_vocab/objects/case_participant.py
220
221
222
223
224
225
226
227
228
229
230
@activitystreams_object
@dataclass_json(letter_case=LetterCase.CAMEL)
@dataclass(kw_only=True)
class OtherParticipant(CaseParticipant):
    """
    An OtherParticipant is a CaseParticipant that has the OTHER role in a VulnerabilityCase.
    """

    def __post_init__(self):
        super().__post_init__()
        self.add_role(CVDRole.OTHER, reset=True)

ReporterParticipant dataclass

Bases: CaseParticipant

A ReporterParticipant is a CaseParticipant that has the REPORTER role in a VulnerabilityCase.

Source code in vultron/as_vocab/objects/case_participant.py
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
@activitystreams_object
@dataclass_json(letter_case=LetterCase.CAMEL)
@dataclass(kw_only=True)
class ReporterParticipant(CaseParticipant):
    """
    A ReporterParticipant is a CaseParticipant that has the REPORTER role in a VulnerabilityCase.
    """

    as_type = "CaseParticipant"

    def __post_init__(self):
        super().__post_init__()
        self.add_role(CVDRole.REPORTER, reset=True)
        # by definition, to be a reporter, you must have accepted the report
        pstatus = ParticipantStatus(
            context=self.context,
            actor=self.actor,
            rm_state=RM.ACCEPTED,
        )
        self.participant_status = [pstatus]

VendorParticipant dataclass

Bases: CaseParticipant

A VendorParticipant is a CaseParticipant that has the VENDOR role in a VulnerabilityCase.

Source code in vultron/as_vocab/objects/case_participant.py
175
176
177
178
179
180
181
182
183
184
185
186
187
@activitystreams_object
@dataclass_json(letter_case=LetterCase.CAMEL)
@dataclass(kw_only=True)
class VendorParticipant(CaseParticipant):
    """
    A VendorParticipant is a CaseParticipant that has the VENDOR role in a VulnerabilityCase.
    """

    as_type = "CaseParticipant"

    def __post_init__(self):
        super().__post_init__()
        self.add_role(CVDRole.VENDOR, reset=True)

vultron.as_vocab.objects.case_status

Provides Case Status objects for the Vultron ActivityStreams Vocabulary.

CaseStatus dataclass

Bases: VultronObject

Represents the case-level (global, participant-agnostic) status of a VulnerabilityCase.

Source code in vultron/as_vocab/objects/case_status.py
35
36
37
38
39
40
41
42
43
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
@activitystreams_object
@dataclass_json(letter_case=LetterCase.CAMEL)
@dataclass(kw_only=True)
class CaseStatus(VultronObject):
    """
    Represents the case-level (global, participant-agnostic) status of a VulnerabilityCase.
    """

    context: Optional[str] = None  # Case ID goes here
    em_state: EM = field(
        default=EM.NO_EMBARGO,
        metadata={
            "dataclasses_json": {
                "encoder": lambda value: EM(value).name,
                "decoder": lambda name: EM[name],
                "mm_field": fields.Enum,
            }
        },
    )
    pxa_state: CS_pxa = field(
        default=CS_pxa.pxa,
        metadata={
            "dataclasses_json": {
                "encoder": lambda value: CS_pxa(value).name,
                "decoder": lambda name: CS_pxa[name],
                "mm_field": fields.Enum,
            },
        },
    )

    def __post_init__(self) -> None:
        """
        Sets the name of the CaseStatus to the name of the EM state and the name of the PXA state.

        Returns:
            None
        """
        super().__post_init__()
        if self.name is None:
            self.name = " ".join([self.em_state.name, self.pxa_state.name])

__post_init__()

Sets the name of the CaseStatus to the name of the EM state and the name of the PXA state.

Returns:

Type Description
None

None

Source code in vultron/as_vocab/objects/case_status.py
65
66
67
68
69
70
71
72
73
74
def __post_init__(self) -> None:
    """
    Sets the name of the CaseStatus to the name of the EM state and the name of the PXA state.

    Returns:
        None
    """
    super().__post_init__()
    if self.name is None:
        self.name = " ".join([self.em_state.name, self.pxa_state.name])

ParticipantStatus dataclass

Bases: VultronObject

Represents the status of a participant with respect to a VulnerabilityCase (participant-specific).

Source code in vultron/as_vocab/objects/case_status.py
 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
@activitystreams_object
@dataclass_json(letter_case=LetterCase.CAMEL)
@dataclass(kw_only=True)
class ParticipantStatus(VultronObject):
    """
    Represents the status of a participant with respect to a VulnerabilityCase (participant-specific).
    """

    actor: Optional[as_Actor | as_Link | str] = field(default=None)
    context: Optional[as_Object | as_Link | str] = field(default=None)
    rm_state: RM = field(
        default=RM.START,
        repr=True,
        metadata={
            "dataclasses_json": {
                "encoder": lambda value: RM(value).name,
                "decoder": lambda name: RM[name],
                "mm_field": fields.Enum,
            }
        },
    )
    vfd_state: CS_vfd = field(
        default=CS_vfd.vfd,
        metadata={
            "dataclasses_json": {
                "encoder": lambda value: CS_vfd(value).name,
                "decoder": lambda name: CS_vfd[name],
                "mm_field": fields.Enum,
            }
        },
    )
    case_engagement: bool = True
    embargo_adherence: bool = True
    tracking_id: Optional[str] = field(
        metadata=config(exclude=exclude_if_none), default=None
    )
    case_status: Optional[CaseStatus] = field(
        metadata=config(exclude=exclude_if_none), default=None
    )

    def __post_init__(self) -> None:
        """
        Sets the name of the ParticipantStatus to the name of the RM state, the name of the VFD state, and the name of
        the CaseStatus (if present).

        Returns:
            None
        """
        super().__post_init__()
        if self.name is None:
            parts = [self.rm_state.name, self.vfd_state.name]
            if self.case_status is not None:
                parts.append(self.case_status.name)
            self.name = " ".join(parts)

__post_init__()

Sets the name of the ParticipantStatus to the name of the RM state, the name of the VFD state, and the name of the CaseStatus (if present).

Returns:

Type Description
None

None

Source code in vultron/as_vocab/objects/case_status.py
117
118
119
120
121
122
123
124
125
126
127
128
129
130
def __post_init__(self) -> None:
    """
    Sets the name of the ParticipantStatus to the name of the RM state, the name of the VFD state, and the name of
    the CaseStatus (if present).

    Returns:
        None
    """
    super().__post_init__()
    if self.name is None:
        parts = [self.rm_state.name, self.vfd_state.name]
        if self.case_status is not None:
            parts.append(self.case_status.name)
        self.name = " ".join(parts)

vultron.as_vocab.objects.embargo_event

Provides an EmbargoEvent object for the Vultron ActivityStreams Vocabulary.

EmbargoEvent dataclass

Bases: as_Event

An EmbargoEvent is an Event that represents an embargo on a VulnerabilityCase.

Source code in vultron/as_vocab/objects/embargo_event.py
40
41
42
43
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
@activitystreams_object
@dataclass_json(letter_case=LetterCase.CAMEL)
@dataclass(kw_only=True)
class EmbargoEvent(as_Event):
    """
    An EmbargoEvent is an Event that represents an embargo on a VulnerabilityCase.
    """

    start_time: Optional[datetime] = field(
        metadata=config(
            exclude=exclude_if_none,
            encoder=to_isofmt,
            decoder=from_isofmt,
            mm_field=fields.DateTime(format="iso"),
        ),
        default_factory=now_utc,
    )
    end_time: Optional[datetime] = field(
        metadata=config(
            exclude=exclude_if_none,
            encoder=to_isofmt,
            decoder=from_isofmt,
            mm_field=fields.DateTime(format="iso"),
        ),
        default_factory=_45_days_hence,
    )

    def __post_init__(self):
        super().__post_init__()
        start_iso = self.start_time.isoformat()
        end_iso = self.end_time.isoformat()

        # self.as_id = "_".join([start_iso, end_iso])

        parts = [
            "Embargo for",
            name_of(self.context),
        ]
        if self.start_time:
            parts.append(f"start: {start_iso}")
        if self.end_time:
            parts.append(f"end: {end_iso}")
        self.name = " ".join([str(part) for part in parts])

vultron.as_vocab.objects.vulnerability_case

Provides a VulnerabilityCase object for the Vultron ActivityStreams Vocabulary.

VulnerabilityCase dataclass

Bases: VultronObject

A Vulnerability Case is a container for vulnerability reports, and is used to track the lifecycle of the case and its constituent vulnerability reports, including the status of the case itself, the participants in the case, and the embargo status of the case.

Source code in vultron/as_vocab/objects/vulnerability_case.py
 40
 41
 42
 43
 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
@activitystreams_object
@dataclass_json(letter_case=LetterCase.CAMEL)
@dataclass
class VulnerabilityCase(VultronObject):
    """
    A Vulnerability Case is a container for vulnerability reports, and is used to track the
    lifecycle of the case and its constituent vulnerability reports, including the status of the case itself,
    the participants in the case, and the embargo status of the case.
    """

    case_participants: list[CaseParticipant] = field(
        default_factory=list, metadata=config(exclude=exclude_if_empty)
    )
    vulnerability_reports: list[VulnerabilityReport] = field(
        default_factory=list, metadata=config(exclude=exclude_if_empty)
    )
    case_status: list[CaseStatus] = field(default_factory=init_case_status)

    # don't excludeIfNone here to make it explicit when there is no embargo
    active_embargo: Optional[EmbargoEvent] = None

    proposed_embargoes: list[EmbargoEvent] = field(
        default_factory=list, metadata=config(exclude=exclude_if_empty)
    )

    case_activity: list[as_Activity] = field(
        default_factory=list, metadata=config(exclude=exclude_if_empty)
    )

    # case relationships
    parent_cases: Optional[list[str]] = field(
        default_factory=list, metadata=config(exclude=exclude_if_empty)
    )
    child_cases: Optional[list[str]] = field(
        default_factory=list, metadata=config(exclude=exclude_if_empty)
    )
    sibling_cases: Optional[list[str]] = field(
        default_factory=list, metadata=config(exclude=exclude_if_empty)
    )

    def __post_init__(self):
        super().__post_init__()

        # set the context of the case status objects to the case id
        for cs in self.case_status:
            cs.context = self.as_id

    def add_report(self, report: VulnerabilityReport) -> None:
        """Add a vulnerability report to the case

        Args:
            report: a VulnerabilityReport object
        """
        self.vulnerability_reports.append(report)

    def add_participant(self, participant: CaseParticipant) -> None:
        """Add a participant to the case

        Args:
            participant: a CaseParticipant object
        """
        self.case_participants.append(participant)

    def set_embargo(self, embargo: EmbargoEvent) -> None:
        """Set the active embargo for the case

        Args:
            embargo: an EmbargoEvent object
        """
        self.active_embargo = embargo
        self.case_status.em_state = EM.ACTIVE

    def record_activity(self, activity: as_Activity) -> None:
        """Record an activity in the case

        Args:
            activity: an as_Activity object

        """
        ids = set([a.as_id for a in self.case_activity])
        if activity.as_id not in ids:
            self.case_activity.append(activity)

add_participant(participant)

Add a participant to the case

Parameters:

Name Type Description Default
participant CaseParticipant

a CaseParticipant object

required
Source code in vultron/as_vocab/objects/vulnerability_case.py
 95
 96
 97
 98
 99
100
101
def add_participant(self, participant: CaseParticipant) -> None:
    """Add a participant to the case

    Args:
        participant: a CaseParticipant object
    """
    self.case_participants.append(participant)

add_report(report)

Add a vulnerability report to the case

Parameters:

Name Type Description Default
report VulnerabilityReport

a VulnerabilityReport object

required
Source code in vultron/as_vocab/objects/vulnerability_case.py
87
88
89
90
91
92
93
def add_report(self, report: VulnerabilityReport) -> None:
    """Add a vulnerability report to the case

    Args:
        report: a VulnerabilityReport object
    """
    self.vulnerability_reports.append(report)

record_activity(activity)

Record an activity in the case

Parameters:

Name Type Description Default
activity as_Activity

an as_Activity object

required
Source code in vultron/as_vocab/objects/vulnerability_case.py
112
113
114
115
116
117
118
119
120
121
def record_activity(self, activity: as_Activity) -> None:
    """Record an activity in the case

    Args:
        activity: an as_Activity object

    """
    ids = set([a.as_id for a in self.case_activity])
    if activity.as_id not in ids:
        self.case_activity.append(activity)

set_embargo(embargo)

Set the active embargo for the case

Parameters:

Name Type Description Default
embargo EmbargoEvent

an EmbargoEvent object

required
Source code in vultron/as_vocab/objects/vulnerability_case.py
103
104
105
106
107
108
109
110
def set_embargo(self, embargo: EmbargoEvent) -> None:
    """Set the active embargo for the case

    Args:
        embargo: an EmbargoEvent object
    """
    self.active_embargo = embargo
    self.case_status.em_state = EM.ACTIVE

vultron.as_vocab.objects.vulnerability_report

Provides a VulnerabilityReport object for the Vultron ActivityStreams Vocabulary.

VulnerabilityReport dataclass

Bases: VultronObject

Represents a Vulnerability Report as an ActivityStreams Object.

Source code in vultron/as_vocab/objects/vulnerability_report.py
26
27
28
29
30
31
32
@activitystreams_object
@dataclass_json(letter_case=LetterCase.CAMEL)
@dataclass
class VulnerabilityReport(VultronObject):
    """
    Represents a Vulnerability Report as an ActivityStreams Object.
    """