Skip to content

Vultron Case States Module

vultron.core.case_states

The vultron.core.case_states package implements the CVD Case State Model.

vultron.core.case_states.hypercube

The vultron.core.case_states.hypercube module contains the CVDmodel class, which represents the state graph of a Coordinated Vulnerability Disclosure case.

Based on Householder, A. D., and Jonathan Spring. A State-Based Model for Multi-Party Coordinated Vulnerability Disclosure (MPCVD). Tech. Rep. CMU/SEI-2021-SR-021, Software Engineering Institute, Carnegie-Mellon University, Pittsburgh, PA, 2021.

DESIDERATA = (('V', 'P'), ('V', 'X'), ('V', 'A'), ('F', 'P'), ('F', 'X'), ('F', 'A'), ('D', 'P'), ('D', 'X'), ('D', 'A'), ('P', 'X'), ('P', 'A'), ('X', 'A')) module-attribute

Taken directly from the paper: Given (A,B), you prefer histories in which A precedes B over ones in which B precedes A.

CVDmodel

A CVDmodel is a graph of states and transitions between them. The model reflects the CVD process and the actions that can be taken at a high level. It also has a set of histories that can be scored.

histories property

A list of all possible case histories traversing the case state space from vfdpxa to VFDPXA.

states property

Returns the states in the model

compute_pagerank()

Compute the pagerank of each state in the model. Runs the NetworkX pagerank algorithm on the model graph 10000 times. Because the model is a directed graph, we need to add a wraparound link so that the pagerank algorithm can walk from the end back to the beginning naturally.

Returns:

Type Description
dict[str, float]

a dict of state: pagerank

find_states(pat)

Find states that match a given pattern Args: pat: a regex pattern to match

Returns:

Type Description
list

a list of states that match the pattern

Raises:

Type Description
CVDmodelError

if the pattern is invalid

move_score(from_state, to_state)

Compute the score of moving from one state to another Args: from_state: The state to move from to_state: The state to move to

Returns:

Type Description
float

the score of the move

paths_between(start='vfdpxa', end='VFDPXA')

Return all paths of transitions between two states

Parameters:

Name Type Description Default
start str

the start state, default="vfdpxa"

'vfdpxa'
end str

the end state, default="VFDPXA"

'VFDPXA'

Returns:

Type Description
list[Any] | None

a list of paths

paths_from(state='vfdpxa')

Return all paths of transitions that lead from a given state

Parameters:

Name Type Description Default
state str

the state to return paths from, default="vfdpxa"

'vfdpxa'

Returns:

Type Description
list[Any] | None

a list of paths

paths_to(state='VFDPXA')

Return all paths of transitions that lead to a given state

Parameters:

Name Type Description Default
state str

the state to return paths to, default="VFDPXA"

'VFDPXA'

Returns:

Type Description
list[Any] | None

a list of paths

previous_state(state)

For a given state, return the previous state(s)

Parameters:

Name Type Description Default
state str

the state to return the previous state(s) for

required

Returns:

Type Description
list[str]

a list of previous states

score_hist(h)

Compute the score for a given history

Parameters:

Name Type Description Default
h str

the history to score

required

Returns:

Type Description
float

the score for the history

sequences_between(start='vfdpxa', end='VFDPXA')

Return all sequences of transitions between two states

Parameters:

Name Type Description Default
start str

the start state, default="vfdpxa"

'vfdpxa'
end str

the end state, default="VFDPXA"

'VFDPXA'

Returns:

Type Description
list[tuple[str]]

a list of sequences

sequences_from(state='vfdpxa')

Return all sequences of transitions that lead from a given state

Parameters:

Name Type Description Default
state str

the state to return sequences from

'vfdpxa'

Returns:

Type Description
list[tuple[str]]

a list of sequences

sequences_to(state)

Return all sequences of transitions that lead to a given state

Parameters:

Name Type Description Default
state str

the state to return sequences to

required

Returns:

Type Description
list[tuple[str]]

a list of sequences

state_adjacency_matrix()

