From de5be8f66e05fc1abdf76c782c73a6bc4c5415cd Mon Sep 17 00:00:00 2001 From: PAN CHAO <193720202+arthurpanhku@users.noreply.github.com> Date: Sat, 18 Jul 2026 09:15:48 +0800 Subject: [PATCH] docs: align dependency wording and document self-update egress exemption MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - CONTRIBUTING: change "Zero runtime deps" to "Minimal runtime deps" — the project ships nine runtime dependencies, so the old wording overstated reality; the rule's force (new deps need a very strong case) is unchanged and the supply-chain rationale is now explicit. - EGRESS-THREAT-MODEL: add a "Self-update egress" section characterising the updater paths (CLI `dvalincode update` + desktop GUI updater) that fetch outside `governedProviderFetch`: GitHub-pinned hosts, mandatory SHA256SUMS verification, explicit user confirmation. Recorded as a documented Known exemption with a Forward guardrail (configurable update URL / unpinned host / silent auto-install = release blocker), plus matching Acceptance Matrix row and Non-goals entry. Follows the "Honest enforcement — document exemptions in the threat model instead of hiding them" governance rule. Co-Authored-By: Claude Opus 4.8 --- CONTRIBUTING.md | 2 +- docs/EGRESS-THREAT-MODEL.md | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 05d6ecb..a278bd4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -32,7 +32,7 @@ These are what make the project what it is. A PR that violates one will be asked 2. **Narrowing only.** Policy changes may add restrictions; they may never let a repo-level source widen a machine-level one, and must keep the canonical policy hash stable for unchanged policies. 3. **Minimize, don't leak.** Audit records carry hashes, sizes, and structure — never prompts, file contents, shell arguments, or credentials. 4. **Honest enforcement.** If a control can't be enforced on some platform, it fails closed or reports `unavailable` — it is never silently advisory. Document exemptions in the threat model instead of hiding them. -5. **Zero runtime deps is a feature.** New runtime dependencies need a very strong case; prefer hand-rolling small clients (see `src/mcp/client.ts` for the pattern). +5. **Minimal runtime deps is a feature.** The runtime dependency list is deliberately short (a handful of vetted packages — see `package.json`); every new runtime dependency widens the supply-chain surface a reviewer must approve, so it needs a very strong case. Prefer hand-rolling small clients (see `src/mcp/client.ts` for the pattern). ## Everyday guidelines diff --git a/docs/EGRESS-THREAT-MODEL.md b/docs/EGRESS-THREAT-MODEL.md index 2b66c70..2d14fd4 100644 --- a/docs/EGRESS-THREAT-MODEL.md +++ b/docs/EGRESS-THREAT-MODEL.md @@ -122,6 +122,39 @@ remediation directory first. > ungoverned execution + egress path and must be treated as a release blocker, > exactly like an ungoverned provider adapter. +### Self-update egress + +The updater paths — the `dvalincode update` command (`commands/update.ts` + +`core/selfUpdate.ts`) and the desktop GUI updater (`gui/updater.ts` + +`core/guiUpdate.ts`) — make outbound HTTPS requests with a direct `fetch`, +**outside** `governedProviderFetch` and outside any run's egress policy. They +are characterised here so this stays a documented channel, not a silent gap: + +- **Pinned destinations.** Release metadata comes only from `api.github.com` + and assets only from `github.com` (`RELEASE_HOSTS` in `core/selfUpdate.ts`); + the GUI updater additionally rejects any asset URL whose protocol, hostname, + or release-path prefix does not match the expected GitHub release + (`assertTrustedGuiAssetUrl`). There is no configurable update source. +- **Integrity before install.** Downloaded archives are verified against the + release's `SHA256SUMS.txt` before anything is swapped in place; a checksum + mismatch aborts the update. +- **User-initiated, user-confirmed.** The CLI path runs only on an explicit + `dvalincode update`; the GUI path installs only after the user confirms a + native dialog. Nothing downloads or installs silently in the background. + +**Known exemption.** Because these requests bypass the governed fetch, a +`network: off` policy does not block an explicit update. This is deliberate +bootstrap-channel egress — the updater must work even when (indeed, especially +when) run policy is restrictive — but it is an explicit, documented exemption, +not an enforced control. + +> **Forward guardrail.** The update channel must stay exactly this narrow: +> hosts pinned in code to GitHub releases, checksum verification mandatory, +> and installation always behind an explicit user action. Adding a +> configurable update URL, an unpinned host, or any automatic +> download-and-install without user confirmation is a new ungoverned egress +> path and must be treated as a release blocker. + ## Audit Data Policy Audit data is minimized before persistence: @@ -156,6 +189,7 @@ best-effort defense in depth and must not be described as complete redaction. | `run_security_scan` local scan | Runs fully in-process; performs no subprocess and no network I/O | | `prepare_remediation_worktree` | Runs only fixed-argv local git; writes only inside `~/.dvalincode/projects/remediations`; applies no fix | | Future remediation fix-execution step | Routed through `runGovernedProcess` and audited; a direct `execFile`/`spawn` is a release blocker | +| `dvalincode update` / GUI update | Contacts only `api.github.com` + `github.com`; installs only after checksum verification and explicit user confirmation | ## Non-goals @@ -166,5 +200,8 @@ best-effort defense in depth and must not be described as complete redaction. - Network isolation for the two local git commands in `remediation/worktree.ts` (a documented exemption — local git only — pending sandbox-profile support for the remediation directory). +- Blocking the user-initiated self-update channel under `network: off` (a + documented exemption — GitHub-pinned, checksum-verified, user-confirmed; see + "Self-update egress"). - Claiming transport confidentiality for a configured plain-HTTP endpoint. - Claiming tamper-proof audit custody against a hostile local administrator.