The CPSSA module provides a series of features that can be combined with existing OSS (Open-Source Software) for TARA (Threat Analysis and Risk Assessment) to carry out efficient and practical CPSSA following a TaC (TARA as Code) paradigm. This involves code-based and/or machine-readable threat model specifications that can, among other things, be easily integrated into CI/CD pipelines. We build on and provide support for threagile for DevSecOps oriented threat modelling (TM) and security risk assessment (SRA), OWASP pytm for programmatic threat modelling with automatic threat enumeration, and pyfair for quantitative risk analysis following the FAIR (Factor Analysis of Information Risk) approach relying on Monte Carlo simulations.
For more information, we refer the reader to our CPSSA report, published as part of the knowledge base elements of C5-DEC; see the README section on the C5-DEC knowledge base (KB) reports to learn about gaining access to these. In our CPSSA report, in addition to providing a literature review, we describe our threat modelling and security risk assessment method adapted to the Common Criteria, while building on best practices and well-established methods such as the hybrid method developed by the software engineering institute (SEI) of Carnegie Mellon University (CMU).
Here we address system-oriented threat modelling and risk assessment, for organization-centric risk assessment requiring comprehensive risk management according to ISO/IEC 27005, we recommend TRICK Service, enabled by the open-source OpenTRICK software, which supports a detailed quantitative risk assessment approach following a ROSI (Return On Security Investment) method; OpenTRICK has also been further improved and released as open-source software in project CyFORT.
Finally, we also recommend OWASP Threat Dragon for GUI-based TM and Capella Darc Viewpoint for more advanced and detailed TM using Capella for model-based systems engineering, following the ARCADIA method, and ADTool for attack tree modelling and analysis.
C5-DEC provides built-in commands that automate the initial steps of a CPSSA engagement directly from Doorstop project artefacts.
Reads architecture (ARC/HARC/LARC) Doorstop items from a C5-DEC SSDLC project and generates a threat-model template in one of three formats. SWD (software-design) items are not processed.
- threagile (default) — Threagile-compatible YAML. Uses ARC items only.
- pytm-python — executable Python script using the OWASP pytm library. Uses ARC items only.
- pytm-json — JSON file consumable by
pytm.load()orc5dec cpssa risk-analysis. Uses ARC items only.
# Threagile YAML (default) — auto-discovers arc/harc/larc folder
c5dec cpssa create-threat-model --project /path/to/project -o threat-model.yml
# With an explicit architecture folder path
c5dec cpssa create-threat-model --project /path/to/project \
--arc-folder /path/to/project/docs/specs/arc
# pytm executable Python script
c5dec cpssa create-threat-model --project /path/to/project --format pytm-python
# pytm JSON
c5dec cpssa create-threat-model --project /path/to/project --format pytm-json| Argument | Default | Description |
|---|---|---|
--project |
. (current directory) |
C5-DEC SSDLC project root |
-o / --output |
depends on --format |
Destination file |
--format |
threagile |
Output format: threagile, pytm-python, pytm-json |
--arc-folder |
(auto-discover) | Full path to the directory containing architecture item files. When omitted the command searches for a folder named arc, harc, or larc (case-insensitive) with a .doorstop.yml file under the Doorstop specs root. A .doorstop.yml file is not required when the path is explicitly provided. |
Default output file names by format:
| Format | Default output |
|---|---|
threagile |
<project>/threat-model.yml |
pytm-python |
<project>/threat-model-pytm.py |
pytm-json |
<project>/threat-model-pytm.json |
- A
title,date, andauthorsection pre-populated from the project. - A
security_requirementsmap (empty placeholder — populate manually after generation with the relevant security requirement identifiers and descriptions). - A
technical_assetsmap derived from architecture (ARC/HARC/LARC) Doorstop items (up to 40), each withcommunication_linkspopulated from theflowsfield (with fallback to ARC-prefixed Doorstop links). IDs are Threagile-safe (lowercase, hyphens only, max 31 characters to comply with the Excel sheet name limit). - Each communication link includes
protocol,authentication,authorization,vpn,ip_filtered,readonly,data_assets_sent, anddata_assets_received— all derived from theflowsentries on the source ARC item. - Threagile
protocol,authentication,authorization,technology,encryption,machine,size,confidentiality,integrity,availability,trust_boundary_type, anddata_formatvalues are normalised through an external mapping file (threagile-mappings.yml). Free-text field values on ARC items are mapped to Threagile-schema-compatible enumerated values (e.g.OPC-UA→unknown-protocol,https→https). trust_boundariesauto-populated fromzonefields in architecture items, plus an internet perimeter entry. Boundary types are mapped from zone names.- A
data_assetssection populated from uniquedata_assetsfield values across architecture items, plus a baselineuser-dataentry when not already present. threat_actorssourced from thethreat-actors.ymlsidecar file in the ARC directory (see Sidecar files).assumptionssourced from theassumptions.ymlsidecar file in the ARC directory.tags_availablelist auto-populated as the union of all tags used across assets, communication links, and trust boundaries (Threagile validates this).- A
questionsblock and abuse cases covering Unauthorized Data Access and Denial of Service.
Next steps:
- Open
threat-model.ymland complete allTBDfields. - Add or refine
communication_linksentries within each technical asset. - Run Threagile risk analysis:
alternatively, you can run the threagile server and simply browse the file system, load the threat model and run your analysis:
docker run --rm -it -v "$(pwd):/app/work" threagile/threagile:latest \ --model /app/work/threat-model.yml --output /app/work/outputdocker run --rm -it -p 8080:8080 threagile/threagile -server 8080
The generated .py file is a self-contained executable script. It maps each
architecture item to the correct pytm element class (Server, Process,
Datastore, Actor, ExternalEntity, Lambda) based on the item type
field. Trust boundaries are created from zone values. Security control
properties (controls.isEncrypted, controls.hasAccessControl,
controls.authenticatesSource, etc.) are set from optional architecture item fields.
Usage after generation:
# Generate a DFD diagram
python threat-model-pytm.py --dfd | dot -Tpng -o dfd.png
# List all identified threats
python threat-model-pytm.py --list
# Export to JSON (for risk-analysis or archival)
python threat-model-pytm.py --json threat-model-pytm.json
# Generate a threat report from a Markdown template
python threat-model-pytm.py --report docs/basic_template.mdA machine-readable JSON file containing elements, boundaries, dataflows,
abuse cases and security requirements. Can be used as input to
c5dec cpssa risk-analysis for FAIR-based quantitative risk analysis.
Takes a (possibly Threagile-processed) threat model YAML and renders a structured CPSSA Markdown report ready for review or DocEngine publishing.
c5dec cpssa generate-report --model threat-model.yml -o cpssa-report.md| Argument | Default | Description |
|---|---|---|
--model |
threat-model.yml |
Path to threat model YAML |
-o / --output |
cpssa-report.md |
Destination Markdown file |
Report structure:
- Executive summary
- System description (business and technical overview)
- Assets and dependencies (technical assets, data assets, trust boundaries)
- Threat landscape (STRIDE categories)
- 4.1 Threat actors and personas (from
threat-actors.ymlsidecar file) - 4.2 Documented assumptions (from
assumptions.ymlsidecar file)
- 4.1 Threat actors and personas (from
- Attack scenarios (from
abuse_casesin the threat model) - Risk assessment table (requires manual completion)
- Security requirements (extracted from
security_requirementsmap, up to 20 displayed) - Recommended controls (template table)
- Residual risk
- Conclusion
The report is a Markdown file that can be published with Quarto via the C5-DEC DocEngine:
c5dec docengine report -n cpssa-assessmentGenerates a PlantUML Data Flow Diagram from Doorstop architecture (ARC/HARC/LARC)
items. Elements are classified using the type field (see
Doorstop item conventions) and grouped
into trust boundaries derived from zone values.
SWD items are not processed. At most 40 architecture items are included
(same cap as create-threat-model).
Element IDs, asset-type classification, trust-boundary IDs, and flow labels
are all aligned with the Threagile output produced by create-threat-model so
that both artefacts are cross-referenceable:
- Element IDs use the Threagile-safe format (lowercase, hyphens, max 31 chars).
- Flows are labelled
flow-N [protocol / enc|no-enc / auth|no-auth]matching Threagilecommunication_linkskeys with added encryption status and authentication annotations. - Trust-boundary rectangle IDs follow the
<zone>-zoneconvention.
c5dec cpssa generate-dfd --project /path/to/project -o cpssa-dfd.puml
# With an explicit architecture folder
c5dec cpssa generate-dfd --project /path/to/project \
--arc-folder /path/to/project/docs/specs/arc| Argument | Default | Description |
|---|---|---|
--project |
. (current directory) |
C5-DEC SSDLC project root |
-o / --output |
<project>/cpssa-dfd.puml |
Destination PlantUML file |
--arc-folder |
(auto-discover) | Full path to the architecture items directory |
Generates a FAIR parameters YAML template from a threat model. The template
contains per-scenario PERT distribution placeholders for Loss Event Frequency (LEF)
and Loss Magnitude (LM) that the user should calibrate before running
risk-analysis.
For pytm JSON models without explicit abuse_cases, one scenario per element
is synthesised automatically (e.g. "Compromise of HMI Console").
c5dec cpssa fair-input --model threat-model.yml -o fair-params.yml| Argument | Default | Description |
|---|---|---|
--model |
threat-model.yml |
Threagile YAML or pytm JSON threat model |
-o / --output |
<model_dir>/fair-params.yml |
Destination YAML |
Template structure:
The template exposes the full FAIR model tree. Simple lef + lm inputs are
active by default; advanced decomposition nodes are included as commented-out lines
that can be uncommented to replace their parent node:
defaults:
lef: {low: 1, mode: 5, high: 20}
# --- Advanced LEF decomposition (uncomment to replace lef) ---
# tef: {low: 10, mode: 50, high: 200}
# vulnerability: {low: 0.1, mode: 0.3, high: 0.7}
# --- Further TEF decomposition ---
# contact: {low: 100, mode: 500, high: 2000}
# action: {low: 0.05, mode: 0.1, high: 0.3}
# --- Further Vulnerability decomposition ---
# tc: {low: 0.3, mode: 0.5, high: 0.8}
# cs: {low: 0.2, mode: 0.4, high: 0.6}
lm: {low: 10000, mode: 100000, high: 1000000}
# --- Advanced LM decomposition (uncomment to replace lm) ---
# pl: {low: 5000, mode: 50000, high: 500000}
# sl: {low: 5000, mode: 50000, high: 500000}
# --- Further SL decomposition ---
# slef: {low: 0.1, mode: 0.3, high: 0.7}
# slem: {low: 10000, mode: 50000, high: 500000}
scenarios:
"Unauthorized Data Access":
description: "An attacker gains unauthorized access ..."
lef: {low: 1, mode: 5, high: 20}
# ... (same advanced options as defaults, per-scenario)
lm: {low: 10000, mode: 100000, high: 1000000}Usage:
- Generate the template:
c5dec cpssa fair-input --model threat-model.yml - Edit the file to calibrate the FAIR parameter values per scenario.
- Run the analysis:
c5dec cpssa risk-analysis --model threat-model.yml --fair-params fair-params.yml
Runs a FAIR-based Monte Carlo simulation for each abuse case using pyfair. Accepts both Threagile YAML and pytm JSON threat models (auto-detected by file extension).
For pytm JSON models without explicit abuse_cases, the function synthesises
one scenario per element (e.g. "Compromise of HMI Console").
Calibration parameters (Loss Event Frequency and Loss Magnitude PERT distribution bounds) are resolved in the following order of precedence:
- Dedicated FAIR parameters file (
--fair-params) — a YAML file with per-scenario calibration. Generate a template withc5dec cpssa fair-input --model <model>. - Inline in threat model — each abuse case value can be a dict with
description,lef(low/mode/high), andlm(low/mode/high). - Fallback defaults — conservative placeholders:
LEF
{low: 1, mode: 5, high: 20}, LM{low: 10000, mode: 100000, high: 1000000}. A warning is emitted for each scenario using defaults.
# From a Threagile YAML
c5dec cpssa risk-analysis --model threat-model.yml -o results/
# From a pytm JSON
c5dec cpssa risk-analysis --model threat-model-pytm.json -o results/
# With calibrated FAIR parameters
c5dec cpssa risk-analysis --model threat-model.yml \
--fair-params fair-params.yml -o results/| Argument | Default | Description |
|---|---|---|
--model |
threat-model.yml |
Threagile YAML or pytm JSON |
-o / --output |
model parent directory | Output directory for results |
--simulations |
10000 |
Monte Carlo iteration count |
--fair-params |
(none) | YAML file with per-scenario FAIR calibration (see fair-input) |
Outputs:
cpssa-risk-summary.md— human-readable Markdown summary with an input parameter table (showing all supplied FAIR nodes), per-scenario ALE (mean, 95th percentile, max), and a warning banner for scenarios using default parameters.cpssa-risk-results.csv— raw Monte Carlo results.cpssa-risk-{N}.html— one interactive pyfair report per scenario (indexed from 1), each comparing the individual scenario model against the meta-model.
For create-threat-model, generate-dfd and generate-report to produce
meaningful output, architecture (ARC/HARC/LARC) Doorstop items must follow
the conventions described below. SWD (software-design) items are not scanned
by these commands. The water-treatment example under
c5dec/core/cpssa/examples/water-treatment/ demonstrates all conventions.
Mandatory fields:
| Field | Description | Example |
|---|---|---|
header |
Short human-readable component name | HMI Console |
type |
Component type (see table below) | hmi |
zone |
Deployment zone | IT, DMZ, SCADA, OT, CLOUD |
text |
Free-text description of the component | multi-line block scalar |
links |
Doorstop UIDs this item depends on or connects to | [ARC-006, SRS-002] |
Links to SRS items express requirement coverage. Links to other
architecture items express interfaces / data flows and are rendered as arrows
in the DFD and as Dataflow objects in the pytm model. For explicit
control over data flows, use the flows field instead (see
Data flows (flows field)).
Recognised type values and pytm mapping:
type value(s) |
pytm class | DFD kind |
|---|---|---|
server, web-server, app-server, scada-server |
Server |
process |
process, service, api, lambda |
Process / Lambda |
process |
plc, hmi, workstation, jump-server |
Process |
process |
module, library, cli |
Process |
process |
datastore, database, historian, repo |
Datastore |
datastore |
actor, user, operator, external |
Actor |
external |
firewall, gateway, rtu, switch, router |
ExternalEntity |
external |
If type is absent or unrecognised, keyword heuristics on the text field are
used as a fallback.
Optional fields (improve pytm and Threagile model fidelity):
| Field | Type | pytm property | Threagile property | Notes |
|---|---|---|---|---|
os |
string | element.OS |
— | Operating system |
os_version |
string | — | — | OS version (informational) |
vendor |
string | — | owner |
Hardware/software vendor |
model |
string | — | — | Hardware/appliance model |
port |
int | element.port |
— | Primary listening port |
protocol |
string | element.protocol |
— | Primary network protocol |
is_encrypted |
bool | controls.isEncrypted |
encryption (fallback) |
Data-in-transit encryption |
encryption |
string | — | encryption |
Encryption scheme (mapped via threagile-mappings.yml) |
has_access_control |
bool | controls.hasAccessControl |
ip_filtered (on links) |
Access control enabled |
authenticates_source |
bool | controls.authenticatesSource |
— | Source authentication |
stores_pii |
bool | element.storesPII |
— | Datastore stores PII |
is_sql |
bool | element.isSQL |
— | SQL database |
safety_rated |
bool | — | — | Safety-rated device (PLC/RTU) |
machine |
string | — | machine |
physical or virtual (mapped) |
size |
string | — | size |
Component size (mapped) |
confidentiality |
string | — | confidentiality |
CIA rating (mapped) |
integrity |
string | — | integrity |
CIA rating (mapped) |
availability |
string | — | availability |
CIA rating (mapped) |
justification_cia_rating |
string | — | justification_cia_rating |
Rationale for CIA ratings |
data_assets |
list | — | data_assets_processed |
Data asset names processed by this component |
data_assets_stored |
list | — | data_assets_stored |
Data asset IDs stored |
data_formats_accepted |
list | — | data_formats_accepted |
Accepted data formats (mapped) |
internet |
bool | — | internet |
Exposed to the internet |
out_of_scope |
bool | — | out_of_scope |
Mark component as out of scope |
justification_out_of_scope |
string | — | justification_out_of_scope |
Rationale for excluding |
multi_tenant |
bool | — | multi_tenant |
Multi-tenant deployment |
redundancy / redundant |
bool | — | redundant |
Redundant deployment |
custom_developed_parts |
bool | — | custom_developed_parts |
Contains custom code |
Example architecture item (ARC-005.yml):
active: true
header: HMI Console
type: hmi
zone: SCADA
text: |
Operator HMI running Wonderware InTouch for process visualisation, alarm
management, and manual override of pump speeds and chemical dosing rates.
Located in the control room; access requires badge + PIN.
Communicates with field PLCs over OPC-UA.
vendor: Schneider Electric
model: Magelis XBTGT7340
os: Windows Embedded Standard 7
port: 4840
protocol: OPC-UA
encryption: none
machine: physical
size: component
confidentiality: restricted
integrity: critical
availability: critical
justification_cia_rating: >-
Operators issue safety-relevant commands through this console; integrity
and availability are critical for process safety.
has_access_control: true
authenticates_source: false
links:
- SRS-002
- SRS-004
flows:
- target: ARC-006
protocol: OPC-UA
port: 4840
encrypted: false
authentication: none
authorization: none
data_assets:
- operator-commands
- process-displays
data_assets_stored: []
data_formats_accepted:
- serialization
reviewed: falseARC items support an explicit flows field that describes outgoing data-flow
connections to other architecture items. Each entry must have at least a
target key (the destination UID); all other keys are optional:
flows:
- target: ARC-006
protocol: OPC-UA
port: 4840
encrypted: false
authentication: none
authorization: none
vpn: false
readonly: false
data_assets_sent:
- operator-commands
data_assets_received:
- process-displays| Flow field | Type | Default | Description |
|---|---|---|---|
target |
string | (required) | Destination ARC item UID |
protocol |
string | "" |
Network protocol |
port |
int | -1 |
Destination port |
encrypted |
bool | false |
Encrypted channel |
authentication |
string | none |
Authentication mechanism |
authorization |
string | none |
Authorization mechanism |
vpn |
bool | false |
VPN tunnel |
readonly |
bool | false |
Read-only data flow |
data_assets_sent |
list | [] |
Data asset IDs sent |
data_assets_received |
list | [] |
Data asset IDs received |
When flows is absent, the module falls back to the legacy behaviour: it reads
every entry in the Doorstop links field whose UID starts with an
architecture-document prefix (ARC-, HARC-, LARC-) and constructs a
minimal flow using the item-level protocol and port fields. Items that
have not yet been migrated to the flows field continue to produce data-flow
edges automatically.
Two optional YAML sidecar files can be placed alongside architecture items in
the ARC directory. They are read by create-threat-model (Threagile format)
and generate-report, and are automatically skipped by the Doorstop item
loader.
Defines threat actor profiles relevant to the system. Each entry becomes a row
in the CPSSA report's "Threat actors and personas" table and is included in the
Threagile threat_actors section.
threat_actors:
- id: nation-state-apt
name: Nation-State APT
motivation: sabotage, espionage
capability: high
access: external
description: >-
State-sponsored actor targeting critical infrastructure.| Field | Description |
|---|---|
id |
Unique identifier |
name |
Human-readable name |
motivation |
Comma-separated motivations |
capability |
low, medium, or high |
access |
external, internal, or physical |
description |
Free-text profile description |
Documents security assumptions that must be verified. Each entry appears in the
CPSSA report's "Documented assumptions" table and is included in the Threagile
assumptions section.
assumptions:
- id: ASSUM-001
text: >-
All remote access is routed through the jump server.
verified: false| Field | Description |
|---|---|
id |
Unique identifier (e.g. ASSUM-001) |
text |
Concise statement of the assumption |
verified |
true or false (false = open item) |
SRS items are extracted into the security_requirements section of the
Threagile threat model. The first 30 active items with non-empty text are
included. SRS items are not used for pytm formats.
Mandatory fields:
| Field | Description |
|---|---|
header |
Short requirement title |
text |
Requirement statement |
links |
Upward links to MRS or parent requirements |
C5-DEC SSDLC project
│
│ c5dec cpssa create-threat-model [--format threagile]
▼
threat-model.yml ──► Manual completion of TBD fields
│
│ Threagile (optional) or manual risk analysis
▼
(enriched) threat-model.yml
│
│ c5dec cpssa generate-report
▼
cpssa-report.md ──► DocEngine (Quarto) ──► cpssa-report.pdf / .html
C5-DEC SSDLC project
│
│ c5dec cpssa create-threat-model --format pytm-python
▼
threat-model-pytm.py
│
├──► python threat-model-pytm.py --dfd | dot -Tpng -o dfd.png
├──► python threat-model-pytm.py --list (threat list)
├──► python threat-model-pytm.py --json out.json (export JSON)
│
│ c5dec cpssa create-threat-model --format pytm-json
▼
threat-model-pytm.json
│
│ c5dec cpssa fair-input --model threat-model-pytm.json
▼
fair-params.yml ──► Manual calibration of LEF/LM values
│
│ c5dec cpssa risk-analysis --model threat-model-pytm.json --fair-params fair-params.yml
▼
cpssa-risk-summary.md + cpssa-risk-results.csv
C5-DEC SSDLC project
│
├──► c5dec cpssa create-threat-model (Threagile YAML)
├──► c5dec cpssa create-threat-model --format pytm-python (pytm script)
├──► c5dec cpssa create-threat-model --format pytm-json (pytm JSON)
├──► c5dec cpssa generate-dfd (PlantUML DFD)
│
▼
Threat models ──► Manual review & enrichment
│
├──► c5dec cpssa generate-report --model threat-model.yml
├──► c5dec cpssa fair-input --model threat-model.yml (calibration template)
├──► c5dec cpssa risk-analysis --model threat-model.yml --fair-params fair-params.yml
├──► c5dec cpssa risk-analysis --model threat-model-pytm.json
│
▼
Reports & analysis results ──► DocEngine (Quarto)
| Topic | Page |
|---|---|
| Cryptography | Cryptography |
| SSDLC project scaffolding | SSDLC |
| DocEngine publishing | SSDLC — DocEngine |
| Common Criteria toolbox | CCT |