Return the state adjacency matrix for the model

Returns:

Type Description
DataFrame

a dataframe of the state adjacency matrix

state_info(state)

Returns the info for a given state

Parameters:

Name Type Description Default
state str

the state to return info for

required

Returns:

Type Description
dict

a dict of info for the state

state_transition_matrix()

Return the state transition matrix for the model Returns: a dataframe of the state transition matrix

transitions_in_path(path)

Return the transitions in a path

Parameters:

Name Type Description Default
path list

a list of graph edges

required

Returns:

Type Description
tuple[str]

a tuple of the edge labels

walk_from(start=None, end='VFDPXA')

Randomly walk from a given state to a given state

Parameters:

Name Type Description Default
start str | None

the start state, default=None

None
end str

the end state, default="VFDPXA"

'VFDPXA'

Returns:

Type Description
tuple

a tuple of the path and the probabilities of each step

vultron.core.states.cs

The vultron.core.states.cs module implements the CVD Case State Model enums.

It also provides functions for converting between state strings and enums.

AttackObservation

Bases: StrEnum

Represents the attack observation state of a case.

CS_d

Bases: StrEnum

Deployer-path sub-machine: fix deployment (2 states).

Monotone ladder: d → D.

CS_pxa

Bases: Enum

Represents the public state of a case.

  • pxa indicates the public is unaware, no exploit has been published, and no attacks have been observed.
  • Pxa indicates the public is aware, no exploit has been published, and no attacks have been observed.
  • pxA indicates the public is unaware, no exploit has been published, and attacks have been observed.
  • PxA indicates the public is aware, no exploit has been published, and attacks have been observed.
  • pXa indicates the public is unaware, an exploit has been published, and no attacks have been observed.
  • pXA indicates the public is unaware, an exploit has been published, and attacks have been observed.
  • PXa indicates the public is aware, an exploit has been published, and no attacks have been observed.
  • PXA indicates the public is aware, an exploit has been published, and attacks have been observed.

Note that pXa and pXA are ephemeral states: the pX→PX invariant means that once an exploit is published the public immediately becomes aware, so these states resolve to PXa/PXA in practice.

CS_vf

Bases: StrEnum

Vendor-path sub-machine: vendor awareness + fix readiness (3 states).

Monotone ladder: vf → Vf → VF.

DState

Bases: NamedTuple

Deployer-path sub-machine state (D bit only).

ExploitPublication

Bases: StrEnum

Represents the exploit publication state of a case.

FixDeployment

Bases: StrEnum

Represents the fix deployment state of a case.

FixReadiness

Bases: StrEnum

Represents the fix readiness state of a case.

PublicAwareness

Bases: StrEnum

Represents the public awareness state of a case.

PxaState

Bases: NamedTuple

Represents the public exploit path state of a case.

State

Bases: NamedTuple

Represents the state of a case.

VendorAwareness

Bases: StrEnum

Represents the vendor awareness state of a case.

VfState

Bases: NamedTuple

Vendor-path sub-machine state (V+F bits only).

create_pxa_machine()

Generates a new Case State Public Exploit Attacks Machine object

Returns:

Name Type Description
Machine Machine

New Machine object

is_d_fix_deployed(state)

Return True when fix deployment is set (D bit).

Examples::

is_d_fix_deployed(CS_d.D)  # True
is_d_fix_deployed(CS_d.d)  # False

is_monotonic_d_forward(source, dest)

Return True if (source → dest) advances D without regressing.

Examples::

is_monotonic_d_forward(CS_d.d, CS_d.D)  # True
is_monotonic_d_forward(CS_d.D, CS_d.d)  # False (D un-set)
is_monotonic_d_forward(CS_d.d, CS_d.d)  # False (no change)

is_monotonic_pxa_forward(source, dest)

Return True if (source → dest) advances PXA without regressing.

The P/X/A components are mutually independent one-way latches, so any combination of them being newly set is monotone forward — including multi-component jumps such as pxa → PXA that :func:is_valid_pxa_transition does not recognise.

