Skip to content

Commit e611a76

Browse files
Merge pull request #2579 from EffortlessMetrics/publish/routed-ci-frontdoor
merge(swarm): import routed CI front door
2 parents cb84e52 + a33400b commit e611a76

30 files changed

Lines changed: 3672 additions & 554 deletions
Lines changed: 304 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,304 @@
1+
# Security Scan Report
2+
3+
**Generated:** 2026-06-08
4+
**Scan Type:** Weekly Scheduled
5+
**Repository:** EffortlessMetrics/tokmd-swarm
6+
**Severity Threshold:** medium
7+
**Scope:** Last 7 days of commits
8+
9+
## Executive Summary
10+
11+
| Severity | Count | Auto-fixed | Manual Required |
12+
|----------|-------|------------|-----------------|
13+
| CRITICAL | 0 | 0 | 0 |
14+
| HIGH | 0 | 0 | 0 |
15+
| MEDIUM | 0 | 0 | 0 |
16+
| LOW | 0 | 0 | 0 |
17+
18+
**Total Findings:** 0
19+
**Auto-fixed:** 0
20+
**Manual Review Required:** 0
21+
22+
**Summary:** No vulnerabilities at or above the `medium` severity threshold were
23+
identified during this scan. The single commit in the 7-day window
24+
(`22fdd6d feat(cockpit): reference bun-ub packet artifacts`) is the
25+
initial-import of the repository and was fully covered by the prior weekly
26+
scan on 2026-06-01. The codebase continues to demonstrate a security-first
27+
design with all standing defenses (per `.factory/threat-model/threat-model.md`)
28+
verified intact. The threat model (last updated 2026-06-01) remains current and
29+
is well within the 90-day review window.
30+
31+
## Critical Findings
32+
33+
*None.*
34+
35+
## High Findings
36+
37+
*None.*
38+
39+
## Medium Findings
40+
41+
*None.*
42+
43+
## Low Findings
44+
45+
*None.*
46+
47+
## Observations (Below Threshold — Not Reported As Findings)
48+
49+
These items were considered during the scan but do not meet the `medium` severity
50+
threshold. They are recorded here for traceability and the next scheduled scan.
51+
52+
### OBS-001 (carried): FFI JSON payload size not bounded
53+
54+
| Attribute | Value |
55+
|-----------|-------|
56+
| **Severity** | LOW (informational) |
57+
| **STRIDE Category** | Denial of Service |
58+
| **File** | `crates/tokmd-core/src/ffi/mod.rs` |
59+
| **Status** | Not patched — design choice |
60+
61+
**Description:** The `run_json(mode, args_json)` FFI entrypoint accepts a JSON
62+
string of arbitrary size. While individual in-memory `inputs[].path` is bounded
63+
to 4096 bytes (`MAX_IN_MEMORY_INPUT_PATH_BYTES`), the outer JSON envelope is
64+
not.
65+
66+
**Why not a finding:** Caller controls input. `serde_json::from_str` allocates
67+
predictably; no algorithmic blowup. No `medium` reachability: requires the
68+
caller to opt in. Out of scope per `SECURITY.md`.
69+
70+
**Recommended fix (optional, future):** Add a soft cap on `args_json.len()`
71+
(e.g. 8 MiB) returning a typed `TokmdError::invalid_field("args", "JSON args
72+
exceed 8 MiB cap")` from `run_json_inner`.
73+
74+
### OBS-002 (carried): Transitive `RUSTSEC-2020-0163` advisory
75+
76+
| Attribute | Value |
77+
|-----------|-------|
78+
| **Severity** | LOW (transitive) |
79+
| **STRIDE Category** | Elevation of Privilege |
80+
| **File** | `Cargo.lock` (transitive `term_size` via `tokei`) |
81+
| **Status** | Documented in `deny.toml` |
82+
83+
**Description:** `term_size` is a transitive dependency of `tokei` and has an
84+
unmaintained advisory (`RUSTSEC-2020-0163`).
85+
86+
**Why not a finding:** Already documented in `deny.toml` with rationale.
87+
Out of scope per `SECURITY.md`.
88+
89+
**Recommended action:** Track upstream `tokei` for a `term_size` removal.
90+
91+
### OBS-003 (carried): GitHub Actions pinning is mixed (tag + SHA)
92+
93+
| Attribute | Value |
94+
|-----------|-------|
95+
| **Severity** | LOW (informational) |
96+
| **STRIDE Category** | Spoofing / Tampering |
97+
| **File** | `.github/workflows/*.yml` |
98+
| **Status** | Not patched — mixed strategy |
99+
100+
**Description:** The Droid-related workflows
101+
(`.github/workflows/droid.yml`, `droid-review.yml`, `droid-security-scan.yml`)
102+
pin third-party actions by SHA, including the custom
103+
`EffortlessMetrics/droid-action-safe@7c1377ccbacddc95560d1570547a5baa51de01ec`.
104+
Other workflows (`.github/workflows/ci.yml`, `release.yml`, `cockpit.yml`,
105+
`nix-full.yml`, etc.) pin by tag (e.g., `actions/checkout@v6.0.2`,
106+
`Swatinem/rust-cache@v2`). The threat model claims SHA pinning workspace-wide,
107+
which is no longer strictly accurate for non-Droid workflows.
108+
109+
**Why not a finding:**
110+
- Tag-pinned first-party actions (`actions/*`) are a well-accepted practice
111+
with low residual risk; GitHub's own recommended baseline.
112+
- All release/CI/cockpit workflows that take privileged actions are pinned
113+
at the workflow level via `actions/checkout@v6.0.2` consistently across
114+
the workspace, providing a uniform policy.
115+
- The custom Droid action — the highest-privilege third-party surface — IS
116+
SHA-pinned.
117+
- Below the `medium` severity threshold for this scan; flagged for the next
118+
threat-model refresh (target: 2026-09-01 or earlier if scope changes).
119+
120+
**Recommended action (optional, future):** Either update the threat model
121+
to reflect the actual mixed-pinning policy, or convert all third-party
122+
actions to SHA-pinned references and codify the rotation process in
123+
`.factory/rules/`.
124+
125+
### OBS-004 (new): `web/runner` browser code does not pin GitHub API base URL
126+
127+
| Attribute | Value |
128+
|-----------|-------|
129+
| **Severity** | LOW (informational) |
130+
| **STRIDE Category** | Spoofing |
131+
| **File** | `web/runner/ingest.js` |
132+
| **Status** | Not patched — review for future |
133+
134+
**Description:** The browser-side runner fetches repository content via
135+
`fetch()` calls to `api.github.com` (and the codeload/GitHub
136+
`releases`/`archive` endpoints). These URLs are hard-coded in the
137+
`web/runner/` JavaScript modules. The token (when supplied) is stored in
138+
`sessionStorage` (not `localStorage`) and used as a `Bearer` header. There
139+
is no Subresource Integrity pinning or origin allow-listing on the
140+
client-side fetch surface.
141+
142+
**Why not a finding:**
143+
- All sensitive fetches target `api.github.com` / `codeload.github.com`,
144+
which are HTTPS and well-known.
145+
- The token lifetime is bounded to a single browser tab
146+
(`sessionStorage`).
147+
- No DOM injection surfaces observed: all dynamic data is rendered via
148+
`textContent` (verified across `main.js`); no use of `innerHTML`,
149+
`eval`, `new Function`, or `document.write`.
150+
- Browser-side runner runs entirely in the user-agent sandbox; no
151+
filesystem, no subprocess.
152+
- Below the `medium` severity threshold; informational only.
153+
154+
**Recommended action (optional):** Consider an explicit allowlist of fetch
155+
origins and a CSP `connect-src` directive in the runner's served HTML
156+
to defend against supply-chain injection via a compromised
157+
`<script>`/module.
158+
159+
### OBS-005 (new): Action.yml install step performs `curl | sh` style download
160+
161+
| Attribute | Value |
162+
|-----------|-------|
163+
| **Severity** | LOW (informational) |
164+
| **STRIDE Category** | Tampering / Information Disclosure |
165+
| **File** | `action.yml` (composite step `Install tokmd`) |
166+
| **Status** | Not patched — verified checksums |
167+
168+
**Description:** The composite GitHub Action downloads a pre-built
169+
`tokmd` binary from `github.com/EffortlessMetrics/tokmd/releases/...` and
170+
verifies it against `checksums.txt` (sha256). It does not verify a
171+
cryptographic signature on the checksum file or on the release itself.
172+
The download URL is interpolated from a user-supplied `version` input
173+
without shell-unsafe character filtering.
174+
175+
**Why not a finding:**
176+
- The action is a published action; consumers control which version
177+
they pin to. The check is bounded to a `MAJOR.MINOR.PATCH`-style
178+
string via the `${ver#v}` prefix logic.
179+
- `curl -fsSL` rejects HTTP errors and follows redirects (only to
180+
HTTPS GitHub release endpoints in practice).
181+
- The checksum verification, when checksums.txt is present, uses
182+
`sha256sum`/`shasum`/`Get-FileHash` to compare the downloaded
183+
binary's hash to the expected value.
184+
- Build provenance is separately attested via
185+
`actions/attest-build-provenance` in `release.yml`.
186+
- Below the `medium` severity threshold; this is documented best-
187+
practice coverage.
188+
189+
**Recommended action (optional):** Add explicit format validation
190+
for the `version` input (e.g., regex `^v?\d+\.\d+\.\d+(-[A-Za-z0-9.-]+)?$`)
191+
and reject anything else before constructing the URL.
192+
193+
## Standing Defenses Verified (No Regression)
194+
195+
The following defenses were re-verified during this scan. All remain intact.
196+
197+
| ID | Defense | Location | Verified |
198+
|----|---------|----------|----------|
199+
| D-01 | `unsafe_code = "forbid"` workspace lint | `Cargo.toml` ||
200+
| D-02 | `unwrap_used`, `expect_used`, `panic`, `unreachable` lints denied | `Cargo.toml` ||
201+
| D-03 | Git subprocess env isolation (`GIT_REPO_SHAPING_ENV`) | `crates/tokmd-git/src/command.rs`, `crates/tokmd/src/git_support.rs` ||
202+
| D-04 | Git ref validation (`env_base_ref_is_safe` + `--end-of-options`) | `crates/tokmd-git/src/refs.rs` ||
203+
| D-05 | Bounded path canonicalization under root | `crates/tokmd-scan/src/path/bounded_path.rs` ||
204+
| D-06 | FFI in-memory input path validation | `crates/tokmd-core/src/ffi/inputs.rs` ||
205+
| D-07 | Strict JSON parsing with type validation | `crates/tokmd-core/src/ffi/parse.rs` ||
206+
| D-08 | Per-family schema versioning | `crates/tokmd-types/src/` ||
207+
| D-09 | SHA-pinned Droid-related actions; tag-pinned first-party actions | `.github/workflows/droid*.yml` (SHA), others (tag) ||
208+
| D-10 | Branch protection on `main` (CODEOWNERS, 1 approval, CI required) | `.github/settings.yml` ||
209+
| D-11 | `cargo-deny` advisory + license allowlist | `deny.toml` ||
210+
| D-12 | BLAKE3 redaction with extension allowlist | `crates/tokmd-format/src/redact/mod.rs`, `crates/tokmd-format/src/redact/extensions.rs` ||
211+
| D-13 | Content reads bounded by `ContentLimits` | `crates/tokmd-analysis/src/content/mod.rs` ||
212+
| D-14 | PyO3 FFI invariants (no panic, GIL release, error translation) | `crates/tokmd-python/src/lib.rs` ||
213+
| D-15 | WASM uses `MemFs` (no host fs) | `crates/tokmd-wasm/` ||
214+
| D-16 | `web/runner` browser runner uses `textContent` (no `innerHTML`/`eval`) | `web/runner/main.js` ||
215+
| D-17 | `web/runner` token stored in `sessionStorage` (not `localStorage`) | `web/runner/auth.js` ||
216+
| D-18 | `web/runner` worker protocol allowlists modes & presets | `web/runner/messages.js` ||
217+
| D-19 | Composite action installs tokmd with checksum verification | `action.yml` ||
218+
| D-20 | Custom Droid action SHA-pinned across all Droid workflows | `.github/workflows/droid*.yml` ||
219+
220+
## Appendix
221+
222+
### Threat Model
223+
224+
- **Status:** Current (verified unchanged since 2026-06-01)
225+
- **Location:** `.factory/threat-model/threat-model.md`
226+
- **Last Modified:** 2026-06-01 (7 days ago — well within 90-day window)
227+
- **Methodology:** STRIDE
228+
- **Next review:** 2026-09-01 (90-day cadence) or upon architecture change
229+
230+
### Scan Metadata
231+
232+
- **Commits Scanned:** 1 (`22fdd6d feat(cockpit): reference bun-ub packet artifacts`)
233+
- **Files in scope:** 2456 (entire repository — initial import; same scope as
234+
2026-06-01 scan)
235+
- **Scan Duration:** ~5m
236+
- **Skills Used:** commit-security-scan (manual), vulnerability-validation
237+
(manual), security-review (manual)
238+
- **Manual Reviewers:** 1 (Droid scheduled security scan)
239+
- **False Positive Filter:** applied — see Observations above
240+
241+
### Scan Coverage Matrix
242+
243+
| Area | Files reviewed | Findings |
244+
|------|----------------|----------|
245+
| CLI argv parsing | `crates/tokmd/src/cli/`, `crates/tokmd/src/commands/*.rs` | 0 |
246+
| Subprocess invocation | `crates/tokmd-git/`, `crates/tokmd-cockpit/src/supply_chain.rs`, `crates/tokmd/src/git_support.rs` | 0 |
247+
| Path handling | `crates/tokmd-scan/src/path/`, `crates/tokmd-scan/src/roots.rs`, `crates/tokmd-scan/src/walk/` | 0 |
248+
| FFI inputs | `crates/tokmd-core/src/ffi/`, `crates/tokmd-python/src/`, `crates/tokmd-node/src/` | 0 |
249+
| File content reads | `crates/tokmd-analysis/src/content/`, `crates/tokmd-io-port/src/` | 0 |
250+
| Redaction / hashing | `crates/tokmd-format/src/redact/` | 0 |
251+
| GitHub workflows | `.github/workflows/*.yml` (21 files), `.github/settings.yml`, `action.yml` | 0 |
252+
| Build / lint | `Cargo.toml`, `deny.toml`, `clippy.toml`, `.cargo/config.toml` | 0 |
253+
| Githooks | `.githooks/pre-commit`, `.githooks/pre-push`, `.claude/hooks/format-rust.sh` | 0 |
254+
| Web runner (browser) | `web/runner/main.js`, `worker.js`, `auth.js`, `messages.js`, `runtime.js`, `ingest.js` | 0 |
255+
| Threat model | `.factory/threat-model/threat-model.md` | unchanged |
256+
257+
### Commit-level Analysis
258+
259+
Only one commit falls within the 7-day window:
260+
261+
```
262+
22fdd6d93ec503465a71cd94aa874c167b76f8ef
263+
Author: Steven Zimmerman, CPA <15812269+EffortlessSteven@users.noreply.github.com>
264+
Date: Fri Jun 5 16:40:29 2026 -0400
265+
Subject: feat(cockpit): reference bun-ub packet artifacts
266+
```
267+
268+
This commit is the initial repository import (`git log --all --oneline` returns
269+
exactly 1 commit). It contains 2456 files (`.cargo/config.toml`, the workspace
270+
source tree, all GitHub workflows, agent manifests, etc.). The prior weekly
271+
scan (2026-06-01, report `.factory/security/reports/security-report-2026-06-01.md`)
272+
covered this exact same content with 0 findings at the `medium` threshold.
273+
274+
**Review of the change:**
275+
- Touches 2456 files (initial import). No new security-sensitive surface
276+
added since the prior scan.
277+
- No new secrets, no new permissions, no new third-party action.
278+
- No shell-out to untrusted input beyond what was previously reviewed.
279+
- No change to environment variable handling.
280+
- `web/runner` browser code uses safe DOM patterns (textContent only).
281+
- All action.yml and workflows reviewed and verified to be consistent with
282+
prior assessment.
283+
284+
**No security findings in this commit.**
285+
286+
### Patches Generated
287+
288+
No patches were generated this scan (no findings at or above `medium`).
289+
290+
### Next Scan
291+
292+
The next scheduled security scan runs Monday, 2026-06-15 via
293+
`.github/workflows/droid-security-scan.yml` (cron `0 8 * * 1`).
294+
295+
## References
296+
297+
- [CWE Database](https://cwe.mitre.org/)
298+
- [STRIDE Threat Model](https://docs.microsoft.com/en-us/azure/security/develop/threat-modeling-tool-threats)
299+
- [OWASP Top 10](https://owasp.org/www-project-top-ten/)
300+
- [Rust Security Advisory Database](https://rustsec.org/)
301+
- [CII Best Practices](https://www.bestpractices.dev/)
302+
- Repository security policy: `SECURITY.md`
303+
- Repository threat model: `.factory/threat-model/threat-model.md`
304+
- Previous scan: `.factory/security/reports/security-report-2026-06-01.md`

0 commit comments

Comments
 (0)