From e8397ab397f6e039dacefabf3e51d2bbdd0e3e8b Mon Sep 17 00:00:00 2001 From: Ron <45816308+rjaegers@users.noreply.github.com> Date: Wed, 1 Jul 2026 19:44:35 +0000 Subject: [PATCH 01/11] docs: add thread model document --- .github/workflows/wc-document-generation.yml | 10 +- .../templates/partials/document-control.md.j2 | 14 +- docs/templates/threat-model.md.j2 | 250 +++++++ docs/threat-model.sbdl | 613 ++++++++++++++++++ 4 files changed, 879 insertions(+), 8 deletions(-) create mode 100644 docs/templates/threat-model.md.j2 create mode 100644 docs/threat-model.sbdl diff --git a/.github/workflows/wc-document-generation.yml b/.github/workflows/wc-document-generation.yml index 0683f8cb..6c1ba098 100644 --- a/.github/workflows/wc-document-generation.yml +++ b/.github/workflows/wc-document-generation.yml @@ -28,7 +28,7 @@ jobs: run: | set -Eeuo pipefail - sudo apt-get update && sudo apt-get install --no-install-recommends -y plantuml + sudo apt-get update && sudo apt-get install --no-install-recommends -y graphviz plantuml python -m pip install sbdl==1.22.7 - name: Build & Validate SBDL model run: sbdl -m compile test/cpp/integration-tests.bats test/cpp/features/*.feature test/embedded-cpp/integration-tests.bats test/embedded-cpp/features/*.feature > amp-devcontainer.sbdl @@ -58,6 +58,10 @@ jobs: run: sbdl -m template-fill --set-config template_extensions_file docs/templates/jinja-extensions.py --template docs/templates/software-test-plan.md.j2 amp-devcontainer.sbdl document-control.sbdl > software-test-plan.md - name: ๐Ÿงฉ Generate RTM document run: sbdl -m template-fill --set-config template_extensions_file docs/templates/jinja-extensions.py --template docs/templates/requirements-traceability-matrix.md.j2 amp-devcontainer.sbdl document-control.sbdl > requirements-traceability-matrix.md + - name: ๐Ÿ›ก๏ธ Generate Threat Model document + run: sbdl -m template-fill --set-config template_extensions_file docs/templates/jinja-extensions.py --template docs/templates/threat-model.md.j2 docs/threat-model.sbdl document-control.sbdl > threat-model.md + - name: ๐Ÿ“Š Generate Threat Model diagram + run: sbdl -m aspect-diagram docs/threat-model.sbdl -o threat-model-dfd.png - name: ๐Ÿ“„ Generate SRS PDF uses: docker://pandoc/extra:3.9.0.0-ubuntu@sha256:72afa9c8d3300e5f10c9c4330e101725687f2179bffd912fb859c6d2ae85de62 with: @@ -70,6 +74,10 @@ jobs: uses: docker://pandoc/extra:3.9.0.0-ubuntu@sha256:72afa9c8d3300e5f10c9c4330e101725687f2179bffd912fb859c6d2ae85de62 with: args: --template eisvogel --syntax-highlighting idiomatic --number-sections --output requirements-traceability-matrix.pdf requirements-traceability-matrix.md + - name: ๐Ÿ›ก๏ธ Generate Threat Model PDF + uses: docker://pandoc/extra:3.9.0.0-ubuntu@sha256:72afa9c8d3300e5f10c9c4330e101725687f2179bffd912fb859c6d2ae85de62 + with: + args: --template eisvogel --syntax-highlighting idiomatic --number-sections --output threat-model.pdf threat-model.md - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: documents diff --git a/docs/templates/partials/document-control.md.j2 b/docs/templates/partials/document-control.md.j2 index 817e049c..04aa98a7 100644 --- a/docs/templates/partials/document-control.md.j2 +++ b/docs/templates/partials/document-control.md.j2 @@ -1,7 +1,7 @@ -| Property | Value | -|-------------------|---------------------------------------------------------------------------------------------------------------------------| -| Document version | {{ sbdl['doc_control']['custom:version'] }} | -| Generation date | {{ sbdl['doc_control']['custom:generated_at'] | strftime('%Y-%m-%d') }} | -| Source revision | {{ sbdl['doc_control']['custom:git_sha'] }} | -| Source branch/tag | {{ sbdl['doc_control']['custom:git_ref'] }} | -| Model | SBDL {{ sbdl['doc_control']['custom:sbdl_compiler_version'] }} (DSL {{ sbdl['doc_control']['custom:sbdl_dsl_version'] }}) | +| Property | Value | +|-------------------------|---------------------------------------------------------------------------------------------------------------------------| +| Document version | {{ sbdl['doc_control']['custom:version'] }} | +| Generation date | {{ sbdl['doc_control']['custom:generated_at'] | strftime('%Y-%m-%d') }} | +| Source revision | {{ sbdl['doc_control']['custom:git_sha'] }} | +| Source branch/tag | {{ sbdl['doc_control']['custom:git_ref'] }} | +| Model | SBDL {{ sbdl['doc_control']['custom:sbdl_compiler_version'] }} (DSL {{ sbdl['doc_control']['custom:sbdl_dsl_version'] }}) | diff --git a/docs/templates/threat-model.md.j2 b/docs/templates/threat-model.md.j2 new file mode 100644 index 00000000..6cea5d66 --- /dev/null +++ b/docs/templates/threat-model.md.j2 @@ -0,0 +1,250 @@ +--- +title: "Threat model for amp-devcontainer" +author: ["@rjaegers"] +colorlinks: true +date: "{{ sbdl['doc_control']['custom:generated_at'] | strftime('%Y-%m-%d') }}" +keywords: [Threat, Model, Security, STRIDE, FMEA, amp-devcontainer] +lang: "en" +titlepage: true +titlepage-color: "0B5ED7" +titlepage-text-color: "FFFFFF" +titlepage-rule-color: "FFFFFF" +titlepage-rule-height: 2 +toc: true +toc-own-page: true +header-includes: + - \AtEndDocument{\label{lastpage}} +{%- if sbdl['doc_control']['custom:is_release'] != 'true' %} +watermark: "DRAFT" +{%- endif %} +footer-right: "\\thepage \\hspace{1pt} of \\pageref*{lastpage}" +... + +{% import "partials/text-utilities.j2" as utils %} +{%- set system = sbdl['system_amp_devcontainer'] -%} + +# Introduction + +## Purpose + +This document describes the security threat model for amp-devcontainer. +It identifies the assets, trust boundaries, and data flows of the system, enumerates the credible threats against it, and records the mitigations that reduce the associated risk to an acceptable level. + +## Scope + +This threat model covers the supply chain and runtime security of the amp-devcontainer container images, their build pipeline, and their distribution. +The following is in scope: + +- The container build pipeline and its execution environment +- Dependency acquisition, pinning, and integrity verification +- Container image signing, publication, and consumption +- The runtime posture of the released container images + +The following is out of scope: + +- Application-level software built using the containers +- Security of third-party services beyond the project's control +- Physical security of developer workstations + +## Methodology + +Threats are identified using the [STRIDE](https://learn.microsoft.com/en-us/azure/security/develop/threat-modeling-tool-threats) classification (Spoofing, Tampering, Repudiation, Information Disclosure, Denial of Service, Elevation of Privilege). + +Each threat is quantified using a Failure Mode and Effects Analysis (FMEA) style Risk Priority Number (RPN): + +$$RPN = S \times O \times D$$ + +where *Severity* ($S$) is a property of the threat's impact, *Occurrence* ($O$) is a property of its attack vector, and *Detectability* ($D$) is a property of the threat itself. Each factor is rated on a scale of 1 (low) to 10 (high). A residual RPN is computed from the post-mitigation occurrence and detectability values to show the effect of the implemented controls. + +The complete model โ€” assets, boundaries, data flows, threats, and mitigations โ€” is expressed in [sbdl](https://sbdl.dev) using custom types layered on the built-in FMEA types, and is versioned alongside the source code. This document is generated from that single source of truth, exactly as the requirements documents are. + +## References + +| Identifier | Title | +|------------|----------------------------------------------------------------------------------------------------------------------------------------| +| STRIDE | [The STRIDE Threat Model](https://learn.microsoft.com/en-us/azure/security/develop/threat-modeling-tool-threats) | +| FMEA | [Failure Mode and Effects Analysis](https://en.wikipedia.org/wiki/Failure_mode_and_effects_analysis) | +| CAPEC | [Common Attack Pattern Enumeration and Classification](https://capec.mitre.org/) | +| CWE | [Common Weakness Enumeration](https://cwe.mitre.org/) | +| SLSA | [Supply-chain Levels for Software Artifacts v1.0](https://slsa.dev/spec/v1.0/levels) | + +## Document Control + +{% include "partials/document-control.md.j2" with context %} + +This document is generated from a formal model defined in [sbdl](https://sbdl.dev) and versioned alongside the source code in Git. +The authoritative source of change history is the [Git log](https://github.com/philips-software/amp-devcontainer/commits/) of the source material from which the model is built. + +# System overview + +{{ utils.reencode(system.description) }} + +| Property | Value | +|-----------------------|----------------------------------------------| +| Business criticality | {{ system['custom:business_criticality'] }} | +| Exposure | {{ system['custom:exposure'] }} | +| Last reviewed | {{ system['custom:reviewed_at'] }} | + +# Trust boundaries + +The system is decomposed into the following trust boundaries. Data crossing a boundary is subject to the threats analysed in this document. + +| Trust boundary | Description | +|----------------|-------------| +{%- for id, item in sbdl.items() if item.type == 'trust_boundary' %} +| {{ item['custom:title'] }} | {{ utils.reencode(item.description) }} | +{%- endfor %} + +# Actors + +| Actor | Type | Trust boundary | Description | +|-------|------|----------------|-------------| +{%- for id, item in sbdl.items() if item.type == 'actor' %} +| {{ item['custom:title'] }} | {{ item['custom:actor_type'] }} | {{ sbdl[item['parent'][0].identifier]['custom:title'] if 'parent' in item else 'โ€”' }} | {{ utils.reencode(item.description) }} | +{%- endfor %} + +# Components + +The processes, servers, and external entities that make up the system. + +| Component | Kind | Trust boundary | Description | +|-----------|------|----------------|-------------| +{%- for id, item in sbdl.items() if item.type in ['process', 'server', 'external_entity'] %} +| {{ item['custom:title'] }} | {{ item.type | replace('_', ' ') }} | {{ sbdl[item['parent'][0].identifier]['custom:title'] if 'parent' in item else 'โ€”' }} | {{ utils.reencode(item.description) }} | +{%- endfor %} + +# Data stores + +| Data store | Type | Encrypted | Trust boundary | Description | +|------------|------|-----------|----------------|-------------| +{%- for id, item in sbdl.items() if item.type == 'datastore' %} +| {{ item['custom:title'] }} | {{ item['custom:store_type'] }} | {{ 'yes' if item['custom:encrypted'] is defined and item['custom:encrypted'] == 'true' else 'no' }} | {{ sbdl[item['parent'][0].identifier]['custom:title'] if 'parent' in item else 'โ€”' }} | {{ utils.reencode(item.description) }} | +{%- endfor %} + +# Data assets + +| Data asset | Classification | Sensitivity | Description | +|------------|----------------|-------------|-------------| +{%- for id, item in sbdl.items() if item.type == 'data_asset' %} +| {{ item['custom:title'] }} | {{ item['custom:classification'] }} | {{ item['custom:sensitivity'] }} | {{ utils.reencode(item.description) }} | +{%- endfor %} + +# Data flows + +| Data flow | Source | Destination | Protocol | Port | Encrypted | Data asset | +|-----------|--------|-------------|----------|------|-----------|------------| +{%- for id, item in sbdl.items() if item.type == 'dataflow' %} +| {{ item['custom:title'] }} | {{ sbdl[item['custom:source']]['custom:title'] }} | {{ sbdl[item['custom:destination']]['custom:title'] }} | {{ item['custom:protocol'] }} | {{ item['custom:port'] }} | {{ 'yes' if item['custom:encrypted'] == 'true' else 'no' }} | {{ sbdl[item['custom:data']]['custom:title'] if 'custom:data' in item else 'โ€”' }} | +{%- endfor %} + +# Data flow diagram + +The diagram below shows the system decomposed into its trust boundaries, with the components, actors, and data stores placed within them, and the data flows linking their sources and destinations. It is generated automatically from the same SBDL model using SBDL's `aspect-diagram` rendering. + +![Data flow diagram for amp-devcontainer, showing trust boundaries, components, actors, data stores, and the data flows between them.](threat-model-dfd.png) + +# Threat analysis +{%- for id, threat in sbdl.items() if threat.type == 'threat' %} +{%- set effect = sbdl[threat['fmea:effect'][0].identifier] %} +{%- set cause = sbdl[threat['fmea:cause'][0].identifier] %} +{%- set control = sbdl[threat['fmea:control'][0].identifier] %} +{%- set severity = effect.severity | int %} +{%- set occurrence = cause.occurrence | int %} +{%- set detect = threat.detectability | int %} +{%- set rpn = severity * occurrence * detect %} +{%- set occ_post = (cause.occurrence_post | int) if 'occurrence_post' in cause else occurrence %} +{%- set det_post = (threat.detectability_post | int) if 'detectability_post' in threat else detect %} +{%- set rpn_post = severity * occ_post * det_post %} + +## {{ threat['custom:threat_id'] }} โ€” {{ utils.reencode(threat['custom:title']) }} + +| Property | Value | +|----------|-------| +| STRIDE category | {{ threat['custom:stride'] }} | +| Qualitative risk | {{ threat['custom:risk_level'] }} | +| Target(s) | {% for a in threat['aspect'] %}{{ sbdl[a.identifier]['custom:title'] }}{% if not loop.last %}, {% endif %}{% endfor %} | +| Severity (S) | {{ severity }} | +| Occurrence (O) | {{ occurrence }} | +| Detectability (D) | {{ detect }} | +| **RPN (S ร— O ร— D)** | **{{ rpn }}** | +| Residual RPN | {{ rpn_post }} | +| Weakness (CWE) | {{ threat['custom:cwe'] }} | +| Attack pattern (CAPEC) | {{ threat['custom:capec'] }} | + +**Description** + +{{ utils.reencode(threat.description) }} + +{{ utils.reencode(threat.remark) }} + +**Attack vector** + +{{ utils.reencode(cause.description) }} + +**Impact** + +{{ utils.reencode(effect.description) }} + +**Mitigation** ({{ control['custom:status'] }}) + +{{ utils.reencode(control.description) }} +{%- endfor %} + +# FMEA risk summary + +The table below ranks all identified threats by their Risk Priority Number (RPN). Higher values indicate higher priority for mitigation. + +{%- set ns = namespace(rows=[]) -%} +{%- for id, threat in sbdl.items() if threat.type == 'threat' -%} +{%- set effect = sbdl[threat['fmea:effect'][0].identifier] -%} +{%- set cause = sbdl[threat['fmea:cause'][0].identifier] -%} +{%- set severity = effect.severity | int -%} +{%- set occurrence = cause.occurrence | int -%} +{%- set detect = threat.detectability | int -%} +{%- set occ_post = (cause.occurrence_post | int) if 'occurrence_post' in cause else occurrence -%} +{%- set det_post = (threat.detectability_post | int) if 'detectability_post' in threat else detect -%} +{%- set _ = ns.rows.append({ + 'tid': threat['custom:threat_id'], + 'stride': threat['custom:stride'], + 'risk': threat['custom:risk_level'], + 's': severity, 'o': occurrence, 'd': detect, + 'rpn': severity * occurrence * detect, + 'rpn_post': severity * occ_post * det_post}) -%} +{%- endfor %} + +| Threat | STRIDE | S | O | D | RPN | Residual RPN | Risk | +|--------|--------|---|---|---|-----|--------------|------| +{%- for row in ns.rows | sort(attribute='rpn', reverse=true) %} +| {{ row.tid }} | {{ row.stride }} | {{ row.s }} | {{ row.o }} | {{ row.d }} | {{ row.rpn }} | {{ row.rpn_post }} | {{ row.risk }} | +{%- endfor %} + +# Residual risk and planned actions + +The following actions are planned to further reduce residual risk. + +{% for id, item in sbdl.items() if item.type == 'planned_mitigation' -%} +{%- set linked_cause = sbdl[item['fmea:cause'][0].identifier] if 'fmea:cause' in item else none -%} +{%- set linked_threat = sbdl[linked_cause['fmea:mode'][0].identifier] if linked_cause is not none and 'fmea:mode' in linked_cause else none -%} +- **{{ id }}**{% if linked_threat is not none %} (addresses {{ linked_threat['custom:threat_id'] }}){% endif %}: {{ utils.reencode(item.description) }} +{% else -%} +*No outstanding planned actions; all identified threats have implemented mitigations.* +{% endfor %} +# Risk summary + +{%- set counts = namespace(high=0, medium=0, low=0, total=0) -%} +{%- for id, item in sbdl.items() if item.type == 'threat' -%} +{%- set counts.total = counts.total + 1 -%} +{%- if item['custom:risk_level'] == 'High' -%}{%- set counts.high = counts.high + 1 -%} +{%- elif item['custom:risk_level'] == 'Medium' -%}{%- set counts.medium = counts.medium + 1 -%} +{%- else -%}{%- set counts.low = counts.low + 1 -%} +{%- endif -%} +{%- endfor %} + +| Qualitative risk | Count | +|------------------|-------| +| High | {{ counts.high }} | +| Medium | {{ counts.medium }} | +| Low | {{ counts.low }} | +| **Total** | **{{ counts.total }}** | + +All high-risk threats have implemented, verifiable mitigations. Residual risk is tracked through the project's standard change control process and re-evaluated whenever the model or its source material changes. diff --git a/docs/threat-model.sbdl b/docs/threat-model.sbdl new file mode 100644 index 00000000..61512938 --- /dev/null +++ b/docs/threat-model.sbdl @@ -0,0 +1,613 @@ +#!sbdl +# +# Supply-chain security threat model for amp-devcontainer, expressed in SBDL. +# +# This model is a pilot port of the former PyTM threat model (threat-model-pytm.py) +# onto SBDL, consolidating the threat model with the requirements model so that a +# single tool-chain (sbdl) drives all generated documentation. +# +# The STRIDE / threat-modelling concepts are mapped onto SBDL base types as follows: +# +# PyTM / STRIDE concept SBDL custom type SBDL base type +# --------------------- ---------------- -------------- +# Trust boundary / zone trust_boundary aspect +# Actor actor aspect +# External entity external_entity aspect +# Process / component process aspect +# Server server aspect +# Data store datastore aspect +# Data asset / data set data_asset aspect +# Data flow dataflow aspect +# Threat (failure/attack mode) threat fmea:mode +# Attack vector (cause) attack_vector fmea:cause +# Impact (effect) impact fmea:effect +# Mitigation (control) mitigation fmea:control +# Planned mitigation (action) planned_mitigation fmea:action-control +# +# Modelling threats as an FMEA lets the model carry Severity (on the impact), +# Occurrence (on the attack vector) and Detectability (on the threat) so that a +# Risk Priority Number (RPN = S x O x D) can be rendered, mirroring the qualitative +# High/Medium risk levels from the original model. + +# --------------------------------------------------------------------------- +# Custom types +# --------------------------------------------------------------------------- + +customtype trust_boundary is aspect {} +customtype actor is aspect {} +customtype external_entity is aspect {} +customtype process is aspect {} +customtype server is aspect {} +customtype datastore is aspect {} +customtype data_asset is aspect {} +customtype dataflow is aspect {} +customtype threat is fmea:mode {} +customtype attack_vector is fmea:cause {} +customtype impact is fmea:effect {} +customtype mitigation is fmea:control {} +customtype planned_mitigation is fmea:action-control {} + +# --------------------------------------------------------------------------- +# System under analysis +# --------------------------------------------------------------------------- + +system_amp_devcontainer is aspect { + custom:title is "amp-devcontainer" + description is "The amp-devcontainer project provides secure, supply-chain hardened development containers for regulated software development. Key security features include: pinned dependencies with SHA checksums, signed container images with SBOMs, vulnerability scanning with Trivy, OSSF Scorecard compliance, and comprehensive dependency management via Dependabot. The containers support both x64 and arm64 architectures and include development toolchains for C++ (GCC, Clang, ARM GCC) and Rust, along with security analysis tools." + custom:business_criticality is "high" + custom:exposure is "external" + custom:reviewed_at is "2025-09-23" +} + +# --------------------------------------------------------------------------- +# Trust boundaries (trust zones) +# --------------------------------------------------------------------------- + +using { parent is system_amp_devcontainer } + +tz_public_internet is trust_boundary { + custom:title is "Public Internet" + description is "Untrusted external network including package repositories, container registries, and third-party services." +} + +tz_github_infrastructure is trust_boundary { + custom:title is "GitHub Infrastructure" + description is "GitHub's hosted infrastructure including Actions runners, Container Registry, and source code repository." +} + +tz_build_environment is trust_boundary { + custom:title is "Container Build Environment" + description is "GitHub Actions runners executing container builds with elevated privileges." +} + +tz_container_runtime is trust_boundary { + custom:title is "Container Runtime Environment" + description is "Developer workstations and CI/CD systems running the devcontainer images." +} + +tz_developer_workstation is trust_boundary { + custom:title is "Developer Workstation" + description is "Local development environments where developers use the containers." +} + +using { parent is "" } + +# --------------------------------------------------------------------------- +# Actors +# --------------------------------------------------------------------------- + +actor_developer is actor { + custom:title is "Software Developer" + description is "Developers using the devcontainer for local development and testing." + custom:actor_type is "user" + custom:permissions is "Read container images, execute development tools, access source code." + parent is tz_developer_workstation +} + +actor_ci_cd_system is actor { + custom:title is "CI/CD System" + description is "Automated systems using containers for building and testing software." + custom:actor_type is "system" + custom:permissions is "Pull container images, execute builds, publish artifacts." + parent is tz_container_runtime +} + +actor_malicious is actor { + custom:title is "Malicious Actor" + description is "Threat actor attempting to compromise the supply chain or development environment." + custom:actor_type is "third_party" + custom:permissions is "None (attempting to gain unauthorized access)." + parent is tz_public_internet +} + +actor_maintainer is actor { + custom:title is "Project Maintainer" + description is "Authorized maintainers with commit and release permissions." + custom:actor_type is "administrator" + custom:permissions is "Write access to repository, trigger releases, manage security policies." + parent is tz_github_infrastructure +} + +# --------------------------------------------------------------------------- +# External entities +# --------------------------------------------------------------------------- + +ext_package_repos is external_entity { + custom:title is "External Package Repositories" + description is "Ubuntu apt repositories, Python PyPI, Rust crates.io, and other package sources." + parent is tz_public_internet +} + +# --------------------------------------------------------------------------- +# Processes / components +# --------------------------------------------------------------------------- + +proc_github_actions_build is process { + custom:title is "GitHub Actions Build Pipeline" + description is "Automated pipeline for building, testing, and publishing container images with security scanning." + parent is tz_build_environment + custom:repo_link is "https://github.com/philips-software/amp-devcontainer/tree/main/.github/workflows" +} + +proc_dependency_mgmt is process { + custom:title is "Dependency Management System" + description is "Comprehensive dependency pinning including apt packages, Python packages, and binary downloads." + parent is tz_github_infrastructure +} + +proc_vscode_extensions is process { + custom:title is "VS Code Extensions Configuration" + description is "Pinned VS Code extensions with specific versions for development environment setup." + parent is tz_container_runtime +} + +# --------------------------------------------------------------------------- +# Servers +# --------------------------------------------------------------------------- + +srv_dockerfile_cpp is server { + custom:title is "C++ Devcontainer Dockerfile" + description is "Multi-stage Dockerfile for building the C++ development environment with GCC, Clang, and embedded toolchains." + parent is tz_github_infrastructure + custom:os is "Ubuntu" + custom:hardened is "true" + custom:repo_link is "https://github.com/philips-software/amp-devcontainer/blob/main/.devcontainer/cpp/Dockerfile" +} + +srv_dockerfile_rust is server { + custom:title is "Rust Devcontainer Dockerfile" + description is "Dockerfile for building the Rust development environment with embedded targets and analysis tools." + parent is tz_github_infrastructure + custom:os is "Ubuntu" + custom:hardened is "true" + custom:privileged is "true" + custom:repo_link is "https://github.com/philips-software/amp-devcontainer/blob/main/.devcontainer/rust/Dockerfile" +} + +# --------------------------------------------------------------------------- +# Data stores +# --------------------------------------------------------------------------- + +ds_source_repository is datastore { + custom:title is "GitHub Source Repository" + description is "Git repository containing source code, build configurations, and security policies." + custom:store_type is "document" + custom:encrypted is "true" + parent is tz_github_infrastructure +} + +ds_ghcr_registry is datastore { + custom:title is "GitHub Container Registry" + description is "OCI-compatible registry storing container images with metadata, SBOMs, and vulnerability scan results." + custom:store_type is "object" + custom:encrypted is "true" + parent is tz_github_infrastructure +} + +ds_build_cache is datastore { + custom:title is "GitHub Actions Cache" + description is "Build cache storage for Docker layers and build artifacts." + custom:store_type is "key_value" + parent is tz_build_environment +} + +# --------------------------------------------------------------------------- +# Data assets +# --------------------------------------------------------------------------- + +data_container_images is data_asset { + custom:title is "Container Images" + description is "Signed multi-platform container images with embedded development toolchains." + custom:classification is "SENSITIVE" + custom:sensitivity is "ip" +} + +data_build_artifacts is data_asset { + custom:title is "Build Artifacts and SBOMs" + description is "Software Bill of Materials, vulnerability scan results, and build provenance." + custom:classification is "SENSITIVE" + custom:sensitivity is "biz" +} + +data_source_code is data_asset { + custom:title is "Source Code and Configuration" + description is "Dockerfiles, build scripts, dependency manifests, and security configurations." + custom:classification is "SENSITIVE" + custom:sensitivity is "ip" +} + +# --------------------------------------------------------------------------- +# Data flows +# --------------------------------------------------------------------------- + +flow_dependency_download is dataflow { + custom:title is "External Dependency Download" + description is "Download of packages, binaries, and toolchains from external repositories during build." + custom:source is "ext_package_repos" + custom:destination is "proc_github_actions_build" + custom:protocol is "HTTPS" + custom:port is "443" + custom:encrypted is "true" + related is ext_package_repos, proc_github_actions_build +} + +flow_image_publish is dataflow { + custom:title is "Container Image Publication" + description is "Publishing of built and signed container images to the registry." + custom:source is "proc_github_actions_build" + custom:destination is "ds_ghcr_registry" + custom:protocol is "HTTPS" + custom:port is "443" + custom:encrypted is "true" + custom:data is "data_container_images" + related is proc_github_actions_build, ds_ghcr_registry +} + +flow_image_consumption is dataflow { + custom:title is "Container Image Consumption" + description is "Pull of container images by developers and CI/CD systems." + custom:source is "ds_ghcr_registry" + custom:destination is "actor_developer" + custom:protocol is "HTTPS" + custom:port is "443" + custom:encrypted is "true" + custom:data is "data_container_images" + related is ds_ghcr_registry, actor_developer +} + +flow_source_access is dataflow { + custom:title is "Source Code Access" + description is "Maintainer access to the source code repository for updates and releases." + custom:source is "actor_maintainer" + custom:destination is "ds_source_repository" + custom:protocol is "HTTPS" + custom:port is "443" + custom:encrypted is "true" + custom:data is "data_source_code" + related is actor_maintainer, ds_source_repository +} + +flow_build_trigger is dataflow { + custom:title is "Build Trigger" + description is "GitHub Actions build triggered by source code changes." + custom:source is "ds_source_repository" + custom:destination is "proc_github_actions_build" + custom:protocol is "HTTPS" + custom:port is "443" + custom:encrypted is "true" + custom:data is "data_source_code" + related is ds_source_repository, proc_github_actions_build +} + +# --------------------------------------------------------------------------- +# Threats (STRIDE), with attack vectors, impacts and mitigations (FMEA) +# --------------------------------------------------------------------------- + +# --- SUPPLY_CHAIN_01: Dependency confusion -------------------------------- + +threat_sc01_dependency_confusion is threat { + custom:title is "Dependency Confusion Attack" + custom:threat_id is "SUPPLY_CHAIN_01" + custom:stride is "Tampering" + custom:risk_level is "High" + custom:capec is "CAPEC-439: Manipulation During Distribution" + custom:cwe is "CWE-494: Download of Code Without Integrity Check" + description is "An attacker uploads malicious packages with names similar to internal dependencies to public repositories, which could be installed during the container build." + remark is "Malicious packages could be installed during container build if dependency management is not properly secured. Affects the dependency management system and the GitHub Actions build pipeline." + detectability is 4 + detectability_post is 3 + aspect is proc_dependency_mgmt + fmea:cause is cause_sc01 + fmea:effect is impact_sc01 + fmea:control is mit_sc01 +} + +cause_sc01 is attack_vector { + description is "Public package repositories resolve a malicious same-named package in preference to the intended dependency." + occurrence is 4 + occurrence_post is 2 + fmea:mode is threat_sc01_dependency_confusion +} + +impact_sc01 is impact { + description is "Execution of attacker-controlled code inside the build, potentially propagating to all downstream users including safety-critical systems." + severity is 8 + fmea:mode is threat_sc01_dependency_confusion +} + +mit_sc01 is mitigation { + custom:status is "Implemented" + description is "Mitigations implemented:\n\n- Comprehensive dependency pinning with SHA256 checksums\n- Use of private package repositories where possible\n- Dependency scanning and validation during build\n- Regular security audits with tools like pip-audit" + fmea:mode is threat_sc01_dependency_confusion +} + +# --- SUPPLY_CHAIN_02: Compromised base image ------------------------------ + +threat_sc02_base_image is threat { + custom:title is "Compromised Base Image" + custom:threat_id is "SUPPLY_CHAIN_02" + custom:stride is "Tampering" + custom:risk_level is "High" + custom:capec is "CAPEC-439: Manipulation During Distribution" + custom:cwe is "CWE-829: Inclusion of Functionality from Untrusted Source" + description is "The Ubuntu base image contains malicious code or vulnerabilities that propagate to the final container images." + remark is "Base images could contain vulnerabilities or malicious code that propagates to final containers, affecting both the C++ and Rust development environments." + detectability is 3 + detectability_post is 2 + aspect is srv_dockerfile_cpp, srv_dockerfile_rust + fmea:cause is cause_sc02 + fmea:effect is impact_sc02 + fmea:control is mit_sc02 +} + +cause_sc02 is attack_vector { + description is "A mutable base image tag is repointed to a tampered image, or the upstream base image is compromised." + occurrence is 3 + occurrence_post is 2 + fmea:mode is threat_sc02_base_image +} + +impact_sc02 is impact { + description is "Malicious functionality embedded in every derived container image and executed on developer and CI systems." + severity is 8 + fmea:mode is threat_sc02_base_image +} + +mit_sc02 is mitigation { + custom:status is "Implemented" + description is "Mitigations implemented:\n\n- Base images pinned to specific SHA256 digests rather than mutable tags\n- Regular vulnerability scanning of base images with Trivy\n- Multi-stage builds to reduce attack surface\n- Minimal base images where possible" + fmea:mode is threat_sc02_base_image +} + +# --- RUNTIME_01: Privileged container escape ------------------------------ + +threat_runtime01_priv_escape is threat { + custom:title is "Privileged Container Escape" + custom:threat_id is "RUNTIME_01" + custom:stride is "Elevation of Privilege" + custom:risk_level is "Medium" + custom:capec is "CAPEC-233: Privilege Escalation" + custom:cwe is "CWE-250: Execution with Unnecessary Privileges" + description is "The Rust container runs with the privileged flag, creating the potential for a container escape to the host system." + remark is "Privileged containers have elevated permissions that could enable escape to the host system, specifically affecting the Rust development environment. Status: under active review and optimization." + detectability is 5 + detectability_post is 3 + aspect is srv_dockerfile_rust + fmea:cause is cause_runtime01 + fmea:effect is impact_runtime01 + fmea:control is mit_runtime01 +} + +cause_runtime01 is attack_vector { + description is "A vulnerability in the privileged container runtime is exploited to break out of container isolation." + occurrence is 3 + occurrence_post is 2 + fmea:mode is threat_runtime01_priv_escape +} + +impact_runtime01 is impact { + description is "Host system compromise and lateral movement from the developer workstation or CI runner." + severity is 6 + fmea:mode is threat_runtime01_priv_escape +} + +mit_runtime01 is mitigation { + custom:status is "Under review" + description is "Mitigations under review:\n\n- Regular review of privileged flag necessity\n- Investigation of specific capabilities instead of full privilege escalation\n- Container runtime security monitoring implementation\n- User namespaces and security profiles evaluation" + fmea:mode is threat_runtime01_priv_escape +} + +action_runtime01_priv_review is planned_mitigation { + description is "Assess the necessity of the privileged flag on the Rust container and replace it with the minimal set of required capabilities." + fmea:cause is cause_runtime01 +} + +# --- SUPPLY_CHAIN_03: GitHub Actions runner compromise -------------------- + +threat_sc03_runner_compromise is threat { + custom:title is "GitHub Actions Runner Compromise" + custom:threat_id is "SUPPLY_CHAIN_03" + custom:stride is "Tampering" + custom:risk_level is "High" + custom:capec is "CAPEC-187: Malicious Automated Software Update" + custom:cwe is "CWE-346: Origin Validation Error" + description is "Compromise of a GitHub Actions runner during the build process allows injection of malicious code into the container images." + remark is "Compromised GitHub Actions runners could inject malicious code into container images during the build process." + detectability is 4 + detectability_post is 2 + aspect is proc_github_actions_build + fmea:cause is cause_sc03 + fmea:effect is impact_sc03 + fmea:control is mit_sc03 +} + +cause_sc03 is attack_vector { + description is "A malicious or compromised GitHub Action or runner step executes attacker-controlled code within the build environment." + occurrence is 2 + occurrence_post is 1 + fmea:mode is threat_sc03_runner_compromise +} + +impact_sc03 is impact { + description is "Injection of malicious code into signed, published container images consumed by all downstream users." + severity is 8 + fmea:mode is threat_sc03_runner_compromise +} + +mit_sc03 is mitigation { + custom:status is "Implemented" + description is "Mitigations implemented:\n\n- Step Security harden-runner action for build environment hardening\n- All GitHub Actions pinned to specific commit SHAs\n- Minimal permissions principle implemented\n- Ephemeral, isolated build environments\n- Container image signing and verification with ephemeral keys" + fmea:mode is threat_sc03_runner_compromise +} + +# --- DATA_01: Development secrets exposure --------------------------------- + +threat_data01_secrets is threat { + custom:title is "Development Secrets Exposure" + custom:threat_id is "DATA_01" + custom:stride is "Information Disclosure" + custom:risk_level is "Medium" + custom:capec is "CAPEC-204: Lifting Sensitive Data Embedded in Cache" + custom:cwe is "CWE-312: Cleartext Storage of Sensitive Information" + description is "Accidental inclusion of secrets, API keys, or credentials in container layers or build logs." + remark is "Secrets, API keys, or credentials could be accidentally included in container images or exposed in build logs during the build process." + detectability is 3 + detectability_post is 2 + aspect is proc_github_actions_build + fmea:cause is cause_data01 + fmea:effect is impact_data01 + fmea:control is mit_data01 +} + +cause_data01 is attack_vector { + description is "A build step writes a secret into an image layer or emits it to the build log." + occurrence is 3 + occurrence_post is 2 + fmea:mode is threat_data01_secrets +} + +impact_data01 is impact { + description is "Unauthorized access to development systems using leaked credentials." + severity is 6 + fmea:mode is threat_data01_secrets +} + +mit_data01 is mitigation { + custom:status is "Implemented" + description is "Mitigations implemented:\n\n- GitHub native secrets scanning enabled\n- .dockerignore files to prevent credential inclusion\n- Secret detection in CI/CD pipelines\n- Ephemeral secrets with regular rotation\n- Separation of build-time and runtime secrets" + fmea:mode is threat_data01_secrets +} + +# --- SUPPLY_CHAIN_04: Container registry account takeover ------------------ + +threat_sc04_registry_takeover is threat { + custom:title is "Container Registry Account Takeover" + custom:threat_id is "SUPPLY_CHAIN_04" + custom:stride is "Spoofing" + custom:risk_level is "High" + custom:capec is "CAPEC-151: Identity Spoofing" + custom:cwe is "CWE-287: Improper Authentication" + description is "Compromise of a GitHub account or organization leads to malicious container images being published to the registry." + remark is "Account compromise could allow attackers to publish malicious container images to the GitHub Container Registry." + detectability is 4 + detectability_post is 2 + aspect is ds_ghcr_registry + fmea:cause is cause_sc04 + fmea:effect is impact_sc04 + fmea:control is mit_sc04 +} + +cause_sc04 is attack_vector { + description is "An attacker obtains publish credentials through phishing, credential theft, or a compromised token." + occurrence is 2 + occurrence_post is 1 + fmea:mode is threat_sc04_registry_takeover +} + +impact_sc04 is impact { + description is "Distribution of malicious images under a trusted identity to all consumers of the registry." + severity is 9 + fmea:mode is threat_sc04_registry_takeover +} + +mit_sc04 is mitigation { + custom:status is "Implemented" + description is "Mitigations implemented:\n\n- Strong authentication with 2FA/MFA requirements\n- Least privilege access controls and RBAC\n- Container images signed with ephemeral keys using GitHub OIDC\n- Automated vulnerability scanning and detection\n- Registry access logging and monitoring\n- OSSF Scorecard compliance monitoring" + fmea:mode is threat_sc04_registry_takeover +} + +# --- VULN_01: Vulnerable dependencies ------------------------------------- + +threat_vuln01_vuln_deps is threat { + custom:title is "Vulnerable Dependencies" + custom:threat_id is "VULN_01" + custom:stride is "Elevation of Privilege" + custom:risk_level is "Medium" + custom:capec is "CAPEC-549: Local Execution of Code" + custom:cwe is "CWE-1104: Use of Unmaintained Third Party Components" + description is "Use of dependencies with known security vulnerabilities, including the acknowledged CVE-2025-50181 and CVE-2025-50182 in Conan." + remark is "Known vulnerabilities in dependencies could be exploited for code execution or privilege escalation. Some vulnerabilities such as CVE-2025-50181 and CVE-2025-50182 are acknowledged, tracked, and monitored." + detectability is 2 + detectability_post is 2 + aspect is proc_dependency_mgmt + fmea:cause is cause_vuln01 + fmea:effect is impact_vuln01 + fmea:control is mit_vuln01 +} + +cause_vuln01 is attack_vector { + description is "A known-vulnerable component shipped in the image is exercised by an attacker." + occurrence is 5 + occurrence_post is 3 + fmea:mode is threat_vuln01_vuln_deps +} + +impact_vuln01 is impact { + description is "Code execution or privilege escalation on systems running the affected tooling." + severity is 6 + fmea:mode is threat_vuln01_vuln_deps +} + +mit_vuln01 is mitigation { + custom:status is "Implemented" + description is "Mitigations implemented:\n\n- Automated vulnerability scanning with Trivy (daily scans)\n- Dependabot for automated dependency updates\n- Software Bill of Materials (SBOM) generation and maintenance\n- Regular security audits of dependencies\n- Acknowledged CVE tracking with documented mitigation plans\n- SARIF upload to the GitHub Security tab for visibility" + fmea:mode is threat_vuln01_vuln_deps +} + +# --- SUPPLY_CHAIN_05: Malicious VS Code extension ------------------------- + +threat_sc05_malicious_extension is threat { + custom:title is "Malicious VS Code Extension" + custom:threat_id is "SUPPLY_CHAIN_05" + custom:stride is "Tampering" + custom:risk_level is "Medium" + custom:capec is "CAPEC-549: Local Execution of Code" + custom:cwe is "CWE-829: Inclusion of Functionality from Untrusted Source" + description is "A compromised or malicious VS Code extension gains access to the development environment and source code." + remark is "Malicious VS Code extensions could access source code, credentials, or compromise the development environment." + detectability is 4 + detectability_post is 3 + aspect is proc_vscode_extensions + fmea:cause is cause_sc05 + fmea:effect is impact_sc05 + fmea:control is mit_sc05 +} + +cause_sc05 is attack_vector { + description is "A pinned extension version is republished with malicious code, or an unvetted extension is installed." + occurrence is 3 + occurrence_post is 2 + fmea:mode is threat_sc05_malicious_extension +} + +impact_sc05 is impact { + description is "Disclosure of source code or credentials and compromise of the developer workstation." + severity is 5 + fmea:mode is threat_sc05_malicious_extension +} + +mit_sc05 is mitigation { + custom:status is "Implemented" + description is "Mitigations implemented:\n\n- All VS Code extensions pinned to specific versions\n- Extension allow-lists in development environments\n- Regular review of extension permissions and source code\n- Use of only trusted extensions from verified publishers\n- Version control of extension configurations" + fmea:mode is threat_sc05_malicious_extension +} From 5a52d2bb44183389225fca9cc14cea6bc262be22 Mon Sep 17 00:00:00 2001 From: Ron <45816308+rjaegers@users.noreply.github.com> Date: Wed, 1 Jul 2026 20:17:16 +0000 Subject: [PATCH 02/11] docs: include common header --- .github/workflows/wc-document-generation.yml | 16 ++++++++-------- docs/templates/partials/common-header.yml | 13 +++++++++++++ .../requirements-traceability-matrix.md.j2 | 13 ++----------- .../software-requirements-specification.md.j2 | 14 ++------------ docs/templates/software-test-plan.md.j2 | 14 ++------------ docs/templates/threat-model.md.j2 | 14 ++------------ 6 files changed, 29 insertions(+), 55 deletions(-) create mode 100644 docs/templates/partials/common-header.yml diff --git a/.github/workflows/wc-document-generation.yml b/.github/workflows/wc-document-generation.yml index 6c1ba098..1485f162 100644 --- a/.github/workflows/wc-document-generation.yml +++ b/.github/workflows/wc-document-generation.yml @@ -63,21 +63,21 @@ jobs: - name: ๐Ÿ“Š Generate Threat Model diagram run: sbdl -m aspect-diagram docs/threat-model.sbdl -o threat-model-dfd.png - name: ๐Ÿ“„ Generate SRS PDF - uses: docker://pandoc/extra:3.9.0.0-ubuntu@sha256:72afa9c8d3300e5f10c9c4330e101725687f2179bffd912fb859c6d2ae85de62 + uses: docker://pandoc/extra:3.10.0.0-ubuntu@sha256:01b2c9cf36d1056650af724934c5b4663276bbb0c7ab72579a345db189c8b885 with: - args: --template eisvogel --syntax-highlighting idiomatic --number-sections --output software-requirements-specification.pdf software-requirements-specification.md + args: --template eisvogel --syntax-highlighting idiomatic --number-sections --filter pandoc-include --output software-requirements-specification.pdf software-requirements-specification.md - name: ๐Ÿงช Generate STP PDF - uses: docker://pandoc/extra:3.9.0.0-ubuntu@sha256:72afa9c8d3300e5f10c9c4330e101725687f2179bffd912fb859c6d2ae85de62 + uses: docker://pandoc/extra:3.10.0.0-ubuntu@sha256:01b2c9cf36d1056650af724934c5b4663276bbb0c7ab72579a345db189c8b885 with: - args: --template eisvogel --syntax-highlighting idiomatic --number-sections --output software-test-plan.pdf software-test-plan.md + args: --template eisvogel --syntax-highlighting idiomatic --number-sections --filter pandoc-include --output software-test-plan.pdf software-test-plan.md - name: ๐Ÿงฉ Generate RTM PDF - uses: docker://pandoc/extra:3.9.0.0-ubuntu@sha256:72afa9c8d3300e5f10c9c4330e101725687f2179bffd912fb859c6d2ae85de62 + uses: docker://pandoc/extra:3.10.0.0-ubuntu@sha256:01b2c9cf36d1056650af724934c5b4663276bbb0c7ab72579a345db189c8b885 with: - args: --template eisvogel --syntax-highlighting idiomatic --number-sections --output requirements-traceability-matrix.pdf requirements-traceability-matrix.md + args: --template eisvogel --syntax-highlighting idiomatic --number-sections --filter pandoc-include --output requirements-traceability-matrix.pdf requirements-traceability-matrix.md - name: ๐Ÿ›ก๏ธ Generate Threat Model PDF - uses: docker://pandoc/extra:3.9.0.0-ubuntu@sha256:72afa9c8d3300e5f10c9c4330e101725687f2179bffd912fb859c6d2ae85de62 + uses: docker://pandoc/extra:3.10.0.0-ubuntu@sha256:01b2c9cf36d1056650af724934c5b4663276bbb0c7ab72579a345db189c8b885 with: - args: --template eisvogel --syntax-highlighting idiomatic --number-sections --output threat-model.pdf threat-model.md + args: --template eisvogel --syntax-highlighting idiomatic --number-sections --filter pandoc-include --output threat-model.pdf threat-model.md - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: documents diff --git a/docs/templates/partials/common-header.yml b/docs/templates/partials/common-header.yml new file mode 100644 index 00000000..6f81ef9f --- /dev/null +++ b/docs/templates/partials/common-header.yml @@ -0,0 +1,13 @@ +--- +colorlinks: true +footer-right: "\\thepage \\hspace{1pt} of \\pageref*{lastpage}" +header-includes: + - \AtEndDocument{\label{lastpage}} +lang: "en" +titlepage: true +titlepage-color: "0B5ED7" +titlepage-rule-color: "FFFFFF" +titlepage-rule-height: 2 +titlepage-text-color: "FFFFFF" +toc: true +toc-own-page: true diff --git a/docs/templates/requirements-traceability-matrix.md.j2 b/docs/templates/requirements-traceability-matrix.md.j2 index 00ad60ec..2b750631 100644 --- a/docs/templates/requirements-traceability-matrix.md.j2 +++ b/docs/templates/requirements-traceability-matrix.md.j2 @@ -1,25 +1,16 @@ --- title: "Requirements traceability matrix for amp-devcontainer" author: ["@rjaegers"] -colorlinks: true date: "{{ sbdl['doc_control']['custom:generated_at'] | strftime('%Y-%m-%d') }}" keywords: [Traceability, Requirements, RTM, amp-devcontainer] lang: "en" -titlepage: true -titlepage-color: "0B5ED7" -titlepage-text-color: "FFFFFF" -titlepage-rule-color: "FFFFFF" -titlepage-rule-height: 2 -toc: true -toc-own-page: true -header-includes: - - \AtEndDocument{\label{lastpage}} {%- if sbdl['doc_control']['custom:is_release'] != 'true' %} watermark: "DRAFT" {%- endif %} -footer-right: "\\thepage \\hspace{1pt} of \\pageref*{lastpage}" ... +!include-header partials/common-header.yml + {% import "partials/text-utilities.j2" as utils %} # Introduction diff --git a/docs/templates/software-requirements-specification.md.j2 b/docs/templates/software-requirements-specification.md.j2 index b93bf0d5..9ef25b26 100644 --- a/docs/templates/software-requirements-specification.md.j2 +++ b/docs/templates/software-requirements-specification.md.j2 @@ -1,25 +1,15 @@ --- title: "Software requirements specification for amp-devcontainer" author: ["@rjaegers"] -colorlinks: true date: "{{ sbdl['doc_control']['custom:generated_at'] | strftime('%Y-%m-%d') }}" keywords: [Software, Requirements, SRS, amp-devcontainer] -lang: "en" -titlepage: true -titlepage-color: "0B5ED7" -titlepage-text-color: "FFFFFF" -titlepage-rule-color: "FFFFFF" -titlepage-rule-height: 2 -toc: true -toc-own-page: true -header-includes: - - \AtEndDocument{\label{lastpage}} {%- if sbdl['doc_control']['custom:is_release'] != 'true' %} watermark: "DRAFT" {%- endif %} -footer-right: "\\thepage \\hspace{1pt} of \\pageref*{lastpage}" ... +!include-header partials/common-header.yml + {% import "partials/text-utilities.j2" as utils %} # Introduction diff --git a/docs/templates/software-test-plan.md.j2 b/docs/templates/software-test-plan.md.j2 index 3e473012..1b3a49a1 100644 --- a/docs/templates/software-test-plan.md.j2 +++ b/docs/templates/software-test-plan.md.j2 @@ -1,25 +1,15 @@ --- title: "Software test plan for amp-devcontainer" author: ["@rjaegers"] -colorlinks: true date: "{{ sbdl['doc_control']['custom:generated_at'] | strftime('%Y-%m-%d') }}" keywords: [Software, Test, Plan, STP, amp-devcontainer] -lang: "en" -titlepage: true -titlepage-color: "0B5ED7" -titlepage-text-color: "FFFFFF" -titlepage-rule-color: "FFFFFF" -titlepage-rule-height: 2 -toc: true -toc-own-page: true -header-includes: - - \AtEndDocument{\label{lastpage}} {%- if sbdl['doc_control']['custom:is_release'] != 'true' %} watermark: "DRAFT" {%- endif %} -footer-right: "\\thepage \\hspace{1pt} of \\pageref*{lastpage}" ... +!include-header partials/common-header.yml + {% import "partials/text-utilities.j2" as utils %} # Introduction diff --git a/docs/templates/threat-model.md.j2 b/docs/templates/threat-model.md.j2 index 6cea5d66..ad69b80d 100644 --- a/docs/templates/threat-model.md.j2 +++ b/docs/templates/threat-model.md.j2 @@ -1,25 +1,15 @@ --- title: "Threat model for amp-devcontainer" author: ["@rjaegers"] -colorlinks: true date: "{{ sbdl['doc_control']['custom:generated_at'] | strftime('%Y-%m-%d') }}" keywords: [Threat, Model, Security, STRIDE, FMEA, amp-devcontainer] -lang: "en" -titlepage: true -titlepage-color: "0B5ED7" -titlepage-text-color: "FFFFFF" -titlepage-rule-color: "FFFFFF" -titlepage-rule-height: 2 -toc: true -toc-own-page: true -header-includes: - - \AtEndDocument{\label{lastpage}} {%- if sbdl['doc_control']['custom:is_release'] != 'true' %} watermark: "DRAFT" {%- endif %} -footer-right: "\\thepage \\hspace{1pt} of \\pageref*{lastpage}" ... +!include-header partials/common-header.yml + {% import "partials/text-utilities.j2" as utils %} {%- set system = sbdl['system_amp_devcontainer'] -%} From 9947d5b1141351ca3856a8cc90734eef0c69ec9a Mon Sep 17 00:00:00 2001 From: Ron <45816308+rjaegers@users.noreply.github.com> Date: Wed, 1 Jul 2026 20:49:04 +0000 Subject: [PATCH 03/11] Revert "docs: include common header" This reverts commit 5a52d2bb44183389225fca9cc14cea6bc262be22. --- .github/workflows/wc-document-generation.yml | 16 ++++++++-------- docs/templates/partials/common-header.yml | 13 ------------- .../requirements-traceability-matrix.md.j2 | 13 +++++++++++-- .../software-requirements-specification.md.j2 | 14 ++++++++++++-- docs/templates/software-test-plan.md.j2 | 14 ++++++++++++-- docs/templates/threat-model.md.j2 | 14 ++++++++++++-- 6 files changed, 55 insertions(+), 29 deletions(-) delete mode 100644 docs/templates/partials/common-header.yml diff --git a/.github/workflows/wc-document-generation.yml b/.github/workflows/wc-document-generation.yml index 1485f162..6c1ba098 100644 --- a/.github/workflows/wc-document-generation.yml +++ b/.github/workflows/wc-document-generation.yml @@ -63,21 +63,21 @@ jobs: - name: ๐Ÿ“Š Generate Threat Model diagram run: sbdl -m aspect-diagram docs/threat-model.sbdl -o threat-model-dfd.png - name: ๐Ÿ“„ Generate SRS PDF - uses: docker://pandoc/extra:3.10.0.0-ubuntu@sha256:01b2c9cf36d1056650af724934c5b4663276bbb0c7ab72579a345db189c8b885 + uses: docker://pandoc/extra:3.9.0.0-ubuntu@sha256:72afa9c8d3300e5f10c9c4330e101725687f2179bffd912fb859c6d2ae85de62 with: - args: --template eisvogel --syntax-highlighting idiomatic --number-sections --filter pandoc-include --output software-requirements-specification.pdf software-requirements-specification.md + args: --template eisvogel --syntax-highlighting idiomatic --number-sections --output software-requirements-specification.pdf software-requirements-specification.md - name: ๐Ÿงช Generate STP PDF - uses: docker://pandoc/extra:3.10.0.0-ubuntu@sha256:01b2c9cf36d1056650af724934c5b4663276bbb0c7ab72579a345db189c8b885 + uses: docker://pandoc/extra:3.9.0.0-ubuntu@sha256:72afa9c8d3300e5f10c9c4330e101725687f2179bffd912fb859c6d2ae85de62 with: - args: --template eisvogel --syntax-highlighting idiomatic --number-sections --filter pandoc-include --output software-test-plan.pdf software-test-plan.md + args: --template eisvogel --syntax-highlighting idiomatic --number-sections --output software-test-plan.pdf software-test-plan.md - name: ๐Ÿงฉ Generate RTM PDF - uses: docker://pandoc/extra:3.10.0.0-ubuntu@sha256:01b2c9cf36d1056650af724934c5b4663276bbb0c7ab72579a345db189c8b885 + uses: docker://pandoc/extra:3.9.0.0-ubuntu@sha256:72afa9c8d3300e5f10c9c4330e101725687f2179bffd912fb859c6d2ae85de62 with: - args: --template eisvogel --syntax-highlighting idiomatic --number-sections --filter pandoc-include --output requirements-traceability-matrix.pdf requirements-traceability-matrix.md + args: --template eisvogel --syntax-highlighting idiomatic --number-sections --output requirements-traceability-matrix.pdf requirements-traceability-matrix.md - name: ๐Ÿ›ก๏ธ Generate Threat Model PDF - uses: docker://pandoc/extra:3.10.0.0-ubuntu@sha256:01b2c9cf36d1056650af724934c5b4663276bbb0c7ab72579a345db189c8b885 + uses: docker://pandoc/extra:3.9.0.0-ubuntu@sha256:72afa9c8d3300e5f10c9c4330e101725687f2179bffd912fb859c6d2ae85de62 with: - args: --template eisvogel --syntax-highlighting idiomatic --number-sections --filter pandoc-include --output threat-model.pdf threat-model.md + args: --template eisvogel --syntax-highlighting idiomatic --number-sections --output threat-model.pdf threat-model.md - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: documents diff --git a/docs/templates/partials/common-header.yml b/docs/templates/partials/common-header.yml deleted file mode 100644 index 6f81ef9f..00000000 --- a/docs/templates/partials/common-header.yml +++ /dev/null @@ -1,13 +0,0 @@ ---- -colorlinks: true -footer-right: "\\thepage \\hspace{1pt} of \\pageref*{lastpage}" -header-includes: - - \AtEndDocument{\label{lastpage}} -lang: "en" -titlepage: true -titlepage-color: "0B5ED7" -titlepage-rule-color: "FFFFFF" -titlepage-rule-height: 2 -titlepage-text-color: "FFFFFF" -toc: true -toc-own-page: true diff --git a/docs/templates/requirements-traceability-matrix.md.j2 b/docs/templates/requirements-traceability-matrix.md.j2 index 2b750631..00ad60ec 100644 --- a/docs/templates/requirements-traceability-matrix.md.j2 +++ b/docs/templates/requirements-traceability-matrix.md.j2 @@ -1,16 +1,25 @@ --- title: "Requirements traceability matrix for amp-devcontainer" author: ["@rjaegers"] +colorlinks: true date: "{{ sbdl['doc_control']['custom:generated_at'] | strftime('%Y-%m-%d') }}" keywords: [Traceability, Requirements, RTM, amp-devcontainer] lang: "en" +titlepage: true +titlepage-color: "0B5ED7" +titlepage-text-color: "FFFFFF" +titlepage-rule-color: "FFFFFF" +titlepage-rule-height: 2 +toc: true +toc-own-page: true +header-includes: + - \AtEndDocument{\label{lastpage}} {%- if sbdl['doc_control']['custom:is_release'] != 'true' %} watermark: "DRAFT" {%- endif %} +footer-right: "\\thepage \\hspace{1pt} of \\pageref*{lastpage}" ... -!include-header partials/common-header.yml - {% import "partials/text-utilities.j2" as utils %} # Introduction diff --git a/docs/templates/software-requirements-specification.md.j2 b/docs/templates/software-requirements-specification.md.j2 index 9ef25b26..b93bf0d5 100644 --- a/docs/templates/software-requirements-specification.md.j2 +++ b/docs/templates/software-requirements-specification.md.j2 @@ -1,15 +1,25 @@ --- title: "Software requirements specification for amp-devcontainer" author: ["@rjaegers"] +colorlinks: true date: "{{ sbdl['doc_control']['custom:generated_at'] | strftime('%Y-%m-%d') }}" keywords: [Software, Requirements, SRS, amp-devcontainer] +lang: "en" +titlepage: true +titlepage-color: "0B5ED7" +titlepage-text-color: "FFFFFF" +titlepage-rule-color: "FFFFFF" +titlepage-rule-height: 2 +toc: true +toc-own-page: true +header-includes: + - \AtEndDocument{\label{lastpage}} {%- if sbdl['doc_control']['custom:is_release'] != 'true' %} watermark: "DRAFT" {%- endif %} +footer-right: "\\thepage \\hspace{1pt} of \\pageref*{lastpage}" ... -!include-header partials/common-header.yml - {% import "partials/text-utilities.j2" as utils %} # Introduction diff --git a/docs/templates/software-test-plan.md.j2 b/docs/templates/software-test-plan.md.j2 index 1b3a49a1..3e473012 100644 --- a/docs/templates/software-test-plan.md.j2 +++ b/docs/templates/software-test-plan.md.j2 @@ -1,15 +1,25 @@ --- title: "Software test plan for amp-devcontainer" author: ["@rjaegers"] +colorlinks: true date: "{{ sbdl['doc_control']['custom:generated_at'] | strftime('%Y-%m-%d') }}" keywords: [Software, Test, Plan, STP, amp-devcontainer] +lang: "en" +titlepage: true +titlepage-color: "0B5ED7" +titlepage-text-color: "FFFFFF" +titlepage-rule-color: "FFFFFF" +titlepage-rule-height: 2 +toc: true +toc-own-page: true +header-includes: + - \AtEndDocument{\label{lastpage}} {%- if sbdl['doc_control']['custom:is_release'] != 'true' %} watermark: "DRAFT" {%- endif %} +footer-right: "\\thepage \\hspace{1pt} of \\pageref*{lastpage}" ... -!include-header partials/common-header.yml - {% import "partials/text-utilities.j2" as utils %} # Introduction diff --git a/docs/templates/threat-model.md.j2 b/docs/templates/threat-model.md.j2 index ad69b80d..6cea5d66 100644 --- a/docs/templates/threat-model.md.j2 +++ b/docs/templates/threat-model.md.j2 @@ -1,15 +1,25 @@ --- title: "Threat model for amp-devcontainer" author: ["@rjaegers"] +colorlinks: true date: "{{ sbdl['doc_control']['custom:generated_at'] | strftime('%Y-%m-%d') }}" keywords: [Threat, Model, Security, STRIDE, FMEA, amp-devcontainer] +lang: "en" +titlepage: true +titlepage-color: "0B5ED7" +titlepage-text-color: "FFFFFF" +titlepage-rule-color: "FFFFFF" +titlepage-rule-height: 2 +toc: true +toc-own-page: true +header-includes: + - \AtEndDocument{\label{lastpage}} {%- if sbdl['doc_control']['custom:is_release'] != 'true' %} watermark: "DRAFT" {%- endif %} +footer-right: "\\thepage \\hspace{1pt} of \\pageref*{lastpage}" ... -!include-header partials/common-header.yml - {% import "partials/text-utilities.j2" as utils %} {%- set system = sbdl['system_amp_devcontainer'] -%} From 1e7ef744feae50e2fa2af8c347907a22d745e01c Mon Sep 17 00:00:00 2001 From: Ron <45816308+rjaegers@users.noreply.github.com> Date: Wed, 1 Jul 2026 21:14:14 +0000 Subject: [PATCH 04/11] docs: update thread model after review --- docs/templates/threat-model.md.j2 | 22 +- docs/threat-model.sbdl | 363 +++++++++++++++++++++++++++++- 2 files changed, 373 insertions(+), 12 deletions(-) diff --git a/docs/templates/threat-model.md.j2 b/docs/templates/threat-model.md.j2 index 6cea5d66..28fbbf91 100644 --- a/docs/templates/threat-model.md.j2 +++ b/docs/templates/threat-model.md.j2 @@ -95,6 +95,13 @@ The system is decomposed into the following trust boundaries. Data crossing a bo | {{ item['custom:title'] }} | {{ utils.reencode(item.description) }} | {%- endfor %} +## Trust assumptions + +The threat analysis relies on the following assumptions about each trust boundary. + +{% for id, item in sbdl.items() if item.type == 'trust_boundary' -%} +- **{{ item['custom:title'] }}:** {{ utils.reencode(item['custom:assumption']) }} +{% endfor %} # Actors | Actor | Type | Trust boundary | Description | @@ -175,8 +182,6 @@ The diagram below shows the system decomposed into its trust boundaries, with th {{ utils.reencode(threat.description) }} -{{ utils.reencode(threat.remark) }} - **Attack vector** {{ utils.reencode(cause.description) }} @@ -218,6 +223,17 @@ The table below ranks all identified threats by their Risk Priority Number (RPN) | {{ row.tid }} | {{ row.stride }} | {{ row.s }} | {{ row.o }} | {{ row.d }} | {{ row.rpn }} | {{ row.rpn_post }} | {{ row.risk }} | {%- endfor %} +# Control evidence + +Each threat's mitigation is backed by objective, reviewable evidence in the repository, supporting audit and regulatory review. + +| Threat | Control status | Evidence | +|--------|----------------|----------| +{%- for id, threat in sbdl.items() if threat.type == 'threat' %} +{%- set control = sbdl[threat['fmea:control'][0].identifier] %} +| {{ threat['custom:threat_id'] }} | {{ control['custom:status'] }} | {{ utils.reencode(control['custom:evidence']) if 'custom:evidence' in control else 'โ€”' }} | +{%- endfor %} + # Residual risk and planned actions The following actions are planned to further reduce residual risk. @@ -247,4 +263,4 @@ The following actions are planned to further reduce residual risk. | Low | {{ counts.low }} | | **Total** | **{{ counts.total }}** | -All high-risk threats have implemented, verifiable mitigations. Residual risk is tracked through the project's standard change control process and re-evaluated whenever the model or its source material changes. +Every identified threat has a documented mitigation with traceable evidence, summarised in the Control evidence section. High-risk threats whose controls are only partially implemented carry planned actions listed under Residual risk and planned actions. Residual risk is tracked through the project's standard change control process and re-evaluated whenever the model or its source material changes. diff --git a/docs/threat-model.sbdl b/docs/threat-model.sbdl index 61512938..be4dbbd8 100644 --- a/docs/threat-model.sbdl +++ b/docs/threat-model.sbdl @@ -2,8 +2,8 @@ # # Supply-chain security threat model for amp-devcontainer, expressed in SBDL. # -# This model is a pilot port of the former PyTM threat model (threat-model-pytm.py) -# onto SBDL, consolidating the threat model with the requirements model so that a +# This model maps the threat model for amp-devcontainer onto SBDL, +# consolidating the threat model with the requirements model so that a # single tool-chain (sbdl) drives all generated documentation. # # The STRIDE / threat-modelling concepts are mapped onto SBDL base types as follows: @@ -56,7 +56,7 @@ system_amp_devcontainer is aspect { description is "The amp-devcontainer project provides secure, supply-chain hardened development containers for regulated software development. Key security features include: pinned dependencies with SHA checksums, signed container images with SBOMs, vulnerability scanning with Trivy, OSSF Scorecard compliance, and comprehensive dependency management via Dependabot. The containers support both x64 and arm64 architectures and include development toolchains for C++ (GCC, Clang, ARM GCC) and Rust, along with security analysis tools." custom:business_criticality is "high" custom:exposure is "external" - custom:reviewed_at is "2025-09-23" + custom:reviewed_at is "2026-07-01" } # --------------------------------------------------------------------------- @@ -67,27 +67,56 @@ using { parent is system_amp_devcontainer } tz_public_internet is trust_boundary { custom:title is "Public Internet" - description is "Untrusted external network including package repositories, container registries, and third-party services." + description is "The untrusted external network over which all third-party sources are reached and from which unauthenticated attackers operate." + custom:assumption is "Treated as fully untrusted; all inbound data is integrity-verified and no confidentiality or authenticity is assumed for anything originating here." +} + +tz_package_registries is trust_boundary { + custom:title is "Package Registries" + description is "Language and OS package sources such as Ubuntu apt repositories, Python PyPI, and Rust crates.io." + custom:assumption is "Registries are reachable and authentic at the transport layer, but individual packages are untrusted until verified against pinned SHA256 checksums." +} + +tz_github_marketplace is trust_boundary { + custom:title is "GitHub Marketplace" + description is "Third-party GitHub Actions consumed by the build pipeline." + custom:assumption is "Actions are untrusted third-party code; only commit-SHA-pinned, reviewed actions are executed and their permissions are minimised." +} + +tz_vendor_sources is trust_boundary { + custom:title is "Vendor Binary Sources" + description is "Vendor and project download sites providing toolchain binaries and archives fetched during the build." + custom:assumption is "Vendor binaries are untrusted until verified by pinned checksum and, where the vendor publishes one, a cryptographic signature." +} + +tz_vscode_marketplace is trust_boundary { + custom:title is "VS Code Marketplace" + description is "The Visual Studio Code extension marketplace from which development extensions are installed." + custom:assumption is "Extensions are untrusted third-party code; only version-pinned extensions from verified publishers are installed." } tz_github_infrastructure is trust_boundary { custom:title is "GitHub Infrastructure" description is "GitHub's hosted infrastructure including Actions runners, Container Registry, and source code repository." + custom:assumption is "GitHub authenticates identities and enforces RBAC and 2FA, but account or token compromise is assumed to remain possible." } tz_build_environment is trust_boundary { custom:title is "Container Build Environment" description is "GitHub Actions runners executing container builds with elevated privileges." + custom:assumption is "Runners are ephemeral and isolated per build; a single build may be compromised, but compromise must not persist across builds." } tz_container_runtime is trust_boundary { custom:title is "Container Runtime Environment" description is "Developer workstations and CI/CD systems running the devcontainer images." + custom:assumption is "Consumers pull only published images and are expected to verify image signatures and provenance before use." } tz_developer_workstation is trust_boundary { custom:title is "Developer Workstation" description is "Local development environments where developers use the containers." + custom:assumption is "Host integrity is the developer's responsibility; the container reduces but cannot eliminate risk originating on the host." } using { parent is "" } @@ -134,8 +163,26 @@ actor_maintainer is actor { ext_package_repos is external_entity { custom:title is "External Package Repositories" - description is "Ubuntu apt repositories, Python PyPI, Rust crates.io, and other package sources." - parent is tz_public_internet + description is "Ubuntu apt repositories, Python PyPI, Rust crates.io, and other language and OS package sources." + parent is tz_package_registries +} + +ext_github_actions is external_entity { + custom:title is "GitHub Actions Marketplace" + description is "Third-party GitHub Actions referenced by the build workflows." + parent is tz_github_marketplace +} + +ext_vendor_downloads is external_entity { + custom:title is "Vendor Binary Downloads" + description is "Vendor and project download sites providing toolchain binaries such as compilers, analysers, and ccache." + parent is tz_vendor_sources +} + +ext_vscode_marketplace is external_entity { + custom:title is "VS Code Extension Marketplace" + description is "Marketplace source for the pinned Visual Studio Code extensions installed into the environment." + parent is tz_vscode_marketplace } # --------------------------------------------------------------------------- @@ -337,6 +384,7 @@ impact_sc01 is impact { mit_sc01 is mitigation { custom:status is "Implemented" + custom:evidence is "SHA256-pinned packages and downloads in .devcontainer/**/Dockerfile; dependency validation in the CI build." description is "Mitigations implemented:\n\n- Comprehensive dependency pinning with SHA256 checksums\n- Use of private package repositories where possible\n- Dependency scanning and validation during build\n- Regular security audits with tools like pip-audit" fmea:mode is threat_sc01_dependency_confusion } @@ -375,6 +423,7 @@ impact_sc02 is impact { mit_sc02 is mitigation { custom:status is "Implemented" + custom:evidence is "Digest-pinned base images in .devcontainer/**/Dockerfile; Trivy image scanning in .github/workflows/." description is "Mitigations implemented:\n\n- Base images pinned to specific SHA256 digests rather than mutable tags\n- Regular vulnerability scanning of base images with Trivy\n- Multi-stage builds to reduce attack surface\n- Minimal base images where possible" fmea:mode is threat_sc02_base_image } @@ -385,7 +434,7 @@ threat_runtime01_priv_escape is threat { custom:title is "Privileged Container Escape" custom:threat_id is "RUNTIME_01" custom:stride is "Elevation of Privilege" - custom:risk_level is "Medium" + custom:risk_level is "High" custom:capec is "CAPEC-233: Privilege Escalation" custom:cwe is "CWE-250: Execution with Unnecessary Privileges" description is "The Rust container runs with the privileged flag, creating the potential for a container escape to the host system." @@ -406,13 +455,14 @@ cause_runtime01 is attack_vector { } impact_runtime01 is impact { - description is "Host system compromise and lateral movement from the developer workstation or CI runner." - severity is 6 + description is "Host compromise on a developer workstation or CI runner, enabling malicious code injection, build-artifact tampering, and compromise of signing workflows โ€” a direct path into the software supply chain." + severity is 8 fmea:mode is threat_runtime01_priv_escape } mit_runtime01 is mitigation { custom:status is "Under review" + custom:evidence is "Privileged-flag necessity tracked in the Rust Dockerfile; capability-scoping planned (see planned actions)." description is "Mitigations under review:\n\n- Regular review of privileged flag necessity\n- Investigation of specific capabilities instead of full privilege escalation\n- Container runtime security monitoring implementation\n- User namespaces and security profiles evaluation" fmea:mode is threat_runtime01_priv_escape } @@ -456,6 +506,7 @@ impact_sc03 is impact { mit_sc03 is mitigation { custom:status is "Implemented" + custom:evidence is "Commit-SHA-pinned actions and step-security/harden-runner across .github/workflows/; least-privilege GITHUB_TOKEN permissions." description is "Mitigations implemented:\n\n- Step Security harden-runner action for build environment hardening\n- All GitHub Actions pinned to specific commit SHAs\n- Minimal permissions principle implemented\n- Ephemeral, isolated build environments\n- Container image signing and verification with ephemeral keys" fmea:mode is threat_sc03_runner_compromise } @@ -494,6 +545,7 @@ impact_data01 is impact { mit_data01 is mitigation { custom:status is "Implemented" + custom:evidence is "GitHub secret scanning; .dockerignore exclusions; secret detection in the CI pipeline." description is "Mitigations implemented:\n\n- GitHub native secrets scanning enabled\n- .dockerignore files to prevent credential inclusion\n- Secret detection in CI/CD pipelines\n- Ephemeral secrets with regular rotation\n- Separation of build-time and runtime secrets" fmea:mode is threat_data01_secrets } @@ -532,6 +584,7 @@ impact_sc04 is impact { mit_sc04 is mitigation { custom:status is "Implemented" + custom:evidence is "Keyless cosign signing via GitHub OIDC in the release workflow; branch and tag protection; OSSF Scorecard workflow." description is "Mitigations implemented:\n\n- Strong authentication with 2FA/MFA requirements\n- Least privilege access controls and RBAC\n- Container images signed with ephemeral keys using GitHub OIDC\n- Automated vulnerability scanning and detection\n- Registry access logging and monitoring\n- OSSF Scorecard compliance monitoring" fmea:mode is threat_sc04_registry_takeover } @@ -570,6 +623,7 @@ impact_vuln01 is impact { mit_vuln01 is mitigation { custom:status is "Implemented" + custom:evidence is "Trivy scans with SARIF upload to the Security tab; .github/dependabot.yml; generated SBOM artifacts." description is "Mitigations implemented:\n\n- Automated vulnerability scanning with Trivy (daily scans)\n- Dependabot for automated dependency updates\n- Software Bill of Materials (SBOM) generation and maintenance\n- Regular security audits of dependencies\n- Acknowledged CVE tracking with documented mitigation plans\n- SARIF upload to the GitHub Security tab for visibility" fmea:mode is threat_vuln01_vuln_deps } @@ -608,6 +662,297 @@ impact_sc05 is impact { mit_sc05 is mitigation { custom:status is "Implemented" + custom:evidence is "Version-pinned extensions in .devcontainer/**/devcontainer.json under version control." description is "Mitigations implemented:\n\n- All VS Code extensions pinned to specific versions\n- Extension allow-lists in development environments\n- Regular review of extension permissions and source code\n- Use of only trusted extensions from verified publishers\n- Version control of extension configurations" fmea:mode is threat_sc05_malicious_extension } + +# --------------------------------------------------------------------------- +# Additional threats from the supply-chain security review +# --------------------------------------------------------------------------- + +# --- SUPPLY_CHAIN_06: Signature verification bypass ----------------------- + +threat_sc06_sig_bypass is threat { + custom:title is "Signature Verification Bypass" + custom:threat_id is "SUPPLY_CHAIN_06" + custom:stride is "Spoofing" + custom:risk_level is "High" + custom:capec is "CAPEC-473: Signature Spoof" + custom:cwe is "CWE-347: Improper Verification of Cryptographic Signature" + description is "Container images are signed at publication, but a consumer that does not verify the signature can be served an unsigned or improperly signed image. The trust assumption that consumers verify signatures is not currently enforced." + detectability is 5 + detectability_post is 3 + aspect is flow_image_consumption, ds_ghcr_registry + fmea:cause is cause_sc06 + fmea:effect is impact_sc06 + fmea:control is mit_sc06 +} + +cause_sc06 is attack_vector { + description is "An attacker publishes or substitutes an unsigned or invalidly signed image and a consumer pulls it without performing cosign verification." + occurrence is 3 + occurrence_post is 2 + fmea:mode is threat_sc06_sig_bypass +} + +impact_sc06 is impact { + description is "A tampered image is trusted and executed on developer and CI systems despite the signing controls, defeating the provenance chain." + severity is 8 + fmea:mode is threat_sc06_sig_bypass +} + +mit_sc06 is mitigation { + custom:status is "Partially implemented" + custom:evidence is "Keyless cosign signing in the release workflow; consumer verification guidance in docs/SLSA-COMPLIANCE.md; policy enforcement planned." + description is "Mitigations:\n\n- Container images signed with cosign using GitHub OIDC\n- Documented, copy-pasteable signature-verification instructions for consumers\n- Verification policy to be enforced in downstream CI and, where applicable, admission control\n- Publication of the expected identity and issuer used for verification" + fmea:mode is threat_sc06_sig_bypass +} + +action_sc06_enforce_verification is planned_mitigation { + description is "Provide and require a cosign verification step (expected identity and OIDC issuer) for consumers, and add an admission or verification policy in downstream pipelines." + fmea:cause is cause_sc06 +} + +# --- SUPPLY_CHAIN_07: Build provenance forgery ---------------------------- + +threat_sc07_provenance_forgery is threat { + custom:title is "Build Provenance Forgery" + custom:threat_id is "SUPPLY_CHAIN_07" + custom:stride is "Tampering" + custom:risk_level is "High" + custom:capec is "CAPEC-194: Fake the Source of Data" + custom:cwe is "CWE-345: Insufficient Verification of Data Authenticity" + description is "Forged attestations or manipulated provenance records could make a compromised image appear to have a trustworthy build history, undermining the SBOMs and provenance artifacts the project relies on." + detectability is 4 + detectability_post is 2 + aspect is proc_github_actions_build, data_build_artifacts + fmea:cause is cause_sc07 + fmea:effect is impact_sc07 + fmea:control is mit_sc07 +} + +cause_sc07 is attack_vector { + description is "An attacker forges in-toto or SLSA attestations, or manipulates provenance records, for example by abusing a compromised signing step." + occurrence is 2 + occurrence_post is 1 + fmea:mode is threat_sc07_provenance_forgery +} + +impact_sc07 is impact { + description is "False trust in a compromised image whose provenance appears valid, allowing tampered artifacts to pass supply-chain checks." + severity is 8 + fmea:mode is threat_sc07_provenance_forgery +} + +mit_sc07 is mitigation { + custom:status is "Partially implemented" + custom:evidence is "SLSA provenance and SBOM attestations signed via GitHub OIDC; artifact retention in the release workflow; verification guidance in docs/SLSA-COMPLIANCE.md." + description is "Mitigations:\n\n- SLSA-style build provenance generated for published images\n- in-toto and SBOM attestations signed with ephemeral OIDC keys\n- Immutable retention of attestations alongside the image digest\n- Consumer-side provenance verification documented and to be enforced" + fmea:mode is threat_sc07_provenance_forgery +} + +action_sc07_verify_provenance is planned_mitigation { + description is "Enforce SLSA provenance verification (trusted builder identity and source repository) in consuming pipelines before an image is promoted." + fmea:cause is cause_sc07 +} + +# --- SUPPLY_CHAIN_08: Build cache poisoning ------------------------------- + +threat_sc08_cache_poisoning is threat { + custom:title is "Build Cache Poisoning" + custom:threat_id is "SUPPLY_CHAIN_08" + custom:stride is "Tampering" + custom:risk_level is "High" + custom:capec is "CAPEC-141: Cache Poisoning" + custom:cwe is "CWE-349: Acceptance of Extraneous Untrusted Data With Trusted Data" + description is "A malicious pull request or a poisoned cache key writes attacker-controlled content into the GitHub Actions cache, which is then reused by a trusted build across a trust boundary." + detectability is 5 + detectability_post is 3 + aspect is ds_build_cache + fmea:cause is cause_sc08 + fmea:effect is impact_sc08 + fmea:control is mit_sc08 +} + +cause_sc08 is attack_vector { + description is "A workflow triggered by an untrusted fork writes a cache entry that a privileged build later restores, or a shared cache key is reused across trust boundaries." + occurrence is 3 + occurrence_post is 2 + fmea:mode is threat_sc08_cache_poisoning +} + +impact_sc08 is impact { + description is "Malicious artifacts injected into an otherwise trusted build, tampering with the resulting container images." + severity is 7 + fmea:mode is threat_sc08_cache_poisoning +} + +mit_sc08 is mitigation { + custom:status is "Partially implemented" + custom:evidence is "Scope-limited cache keys per workflow; restriction of cache writes from untrusted fork triggers planned." + description is "Mitigations:\n\n- Trust-boundary-specific, scoped cache keys\n- No restore of caches written by untrusted pull-request triggers\n- Content-addressed, integrity-checked cache entries where supported\n- Regular cache eviction and restricted cache-write permissions" + fmea:mode is threat_sc08_cache_poisoning +} + +action_sc08_restrict_cache is planned_mitigation { + description is "Segregate cache keys by trust boundary and prevent privileged builds from restoring caches populated by untrusted fork workflows." + fmea:cause is cause_sc08 +} + +# --- SUPPLY_CHAIN_09: Compromised tool download --------------------------- + +threat_sc09_tool_download is threat { + custom:title is "Compromised Tool Download" + custom:threat_id is "SUPPLY_CHAIN_09" + custom:stride is "Tampering" + custom:risk_level is "High" + custom:capec is "CAPEC-185: Malicious Software Download" + custom:cwe is "CWE-494: Download of Code Without Integrity Check" + description is "Toolchain binaries fetched from vendor download sites, rather than package registries, could be tampered with in transit or at the source and executed during the build." + detectability is 4 + detectability_post is 2 + aspect is ext_vendor_downloads, proc_dependency_mgmt + fmea:cause is cause_sc09 + fmea:effect is impact_sc09 + fmea:control is mit_sc09 +} + +cause_sc09 is attack_vector { + description is "A vendor download is replaced with a malicious binary, or a download without integrity verification is served over a compromised channel." + occurrence is 3 + occurrence_post is 2 + fmea:mode is threat_sc09_tool_download +} + +impact_sc09 is impact { + description is "Execution of attacker-controlled tooling inside the build, contaminating every derived container image." + severity is 8 + fmea:mode is threat_sc09_tool_download +} + +mit_sc09 is mitigation { + custom:status is "Implemented" + custom:evidence is "SHA256-pinned binary downloads in .devcontainer/**/Dockerfile; ccache release verified against a pinned minisign public key in .devcontainer/cpp/Dockerfile." + description is "Mitigations implemented:\n\n- All vendor binary downloads pinned to SHA256 checksums\n- Publisher signature verification where available, for example ccache via minisign\n- Downloads performed over HTTPS from documented, pinned URLs\n- Preference for reproducible, source-referenced builds" + fmea:mode is threat_sc09_tool_download +} + +# --- AVAIL_01: Dependency or registry outage ------------------------------ + +threat_avail01_availability is threat { + custom:title is "Dependency or Registry Outage" + custom:threat_id is "AVAIL_01" + custom:stride is "Denial of Service" + custom:risk_level is "Medium" + custom:capec is "CAPEC-125: Flooding" + custom:cwe is "CWE-400: Uncontrolled Resource Consumption" + description is "Unavailability of an upstream package source, the container registry, or CI runners prevents the containers from being built or consumed, stalling development and releases." + detectability is 2 + detectability_post is 2 + aspect is proc_github_actions_build, ext_package_repos + fmea:cause is cause_avail01 + fmea:effect is impact_avail01 + fmea:control is mit_avail01 +} + +cause_avail01 is attack_vector { + description is "An upstream registry or download source becomes unavailable or rate-limited, or CI runner capacity is exhausted." + occurrence is 4 + occurrence_post is 3 + fmea:mode is threat_avail01_availability +} + +impact_avail01 is impact { + description is "Builds and image pulls fail, blocking development, testing, and release of the containers." + severity is 5 + fmea:mode is threat_avail01_availability +} + +mit_avail01 is mitigation { + custom:status is "Partially implemented" + custom:evidence is "APT snapshot pinning (see ADR 0001); build caching; pinned mirrors and retry logic in the build." + description is "Mitigations:\n\n- Pinned apt snapshots reduce reliance on always-current upstreams\n- Build caching limits repeated external fetches\n- Retry and back-off on transient download failures\n- Vendoring of the most critical dependencies where feasible" + fmea:mode is threat_avail01_availability +} + +# --- AUDIT_01: Release action repudiation --------------------------------- + +threat_audit01_repudiation is threat { + custom:title is "Release Action Repudiation" + custom:threat_id is "AUDIT_01" + custom:stride is "Repudiation" + custom:risk_level is "Medium" + custom:capec is "CAPEC-268: Audit Log Manipulation" + custom:cwe is "CWE-778: Insufficient Logging" + description is "Without strong, immutable traceability of who published an image or approved a release, a maintainer could deny having performed an action, or an unauthorised action could go unattributed." + detectability is 4 + detectability_post is 2 + aspect is ds_source_repository, proc_github_actions_build + fmea:cause is cause_audit01 + fmea:effect is impact_audit01 + fmea:control is mit_audit01 +} + +cause_audit01 is attack_vector { + description is "A release or publish action is performed without signed, attributable, tamper-evident records linking it to an authenticated identity." + occurrence is 2 + occurrence_post is 1 + fmea:mode is threat_audit01_repudiation +} + +impact_audit01 is impact { + description is "Loss of accountability for releases, weakening audit readiness and incident response." + severity is 5 + fmea:mode is threat_audit01_repudiation +} + +mit_audit01 is mitigation { + custom:status is "Partially implemented" + custom:evidence is "Signed commits and protected releases; OIDC-attributed publish steps; provenance and workflow-log retention." + description is "Mitigations:\n\n- Signed commits and protected branches and tags\n- Release actions attributed to authenticated identities via GitHub OIDC\n- Immutable retention of build provenance and workflow logs\n- Documented release-approval trail" + fmea:mode is threat_audit01_repudiation +} + +# --- TOOL_01: Development tool integrity and qualification ----------------- + +threat_tool01_tool_integrity is threat { + custom:title is "Development Tool Integrity and Qualification" + custom:threat_id is "TOOL_01" + custom:stride is "Tampering" + custom:risk_level is "Medium" + custom:capec is "CAPEC-444: Development Alteration" + custom:cwe is "CWE-1357: Reliance on Insufficiently Trustworthy Component" + description is "Incorrect, tampered, or unqualified compilers, analysers, and build tools in the container could silently produce defective or malicious output, which matters when the devcontainer forms part of the regulated software lifecycle evidence chain." + detectability is 4 + detectability_post is 3 + aspect is srv_dockerfile_cpp, srv_dockerfile_rust + fmea:cause is cause_tool01 + fmea:effect is impact_tool01 + fmea:control is mit_tool01 +} + +cause_tool01 is attack_vector { + description is "A tool is installed at an unintended, tampered, or unqualified version without a recorded, verifiable identity." + occurrence is 2 + occurrence_post is 2 + fmea:mode is threat_tool01_tool_integrity +} + +impact_tool01 is impact { + description is "Defective or malicious build output that undermines confidence in the toolchain used to produce regulated software." + severity is 7 + fmea:mode is threat_tool01_tool_integrity +} + +mit_tool01 is mitigation { + custom:status is "Partially implemented" + custom:evidence is "Pinned tool versions with checksums in .devcontainer/**/Dockerfile; SBOM enumerates installed tool versions; tool-qualification notes planned." + description is "Mitigations:\n\n- Tool versions pinned with integrity-checked downloads\n- SBOM enumerates the exact installed tool versions\n- Reproducible builds so the toolset can be re-derived\n- Documented tool-qualification assumptions for lifecycle evidence" + fmea:mode is threat_tool01_tool_integrity +} + +action_tool01_qualification is planned_mitigation { + description is "Document tool-qualification assumptions and record the intended, verified versions of safety-relevant tools as lifecycle evidence." + fmea:cause is cause_tool01 +} From 3ff2866e36443464f2712a723e18e208c7e93e6b Mon Sep 17 00:00:00 2001 From: Ron <45816308+rjaegers@users.noreply.github.com> Date: Wed, 1 Jul 2026 21:20:33 +0000 Subject: [PATCH 05/11] docs: fix PDF rendering issue --- docs/threat-model.sbdl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/threat-model.sbdl b/docs/threat-model.sbdl index be4dbbd8..5a2f9d84 100644 --- a/docs/threat-model.sbdl +++ b/docs/threat-model.sbdl @@ -455,7 +455,7 @@ cause_runtime01 is attack_vector { } impact_runtime01 is impact { - description is "Host compromise on a developer workstation or CI runner, enabling malicious code injection, build-artifact tampering, and compromise of signing workflows โ€” a direct path into the software supply chain." + description is "Host compromise on a developer workstation or CI runner, enabling malicious code injection, build-artifact tampering, and compromise of signing workflows, providing a direct path into the software supply chain." severity is 8 fmea:mode is threat_runtime01_priv_escape } From db471130ab70c4530bccc63df537622577ad05c0 Mon Sep 17 00:00:00 2001 From: Ron <45816308+rjaegers@users.noreply.github.com> Date: Sat, 4 Jul 2026 17:29:41 +0000 Subject: [PATCH 06/11] docs: let the model better reflect reality --- docs/threat-model.sbdl | 80 +++++++++++++++++++++++++----------------- 1 file changed, 47 insertions(+), 33 deletions(-) diff --git a/docs/threat-model.sbdl b/docs/threat-model.sbdl index 5a2f9d84..3890feac 100644 --- a/docs/threat-model.sbdl +++ b/docs/threat-model.sbdl @@ -56,7 +56,7 @@ system_amp_devcontainer is aspect { description is "The amp-devcontainer project provides secure, supply-chain hardened development containers for regulated software development. Key security features include: pinned dependencies with SHA checksums, signed container images with SBOMs, vulnerability scanning with Trivy, OSSF Scorecard compliance, and comprehensive dependency management via Dependabot. The containers support both x64 and arm64 architectures and include development toolchains for C++ (GCC, Clang, ARM GCC) and Rust, along with security analysis tools." custom:business_criticality is "high" custom:exposure is "external" - custom:reviewed_at is "2026-07-01" + custom:reviewed_at is "2026-07-04" } # --------------------------------------------------------------------------- @@ -227,7 +227,6 @@ srv_dockerfile_rust is server { parent is tz_github_infrastructure custom:os is "Ubuntu" custom:hardened is "true" - custom:privileged is "true" custom:repo_link is "https://github.com/philips-software/amp-devcontainer/blob/main/.devcontainer/rust/Dockerfile" } @@ -384,8 +383,8 @@ impact_sc01 is impact { mit_sc01 is mitigation { custom:status is "Implemented" - custom:evidence is "SHA256-pinned packages and downloads in .devcontainer/**/Dockerfile; dependency validation in the CI build." - description is "Mitigations implemented:\n\n- Comprehensive dependency pinning with SHA256 checksums\n- Use of private package repositories where possible\n- Dependency scanning and validation during build\n- Regular security audits with tools like pip-audit" + custom:evidence is "Version-pinned apt packages in .devcontainer/**/apt-requirements*.json; hash-locked pip installs (--require-hashes) in .devcontainer/cpp/requirements.txt; SHA256-pinned binary downloads in .devcontainer/**/Dockerfile; Dependabot and dependency review in CI." + description is "Mitigations implemented:\n\n- Explicit version pinning of apt packages from documented, trusted sources\n- Hash-locked Python dependencies installed with pip --require-hashes\n- SHA256-pinned direct binary downloads\n- Automated dependency updates via Dependabot and dependency review in CI" fmea:mode is threat_sc01_dependency_confusion } @@ -423,32 +422,37 @@ impact_sc02 is impact { mit_sc02 is mitigation { custom:status is "Implemented" - custom:evidence is "Digest-pinned base images in .devcontainer/**/Dockerfile; Trivy image scanning in .github/workflows/." - description is "Mitigations implemented:\n\n- Base images pinned to specific SHA256 digests rather than mutable tags\n- Regular vulnerability scanning of base images with Trivy\n- Multi-stage builds to reduce attack surface\n- Minimal base images where possible" + custom:evidence is "Digest-pinned Ubuntu base image in .devcontainer/base/Dockerfile; daily image scanning (Trivy via crazy-max/ghaction-container-scan) in .github/workflows/vulnerability-scan.yml." + description is "Mitigations implemented:\n\n- Upstream Ubuntu base image pinned to a specific SHA256 digest\n- Daily vulnerability scanning of published images (Trivy via ghaction-container-scan) with SARIF upload\n- Multi-stage builds to reduce attack surface\n- Minimal base images where possible" fmea:mode is threat_sc02_base_image } +action_sc02_pin_internal_base is planned_mitigation { + description is "Pin the internal amp-devcontainer-base reference used by the flavor Dockerfiles to a specific digest instead of the mutable :edge tag for released builds." + fmea:cause is cause_sc02 +} + # --- RUNTIME_01: Privileged container escape ------------------------------ threat_runtime01_priv_escape is threat { - custom:title is "Privileged Container Escape" + custom:title is "Container Runs With Root Privileges" custom:threat_id is "RUNTIME_01" custom:stride is "Elevation of Privilege" - custom:risk_level is "High" + custom:risk_level is "Medium" custom:capec is "CAPEC-233: Privilege Escalation" custom:cwe is "CWE-250: Execution with Unnecessary Privileges" - description is "The Rust container runs with the privileged flag, creating the potential for a container escape to the host system." - remark is "Privileged containers have elevated permissions that could enable escape to the host system, specifically affecting the Rust development environment. Status: under active review and optimization." - detectability is 5 + description is "The container images do not define a non-root user, so tools and mounted workspace code run as root inside the container, widening the blast radius of any container breakout or malicious workspace content." + remark is "None of the flavor Dockerfiles set a non-root USER, so processes run as root. This does not by itself grant host privileges, but it increases impact if container isolation is weakened. Affects both the C++ and Rust development environments. Status: under active review and optimization." + detectability is 4 detectability_post is 3 - aspect is srv_dockerfile_rust + aspect is srv_dockerfile_cpp, srv_dockerfile_rust fmea:cause is cause_runtime01 fmea:effect is impact_runtime01 fmea:control is mit_runtime01 } cause_runtime01 is attack_vector { - description is "A vulnerability in the privileged container runtime is exploited to break out of container isolation." + description is "Container processes run as root because no non-root user is configured, so a container breakout or malicious mounted content executes with elevated in-container privileges." occurrence is 3 occurrence_post is 2 fmea:mode is threat_runtime01_priv_escape @@ -462,13 +466,13 @@ impact_runtime01 is impact { mit_runtime01 is mitigation { custom:status is "Under review" - custom:evidence is "Privileged-flag necessity tracked in the Rust Dockerfile; capability-scoping planned (see planned actions)." - description is "Mitigations under review:\n\n- Regular review of privileged flag necessity\n- Investigation of specific capabilities instead of full privilege escalation\n- Container runtime security monitoring implementation\n- User namespaces and security profiles evaluation" + custom:evidence is "No privileged or added-capability run flags are set in .devcontainer/**/devcontainer.json; a non-root default USER is not yet configured in the Dockerfiles." + description is "Mitigations under review:\n\n- Containers are run without the privileged flag or added capabilities\n- Introduction of a non-root default USER in the flavor images\n- Investigation of least-capability runtime configurations for consumers\n- User namespaces and seccomp/AppArmor profiles evaluation" fmea:mode is threat_runtime01_priv_escape } action_runtime01_priv_review is planned_mitigation { - description is "Assess the necessity of the privileged flag on the Rust container and replace it with the minimal set of required capabilities." + description is "Add a non-root default USER to the flavor images and document the minimal set of capabilities consumers should grant at runtime." fmea:cause is cause_runtime01 } @@ -544,12 +548,17 @@ impact_data01 is impact { } mit_data01 is mitigation { - custom:status is "Implemented" - custom:evidence is "GitHub secret scanning; .dockerignore exclusions; secret detection in the CI pipeline." - description is "Mitigations implemented:\n\n- GitHub native secrets scanning enabled\n- .dockerignore files to prevent credential inclusion\n- Secret detection in CI/CD pipelines\n- Ephemeral secrets with regular rotation\n- Separation of build-time and runtime secrets" + custom:status is "Partially implemented" + custom:evidence is "Targeted build bind-mounts rather than broad build-context copies in .devcontainer/**/Dockerfile; GitHub secret scanning and push protection; no build-time secrets persisted into image layers." + description is "Mitigations:\n\n- Build steps bind-mount only the specific files they need instead of copying the whole repository into a layer\n- GitHub native secret scanning and push protection enabled on the repository\n- Build-time secrets kept out of image layers and workflow logs\n- Separation of build-time and runtime secrets" fmea:mode is threat_data01_secrets } +action_data01_dockerignore is planned_mitigation { + description is "Add a .dockerignore to exclude sensitive and irrelevant files from the build context, and add explicit secret detection (for example gitleaks) to the CI pipeline." + fmea:cause is cause_data01 +} + # --- SUPPLY_CHAIN_04: Container registry account takeover ------------------ threat_sc04_registry_takeover is threat { @@ -584,8 +593,8 @@ impact_sc04 is impact { mit_sc04 is mitigation { custom:status is "Implemented" - custom:evidence is "Keyless cosign signing via GitHub OIDC in the release workflow; branch and tag protection; OSSF Scorecard workflow." - description is "Mitigations implemented:\n\n- Strong authentication with 2FA/MFA requirements\n- Least privilege access controls and RBAC\n- Container images signed with ephemeral keys using GitHub OIDC\n- Automated vulnerability scanning and detection\n- Registry access logging and monitoring\n- OSSF Scorecard compliance monitoring" + custom:evidence is "Build-provenance attestations signed via GitHub OIDC (actions/attest, attest-build-provenance) in .github/workflows/wc-build-push.yml; branch and tag protection; OSSF Scorecard workflow." + description is "Mitigations implemented:\n\n- Strong authentication with 2FA/MFA requirements\n- Least privilege access controls and RBAC\n- Container images signed with GitHub artifact attestations using ephemeral OIDC keys\n- Automated vulnerability scanning and detection\n- Registry access logging and monitoring\n- OSSF Scorecard compliance monitoring" fmea:mode is threat_sc04_registry_takeover } @@ -623,8 +632,8 @@ impact_vuln01 is impact { mit_vuln01 is mitigation { custom:status is "Implemented" - custom:evidence is "Trivy scans with SARIF upload to the Security tab; .github/dependabot.yml; generated SBOM artifacts." - description is "Mitigations implemented:\n\n- Automated vulnerability scanning with Trivy (daily scans)\n- Dependabot for automated dependency updates\n- Software Bill of Materials (SBOM) generation and maintenance\n- Regular security audits of dependencies\n- Acknowledged CVE tracking with documented mitigation plans\n- SARIF upload to the GitHub Security tab for visibility" + custom:evidence is "Daily image scanning (Trivy via crazy-max/ghaction-container-scan) with SARIF upload to the Security tab in .github/workflows/vulnerability-scan.yml; .github/dependabot.yml; SBOM attestation via anchore/sbom-action." + description is "Mitigations implemented:\n\n- Automated daily image vulnerability scanning (Trivy via ghaction-container-scan)\n- Dependabot for automated dependency updates\n- Software Bill of Materials (SBOM) attestation generation and maintenance\n- Regular security audits of dependencies\n- Acknowledged CVE tracking with documented mitigation plans\n- SARIF upload to the GitHub Security tab for visibility" fmea:mode is threat_vuln01_vuln_deps } @@ -690,7 +699,7 @@ threat_sc06_sig_bypass is threat { } cause_sc06 is attack_vector { - description is "An attacker publishes or substitutes an unsigned or invalidly signed image and a consumer pulls it without performing cosign verification." + description is "An attacker publishes or substitutes an unsigned or invalidly signed image and a consumer pulls it without performing attestation verification." occurrence is 3 occurrence_post is 2 fmea:mode is threat_sc06_sig_bypass @@ -704,13 +713,13 @@ impact_sc06 is impact { mit_sc06 is mitigation { custom:status is "Partially implemented" - custom:evidence is "Keyless cosign signing in the release workflow; consumer verification guidance in docs/SLSA-COMPLIANCE.md; policy enforcement planned." - description is "Mitigations:\n\n- Container images signed with cosign using GitHub OIDC\n- Documented, copy-pasteable signature-verification instructions for consumers\n- Verification policy to be enforced in downstream CI and, where applicable, admission control\n- Publication of the expected identity and issuer used for verification" + custom:evidence is "Build-provenance attestations signed via GitHub OIDC (actions/attest) in .github/workflows/wc-build-push.yml; consumer verification guidance in README.md ('Verify image signature'); policy enforcement planned." + description is "Mitigations:\n\n- Container images signed with GitHub artifact attestations using ephemeral OIDC keys\n- Documented, copy-pasteable `gh attestation verify` instructions for consumers\n- Verification policy to be enforced in downstream CI and, where applicable, admission control\n- Publication of the expected signer workflow, identity, and issuer used for verification" fmea:mode is threat_sc06_sig_bypass } action_sc06_enforce_verification is planned_mitigation { - description is "Provide and require a cosign verification step (expected identity and OIDC issuer) for consumers, and add an admission or verification policy in downstream pipelines." + description is "Provide and require a `gh attestation verify` step (expected signer workflow and OIDC issuer) for consumers, and add an admission or verification policy in downstream pipelines." fmea:cause is cause_sc06 } @@ -747,7 +756,7 @@ impact_sc07 is impact { mit_sc07 is mitigation { custom:status is "Partially implemented" - custom:evidence is "SLSA provenance and SBOM attestations signed via GitHub OIDC; artifact retention in the release workflow; verification guidance in docs/SLSA-COMPLIANCE.md." + custom:evidence is "SLSA build-provenance and SBOM attestations signed via GitHub OIDC (actions/attest, attest-build-provenance, anchore/sbom-action) in .github/workflows/wc-build-push.yml, with an in-pipeline `gh attestation verify` step; verification guidance in README.md." description is "Mitigations:\n\n- SLSA-style build provenance generated for published images\n- in-toto and SBOM attestations signed with ephemeral OIDC keys\n- Immutable retention of attestations alongside the image digest\n- Consumer-side provenance verification documented and to be enforced" fmea:mode is threat_sc07_provenance_forgery } @@ -832,12 +841,17 @@ impact_sc09 is impact { } mit_sc09 is mitigation { - custom:status is "Implemented" - custom:evidence is "SHA256-pinned binary downloads in .devcontainer/**/Dockerfile; ccache release verified against a pinned minisign public key in .devcontainer/cpp/Dockerfile." - description is "Mitigations implemented:\n\n- All vendor binary downloads pinned to SHA256 checksums\n- Publisher signature verification where available, for example ccache via minisign\n- Downloads performed over HTTPS from documented, pinned URLs\n- Preference for reproducible, source-referenced builds" + custom:status is "Partially implemented" + custom:evidence is "SHA256-pinned binary downloads for most tools in .devcontainer/**/Dockerfile; ccache release verified against a pinned minisign public key in .devcontainer/cpp/Dockerfile; some direct downloads remain unverified (see planned actions)." + description is "Mitigations:\n\n- Most vendor binary downloads pinned to SHA256 checksums (ccache, xwin, ARM GNU toolchain, base image, bats)\n- Publisher signature verification where available, for example ccache via minisign\n- Downloads performed over HTTPS from documented, pinned URLs\n- Some direct downloads (CPM.cmake, include-what-you-use, cargo-binstall and the tools it installs, diffoci) are not yet checksum-verified" fmea:mode is threat_sc09_tool_download } +action_sc09_pin_downloads is planned_mitigation { + description is "Add SHA256 verification for the remaining direct downloads (CPM.cmake, include-what-you-use, cargo-binstall and its installed tools, and diffoci) so every fetched binary is integrity-checked." + fmea:cause is cause_sc09 +} + # --- AVAIL_01: Dependency or registry outage ------------------------------ threat_avail01_availability is threat { @@ -871,8 +885,8 @@ impact_avail01 is impact { mit_avail01 is mitigation { custom:status is "Partially implemented" - custom:evidence is "APT snapshot pinning (see ADR 0001); build caching; pinned mirrors and retry logic in the build." - description is "Mitigations:\n\n- Pinned apt snapshots reduce reliance on always-current upstreams\n- Build caching limits repeated external fetches\n- Retry and back-off on transient download failures\n- Vendoring of the most critical dependencies where feasible" + custom:evidence is "Version-pinned apt packages in .devcontainer/**/apt-requirements*.json; BuildKit cache mounts and GitHub Actions build caching." + description is "Mitigations:\n\n- Explicit version pinning of apt packages reduces reliance on always-current upstreams\n- BuildKit cache mounts and Actions caching limit repeated external fetches\n- Integrity-checked, version-pinned downloads can be re-fetched from documented URLs\n- Vendoring of the most critical dependencies where feasible" fmea:mode is threat_avail01_availability } From c16368fadcc6bbcabf8ae41441bfff6ffb874df9 Mon Sep 17 00:00:00 2001 From: Ron <45816308+rjaegers@users.noreply.github.com> Date: Sat, 4 Jul 2026 17:48:45 +0000 Subject: [PATCH 07/11] ci: point vulnerability scan to correct Dockerfile --- .github/workflows/vulnerability-scan.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/vulnerability-scan.yml b/.github/workflows/vulnerability-scan.yml index 56675382..3262ed17 100644 --- a/.github/workflows/vulnerability-scan.yml +++ b/.github/workflows/vulnerability-scan.yml @@ -14,7 +14,13 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - flavor: ["cpp", "embedded-cpp", "rust"] + include: + - flavor: cpp + dockerfile: .devcontainer/cpp/Dockerfile + - flavor: embedded-cpp + dockerfile: .devcontainer/cpp/Dockerfile + - flavor: rust + dockerfile: .devcontainer/rust/Dockerfile permissions: security-events: write # is needed by github/codeql-action/upload-sarif to upload sarif files steps: @@ -25,7 +31,7 @@ jobs: id: scan with: image: ghcr.io/${{ github.repository }}-${{ matrix.flavor }}:latest - dockerfile: .devcontainer/Dockerfile + dockerfile: ${{ matrix.dockerfile }} - uses: github/codeql-action/upload-sarif@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2 if: steps.scan.outputs.sarif != '' with: From f36590ee5ccef039a0aca8747418f02771412ee4 Mon Sep 17 00:00:00 2001 From: Ron <45816308+rjaegers@users.noreply.github.com> Date: Sat, 4 Jul 2026 17:58:35 +0000 Subject: [PATCH 08/11] ci: tighten the build context --- .dockerignore | 6 ++++++ docs/threat-model.sbdl | 10 +++++----- 2 files changed, 11 insertions(+), 5 deletions(-) create mode 100644 .dockerignore diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..9f606e58 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,6 @@ +# The container builds only consume files under .devcontainer/ (bind-mounted by +# the Dockerfiles); all other build inputs are fetched from checksum-pinned URLs. +# Exclude everything else from the build context so that no source, credentials, +# caches, or test artifacts can ever be copied into an image layer. +* +!.devcontainer/ diff --git a/docs/threat-model.sbdl b/docs/threat-model.sbdl index 3890feac..6085ea69 100644 --- a/docs/threat-model.sbdl +++ b/docs/threat-model.sbdl @@ -548,14 +548,14 @@ impact_data01 is impact { } mit_data01 is mitigation { - custom:status is "Partially implemented" - custom:evidence is "Targeted build bind-mounts rather than broad build-context copies in .devcontainer/**/Dockerfile; GitHub secret scanning and push protection; no build-time secrets persisted into image layers." - description is "Mitigations:\n\n- Build steps bind-mount only the specific files they need instead of copying the whole repository into a layer\n- GitHub native secret scanning and push protection enabled on the repository\n- Build-time secrets kept out of image layers and workflow logs\n- Separation of build-time and runtime secrets" + custom:status is "Implemented" + custom:evidence is "Allowlist .dockerignore restricting the build context to .devcontainer/**; targeted build bind-mounts in .devcontainer/**/Dockerfile; GitHub secret scanning and push protection; MegaLinter secret detection (REPOSITORY_GITLEAKS, REPOSITORY_SECRETLINT) in .mega-linter.yml." + description is "Mitigations implemented:\n\n- Allowlist .dockerignore excludes everything except .devcontainer/ from the build context, so no source, credentials, caches, or test artifacts enter an image layer\n- Build steps bind-mount only the specific files they need instead of copying the whole repository into a layer\n- GitHub native secret scanning and push protection enabled on the repository\n- Secret detection in CI via MegaLinter (gitleaks, secretlint)\n- Build-time secrets kept out of image layers and workflow logs" fmea:mode is threat_data01_secrets } -action_data01_dockerignore is planned_mitigation { - description is "Add a .dockerignore to exclude sensitive and irrelevant files from the build context, and add explicit secret detection (for example gitleaks) to the CI pipeline." +action_data01_narrow_context is planned_mitigation { + description is "Narrow the declared Docker build context root from the repository root to .devcontainer/ (updating devcontainer.json context, initializeCommand, the Dockerfile bind-mount paths, and the build-push workflows) so the context is minimal by construction rather than filtered by .dockerignore." fmea:cause is cause_data01 } From fc24bf41bc6bc54181166211fb8948c22d6f4d55 Mon Sep 17 00:00:00 2001 From: Ron <45816308+rjaegers@users.noreply.github.com> Date: Sat, 4 Jul 2026 18:18:05 +0000 Subject: [PATCH 09/11] refactor: sbdl identifiers are kebab-case --- docs/templates/threat-model.md.j2 | 38 +- docs/threat-model.sbdl | 606 +++++++++++++++--------------- 2 files changed, 322 insertions(+), 322 deletions(-) diff --git a/docs/templates/threat-model.md.j2 b/docs/templates/threat-model.md.j2 index 28fbbf91..2400d060 100644 --- a/docs/templates/threat-model.md.j2 +++ b/docs/templates/threat-model.md.j2 @@ -21,7 +21,7 @@ footer-right: "\\thepage \\hspace{1pt} of \\pageref*{lastpage}" ... {% import "partials/text-utilities.j2" as utils %} -{%- set system = sbdl['system_amp_devcontainer'] -%} +{%- set system = sbdl['system-amp-devcontainer'] -%} # Introduction @@ -81,9 +81,9 @@ The authoritative source of change history is the [Git log](https://github.com/p | Property | Value | |-----------------------|----------------------------------------------| -| Business criticality | {{ system['custom:business_criticality'] }} | +| Business criticality | {{ system['custom:business-criticality'] }} | | Exposure | {{ system['custom:exposure'] }} | -| Last reviewed | {{ system['custom:reviewed_at'] }} | +| Last reviewed | {{ system['custom:reviewed-at'] }} | # Trust boundaries @@ -91,7 +91,7 @@ The system is decomposed into the following trust boundaries. Data crossing a bo | Trust boundary | Description | |----------------|-------------| -{%- for id, item in sbdl.items() if item.type == 'trust_boundary' %} +{%- for id, item in sbdl.items() if item.type == 'trust-boundary' %} | {{ item['custom:title'] }} | {{ utils.reencode(item.description) }} | {%- endfor %} @@ -99,7 +99,7 @@ The system is decomposed into the following trust boundaries. Data crossing a bo The threat analysis relies on the following assumptions about each trust boundary. -{% for id, item in sbdl.items() if item.type == 'trust_boundary' -%} +{% for id, item in sbdl.items() if item.type == 'trust-boundary' -%} - **{{ item['custom:title'] }}:** {{ utils.reencode(item['custom:assumption']) }} {% endfor %} # Actors @@ -107,7 +107,7 @@ The threat analysis relies on the following assumptions about each trust boundar | Actor | Type | Trust boundary | Description | |-------|------|----------------|-------------| {%- for id, item in sbdl.items() if item.type == 'actor' %} -| {{ item['custom:title'] }} | {{ item['custom:actor_type'] }} | {{ sbdl[item['parent'][0].identifier]['custom:title'] if 'parent' in item else 'โ€”' }} | {{ utils.reencode(item.description) }} | +| {{ item['custom:title'] }} | {{ item['custom:actor-type'] }} | {{ sbdl[item['parent'][0].identifier]['custom:title'] if 'parent' in item else 'โ€”' }} | {{ utils.reencode(item.description) }} | {%- endfor %} # Components @@ -116,8 +116,8 @@ The processes, servers, and external entities that make up the system. | Component | Kind | Trust boundary | Description | |-----------|------|----------------|-------------| -{%- for id, item in sbdl.items() if item.type in ['process', 'server', 'external_entity'] %} -| {{ item['custom:title'] }} | {{ item.type | replace('_', ' ') }} | {{ sbdl[item['parent'][0].identifier]['custom:title'] if 'parent' in item else 'โ€”' }} | {{ utils.reencode(item.description) }} | +{%- for id, item in sbdl.items() if item.type in ['process', 'server', 'external-entity'] %} +| {{ item['custom:title'] }} | {{ item.type | replace('-', ' ') }} | {{ sbdl[item['parent'][0].identifier]['custom:title'] if 'parent' in item else 'โ€”' }} | {{ utils.reencode(item.description) }} | {%- endfor %} # Data stores @@ -125,14 +125,14 @@ The processes, servers, and external entities that make up the system. | Data store | Type | Encrypted | Trust boundary | Description | |------------|------|-----------|----------------|-------------| {%- for id, item in sbdl.items() if item.type == 'datastore' %} -| {{ item['custom:title'] }} | {{ item['custom:store_type'] }} | {{ 'yes' if item['custom:encrypted'] is defined and item['custom:encrypted'] == 'true' else 'no' }} | {{ sbdl[item['parent'][0].identifier]['custom:title'] if 'parent' in item else 'โ€”' }} | {{ utils.reencode(item.description) }} | +| {{ item['custom:title'] }} | {{ item['custom:store-type'] }} | {{ 'yes' if item['custom:encrypted'] is defined and item['custom:encrypted'] == 'true' else 'no' }} | {{ sbdl[item['parent'][0].identifier]['custom:title'] if 'parent' in item else 'โ€”' }} | {{ utils.reencode(item.description) }} | {%- endfor %} # Data assets | Data asset | Classification | Sensitivity | Description | |------------|----------------|-------------|-------------| -{%- for id, item in sbdl.items() if item.type == 'data_asset' %} +{%- for id, item in sbdl.items() if item.type == 'data-asset' %} | {{ item['custom:title'] }} | {{ item['custom:classification'] }} | {{ item['custom:sensitivity'] }} | {{ utils.reencode(item.description) }} | {%- endfor %} @@ -163,12 +163,12 @@ The diagram below shows the system decomposed into its trust boundaries, with th {%- set det_post = (threat.detectability_post | int) if 'detectability_post' in threat else detect %} {%- set rpn_post = severity * occ_post * det_post %} -## {{ threat['custom:threat_id'] }} โ€” {{ utils.reencode(threat['custom:title']) }} +## {{ threat['custom:threat-id'] }} โ€” {{ utils.reencode(threat['custom:title']) }} | Property | Value | |----------|-------| | STRIDE category | {{ threat['custom:stride'] }} | -| Qualitative risk | {{ threat['custom:risk_level'] }} | +| Qualitative risk | {{ threat['custom:risk-level'] }} | | Target(s) | {% for a in threat['aspect'] %}{{ sbdl[a.identifier]['custom:title'] }}{% if not loop.last %}, {% endif %}{% endfor %} | | Severity (S) | {{ severity }} | | Occurrence (O) | {{ occurrence }} | @@ -209,9 +209,9 @@ The table below ranks all identified threats by their Risk Priority Number (RPN) {%- set occ_post = (cause.occurrence_post | int) if 'occurrence_post' in cause else occurrence -%} {%- set det_post = (threat.detectability_post | int) if 'detectability_post' in threat else detect -%} {%- set _ = ns.rows.append({ - 'tid': threat['custom:threat_id'], + 'tid': threat['custom:threat-id'], 'stride': threat['custom:stride'], - 'risk': threat['custom:risk_level'], + 'risk': threat['custom:risk-level'], 's': severity, 'o': occurrence, 'd': detect, 'rpn': severity * occurrence * detect, 'rpn_post': severity * occ_post * det_post}) -%} @@ -231,17 +231,17 @@ Each threat's mitigation is backed by objective, reviewable evidence in the repo |--------|----------------|----------| {%- for id, threat in sbdl.items() if threat.type == 'threat' %} {%- set control = sbdl[threat['fmea:control'][0].identifier] %} -| {{ threat['custom:threat_id'] }} | {{ control['custom:status'] }} | {{ utils.reencode(control['custom:evidence']) if 'custom:evidence' in control else 'โ€”' }} | +| {{ threat['custom:threat-id'] }} | {{ control['custom:status'] }} | {{ utils.reencode(control['custom:evidence']) if 'custom:evidence' in control else 'โ€”' }} | {%- endfor %} # Residual risk and planned actions The following actions are planned to further reduce residual risk. -{% for id, item in sbdl.items() if item.type == 'planned_mitigation' -%} +{% for id, item in sbdl.items() if item.type == 'planned-mitigation' -%} {%- set linked_cause = sbdl[item['fmea:cause'][0].identifier] if 'fmea:cause' in item else none -%} {%- set linked_threat = sbdl[linked_cause['fmea:mode'][0].identifier] if linked_cause is not none and 'fmea:mode' in linked_cause else none -%} -- **{{ id }}**{% if linked_threat is not none %} (addresses {{ linked_threat['custom:threat_id'] }}){% endif %}: {{ utils.reencode(item.description) }} +- **{{ id }}**{% if linked_threat is not none %} (addresses {{ linked_threat['custom:threat-id'] }}){% endif %}: {{ utils.reencode(item.description) }} {% else -%} *No outstanding planned actions; all identified threats have implemented mitigations.* {% endfor %} @@ -250,8 +250,8 @@ The following actions are planned to further reduce residual risk. {%- set counts = namespace(high=0, medium=0, low=0, total=0) -%} {%- for id, item in sbdl.items() if item.type == 'threat' -%} {%- set counts.total = counts.total + 1 -%} -{%- if item['custom:risk_level'] == 'High' -%}{%- set counts.high = counts.high + 1 -%} -{%- elif item['custom:risk_level'] == 'Medium' -%}{%- set counts.medium = counts.medium + 1 -%} +{%- if item['custom:risk-level'] == 'High' -%}{%- set counts.high = counts.high + 1 -%} +{%- elif item['custom:risk-level'] == 'Medium' -%}{%- set counts.medium = counts.medium + 1 -%} {%- else -%}{%- set counts.low = counts.low + 1 -%} {%- endif -%} {%- endfor %} diff --git a/docs/threat-model.sbdl b/docs/threat-model.sbdl index 6085ea69..4b49eb76 100644 --- a/docs/threat-model.sbdl +++ b/docs/threat-model.sbdl @@ -10,19 +10,19 @@ # # PyTM / STRIDE concept SBDL custom type SBDL base type # --------------------- ---------------- -------------- -# Trust boundary / zone trust_boundary aspect +# Trust boundary / zone trust-boundary aspect # Actor actor aspect -# External entity external_entity aspect +# External entity external-entity aspect # Process / component process aspect # Server server aspect # Data store datastore aspect -# Data asset / data set data_asset aspect +# Data asset / data set data-asset aspect # Data flow dataflow aspect # Threat (failure/attack mode) threat fmea:mode -# Attack vector (cause) attack_vector fmea:cause +# Attack vector (cause) attack-vector fmea:cause # Impact (effect) impact fmea:effect # Mitigation (control) mitigation fmea:control -# Planned mitigation (action) planned_mitigation fmea:action-control +# Planned mitigation (action) planned-mitigation fmea:action-control # # Modelling threats as an FMEA lets the model carry Severity (on the impact), # Occurrence (on the attack vector) and Detectability (on the threat) so that a @@ -33,87 +33,87 @@ # Custom types # --------------------------------------------------------------------------- -customtype trust_boundary is aspect {} +customtype trust-boundary is aspect {} customtype actor is aspect {} -customtype external_entity is aspect {} +customtype external-entity is aspect {} customtype process is aspect {} customtype server is aspect {} customtype datastore is aspect {} -customtype data_asset is aspect {} +customtype data-asset is aspect {} customtype dataflow is aspect {} customtype threat is fmea:mode {} -customtype attack_vector is fmea:cause {} +customtype attack-vector is fmea:cause {} customtype impact is fmea:effect {} customtype mitigation is fmea:control {} -customtype planned_mitigation is fmea:action-control {} +customtype planned-mitigation is fmea:action-control {} # --------------------------------------------------------------------------- # System under analysis # --------------------------------------------------------------------------- -system_amp_devcontainer is aspect { +system-amp-devcontainer is aspect { custom:title is "amp-devcontainer" description is "The amp-devcontainer project provides secure, supply-chain hardened development containers for regulated software development. Key security features include: pinned dependencies with SHA checksums, signed container images with SBOMs, vulnerability scanning with Trivy, OSSF Scorecard compliance, and comprehensive dependency management via Dependabot. The containers support both x64 and arm64 architectures and include development toolchains for C++ (GCC, Clang, ARM GCC) and Rust, along with security analysis tools." - custom:business_criticality is "high" + custom:business-criticality is "high" custom:exposure is "external" - custom:reviewed_at is "2026-07-04" + custom:reviewed-at is "2026-07-04" } # --------------------------------------------------------------------------- # Trust boundaries (trust zones) # --------------------------------------------------------------------------- -using { parent is system_amp_devcontainer } +using { parent is system-amp-devcontainer } -tz_public_internet is trust_boundary { +trust-boundary-public-internet is trust-boundary { custom:title is "Public Internet" description is "The untrusted external network over which all third-party sources are reached and from which unauthenticated attackers operate." custom:assumption is "Treated as fully untrusted; all inbound data is integrity-verified and no confidentiality or authenticity is assumed for anything originating here." } -tz_package_registries is trust_boundary { +trust-boundary-package-registries is trust-boundary { custom:title is "Package Registries" description is "Language and OS package sources such as Ubuntu apt repositories, Python PyPI, and Rust crates.io." custom:assumption is "Registries are reachable and authentic at the transport layer, but individual packages are untrusted until verified against pinned SHA256 checksums." } -tz_github_marketplace is trust_boundary { +trust-boundary-github-marketplace is trust-boundary { custom:title is "GitHub Marketplace" description is "Third-party GitHub Actions consumed by the build pipeline." custom:assumption is "Actions are untrusted third-party code; only commit-SHA-pinned, reviewed actions are executed and their permissions are minimised." } -tz_vendor_sources is trust_boundary { +trust-boundary-vendor-sources is trust-boundary { custom:title is "Vendor Binary Sources" description is "Vendor and project download sites providing toolchain binaries and archives fetched during the build." custom:assumption is "Vendor binaries are untrusted until verified by pinned checksum and, where the vendor publishes one, a cryptographic signature." } -tz_vscode_marketplace is trust_boundary { +trust-boundary-vscode-marketplace is trust-boundary { custom:title is "VS Code Marketplace" description is "The Visual Studio Code extension marketplace from which development extensions are installed." custom:assumption is "Extensions are untrusted third-party code; only version-pinned extensions from verified publishers are installed." } -tz_github_infrastructure is trust_boundary { +trust-boundary-github-infrastructure is trust-boundary { custom:title is "GitHub Infrastructure" description is "GitHub's hosted infrastructure including Actions runners, Container Registry, and source code repository." custom:assumption is "GitHub authenticates identities and enforces RBAC and 2FA, but account or token compromise is assumed to remain possible." } -tz_build_environment is trust_boundary { +trust-boundary-build-environment is trust-boundary { custom:title is "Container Build Environment" description is "GitHub Actions runners executing container builds with elevated privileges." custom:assumption is "Runners are ephemeral and isolated per build; a single build may be compromised, but compromise must not persist across builds." } -tz_container_runtime is trust_boundary { +trust-boundary-container-runtime is trust-boundary { custom:title is "Container Runtime Environment" description is "Developer workstations and CI/CD systems running the devcontainer images." custom:assumption is "Consumers pull only published images and are expected to verify image signatures and provenance before use." } -tz_developer_workstation is trust_boundary { +trust-boundary-developer-workstation is trust-boundary { custom:title is "Developer Workstation" description is "Local development environments where developers use the containers." custom:assumption is "Host integrity is the developer's responsibility; the container reduces but cannot eliminate risk originating on the host." @@ -125,157 +125,157 @@ using { parent is "" } # Actors # --------------------------------------------------------------------------- -actor_developer is actor { +actor-developer is actor { custom:title is "Software Developer" description is "Developers using the devcontainer for local development and testing." - custom:actor_type is "user" + custom:actor-type is "user" custom:permissions is "Read container images, execute development tools, access source code." - parent is tz_developer_workstation + parent is trust-boundary-developer-workstation } -actor_ci_cd_system is actor { +actor-ci-cd-system is actor { custom:title is "CI/CD System" description is "Automated systems using containers for building and testing software." - custom:actor_type is "system" + custom:actor-type is "system" custom:permissions is "Pull container images, execute builds, publish artifacts." - parent is tz_container_runtime + parent is trust-boundary-container-runtime } -actor_malicious is actor { +actor-malicious is actor { custom:title is "Malicious Actor" description is "Threat actor attempting to compromise the supply chain or development environment." - custom:actor_type is "third_party" + custom:actor-type is "third_party" custom:permissions is "None (attempting to gain unauthorized access)." - parent is tz_public_internet + parent is trust-boundary-public-internet } -actor_maintainer is actor { +actor-maintainer is actor { custom:title is "Project Maintainer" description is "Authorized maintainers with commit and release permissions." - custom:actor_type is "administrator" + custom:actor-type is "administrator" custom:permissions is "Write access to repository, trigger releases, manage security policies." - parent is tz_github_infrastructure + parent is trust-boundary-github-infrastructure } # --------------------------------------------------------------------------- # External entities # --------------------------------------------------------------------------- -ext_package_repos is external_entity { +external-entity-package-repos is external-entity { custom:title is "External Package Repositories" description is "Ubuntu apt repositories, Python PyPI, Rust crates.io, and other language and OS package sources." - parent is tz_package_registries + parent is trust-boundary-package-registries } -ext_github_actions is external_entity { +external-entity-github-actions is external-entity { custom:title is "GitHub Actions Marketplace" description is "Third-party GitHub Actions referenced by the build workflows." - parent is tz_github_marketplace + parent is trust-boundary-github-marketplace } -ext_vendor_downloads is external_entity { +external-entity-vendor-downloads is external-entity { custom:title is "Vendor Binary Downloads" description is "Vendor and project download sites providing toolchain binaries such as compilers, analysers, and ccache." - parent is tz_vendor_sources + parent is trust-boundary-vendor-sources } -ext_vscode_marketplace is external_entity { +external-entity-vscode-marketplace is external-entity { custom:title is "VS Code Extension Marketplace" description is "Marketplace source for the pinned Visual Studio Code extensions installed into the environment." - parent is tz_vscode_marketplace + parent is trust-boundary-vscode-marketplace } # --------------------------------------------------------------------------- # Processes / components # --------------------------------------------------------------------------- -proc_github_actions_build is process { +process-github-actions-build is process { custom:title is "GitHub Actions Build Pipeline" description is "Automated pipeline for building, testing, and publishing container images with security scanning." - parent is tz_build_environment - custom:repo_link is "https://github.com/philips-software/amp-devcontainer/tree/main/.github/workflows" + parent is trust-boundary-build-environment + custom:repo-link is "https://github.com/philips-software/amp-devcontainer/tree/main/.github/workflows" } -proc_dependency_mgmt is process { +process-dependency-mgmt is process { custom:title is "Dependency Management System" description is "Comprehensive dependency pinning including apt packages, Python packages, and binary downloads." - parent is tz_github_infrastructure + parent is trust-boundary-github-infrastructure } -proc_vscode_extensions is process { +process-vscode-extensions is process { custom:title is "VS Code Extensions Configuration" description is "Pinned VS Code extensions with specific versions for development environment setup." - parent is tz_container_runtime + parent is trust-boundary-container-runtime } # --------------------------------------------------------------------------- # Servers # --------------------------------------------------------------------------- -srv_dockerfile_cpp is server { +server-dockerfile-cpp is server { custom:title is "C++ Devcontainer Dockerfile" description is "Multi-stage Dockerfile for building the C++ development environment with GCC, Clang, and embedded toolchains." - parent is tz_github_infrastructure + parent is trust-boundary-github-infrastructure custom:os is "Ubuntu" custom:hardened is "true" - custom:repo_link is "https://github.com/philips-software/amp-devcontainer/blob/main/.devcontainer/cpp/Dockerfile" + custom:repo-link is "https://github.com/philips-software/amp-devcontainer/blob/main/.devcontainer/cpp/Dockerfile" } -srv_dockerfile_rust is server { +server-dockerfile-rust is server { custom:title is "Rust Devcontainer Dockerfile" description is "Dockerfile for building the Rust development environment with embedded targets and analysis tools." - parent is tz_github_infrastructure + parent is trust-boundary-github-infrastructure custom:os is "Ubuntu" custom:hardened is "true" - custom:repo_link is "https://github.com/philips-software/amp-devcontainer/blob/main/.devcontainer/rust/Dockerfile" + custom:repo-link is "https://github.com/philips-software/amp-devcontainer/blob/main/.devcontainer/rust/Dockerfile" } # --------------------------------------------------------------------------- # Data stores # --------------------------------------------------------------------------- -ds_source_repository is datastore { +datastore-source-repository is datastore { custom:title is "GitHub Source Repository" description is "Git repository containing source code, build configurations, and security policies." - custom:store_type is "document" + custom:store-type is "document" custom:encrypted is "true" - parent is tz_github_infrastructure + parent is trust-boundary-github-infrastructure } -ds_ghcr_registry is datastore { +datastore-ghcr-registry is datastore { custom:title is "GitHub Container Registry" description is "OCI-compatible registry storing container images with metadata, SBOMs, and vulnerability scan results." - custom:store_type is "object" + custom:store-type is "object" custom:encrypted is "true" - parent is tz_github_infrastructure + parent is trust-boundary-github-infrastructure } -ds_build_cache is datastore { +datastore-build-cache is datastore { custom:title is "GitHub Actions Cache" description is "Build cache storage for Docker layers and build artifacts." - custom:store_type is "key_value" - parent is tz_build_environment + custom:store-type is "key_value" + parent is trust-boundary-build-environment } # --------------------------------------------------------------------------- # Data assets # --------------------------------------------------------------------------- -data_container_images is data_asset { +data-asset-container-images is data-asset { custom:title is "Container Images" description is "Signed multi-platform container images with embedded development toolchains." custom:classification is "SENSITIVE" custom:sensitivity is "ip" } -data_build_artifacts is data_asset { +data-asset-build-artifacts is data-asset { custom:title is "Build Artifacts and SBOMs" description is "Software Bill of Materials, vulnerability scan results, and build provenance." custom:classification is "SENSITIVE" custom:sensitivity is "biz" } -data_source_code is data_asset { +data-asset-source-code is data-asset { custom:title is "Source Code and Configuration" description is "Dockerfiles, build scripts, dependency manifests, and security configurations." custom:classification is "SENSITIVE" @@ -286,63 +286,63 @@ data_source_code is data_asset { # Data flows # --------------------------------------------------------------------------- -flow_dependency_download is dataflow { +dataflow-dependency-download is dataflow { custom:title is "External Dependency Download" description is "Download of packages, binaries, and toolchains from external repositories during build." - custom:source is "ext_package_repos" - custom:destination is "proc_github_actions_build" + custom:source is "external-entity-package-repos" + custom:destination is "process-github-actions-build" custom:protocol is "HTTPS" custom:port is "443" custom:encrypted is "true" - related is ext_package_repos, proc_github_actions_build + related is external-entity-package-repos, process-github-actions-build } -flow_image_publish is dataflow { +dataflow-image-publish is dataflow { custom:title is "Container Image Publication" description is "Publishing of built and signed container images to the registry." - custom:source is "proc_github_actions_build" - custom:destination is "ds_ghcr_registry" + custom:source is "process-github-actions-build" + custom:destination is "datastore-ghcr-registry" custom:protocol is "HTTPS" custom:port is "443" custom:encrypted is "true" - custom:data is "data_container_images" - related is proc_github_actions_build, ds_ghcr_registry + custom:data is "data-asset-container-images" + related is process-github-actions-build, datastore-ghcr-registry } -flow_image_consumption is dataflow { +dataflow-image-consumption is dataflow { custom:title is "Container Image Consumption" description is "Pull of container images by developers and CI/CD systems." - custom:source is "ds_ghcr_registry" - custom:destination is "actor_developer" + custom:source is "datastore-ghcr-registry" + custom:destination is "actor-developer" custom:protocol is "HTTPS" custom:port is "443" custom:encrypted is "true" - custom:data is "data_container_images" - related is ds_ghcr_registry, actor_developer + custom:data is "data-asset-container-images" + related is datastore-ghcr-registry, actor-developer } -flow_source_access is dataflow { +dataflow-source-access is dataflow { custom:title is "Source Code Access" description is "Maintainer access to the source code repository for updates and releases." - custom:source is "actor_maintainer" - custom:destination is "ds_source_repository" + custom:source is "actor-maintainer" + custom:destination is "datastore-source-repository" custom:protocol is "HTTPS" custom:port is "443" custom:encrypted is "true" - custom:data is "data_source_code" - related is actor_maintainer, ds_source_repository + custom:data is "data-asset-source-code" + related is actor-maintainer, datastore-source-repository } -flow_build_trigger is dataflow { +dataflow-build-trigger is dataflow { custom:title is "Build Trigger" description is "GitHub Actions build triggered by source code changes." - custom:source is "ds_source_repository" - custom:destination is "proc_github_actions_build" + custom:source is "datastore-source-repository" + custom:destination is "process-github-actions-build" custom:protocol is "HTTPS" custom:port is "443" custom:encrypted is "true" - custom:data is "data_source_code" - related is ds_source_repository, proc_github_actions_build + custom:data is "data-asset-source-code" + related is datastore-source-repository, process-github-actions-build } # --------------------------------------------------------------------------- @@ -351,329 +351,329 @@ flow_build_trigger is dataflow { # --- SUPPLY_CHAIN_01: Dependency confusion -------------------------------- -threat_sc01_dependency_confusion is threat { +threat-sc01-dependency-confusion is threat { custom:title is "Dependency Confusion Attack" - custom:threat_id is "SUPPLY_CHAIN_01" + custom:threat-id is "SUPPLY_CHAIN_01" custom:stride is "Tampering" - custom:risk_level is "High" + custom:risk-level is "High" custom:capec is "CAPEC-439: Manipulation During Distribution" custom:cwe is "CWE-494: Download of Code Without Integrity Check" description is "An attacker uploads malicious packages with names similar to internal dependencies to public repositories, which could be installed during the container build." remark is "Malicious packages could be installed during container build if dependency management is not properly secured. Affects the dependency management system and the GitHub Actions build pipeline." detectability is 4 detectability_post is 3 - aspect is proc_dependency_mgmt - fmea:cause is cause_sc01 - fmea:effect is impact_sc01 - fmea:control is mit_sc01 + aspect is process-dependency-mgmt + fmea:cause is attack-vector-sc01 + fmea:effect is impact-sc01 + fmea:control is mitigation-sc01 } -cause_sc01 is attack_vector { +attack-vector-sc01 is attack-vector { description is "Public package repositories resolve a malicious same-named package in preference to the intended dependency." occurrence is 4 occurrence_post is 2 - fmea:mode is threat_sc01_dependency_confusion + fmea:mode is threat-sc01-dependency-confusion } -impact_sc01 is impact { +impact-sc01 is impact { description is "Execution of attacker-controlled code inside the build, potentially propagating to all downstream users including safety-critical systems." severity is 8 - fmea:mode is threat_sc01_dependency_confusion + fmea:mode is threat-sc01-dependency-confusion } -mit_sc01 is mitigation { +mitigation-sc01 is mitigation { custom:status is "Implemented" custom:evidence is "Version-pinned apt packages in .devcontainer/**/apt-requirements*.json; hash-locked pip installs (--require-hashes) in .devcontainer/cpp/requirements.txt; SHA256-pinned binary downloads in .devcontainer/**/Dockerfile; Dependabot and dependency review in CI." description is "Mitigations implemented:\n\n- Explicit version pinning of apt packages from documented, trusted sources\n- Hash-locked Python dependencies installed with pip --require-hashes\n- SHA256-pinned direct binary downloads\n- Automated dependency updates via Dependabot and dependency review in CI" - fmea:mode is threat_sc01_dependency_confusion + fmea:mode is threat-sc01-dependency-confusion } # --- SUPPLY_CHAIN_02: Compromised base image ------------------------------ -threat_sc02_base_image is threat { +threat-sc02-base-image is threat { custom:title is "Compromised Base Image" - custom:threat_id is "SUPPLY_CHAIN_02" + custom:threat-id is "SUPPLY_CHAIN_02" custom:stride is "Tampering" - custom:risk_level is "High" + custom:risk-level is "High" custom:capec is "CAPEC-439: Manipulation During Distribution" custom:cwe is "CWE-829: Inclusion of Functionality from Untrusted Source" description is "The Ubuntu base image contains malicious code or vulnerabilities that propagate to the final container images." remark is "Base images could contain vulnerabilities or malicious code that propagates to final containers, affecting both the C++ and Rust development environments." detectability is 3 detectability_post is 2 - aspect is srv_dockerfile_cpp, srv_dockerfile_rust - fmea:cause is cause_sc02 - fmea:effect is impact_sc02 - fmea:control is mit_sc02 + aspect is server-dockerfile-cpp, server-dockerfile-rust + fmea:cause is attack-vector-sc02 + fmea:effect is impact-sc02 + fmea:control is mitigation-sc02 } -cause_sc02 is attack_vector { +attack-vector-sc02 is attack-vector { description is "A mutable base image tag is repointed to a tampered image, or the upstream base image is compromised." occurrence is 3 occurrence_post is 2 - fmea:mode is threat_sc02_base_image + fmea:mode is threat-sc02-base-image } -impact_sc02 is impact { +impact-sc02 is impact { description is "Malicious functionality embedded in every derived container image and executed on developer and CI systems." severity is 8 - fmea:mode is threat_sc02_base_image + fmea:mode is threat-sc02-base-image } -mit_sc02 is mitigation { +mitigation-sc02 is mitigation { custom:status is "Implemented" custom:evidence is "Digest-pinned Ubuntu base image in .devcontainer/base/Dockerfile; daily image scanning (Trivy via crazy-max/ghaction-container-scan) in .github/workflows/vulnerability-scan.yml." description is "Mitigations implemented:\n\n- Upstream Ubuntu base image pinned to a specific SHA256 digest\n- Daily vulnerability scanning of published images (Trivy via ghaction-container-scan) with SARIF upload\n- Multi-stage builds to reduce attack surface\n- Minimal base images where possible" - fmea:mode is threat_sc02_base_image + fmea:mode is threat-sc02-base-image } -action_sc02_pin_internal_base is planned_mitigation { +planned-mitigation-sc02-pin-internal-base is planned-mitigation { description is "Pin the internal amp-devcontainer-base reference used by the flavor Dockerfiles to a specific digest instead of the mutable :edge tag for released builds." - fmea:cause is cause_sc02 + fmea:cause is attack-vector-sc02 } # --- RUNTIME_01: Privileged container escape ------------------------------ -threat_runtime01_priv_escape is threat { +threat-runtime01-priv-escape is threat { custom:title is "Container Runs With Root Privileges" - custom:threat_id is "RUNTIME_01" + custom:threat-id is "RUNTIME_01" custom:stride is "Elevation of Privilege" - custom:risk_level is "Medium" + custom:risk-level is "Medium" custom:capec is "CAPEC-233: Privilege Escalation" custom:cwe is "CWE-250: Execution with Unnecessary Privileges" description is "The container images do not define a non-root user, so tools and mounted workspace code run as root inside the container, widening the blast radius of any container breakout or malicious workspace content." remark is "None of the flavor Dockerfiles set a non-root USER, so processes run as root. This does not by itself grant host privileges, but it increases impact if container isolation is weakened. Affects both the C++ and Rust development environments. Status: under active review and optimization." detectability is 4 detectability_post is 3 - aspect is srv_dockerfile_cpp, srv_dockerfile_rust - fmea:cause is cause_runtime01 - fmea:effect is impact_runtime01 - fmea:control is mit_runtime01 + aspect is server-dockerfile-cpp, server-dockerfile-rust + fmea:cause is attack-vector-runtime01 + fmea:effect is impact-runtime01 + fmea:control is mitigation-runtime01 } -cause_runtime01 is attack_vector { +attack-vector-runtime01 is attack-vector { description is "Container processes run as root because no non-root user is configured, so a container breakout or malicious mounted content executes with elevated in-container privileges." occurrence is 3 occurrence_post is 2 - fmea:mode is threat_runtime01_priv_escape + fmea:mode is threat-runtime01-priv-escape } -impact_runtime01 is impact { +impact-runtime01 is impact { description is "Host compromise on a developer workstation or CI runner, enabling malicious code injection, build-artifact tampering, and compromise of signing workflows, providing a direct path into the software supply chain." severity is 8 - fmea:mode is threat_runtime01_priv_escape + fmea:mode is threat-runtime01-priv-escape } -mit_runtime01 is mitigation { +mitigation-runtime01 is mitigation { custom:status is "Under review" custom:evidence is "No privileged or added-capability run flags are set in .devcontainer/**/devcontainer.json; a non-root default USER is not yet configured in the Dockerfiles." description is "Mitigations under review:\n\n- Containers are run without the privileged flag or added capabilities\n- Introduction of a non-root default USER in the flavor images\n- Investigation of least-capability runtime configurations for consumers\n- User namespaces and seccomp/AppArmor profiles evaluation" - fmea:mode is threat_runtime01_priv_escape + fmea:mode is threat-runtime01-priv-escape } -action_runtime01_priv_review is planned_mitigation { +planned-mitigation-runtime01-priv-review is planned-mitigation { description is "Add a non-root default USER to the flavor images and document the minimal set of capabilities consumers should grant at runtime." - fmea:cause is cause_runtime01 + fmea:cause is attack-vector-runtime01 } # --- SUPPLY_CHAIN_03: GitHub Actions runner compromise -------------------- -threat_sc03_runner_compromise is threat { +threat-sc03-runner-compromise is threat { custom:title is "GitHub Actions Runner Compromise" - custom:threat_id is "SUPPLY_CHAIN_03" + custom:threat-id is "SUPPLY_CHAIN_03" custom:stride is "Tampering" - custom:risk_level is "High" + custom:risk-level is "High" custom:capec is "CAPEC-187: Malicious Automated Software Update" custom:cwe is "CWE-346: Origin Validation Error" description is "Compromise of a GitHub Actions runner during the build process allows injection of malicious code into the container images." remark is "Compromised GitHub Actions runners could inject malicious code into container images during the build process." detectability is 4 detectability_post is 2 - aspect is proc_github_actions_build - fmea:cause is cause_sc03 - fmea:effect is impact_sc03 - fmea:control is mit_sc03 + aspect is process-github-actions-build + fmea:cause is attack-vector-sc03 + fmea:effect is impact-sc03 + fmea:control is mitigation-sc03 } -cause_sc03 is attack_vector { +attack-vector-sc03 is attack-vector { description is "A malicious or compromised GitHub Action or runner step executes attacker-controlled code within the build environment." occurrence is 2 occurrence_post is 1 - fmea:mode is threat_sc03_runner_compromise + fmea:mode is threat-sc03-runner-compromise } -impact_sc03 is impact { +impact-sc03 is impact { description is "Injection of malicious code into signed, published container images consumed by all downstream users." severity is 8 - fmea:mode is threat_sc03_runner_compromise + fmea:mode is threat-sc03-runner-compromise } -mit_sc03 is mitigation { +mitigation-sc03 is mitigation { custom:status is "Implemented" custom:evidence is "Commit-SHA-pinned actions and step-security/harden-runner across .github/workflows/; least-privilege GITHUB_TOKEN permissions." description is "Mitigations implemented:\n\n- Step Security harden-runner action for build environment hardening\n- All GitHub Actions pinned to specific commit SHAs\n- Minimal permissions principle implemented\n- Ephemeral, isolated build environments\n- Container image signing and verification with ephemeral keys" - fmea:mode is threat_sc03_runner_compromise + fmea:mode is threat-sc03-runner-compromise } # --- DATA_01: Development secrets exposure --------------------------------- -threat_data01_secrets is threat { +threat-data01-secrets is threat { custom:title is "Development Secrets Exposure" - custom:threat_id is "DATA_01" + custom:threat-id is "DATA_01" custom:stride is "Information Disclosure" - custom:risk_level is "Medium" + custom:risk-level is "Medium" custom:capec is "CAPEC-204: Lifting Sensitive Data Embedded in Cache" custom:cwe is "CWE-312: Cleartext Storage of Sensitive Information" description is "Accidental inclusion of secrets, API keys, or credentials in container layers or build logs." remark is "Secrets, API keys, or credentials could be accidentally included in container images or exposed in build logs during the build process." detectability is 3 detectability_post is 2 - aspect is proc_github_actions_build - fmea:cause is cause_data01 - fmea:effect is impact_data01 - fmea:control is mit_data01 + aspect is process-github-actions-build + fmea:cause is attack-vector-data01 + fmea:effect is impact-data01 + fmea:control is mitigation-data01 } -cause_data01 is attack_vector { +attack-vector-data01 is attack-vector { description is "A build step writes a secret into an image layer or emits it to the build log." occurrence is 3 occurrence_post is 2 - fmea:mode is threat_data01_secrets + fmea:mode is threat-data01-secrets } -impact_data01 is impact { +impact-data01 is impact { description is "Unauthorized access to development systems using leaked credentials." severity is 6 - fmea:mode is threat_data01_secrets + fmea:mode is threat-data01-secrets } -mit_data01 is mitigation { +mitigation-data01 is mitigation { custom:status is "Implemented" custom:evidence is "Allowlist .dockerignore restricting the build context to .devcontainer/**; targeted build bind-mounts in .devcontainer/**/Dockerfile; GitHub secret scanning and push protection; MegaLinter secret detection (REPOSITORY_GITLEAKS, REPOSITORY_SECRETLINT) in .mega-linter.yml." description is "Mitigations implemented:\n\n- Allowlist .dockerignore excludes everything except .devcontainer/ from the build context, so no source, credentials, caches, or test artifacts enter an image layer\n- Build steps bind-mount only the specific files they need instead of copying the whole repository into a layer\n- GitHub native secret scanning and push protection enabled on the repository\n- Secret detection in CI via MegaLinter (gitleaks, secretlint)\n- Build-time secrets kept out of image layers and workflow logs" - fmea:mode is threat_data01_secrets + fmea:mode is threat-data01-secrets } -action_data01_narrow_context is planned_mitigation { +planned-mitigation-data01-narrow-context is planned-mitigation { description is "Narrow the declared Docker build context root from the repository root to .devcontainer/ (updating devcontainer.json context, initializeCommand, the Dockerfile bind-mount paths, and the build-push workflows) so the context is minimal by construction rather than filtered by .dockerignore." - fmea:cause is cause_data01 + fmea:cause is attack-vector-data01 } # --- SUPPLY_CHAIN_04: Container registry account takeover ------------------ -threat_sc04_registry_takeover is threat { +threat-sc04-registry-takeover is threat { custom:title is "Container Registry Account Takeover" - custom:threat_id is "SUPPLY_CHAIN_04" + custom:threat-id is "SUPPLY_CHAIN_04" custom:stride is "Spoofing" - custom:risk_level is "High" + custom:risk-level is "High" custom:capec is "CAPEC-151: Identity Spoofing" custom:cwe is "CWE-287: Improper Authentication" description is "Compromise of a GitHub account or organization leads to malicious container images being published to the registry." remark is "Account compromise could allow attackers to publish malicious container images to the GitHub Container Registry." detectability is 4 detectability_post is 2 - aspect is ds_ghcr_registry - fmea:cause is cause_sc04 - fmea:effect is impact_sc04 - fmea:control is mit_sc04 + aspect is datastore-ghcr-registry + fmea:cause is attack-vector-sc04 + fmea:effect is impact-sc04 + fmea:control is mitigation-sc04 } -cause_sc04 is attack_vector { +attack-vector-sc04 is attack-vector { description is "An attacker obtains publish credentials through phishing, credential theft, or a compromised token." occurrence is 2 occurrence_post is 1 - fmea:mode is threat_sc04_registry_takeover + fmea:mode is threat-sc04-registry-takeover } -impact_sc04 is impact { +impact-sc04 is impact { description is "Distribution of malicious images under a trusted identity to all consumers of the registry." severity is 9 - fmea:mode is threat_sc04_registry_takeover + fmea:mode is threat-sc04-registry-takeover } -mit_sc04 is mitigation { +mitigation-sc04 is mitigation { custom:status is "Implemented" custom:evidence is "Build-provenance attestations signed via GitHub OIDC (actions/attest, attest-build-provenance) in .github/workflows/wc-build-push.yml; branch and tag protection; OSSF Scorecard workflow." description is "Mitigations implemented:\n\n- Strong authentication with 2FA/MFA requirements\n- Least privilege access controls and RBAC\n- Container images signed with GitHub artifact attestations using ephemeral OIDC keys\n- Automated vulnerability scanning and detection\n- Registry access logging and monitoring\n- OSSF Scorecard compliance monitoring" - fmea:mode is threat_sc04_registry_takeover + fmea:mode is threat-sc04-registry-takeover } # --- VULN_01: Vulnerable dependencies ------------------------------------- -threat_vuln01_vuln_deps is threat { +threat-vuln01-vuln-deps is threat { custom:title is "Vulnerable Dependencies" - custom:threat_id is "VULN_01" + custom:threat-id is "VULN_01" custom:stride is "Elevation of Privilege" - custom:risk_level is "Medium" + custom:risk-level is "Medium" custom:capec is "CAPEC-549: Local Execution of Code" custom:cwe is "CWE-1104: Use of Unmaintained Third Party Components" description is "Use of dependencies with known security vulnerabilities, including the acknowledged CVE-2025-50181 and CVE-2025-50182 in Conan." remark is "Known vulnerabilities in dependencies could be exploited for code execution or privilege escalation. Some vulnerabilities such as CVE-2025-50181 and CVE-2025-50182 are acknowledged, tracked, and monitored." detectability is 2 detectability_post is 2 - aspect is proc_dependency_mgmt - fmea:cause is cause_vuln01 - fmea:effect is impact_vuln01 - fmea:control is mit_vuln01 + aspect is process-dependency-mgmt + fmea:cause is attack-vector-vuln01 + fmea:effect is impact-vuln01 + fmea:control is mitigation-vuln01 } -cause_vuln01 is attack_vector { +attack-vector-vuln01 is attack-vector { description is "A known-vulnerable component shipped in the image is exercised by an attacker." occurrence is 5 occurrence_post is 3 - fmea:mode is threat_vuln01_vuln_deps + fmea:mode is threat-vuln01-vuln-deps } -impact_vuln01 is impact { +impact-vuln01 is impact { description is "Code execution or privilege escalation on systems running the affected tooling." severity is 6 - fmea:mode is threat_vuln01_vuln_deps + fmea:mode is threat-vuln01-vuln-deps } -mit_vuln01 is mitigation { +mitigation-vuln01 is mitigation { custom:status is "Implemented" custom:evidence is "Daily image scanning (Trivy via crazy-max/ghaction-container-scan) with SARIF upload to the Security tab in .github/workflows/vulnerability-scan.yml; .github/dependabot.yml; SBOM attestation via anchore/sbom-action." description is "Mitigations implemented:\n\n- Automated daily image vulnerability scanning (Trivy via ghaction-container-scan)\n- Dependabot for automated dependency updates\n- Software Bill of Materials (SBOM) attestation generation and maintenance\n- Regular security audits of dependencies\n- Acknowledged CVE tracking with documented mitigation plans\n- SARIF upload to the GitHub Security tab for visibility" - fmea:mode is threat_vuln01_vuln_deps + fmea:mode is threat-vuln01-vuln-deps } # --- SUPPLY_CHAIN_05: Malicious VS Code extension ------------------------- -threat_sc05_malicious_extension is threat { +threat-sc05-malicious-extension is threat { custom:title is "Malicious VS Code Extension" - custom:threat_id is "SUPPLY_CHAIN_05" + custom:threat-id is "SUPPLY_CHAIN_05" custom:stride is "Tampering" - custom:risk_level is "Medium" + custom:risk-level is "Medium" custom:capec is "CAPEC-549: Local Execution of Code" custom:cwe is "CWE-829: Inclusion of Functionality from Untrusted Source" description is "A compromised or malicious VS Code extension gains access to the development environment and source code." remark is "Malicious VS Code extensions could access source code, credentials, or compromise the development environment." detectability is 4 detectability_post is 3 - aspect is proc_vscode_extensions - fmea:cause is cause_sc05 - fmea:effect is impact_sc05 - fmea:control is mit_sc05 + aspect is process-vscode-extensions + fmea:cause is attack-vector-sc05 + fmea:effect is impact-sc05 + fmea:control is mitigation-sc05 } -cause_sc05 is attack_vector { +attack-vector-sc05 is attack-vector { description is "A pinned extension version is republished with malicious code, or an unvetted extension is installed." occurrence is 3 occurrence_post is 2 - fmea:mode is threat_sc05_malicious_extension + fmea:mode is threat-sc05-malicious-extension } -impact_sc05 is impact { +impact-sc05 is impact { description is "Disclosure of source code or credentials and compromise of the developer workstation." severity is 5 - fmea:mode is threat_sc05_malicious_extension + fmea:mode is threat-sc05-malicious-extension } -mit_sc05 is mitigation { +mitigation-sc05 is mitigation { custom:status is "Implemented" custom:evidence is "Version-pinned extensions in .devcontainer/**/devcontainer.json under version control." description is "Mitigations implemented:\n\n- All VS Code extensions pinned to specific versions\n- Extension allow-lists in development environments\n- Regular review of extension permissions and source code\n- Use of only trusted extensions from verified publishers\n- Version control of extension configurations" - fmea:mode is threat_sc05_malicious_extension + fmea:mode is threat-sc05-malicious-extension } # --------------------------------------------------------------------------- @@ -682,291 +682,291 @@ mit_sc05 is mitigation { # --- SUPPLY_CHAIN_06: Signature verification bypass ----------------------- -threat_sc06_sig_bypass is threat { +threat-sc06-sig-bypass is threat { custom:title is "Signature Verification Bypass" - custom:threat_id is "SUPPLY_CHAIN_06" + custom:threat-id is "SUPPLY_CHAIN_06" custom:stride is "Spoofing" - custom:risk_level is "High" + custom:risk-level is "High" custom:capec is "CAPEC-473: Signature Spoof" custom:cwe is "CWE-347: Improper Verification of Cryptographic Signature" description is "Container images are signed at publication, but a consumer that does not verify the signature can be served an unsigned or improperly signed image. The trust assumption that consumers verify signatures is not currently enforced." detectability is 5 detectability_post is 3 - aspect is flow_image_consumption, ds_ghcr_registry - fmea:cause is cause_sc06 - fmea:effect is impact_sc06 - fmea:control is mit_sc06 + aspect is dataflow-image-consumption, datastore-ghcr-registry + fmea:cause is attack-vector-sc06 + fmea:effect is impact-sc06 + fmea:control is mitigation-sc06 } -cause_sc06 is attack_vector { +attack-vector-sc06 is attack-vector { description is "An attacker publishes or substitutes an unsigned or invalidly signed image and a consumer pulls it without performing attestation verification." occurrence is 3 occurrence_post is 2 - fmea:mode is threat_sc06_sig_bypass + fmea:mode is threat-sc06-sig-bypass } -impact_sc06 is impact { +impact-sc06 is impact { description is "A tampered image is trusted and executed on developer and CI systems despite the signing controls, defeating the provenance chain." severity is 8 - fmea:mode is threat_sc06_sig_bypass + fmea:mode is threat-sc06-sig-bypass } -mit_sc06 is mitigation { +mitigation-sc06 is mitigation { custom:status is "Partially implemented" custom:evidence is "Build-provenance attestations signed via GitHub OIDC (actions/attest) in .github/workflows/wc-build-push.yml; consumer verification guidance in README.md ('Verify image signature'); policy enforcement planned." description is "Mitigations:\n\n- Container images signed with GitHub artifact attestations using ephemeral OIDC keys\n- Documented, copy-pasteable `gh attestation verify` instructions for consumers\n- Verification policy to be enforced in downstream CI and, where applicable, admission control\n- Publication of the expected signer workflow, identity, and issuer used for verification" - fmea:mode is threat_sc06_sig_bypass + fmea:mode is threat-sc06-sig-bypass } -action_sc06_enforce_verification is planned_mitigation { +planned-mitigation-sc06-enforce-verification is planned-mitigation { description is "Provide and require a `gh attestation verify` step (expected signer workflow and OIDC issuer) for consumers, and add an admission or verification policy in downstream pipelines." - fmea:cause is cause_sc06 + fmea:cause is attack-vector-sc06 } # --- SUPPLY_CHAIN_07: Build provenance forgery ---------------------------- -threat_sc07_provenance_forgery is threat { +threat-sc07-provenance-forgery is threat { custom:title is "Build Provenance Forgery" - custom:threat_id is "SUPPLY_CHAIN_07" + custom:threat-id is "SUPPLY_CHAIN_07" custom:stride is "Tampering" - custom:risk_level is "High" + custom:risk-level is "High" custom:capec is "CAPEC-194: Fake the Source of Data" custom:cwe is "CWE-345: Insufficient Verification of Data Authenticity" description is "Forged attestations or manipulated provenance records could make a compromised image appear to have a trustworthy build history, undermining the SBOMs and provenance artifacts the project relies on." detectability is 4 detectability_post is 2 - aspect is proc_github_actions_build, data_build_artifacts - fmea:cause is cause_sc07 - fmea:effect is impact_sc07 - fmea:control is mit_sc07 + aspect is process-github-actions-build, data-asset-build-artifacts + fmea:cause is attack-vector-sc07 + fmea:effect is impact-sc07 + fmea:control is mitigation-sc07 } -cause_sc07 is attack_vector { +attack-vector-sc07 is attack-vector { description is "An attacker forges in-toto or SLSA attestations, or manipulates provenance records, for example by abusing a compromised signing step." occurrence is 2 occurrence_post is 1 - fmea:mode is threat_sc07_provenance_forgery + fmea:mode is threat-sc07-provenance-forgery } -impact_sc07 is impact { +impact-sc07 is impact { description is "False trust in a compromised image whose provenance appears valid, allowing tampered artifacts to pass supply-chain checks." severity is 8 - fmea:mode is threat_sc07_provenance_forgery + fmea:mode is threat-sc07-provenance-forgery } -mit_sc07 is mitigation { +mitigation-sc07 is mitigation { custom:status is "Partially implemented" custom:evidence is "SLSA build-provenance and SBOM attestations signed via GitHub OIDC (actions/attest, attest-build-provenance, anchore/sbom-action) in .github/workflows/wc-build-push.yml, with an in-pipeline `gh attestation verify` step; verification guidance in README.md." description is "Mitigations:\n\n- SLSA-style build provenance generated for published images\n- in-toto and SBOM attestations signed with ephemeral OIDC keys\n- Immutable retention of attestations alongside the image digest\n- Consumer-side provenance verification documented and to be enforced" - fmea:mode is threat_sc07_provenance_forgery + fmea:mode is threat-sc07-provenance-forgery } -action_sc07_verify_provenance is planned_mitigation { +planned-mitigation-sc07-verify-provenance is planned-mitigation { description is "Enforce SLSA provenance verification (trusted builder identity and source repository) in consuming pipelines before an image is promoted." - fmea:cause is cause_sc07 + fmea:cause is attack-vector-sc07 } # --- SUPPLY_CHAIN_08: Build cache poisoning ------------------------------- -threat_sc08_cache_poisoning is threat { +threat-sc08-cache-poisoning is threat { custom:title is "Build Cache Poisoning" - custom:threat_id is "SUPPLY_CHAIN_08" + custom:threat-id is "SUPPLY_CHAIN_08" custom:stride is "Tampering" - custom:risk_level is "High" + custom:risk-level is "High" custom:capec is "CAPEC-141: Cache Poisoning" custom:cwe is "CWE-349: Acceptance of Extraneous Untrusted Data With Trusted Data" description is "A malicious pull request or a poisoned cache key writes attacker-controlled content into the GitHub Actions cache, which is then reused by a trusted build across a trust boundary." detectability is 5 detectability_post is 3 - aspect is ds_build_cache - fmea:cause is cause_sc08 - fmea:effect is impact_sc08 - fmea:control is mit_sc08 + aspect is datastore-build-cache + fmea:cause is attack-vector-sc08 + fmea:effect is impact-sc08 + fmea:control is mitigation-sc08 } -cause_sc08 is attack_vector { +attack-vector-sc08 is attack-vector { description is "A workflow triggered by an untrusted fork writes a cache entry that a privileged build later restores, or a shared cache key is reused across trust boundaries." occurrence is 3 occurrence_post is 2 - fmea:mode is threat_sc08_cache_poisoning + fmea:mode is threat-sc08-cache-poisoning } -impact_sc08 is impact { +impact-sc08 is impact { description is "Malicious artifacts injected into an otherwise trusted build, tampering with the resulting container images." severity is 7 - fmea:mode is threat_sc08_cache_poisoning + fmea:mode is threat-sc08-cache-poisoning } -mit_sc08 is mitigation { +mitigation-sc08 is mitigation { custom:status is "Partially implemented" custom:evidence is "Scope-limited cache keys per workflow; restriction of cache writes from untrusted fork triggers planned." description is "Mitigations:\n\n- Trust-boundary-specific, scoped cache keys\n- No restore of caches written by untrusted pull-request triggers\n- Content-addressed, integrity-checked cache entries where supported\n- Regular cache eviction and restricted cache-write permissions" - fmea:mode is threat_sc08_cache_poisoning + fmea:mode is threat-sc08-cache-poisoning } -action_sc08_restrict_cache is planned_mitigation { +planned-mitigation-sc08-restrict-cache is planned-mitigation { description is "Segregate cache keys by trust boundary and prevent privileged builds from restoring caches populated by untrusted fork workflows." - fmea:cause is cause_sc08 + fmea:cause is attack-vector-sc08 } # --- SUPPLY_CHAIN_09: Compromised tool download --------------------------- -threat_sc09_tool_download is threat { +threat-sc09-tool-download is threat { custom:title is "Compromised Tool Download" - custom:threat_id is "SUPPLY_CHAIN_09" + custom:threat-id is "SUPPLY_CHAIN_09" custom:stride is "Tampering" - custom:risk_level is "High" + custom:risk-level is "High" custom:capec is "CAPEC-185: Malicious Software Download" custom:cwe is "CWE-494: Download of Code Without Integrity Check" description is "Toolchain binaries fetched from vendor download sites, rather than package registries, could be tampered with in transit or at the source and executed during the build." detectability is 4 detectability_post is 2 - aspect is ext_vendor_downloads, proc_dependency_mgmt - fmea:cause is cause_sc09 - fmea:effect is impact_sc09 - fmea:control is mit_sc09 + aspect is external-entity-vendor-downloads, process-dependency-mgmt + fmea:cause is attack-vector-sc09 + fmea:effect is impact-sc09 + fmea:control is mitigation-sc09 } -cause_sc09 is attack_vector { +attack-vector-sc09 is attack-vector { description is "A vendor download is replaced with a malicious binary, or a download without integrity verification is served over a compromised channel." occurrence is 3 occurrence_post is 2 - fmea:mode is threat_sc09_tool_download + fmea:mode is threat-sc09-tool-download } -impact_sc09 is impact { +impact-sc09 is impact { description is "Execution of attacker-controlled tooling inside the build, contaminating every derived container image." severity is 8 - fmea:mode is threat_sc09_tool_download + fmea:mode is threat-sc09-tool-download } -mit_sc09 is mitigation { +mitigation-sc09 is mitigation { custom:status is "Partially implemented" custom:evidence is "SHA256-pinned binary downloads for most tools in .devcontainer/**/Dockerfile; ccache release verified against a pinned minisign public key in .devcontainer/cpp/Dockerfile; some direct downloads remain unverified (see planned actions)." description is "Mitigations:\n\n- Most vendor binary downloads pinned to SHA256 checksums (ccache, xwin, ARM GNU toolchain, base image, bats)\n- Publisher signature verification where available, for example ccache via minisign\n- Downloads performed over HTTPS from documented, pinned URLs\n- Some direct downloads (CPM.cmake, include-what-you-use, cargo-binstall and the tools it installs, diffoci) are not yet checksum-verified" - fmea:mode is threat_sc09_tool_download + fmea:mode is threat-sc09-tool-download } -action_sc09_pin_downloads is planned_mitigation { +planned-mitigation-sc09-pin-downloads is planned-mitigation { description is "Add SHA256 verification for the remaining direct downloads (CPM.cmake, include-what-you-use, cargo-binstall and its installed tools, and diffoci) so every fetched binary is integrity-checked." - fmea:cause is cause_sc09 + fmea:cause is attack-vector-sc09 } # --- AVAIL_01: Dependency or registry outage ------------------------------ -threat_avail01_availability is threat { +threat-avail01-availability is threat { custom:title is "Dependency or Registry Outage" - custom:threat_id is "AVAIL_01" + custom:threat-id is "AVAIL_01" custom:stride is "Denial of Service" - custom:risk_level is "Medium" + custom:risk-level is "Medium" custom:capec is "CAPEC-125: Flooding" custom:cwe is "CWE-400: Uncontrolled Resource Consumption" description is "Unavailability of an upstream package source, the container registry, or CI runners prevents the containers from being built or consumed, stalling development and releases." detectability is 2 detectability_post is 2 - aspect is proc_github_actions_build, ext_package_repos - fmea:cause is cause_avail01 - fmea:effect is impact_avail01 - fmea:control is mit_avail01 + aspect is process-github-actions-build, external-entity-package-repos + fmea:cause is attack-vector-avail01 + fmea:effect is impact-avail01 + fmea:control is mitigation-avail01 } -cause_avail01 is attack_vector { +attack-vector-avail01 is attack-vector { description is "An upstream registry or download source becomes unavailable or rate-limited, or CI runner capacity is exhausted." occurrence is 4 occurrence_post is 3 - fmea:mode is threat_avail01_availability + fmea:mode is threat-avail01-availability } -impact_avail01 is impact { +impact-avail01 is impact { description is "Builds and image pulls fail, blocking development, testing, and release of the containers." severity is 5 - fmea:mode is threat_avail01_availability + fmea:mode is threat-avail01-availability } -mit_avail01 is mitigation { +mitigation-avail01 is mitigation { custom:status is "Partially implemented" custom:evidence is "Version-pinned apt packages in .devcontainer/**/apt-requirements*.json; BuildKit cache mounts and GitHub Actions build caching." description is "Mitigations:\n\n- Explicit version pinning of apt packages reduces reliance on always-current upstreams\n- BuildKit cache mounts and Actions caching limit repeated external fetches\n- Integrity-checked, version-pinned downloads can be re-fetched from documented URLs\n- Vendoring of the most critical dependencies where feasible" - fmea:mode is threat_avail01_availability + fmea:mode is threat-avail01-availability } # --- AUDIT_01: Release action repudiation --------------------------------- -threat_audit01_repudiation is threat { +threat-audit01-repudiation is threat { custom:title is "Release Action Repudiation" - custom:threat_id is "AUDIT_01" + custom:threat-id is "AUDIT_01" custom:stride is "Repudiation" - custom:risk_level is "Medium" + custom:risk-level is "Medium" custom:capec is "CAPEC-268: Audit Log Manipulation" custom:cwe is "CWE-778: Insufficient Logging" description is "Without strong, immutable traceability of who published an image or approved a release, a maintainer could deny having performed an action, or an unauthorised action could go unattributed." detectability is 4 detectability_post is 2 - aspect is ds_source_repository, proc_github_actions_build - fmea:cause is cause_audit01 - fmea:effect is impact_audit01 - fmea:control is mit_audit01 + aspect is datastore-source-repository, process-github-actions-build + fmea:cause is attack-vector-audit01 + fmea:effect is impact-audit01 + fmea:control is mitigation-audit01 } -cause_audit01 is attack_vector { +attack-vector-audit01 is attack-vector { description is "A release or publish action is performed without signed, attributable, tamper-evident records linking it to an authenticated identity." occurrence is 2 occurrence_post is 1 - fmea:mode is threat_audit01_repudiation + fmea:mode is threat-audit01-repudiation } -impact_audit01 is impact { +impact-audit01 is impact { description is "Loss of accountability for releases, weakening audit readiness and incident response." severity is 5 - fmea:mode is threat_audit01_repudiation + fmea:mode is threat-audit01-repudiation } -mit_audit01 is mitigation { +mitigation-audit01 is mitigation { custom:status is "Partially implemented" custom:evidence is "Signed commits and protected releases; OIDC-attributed publish steps; provenance and workflow-log retention." description is "Mitigations:\n\n- Signed commits and protected branches and tags\n- Release actions attributed to authenticated identities via GitHub OIDC\n- Immutable retention of build provenance and workflow logs\n- Documented release-approval trail" - fmea:mode is threat_audit01_repudiation + fmea:mode is threat-audit01-repudiation } # --- TOOL_01: Development tool integrity and qualification ----------------- -threat_tool01_tool_integrity is threat { +threat-tool01-tool-integrity is threat { custom:title is "Development Tool Integrity and Qualification" - custom:threat_id is "TOOL_01" + custom:threat-id is "TOOL_01" custom:stride is "Tampering" - custom:risk_level is "Medium" + custom:risk-level is "Medium" custom:capec is "CAPEC-444: Development Alteration" custom:cwe is "CWE-1357: Reliance on Insufficiently Trustworthy Component" description is "Incorrect, tampered, or unqualified compilers, analysers, and build tools in the container could silently produce defective or malicious output, which matters when the devcontainer forms part of the regulated software lifecycle evidence chain." detectability is 4 detectability_post is 3 - aspect is srv_dockerfile_cpp, srv_dockerfile_rust - fmea:cause is cause_tool01 - fmea:effect is impact_tool01 - fmea:control is mit_tool01 + aspect is server-dockerfile-cpp, server-dockerfile-rust + fmea:cause is attack-vector-tool01 + fmea:effect is impact-tool01 + fmea:control is mitigation-tool01 } -cause_tool01 is attack_vector { +attack-vector-tool01 is attack-vector { description is "A tool is installed at an unintended, tampered, or unqualified version without a recorded, verifiable identity." occurrence is 2 occurrence_post is 2 - fmea:mode is threat_tool01_tool_integrity + fmea:mode is threat-tool01-tool-integrity } -impact_tool01 is impact { +impact-tool01 is impact { description is "Defective or malicious build output that undermines confidence in the toolchain used to produce regulated software." severity is 7 - fmea:mode is threat_tool01_tool_integrity + fmea:mode is threat-tool01-tool-integrity } -mit_tool01 is mitigation { +mitigation-tool01 is mitigation { custom:status is "Partially implemented" custom:evidence is "Pinned tool versions with checksums in .devcontainer/**/Dockerfile; SBOM enumerates installed tool versions; tool-qualification notes planned." description is "Mitigations:\n\n- Tool versions pinned with integrity-checked downloads\n- SBOM enumerates the exact installed tool versions\n- Reproducible builds so the toolset can be re-derived\n- Documented tool-qualification assumptions for lifecycle evidence" - fmea:mode is threat_tool01_tool_integrity + fmea:mode is threat-tool01-tool-integrity } -action_tool01_qualification is planned_mitigation { +planned-mitigation-tool01-qualification is planned-mitigation { description is "Document tool-qualification assumptions and record the intended, verified versions of safety-relevant tools as lifecycle evidence." - fmea:cause is cause_tool01 + fmea:cause is attack-vector-tool01 } From e9a92ac01bb5060b62ef5d374b3336c6778d9218 Mon Sep 17 00:00:00 2001 From: Ron <45816308+rjaegers@users.noreply.github.com> Date: Sat, 4 Jul 2026 18:20:41 +0000 Subject: [PATCH 10/11] refactor: change remaining identifiers to kebab-case --- .github/workflows/wc-document-generation.yml | 14 +++++++------- docs/templates/partials/document-control.md.j2 | 10 +++++----- .../requirements-traceability-matrix.md.j2 | 4 ++-- .../software-requirements-specification.md.j2 | 4 ++-- docs/templates/software-test-plan.md.j2 | 4 ++-- docs/templates/threat-model.md.j2 | 4 ++-- 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/.github/workflows/wc-document-generation.yml b/.github/workflows/wc-document-generation.yml index 6c1ba098..d36b99d5 100644 --- a/.github/workflows/wc-document-generation.yml +++ b/.github/workflows/wc-document-generation.yml @@ -41,15 +41,15 @@ jobs: cat > document-control.sbdl < Date: Sat, 4 Jul 2026 18:27:21 +0000 Subject: [PATCH 11/11] docs: refine image pinning misunderstanding --- docs/threat-model.sbdl | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/docs/threat-model.sbdl b/docs/threat-model.sbdl index 4b49eb76..8427dd63 100644 --- a/docs/threat-model.sbdl +++ b/docs/threat-model.sbdl @@ -422,16 +422,11 @@ impact-sc02 is impact { mitigation-sc02 is mitigation { custom:status is "Implemented" - custom:evidence is "Digest-pinned Ubuntu base image in .devcontainer/base/Dockerfile; daily image scanning (Trivy via crazy-max/ghaction-container-scan) in .github/workflows/vulnerability-scan.yml." - description is "Mitigations implemented:\n\n- Upstream Ubuntu base image pinned to a specific SHA256 digest\n- Daily vulnerability scanning of published images (Trivy via ghaction-container-scan) with SARIF upload\n- Multi-stage builds to reduce attack surface\n- Minimal base images where possible" + custom:evidence is "Digest-pinned Ubuntu base image in .devcontainer/base/Dockerfile; flavor builds reference amp-devcontainer-base by digest via the BASE_IMAGE build-arg in .github/workflows/build-push-test.yml; daily image scanning (Trivy via crazy-max/ghaction-container-scan) in .github/workflows/vulnerability-scan.yml." + description is "Mitigations implemented:\n\n- Upstream Ubuntu base image pinned to a specific SHA256 digest\n- Flavor builds reference the internal amp-devcontainer-base by content digest, passed as the BASE_IMAGE build-arg from the base image built in the same pipeline run; the mutable :edge default only applies to un-parameterised ad-hoc local builds\n- Published flavor images are self-contained and carry no mutable base reference\n- Daily vulnerability scanning of published images (Trivy via ghaction-container-scan) with SARIF upload\n- Multi-stage builds to reduce attack surface\n- Minimal base images where possible" fmea:mode is threat-sc02-base-image } -planned-mitigation-sc02-pin-internal-base is planned-mitigation { - description is "Pin the internal amp-devcontainer-base reference used by the flavor Dockerfiles to a specific digest instead of the mutable :edge tag for released builds." - fmea:cause is attack-vector-sc02 -} - # --- RUNTIME_01: Privileged container escape ------------------------------ threat-runtime01-priv-escape is threat {