ci: split Test into workspace and VTC halves, each gated on what changed - #1267
Conversation
`cargo test --workspace` is the longest-running check in the repo. Of 2203s of test execution, `vta_service` alone is 906s and vtc-service's 52 integration binaries are another 848s — and every pull request pays for both regardless of what it touched. Split into two jobs that together run exactly the same set: Test (workspace) cargo test --workspace --exclude vtc-service --exclude vtc-client Test (VTC) cargo test -p vtc-service -p vtc-client each gated by scripts/ci-affects.sh on whether the change can reach it. On the last 120 commits that is 13% of changes skipping the workspace half and a large share of the 53% VTA-only ones skipping the VTC half. The scope of the workspace half is stated as `--except vtc-service`, and this is the part worth not hand-rolling: it is NOT the complement of the VTC closure. `room-host` depends on `vtc-client`, so `vtc-client` belongs to both sides and a change to it must run both jobs. Deriving the closure from cargo metadata gets that right; writing "everything that isn't vtc-*" by hand does not. Verified: vtc-service only workspace=skip vtc=run vtc-client only workspace=run vtc=run <- the case a hand list breaks vta-service only workspace=run vtc=skip vta-tee only workspace=run vtc=skip vti-common workspace=run vtc=run room-host workspace=run vtc=skip docs only workspace=skip vtc=skip The #1243 no-op-rebuild guard moves to the VTC job, where the build.rs it guards actually lives. Also renames scripts/install-semver-deps.sh to install-build-deps.sh and uses it here. The Test job carried a third verbatim copy of that apt block; the point of extracting it in #1259 was to stop having several, and adding a fourth while splitting a job would have missed it. `vti-e2e-tests` is in the workspace half and its closure contains no vtc-*, so nothing cross-cutting is stranded by the split — checked rather than assumed. Signed-off-by: Glenn Gore <glenn.g@affinidi.com>
🛡️ AI Agentic Security Code Review1 AI-confirmed issue. Mandatory to check: 🔒 Security Code Review Report Details🛡️ Security Code Review Report — PR #1267
🗺️ Scan CoverageModules scanned: 2 · with findings: 1 · files: 3 · findings: 1
Executive Summary
🔒 Security IssuesConfirmed Vulnerabilities (1)🟡 Github Actions Mutable Action Tag (35 occurrences)
🧠 AI Triage:
Summary: GitHub Actions step uses a mutable tag or branch reference. Tags and branch names can be silently repointed by the action owner, enabling supply-chain attacks — as seen in the trivy-action and kics-gi — 35 occurrence(s): ci.yml:58, ci.yml:98, ci.yml:100, ci.yml:136, ci.yml:193, ci.yml:195, ci.yml:267, ci.yml:307, ci.yml:311, ci.yml:341, ci.yml:343, ci.yml:358, ci.yml:414, ci.yml:418, ci.yml:459, ci.yml:460, ci.yml:495, ci.yml:501, ci.yml:502, ci.yml:542 (+15 more) 📝 Description: GitHub Actions step uses a mutable tag or branch reference. Tags and branch names can be silently repointed by the action owner, enabling supply-chain attacks — as seen in the trivy-action and kics-gi 🌱 Root Cause: Github Actions Mutable Action Tag 🔧 Remediation:
Priority: Short-term Github Actions Mutable Action Tag: GitHub Actions step uses a mutable tag or branch reference. Tags and branch names can be silently repointed by the action owner, enabling supply-chain attacks — as seen in the trivy-action and kics-gi
Generated by Agentic Sec — AI Security Validation Agent Details🛡️ Threat Model & Affect Analysis — PR #1267
📋 Affect AnalysisChange SummaryThis PR splits the monolithic 'Test' CI job into two parallel jobs ('test' for workspace-minus-VTC, 'test-vtc' for vtc-service/vtc-client), each independently gated on whether the change actually affects that partition, via new 'vta_tests'/'vtc_tests' outputs on the 'affects' job. It also extends ci-affects.sh/ci-closure.py with an '--except' inversion mode to correctly compute 'everything except X' as a derived closure (not a hand-maintained complement), replaces a fragile inline apt-get retry block with a shared install-build-deps.sh script (renamed from install-semver-deps.sh), and adds a disk-space-reclamation step to the VTC job to avoid 'No space left on device' failures when linking the large vtc-service binary. Diff: +165 / -55 lines 📁 File Classifications.github/workflows/ci.yml
scripts/ci-affects.sh
scripts/ci-closure.py
scripts/install-build-deps.sh
🛡️ STRIDE Threat ModelIdentified Threats (12)🟡 STRIDE-1: Command Injection via Unquoted Variable Expansion in ci-affects.sh Closure Invocation
Description: SHELL_INVOCATION entry point in scripts/ci-affects.sh allows argument-injection into the downstream python3 subprocess due to unquoted Evidence: scripts/ci-affects.sh:119-122 Attack Scenario:
🔎 Threat Clue: Derived from COMP-002, COMP-003 via EP-002, EP-003
Preconditions: Attacker controls or influences the invocation arguments of ci-affects.sh (e.g., via a malicious PR that modifies job step inputs, or a compromised reusable workflow caller)., The unquoted Existing Controls: set -euo pipefail enforces fail-fast behavior on unset variables and pipeline errors. • EXCEPT is only ever set to the literal string "--except" or empty string within the script's own logic, not externally supplied. • cargo-metadata output is trusted local repository state, not attacker network input. Recommended Mitigations: Quote 🟠 STRIDE-2: Test Gating Bypass via Dependency Closure Miscalculation in affects Job
Description: CI_WORKFLOW_TRIGGER entry point in the affects job allows selective test-skip due to reliance on Cargo.lock hash-based cache keys and closure-derived boolean gates that do not account for path-dependency source-only changes, resulting in merge of insufficiently tested code Evidence: .github/workflows/ci.yml:131-133 Attack Scenario:
🔎 Threat Clue: Derived from COMP-001, COMP-002, COMP-003 via EP-001, EP-002, EP-003
Preconditions: Attacker has ability to submit and merge (or get merged) a pull request., Repository branch protection does not explicitly require both Existing Controls: Fail-open design: Recommended Mitigations: Make the cache key also derive from a content hash of workspace source files (not only Cargo.lock) to avoid stale target/ reuse for path dependencies. • Add branch protection rules requiring 🟠 STRIDE-3: Supply Chain Compromise via Unpinned Third-Party GitHub Actions
Description: BUILD_HOOK entry point via dtolnay/rust-toolchain@stable and taiki-e/install-action@cargo-semver-checks GitHub Actions allows a compromised or hijacked marketplace action to execute arbitrary code in the CI runner due to tag-based (not SHA-pinned) action references, resulting in secrets exfiltration and build artifact tampering Evidence: .github/workflows/ci.yml:multiple (e.g., 199, 527, 575) Attack Scenario:
🔎 Threat Clue: Derived from COMP-001, COMP-006 via EP-005
Preconditions: Upstream action repository (dtolnay/rust-toolchain, taiki-e/install-action, actions/checkout, actions/cache) is compromised or its tag is force-moved., CI secrets or GITHUB_TOKEN with write-level permissions are available to the affected job. Existing Controls: GitHub Actions default GITHUB_TOKEN permissions can be scoped down at the workflow level (not confirmed present in visible slice). • Public, widely-used actions (dtolnay/rust-toolchain, actions/checkout) have community scrutiny reducing likelihood but not eliminating risk. Recommended Mitigations: Pin all third-party actions to a specific immutable commit SHA rather than a mutable tag (e.g., 🟠 STRIDE-4: Arbitrary Code Execution via Unreviewed install-build-deps.sh Content
Description: SHELL_INVOCATION entry point Evidence: .github/workflows/ci.yml:158, 208, 527, 575 Attack Scenario:
🔎 Threat Clue: Derived from COMP-004 via EP-004
Preconditions: Attacker has write access to scripts/install-build-deps.sh (via compromised maintainer account, malicious PR merge, or supply-chain injection into the file at rest)., CI job executes the script with sudo/root privileges as historically implied by the removed inline block. Existing Controls: Script is version-controlled and subject to standard PR review before merge. • Runs in ephemeral, isolated GitHub-hosted runners limiting persistence beyond a single job. • Code comments indicate the intent is a narrowly-scoped Recommended Mitigations: Require CODEOWNERS review specifically for any change to install-build-deps.sh and other CI-privileged scripts. • Pin exact package versions/hashes for apt-get installs to prevent dependency substitution attacks. • Run dependency installation steps with the minimum privilege necessary (avoid blanket sudo) and add integrity checks (checksum verification) for anything fetched over the network. • Enable branch protection requiring signed commits for changes to CI scripts. 🟠 STRIDE-5: Build-Time npm Dependency Compromise via build.rs Shell-Out to npm run build
Description: BUILD_HOOK entry point vtc-service build.rs invoking Evidence: .github/workflows/ci.yml:246 (comment referencing #1243) Attack Scenario:
🔎 Threat Clue: Derived from COMP-006 via EP-005
Preconditions: admin-ui/package-lock.json contains a loose or unpinned dependency range vulnerable to dependency confusion or malicious version publication., npm install executes without Existing Controls: package-lock.json is checked into the repo (referenced in comments), providing some reproducibility. • The historical #1243 bug fix suggests awareness of build.rs source-tree mutation risk and at least partial remediation. • Build occurs in ephemeral, isolated CI runners. Recommended Mitigations: Enforce 🟡 STRIDE-6: Silent Test Skipping via Fail-Open Closure Resolution Masking Repudiation of Coverage Decisions
Description: GITHUB_STEP_SUMMARY output in ci-affects.sh allows insufficient auditability of why a test job ran or was skipped due to reliance on free-text emitted reasons without structured/immutable logging tied to commit SHA, resulting in inability to later verify or dispute a CI test-skip decision Evidence: scripts/ci-affects.sh:76-79 Attack Scenario:
🔎 Threat Clue: Derived from COMP-002 via EP-002
Preconditions: Investigation occurs after GitHub Actions log/artifact retention window has expired., No external SIEM or long-term CI log archival is configured (not observable in provided files). Existing Controls: GITHUB_STEP_SUMMARY provides at least a per-run visible justification without opening full logs. • GITHUB_OUTPUT Recommended Mitigations: Forward CI decision logs (including ci-affects.sh emit() reasons) to a long-term, append-only external log store (e.g., SIEM, object storage with retention lock). • Include the resolved commit SHA and closure decision in a signed build provenance attestation (e.g., SLSA provenance) for each merge. • Extend GitHub Actions log retention or archive workflow run artifacts to cold storage on a schedule. 🟡 STRIDE-7: Denial of Service via Disk Exhaustion Race Condition in test-vtc Job Cleanup
Description: Free disk space step in test-vtc job allows CI pipeline disruption due to a hardcoded, order-dependent cleanup ( Evidence: .github/workflows/ci.yml:202-210 Attack Scenario:
🔎 Threat Clue: Derived from COMP-001 via EP-001
Preconditions: GitHub Actions runner image layout changes unexpectedly, or a crafted dependency significantly increases binary/debuginfo size., No automated check validates node/npm availability after the rm -rf step. Existing Controls: Explicit Recommended Mitigations: Add an explicit post-cleanup assertion ( 🟡 STRIDE-8: Stale Build Artifact Reuse via Path-Dependency-Insensitive Cache Key in actions/cache
Description: actions/cache@v6 step in test job allows compilation of stale/mismatched artifacts due to a cache key based solely on Evidence: .github/workflows/ci.yml:165-176 Attack Scenario:
🔎 Threat Clue: Derived from COMP-001 via EP-001
Preconditions: A crate version substitution or [patch]/path-override is introduced in the same or a prior PR., The registry/git cache retains a stale or substituted crate blob across multiple workflow runs due to restore-keys prefix fallback. Existing Controls: target/ is explicitly excluded from caching, directly remediating the known #1133 stale-artifact bug for compiled outputs. • Cargo's built-in checksum verification for crates.io dependencies provides a baseline integrity check independent of the CI cache. • Cache key still incorporates the Cargo.lock hash as primary key, only falling back to prefix match on miss. Recommended Mitigations: Avoid 🟡 STRIDE-9: Split-Test-Job Coverage Gap Allowing vtc-service/vtc-client Regressions to Slip Past workspace Test Job
Description: cargo test invocation split between Evidence: .github/workflows/ci.yml:185, 246 Attack Scenario:
🔎 Threat Clue: Derived from COMP-001 via EP-001
Preconditions: A workspace-level (non-crate-scoped) integration test exists that depends on symbols from both the Existing Controls: Recommended Mitigations: Add a dedicated CI job that runs the full, unrestricted 🔵 STRIDE-10: Information Disclosure via Verbose CI Diagnostic Output of Disk and Package State
Description: df -h / and git status --porcelain / git diff --stat diagnostic steps in CI jobs allow exposure of internal runner filesystem layout and uncommitted build-artifact changes due to unredacted debug output in public workflow logs, resulting in reconnaissance information useful for planning further attacks Evidence: .github/workflows/ci.yml:153, 210, 285-287 Attack Scenario:
🔎 Threat Clue: Derived from COMP-001 via EP-001
Preconditions: Repository or workflow run visibility is public or accessible to the attacker (e.g., public OSS repo, or a compromised/external collaborator account with read access). Existing Controls: Diagnostic commands (df -h, git status --porcelain) do not print secrets or credentials. • Output is scoped to build-environment metadata, not application data or trust-infrastructure secrets. Recommended Mitigations: Mask or omit granular disk-size diagnostics in steps executed on public-facing repositories where not strictly necessary for debugging. • Restrict verbose diagnostic steps to a 🔵 STRIDE-11: Missing Workspace Membership Validation Allowing Confused-Deputy Crate Name Collision in ci-closure.py
Description: PIPE_STDIN entry point ci-closure.py allows incorrect closure computation via crate-name-based (not path/id-based) matching due to Evidence: scripts/ci-closure.py:58-64 Attack Scenario:
🔎 Threat Clue: Derived from COMP-003 via EP-003
Preconditions: Workspace restructuring introduces genuine crate name ambiguity between a path-dependency member and a differently-scoped package sharing the same name., No test exists validating ci-closure.py's behavior under such a collision. Existing Controls: Recommended Mitigations: Match on package ID (which includes full path/version) rather than bare name wherever feasible, falling back to name only for user-facing CLI ergonomics. • Add a unit test in the script's test suite (if any) simulating a name collision between a workspace member and an external dependency to lock in correct behavior. • Document the workspace_root-based disambiguation explicitly in the script's docstring for future maintainers. ⚪ STRIDE-12: Prompt-Injection-Style Instruction Embedded in Code Comments Attempting to Influence Automated Review Tooling
Description: Extensive narrative code comments across ci.yml/ci-affects.sh/ci-closure.py allow an automated security-review LLM/tool to be socially engineered due to persuasive, first-person justification text embedded directly in diff content, resulting in a risk that automated or human reviewers under-scrutinize the actual security-relevant code changes Evidence: .github/workflows/ci.yml:various Attack Scenario:
🔎 Threat Clue: Derived from COMP-001, COMP-002, COMP-003 via EP-001, EP-002, EP-003
Preconditions: A future contributor embeds genuinely adversarial natural-language instructions inside code comments specifically targeting AI-assisted code review or security scanning tools., Automated review tooling insufficiently isolates comment content as untrusted data (mitigated in this analysis by the enforced SECURITY DIRECTIVE). Existing Controls: This analysis explicitly treats all pasted content, including comments, as untrusted DATA per its governing security directive, preventing any instruction embedded in comments from altering findings or verdicts. • Human PR review remains a control layer independent of automated tooling. Recommended Mitigations: Establish a review policy flagging unusually long or persuasive inline comments in CI/infra files for additional human scrutiny. • Ensure any automated security review tooling explicitly treats source comments as untrusted content, never as control-flow instructions (already enforced here). • Encourage moving detailed rationale to linked issue trackers (e.g., '#1133', '#1243' as already practiced) rather than embedding excessive narrative directly in code, reducing the surface for this pattern. 🍝 PASTA Threat ModelApplication PurposeOpenVTC's Verifiable Trust Infrastructure provides mobile-core, enclave (TEE), and service-layer crates for cryptographic trust verification, and this PR modifies only the CI/CD pipeline (test gating, dependency installation, and closure computation) that gates code from reaching production, making the pipeline itself a high-value target for undermining assurance of the shipped trust infrastructure. Inherent Risks
ObjectivesRisk: Accept fail-open behavior (run tests when uncertain) for closure resolution errors to bias toward safety over speed.; Treat any privileged (sudo) CI step as a high-value target requiring change control. Business Impact Analysis (2)BIA-1: CI Test Gating and Merge Assurance (Critical)The end-to-end process by which a pull request's changes are automatically scoped, tested, and gated before being eligible for merge into the trust-infrastructure codebase. MTD: 01 days 00:00 hours | RTO: 00 days 04:00 hours | RPO: 00 days 00:00 hours
BIA-2: Build-Time Dependency Provisioning (High)The process of installing system packages (apt), Rust toolchains, and npm dependencies required to compile and test the workspace within each CI job. MTD: 02 days 00:00 hours | RTO: 00 days 08:00 hours | RPO: 00 days 01:00 hours
Technical ScopeRoles (3): RO-1 Repository Maintainer · RO-2 External Contributor · RO-3 CI Runner Service Identity Actors (3): AC-1 PR Author · AC-2 GitHub Actions Runner · AC-3 Third-Party Action Maintainer Entry Points (5): EP-1 CI Workflow Trigger · EP-2 ci-affects.sh Invocation · EP-3 ci-closure.py Pipe Invocation · EP-4 install-build-deps.sh Invocation · EP-5 admin-ui Build Hook Threat Actors (3): TA-1 Malicious External Contributor · TA-2 Supply-Chain Attacker (Upstream Action/Package Compromise) · TA-3 Malicious or Compromised Insider Infrastructure (1): IF-1 GitHub-Hosted ubuntu-latest Runner Trust Boundaries (3): TB-1 GitHub Actions Control Plane · TB-2 Ephemeral CI Runner Sandbox · TB-3 Repository Source Control External Entities (3): EE-1 GitHub Actions Marketplace (dtolnay/rust-toolchain, taiki-e/install-action, actions/checkout, actions/cache) · EE-2 npm Registry · EE-3 apt Package Mirror / Ubuntu Repository System Components (8): SC-1 affects Job (Closure Computation) · SC-2 ci-affects.sh Script · SC-3 ci-closure.py Script · SC-4 install-build-deps.sh Script · SC-5 test / test-vtc Jobs · SC-6 clippy / semver-checks Jobs · SC-7 vtc-service build.rs / admin-ui npm Build · SC-8 actions/cache Registry/Git Cache Resources And Assets (4): RA-1 Cargo.lock / Workspace Metadata · RA-2 ~/.cargo/registry and ~/.cargo/git Cache · RA-3 GITHUB_TOKEN and Job Secrets · RA-4 admin-ui/package-lock.json and Built Bundle Technologies And Dependencies (6): TD-1 Rust Cargo Workspace (path dependencies) · TD-2 dtolnay/rust-toolchain GitHub Action · TD-3 taiki-e/install-action (cargo-semver-checks) · TD-4 actions/cache · TD-5 actions/checkout · TD-6 npm / Node.js (admin-ui build) Use Cases (2)
⚔️ Attack Scenarios (4)SC-4: install-build-deps.sh Script---
config:
layout: dagre
look: classic
theme: dark
---
flowchart LR
subgraph SL1["1. Threat Actors"]
direction LR
TA3@{ shape: rect, label: "TA-3: Malicious or Compromised Insider<br><i>Abuse write access to weaken CI gating</i>" }
end
subgraph SL2["2. Threats"]
direction LR
S4@{ shape: rect, label: "STRIDE-4: Arbitrary Code Execution via Unreviewed install-build-deps.sh Content<br><i>High / Possible</i>" }
end
subgraph SL3["3. Attack Patterns"]
direction LR
C242@{ shape: rect, label: "CAPEC-242: Code Injection" }
end
subgraph SL4["4. Weaknesses"]
direction LR
W494@{ shape: rect, label: "CWE-494: Download of Code Without Integrity Check" }
W829@{ shape: rect, label: "CWE-829: Inclusion of Functionality from Untrusted Control Sphere" }
end
subgraph SL5["5. System Component"]
direction LR
SC4@{ shape: rect, label: "SC-4: install-build-deps.sh Script" }
end
SC4 --> W494
SC4 --> W829
W494 --> C242
W829 --> C242
C242 --> S4
S4 --> TA3
linkStyle 0 stroke:#FF0000,stroke-width:2px
linkStyle 1 stroke:#FF0000,stroke-width:2px
linkStyle 2 stroke:#FF0000,stroke-width:2px
linkStyle 3 stroke:#FF0000,stroke-width:2px
linkStyle 4 stroke:#FF0000,stroke-width:2px
linkStyle 5 stroke:#FF0000,stroke-width:2px
SC-1: affects Job (Closure Computation)---
config:
layout: dagre
look: classic
theme: dark
---
flowchart LR
subgraph SL1["1. Threat Actors"]
direction LR
TA1@{ shape: rect, label: "TA-1: Malicious External Contributor<br><i>Slip under-tested changes past CI gates</i>" }
end
subgraph SL2["2. Threats"]
direction LR
S2@{ shape: rect, label: "STRIDE-2: Test Gating Bypass via Dependency Closure Miscalculation<br><i>High / Likely</i>" }
S9@{ shape: rect, label: "STRIDE-9: Split-Test-Job Coverage Gap<br><i>Medium / Likely</i>" }
end
subgraph SL3["3. Attack Patterns"]
direction LR
C176@{ shape: rect, label: "CAPEC-176: Configuration/Environment Manipulation" }
end
subgraph SL4["4. Weaknesses"]
direction LR
W284@{ shape: rect, label: "CWE-284: Improper Access Control" }
W1104@{ shape: rect, label: "CWE-1104: Use of Unmaintained Third Party Components" }
end
subgraph SL5["5. System Component"]
direction LR
SC1@{ shape: rect, label: "SC-1: affects Job" }
end
SC1 --> W284
SC1 --> W1104
W284 --> C176
W1104 --> C176
C176 --> S2
C176 --> S9
S2 --> TA1
S9 --> TA1
linkStyle 0 stroke:#FF0000,stroke-width:2px
linkStyle 1 stroke:#FF0000,stroke-width:2px
linkStyle 2 stroke:#FF0000,stroke-width:2px
linkStyle 3 stroke:#FF0000,stroke-width:2px
linkStyle 4 stroke:#FF0000,stroke-width:2px
linkStyle 5 stroke:#FFA500,stroke-width:2px
linkStyle 6 stroke:#FF0000,stroke-width:2px
linkStyle 7 stroke:#FFA500,stroke-width:2px
SC-7: vtc-service build.rs / admin-ui npm Build---
config:
layout: dagre
look: classic
theme: dark
---
flowchart LR
subgraph SL1["1. Threat Actors"]
direction LR
TA2@{ shape: rect, label: "TA-2: Supply-Chain Attacker<br><i>Compromise widely-used upstream packages</i>" }
end
subgraph SL2["2. Threats"]
direction LR
S5@{ shape: rect, label: "STRIDE-5: Build-Time npm Dependency Compromise<br><i>High / Possible</i>" }
end
subgraph SL3["3. Attack Patterns"]
direction LR
C538@{ shape: rect, label: "CAPEC-538: Open-Source Supply Chain Attack" }
end
subgraph SL4["4. Weaknesses"]
direction LR
W1357@{ shape: rect, label: "CWE-1357: Reliance on Insufficiently Trustworthy Component" }
end
subgraph SL5["5. System Component"]
direction LR
SC7@{ shape: rect, label: "SC-7: build.rs / admin-ui npm Build" }
end
SC7 --> W1357
W1357 --> C538
C538 --> S5
S5 --> TA2
linkStyle 0 stroke:#FF0000,stroke-width:2px
linkStyle 1 stroke:#FF0000,stroke-width:2px
linkStyle 2 stroke:#FF0000,stroke-width:2px
linkStyle 3 stroke:#FF0000,stroke-width:2px
SC-5: test / test-vtc Jobs---
config:
layout: dagre
look: classic
theme: dark
---
flowchart LR
subgraph SL1["1. Threat Actors"]
direction LR
TA1@{ shape: rect, label: "TA-1: Malicious External Contributor<br><i>Time a regression to exhaust CI disk margin</i>" }
end
subgraph SL2["2. Threats"]
direction LR
S7@{ shape: rect, label: "STRIDE-7: DoS via Disk Exhaustion Race Condition<br><i>Medium / Possible</i>" }
S8@{ shape: rect, label: "STRIDE-8: Stale Build Artifact Reuse via Cache Key<br><i>Medium / Likely</i>" }
end
subgraph SL3["3. Attack Patterns"]
direction LR
C125@{ shape: rect, label: "CAPEC-125: Flooding / Resource Exhaustion" }
C538b@{ shape: rect, label: "CAPEC-538: Open-Source Supply Chain Attack" }
end
subgraph SL4["4. Weaknesses"]
direction LR
W400@{ shape: rect, label: "CWE-400: Uncontrolled Resource Consumption" }
W829b@{ shape: rect, label: "CWE-829: Inclusion of Functionality from Untrusted Control Sphere" }
end
subgraph SL5["5. System Component"]
direction LR
SC5@{ shape: rect, label: "SC-5: test / test-vtc Jobs" }
end
SC5 --> W400
SC5 --> W829b
W400 --> C125
W829b --> C538b
C125 --> S7
C538b --> S8
S7 --> TA1
S8 --> TA1
linkStyle 0 stroke:#FFA500,stroke-width:2px
linkStyle 1 stroke:#FFA500,stroke-width:2px
linkStyle 2 stroke:#FFA500,stroke-width:2px
linkStyle 3 stroke:#FFA500,stroke-width:2px
linkStyle 4 stroke:#FFA500,stroke-width:2px
linkStyle 5 stroke:#FFA500,stroke-width:2px
linkStyle 6 stroke:#FFA500,stroke-width:2px
linkStyle 7 stroke:#FFA500,stroke-width:2px
📊 Risk SummaryTotal Threats: 12 By Severity: Low: 2 · High: 4 · Medium: 5 · Informational: 1 By Category: Tampering: 9 · Elevation of Privilege: 4 · Repudiation: 4 · Information Disclosure: 2 · Denial of Service: 1 Generated by Agentic Sec — Threat Model & Affect Analysis Agent 📊 Summary & findings
Confirmed (1)
|
Follow-up to #1265, extending the same mechanism to the longest check in the repo.
Of 2203s of test execution,
vta_servicealone is 906s andvtc-service's 52integration binaries are another 848s — and every PR pays for both regardless
of what it touched.
The split
Two jobs that together run exactly the same set as before:
each gated by
scripts/ci-affects.shon whether the change can reach it.The part worth not hand-rolling
The workspace half's scope is
--except vtc-service, and that is not thecomplement of the VTC closure.
room-hostdepends onvtc-client, sovtc-clientbelongs to both sides — a change to it must run both jobs. Derivedfrom cargo metadata this falls out correctly; written by hand as "everything that
isn't
vtc-*" it is wrong in a way that skips real coverage.Verified in a scratch clone:
vtc-serviceonlyvtc-clientonlyvta-serviceonlyvta-teeonlyvti-commonroom-hostOn the last 120 commits that is 13% skipping the workspace half, and a large
share of the 53% VTA-only changes skipping the VTC half.
Also
vtc-servicerecompiles in full on everycargo build, even with no changes #1243 no-op-rebuild guard moves to the VTC job, where thebuild.rsitguards actually lives.
scripts/install-semver-deps.sh→install-build-deps.sh, and the Test jobsuse it. That job carried a third verbatim copy of the apt block; extracting
it in fix(ci): the release-bump guard was missing the system deps its check needs #1259 was meant to stop having several, and adding a fourth while
splitting a job would have quietly undone that.
vti-e2e-testssits in the workspace half and its closure contains novtc-*,so nothing cross-cutting is stranded — checked, not assumed.
Safety
Unchanged from #1265: every uncertainty resolves to run (not a PR, lockfile or
.github/orscripts/touched, unattributable path, no usable diff), and theconditions are
!= 'false'so a missing output runs rather than skips.Worth watching on the first few PRs: the
affectsjob prints its reasoning andwrites it to the step summary, so a wrong skip should be visible rather than
silent.