Equality returns False (nothing advanced). Mirrors :func:vultron.core.states.rm.is_monotonic_rm_forward.

Examples::

is_monotonic_pxa_forward(CS_pxa.pxa, CS_pxa.PXa)  # True
is_monotonic_pxa_forward(CS_pxa.Pxa, CS_pxa.pxa)  # False (P un-set)
is_monotonic_pxa_forward(CS_pxa.PxA, CS_pxa.PXa)  # False (A un-set)

is_monotonic_vf_forward(source, dest)

Return True if (source → dest) advances VF without regressing.

Examples::

is_monotonic_vf_forward(CS_vf.vf, CS_vf.VF)  # True
is_monotonic_vf_forward(CS_vf.Vf, CS_vf.Vf)  # False (no change)
is_monotonic_vf_forward(CS_vf.VF, CS_vf.Vf)  # False (F un-set)

is_pxa_assertion_acceptable(current, asserted)

Return True if a received CaseStatus may move PXA current → asserted.

The PXA acceptance rule for a received status (RSH-09-003, RSH-09-005): the asserted state is the current one, or a monotone forward move from it. Deliberately weaker than :func:is_valid_pxa_transition, which applies only to local writes (CSB-16-002). The CASE_MANAGER applies it to a received CaseStatus and ParticipantStatus and when adopting a report's P/X/A; a replica copies the entry instead (CM-23-016).

is_pxa_attacks_observed(state)

Return True if attacks have been observed in the wild (A bit set).

Examples::

is_pxa_attacks_observed(CS_pxa.pxA)  # True
is_pxa_attacks_observed(CS_pxa.PXA)  # True
is_pxa_attacks_observed(CS_pxa.pxa)  # False

is_pxa_exploit_public(state)

Return True if exploit code is publicly available (X bit set).

Note: pX is transient — the pX→PX invariant means an exploit being public without public awareness is ephemeral; in practice P will also be set. This predicate reflects the X bit only.

Examples::

is_pxa_exploit_public(CS_pxa.pXa)  # True
is_pxa_exploit_public(CS_pxa.PXA)  # True
is_pxa_exploit_public(CS_pxa.Pxa)  # False

is_pxa_public_aware(state)

Return True if the public is aware of the vulnerability (P bit set).

Examples::

is_pxa_public_aware(CS_pxa.Pxa)  # True
is_pxa_public_aware(CS_pxa.PXA)  # True
is_pxa_public_aware(CS_pxa.pxa)  # False

is_valid_d_transition(source, dest)

Return True if (source → dest) is a valid D state transition.

is_valid_pxa_transition(source, dest)

Return True if (source → dest) is a valid PXA state transition.

is_valid_vf_transition(source, dest)

Return True if (source → dest) is a valid VF state transition.

is_vf_fix_ready(state)

Return True when fix readiness is set (F bit; implies vendor awareness).

Examples::

is_vf_fix_ready(CS_vf.VF)  # True
is_vf_fix_ready(CS_vf.Vf)  # False
is_vf_fix_ready(CS_vf.vf)  # False

is_vf_vendor_aware(state)

Return True when vendor awareness is set (V bit in the VF path).

Examples::

is_vf_vendor_aware(CS_vf.Vf)  # True
is_vf_vendor_aware(CS_vf.VF)  # True
is_vf_vendor_aware(CS_vf.vf)  # False

state_string_to_enum2(s)

Convert a state string to a list of enums that define the state

Example

state_string_to_enum2('vfdpxa')
returns
( VendorAwareness.VENDOR_UNAWARE,
  FixReadiness.FIX_NOT_READY,
  FixDeployment.FIX_NOT_DEPLOYED,
  PublicAwareness.PUBLIC_UNAWARE,
  ExploitPublication.NO_PUBLIC_EXPLOIT,
  AttackObservation.NO_ATTACKS_OBSERVED)

Parameters:

Name Type Description Default
s str

the state string

required

Returns:

Type Description
tuple[StrEnum, ...]

a list of Enums

state_string_to_enums(s)

Convert a state string to a tuple of enums that define the state (CS_vf, CS_d, CS_pxa)

Parameters:

Name Type Description Default
s str

the state string

required

Returns:

Type Description
tuple[CS_vf, CS_d, CS_pxa]

a tuple of enums

vultron.core.case_states.validations

This module contains functions to validate the various strings and patterns used by the CVD State Model

CS_EVENT_LETTERS = tuple('VFDPXA') module-attribute

The six case-state events, in the order a state string spells them.

ensure_valid_history(func)

Decorator to ensure a valid history is passed to a function

Example

@ensure_valid_history
def my_func(history, ...):
    ...

Args: func: the function to decorate

Returns:

Type Description
F

the decorated function

Raises:

Type Description
HistoryValidationError

if the history is invalid

ensure_valid_pattern(func)

Function decorator to ensure a valid pattern is passed to a function

Example

@ensure_valid_pattern
def my_func(pattern, ...):
     ...

Args: func: the function to decorate

Returns:

Type Description
F

the decorated function

ensure_valid_state(func)

Function Decorator to ensure a valid state is passed to a function

Example

@ensure_valid_state
def my_func(state, ...):
    ...

Parameters:

Name Type Description Default
func F

the function to decorate

required

Returns:

Type Description
F

the decorated function

ensure_valid_state_method_wrapper(func)

Method Decorator to ensure a valid state is passed to a method. Equivalent to ensure_valid_state, but for methods.

Example

class MyClass:
    @ensure_valid_state_method_wrapper
    def my_method(self, state, ...):
        ...

Parameters:

Name Type Description Default
func F

the method to decorate

required

Returns:

Type Description
F

the decorated method

is_valid_history(h)

Validate a history string. Checks that the history is exactly six characters long, is all uppercase, and contains one each of V, F, D, P, X, and A. Also checks that the causally-related events are in the correct order:

  • V \(\prec\) F \(\prec\) D
  • P \(\prec\) X or XP
  • V \(\prec\) P or PV

Example

is_valid_history("VFDPXA")
succeeds, but
is_valid_history("VFDPX")
fails with a HistoryValidationError.

Parameters:

Name Type Description Default
h str

the history string to validate

required

Returns:

Type Description
None

None

Raises:

Type Description
HistoryValidationError

if the history is invalid

is_valid_pattern(pat)

Validate a pattern string. Patterns are expected to be regular expressions with the following constraints:

  • The pattern is exactly six characters long.
  • The pattern contains either upper or lower case v, f, d, p, x, a, in that order, or a dot.

Examples:

is_valid_pattern("vfdpxa")
is_valid_pattern("Vfd.X.")
will succeed but
is_valid_pattern("xpdfva")
is_valid_pattern("vfDPx")
fail with a PatternValidationError.

Parameters:

Name Type Description Default
pat str

the pattern string to validate

required

Returns:

Type Description
None

None

Raises:

Type Description
PatternValidationError

if the pattern is invalid

is_valid_state(state)

Validate a state string. Checks that the state is a valid state pattern. Also checks that the state is not impossible (e.g. vF...., .fD...) Finally, verifies that only allowed symbols (vVfFdDpPxXaA.) are used.

Parameters:

Name Type Description Default
state str

the state string to validate

required

Returns:

Type Description
None

None

Raises:

Type Description
StateValidationError

if the state is invalid

is_valid_transition(src, dst, allow_null=False)

Validate a transition from src to dst

Parameters:

Name Type Description Default
src str

the source state

required
dst str

the destination state

required
allow_null bool

if True, allow null transitions (src==dst), default=False

False

Returns:

Type Description
None

None

Raises:

Type Description
TransitionValidationError

if the transition is invalid

valid_states()

Return every valid case-state string, in lattice product order.

Enumerates each upper/lower-case combination of :data:CS_EVENT_LETTERS and keeps those :func:is_valid_state accepts. The hypercube model builds its state graph from this list, and the pattern modules' report scripts iterate it directly, so neither needs the other to enumerate states.