From 31cc28468d4ed3460e0a048798617d353a9eaf59 Mon Sep 17 00:00:00 2001 From: Joe Guo Date: Sat, 5 Sep 2026 00:41:34 +0000 Subject: [PATCH] docs: record launcher self-poisoning as an accepted risk (#417) Closes #417. Problem: the engineering position on agent-launcher trust was already decided and written into the mechanism spec, but never closed out as a formal accepted risk. `grep -rn "CWE-778" docs/` returned zero hits and the "Known gaps" list in docs/architecture/security-deep-dive.md carried no launcher-substitution or self-poisoning entry, so a reader auditing the residual had nothing to find. What changed: one entry appended to the "Known gaps" list stating the residual, marking it ACCEPTED, and naming the tradeoff. It links to security.md's existing rationale rather than duplicating it. No behavior change. No code touched. The proposed code fix (a signed or root-owned launcher, install-source gating, the resolve-to-exec copy) is already recorded as rejected by design; this closes the paperwork gap, not the code question. CWE: the entry is filed under CWE-345 (Insufficient Verification of Data Authenticity), which is what the residual actually is -- the launcher's bytes are executed with no integrity or authenticity check. CWE-778 (Insufficient Logging) is retained as the tracker label from #371/#417 so the identifier people will grep for resolves, but it describes the SEL-audited-denial half of #371's defense, not the substitution risk. --- docs/architecture/security-deep-dive.md | 32 +++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/docs/architecture/security-deep-dive.md b/docs/architecture/security-deep-dive.md index 84b59ef5bf6..3e68ddaee78 100644 --- a/docs/architecture/security-deep-dive.md +++ b/docs/architecture/security-deep-dive.md @@ -522,3 +522,35 @@ fork bombs and memory balloons requires Linux with cgroup delegation; where it i unavailable (macOS, older Linux, no user session) it is a no-op with a loud warning and only the file-descriptor limit applies. See [`resource-protection.md`](resource-protection.md). + +**Launcher self-poisoning by the same user is accepted, not defended (CWE-345; +tracked as CWE-778 by +[#371](https://github.com/kirodotdev/KiroCrew/pull/371) / +[#417](https://github.com/kirodotdev/KiroCrew/issues/417)).** The resolved +`kiro-cli` launcher is executed in place with no signature, hash, ownership or +install-source check — the only gate is `platform_compat.is_executable_file` +(`kiro_cli.py`) — so an agent running as the invoking user can overwrite its own +launcher and have those bytes executed on the next spawn. **Status: ACCEPTED.** +The mechanism that would close it is *rejected by design*, not missing by +oversight: see +[`security.md` § Kiro prerequisite setup boundary](../system-specs/modules/security.md), +which records that trust is "the CLI runs, and it has a valid login" regardless +of install source, owner, or fixed path, because Kiro Crew is not the authority +on where Kiro CLI lives and its own self-updater legitimately rewrites those +bytes as the user — an owner / path / Developer-ID gate would strand real +installs (toolbox, Homebrew, winget, a self-updated `/Applications` bundle) with +no in-product recovery path. The same section records the sibling resolve-to-exec +byte-binding copy as deliberately removed ("Do NOT reintroduce it") once Kiro CLI +became a multi-call binary. The accepted tradeoff is therefore **install-model +compatibility over a same-UID integrity check**: the attack presupposes local +write access as the operator, which is outside this product's threat model (an +attacker holding the operator's UID already owns the account) and is not +defended against anywhere else — `~/.bashrc`, above, is the same class. Residual +blast radius is bounded on the confined spawn paths (Linux namespace, macOS +seatbelt) which run even a poisoned launcher inside Kiro Crew's own sandbox; +only macOS internal-sandbox delegation exec's it directly. A multi-tenant or +enterprise posture would need signing infrastructure, key management and an +install-layout decision, and any such gate must default **off** — the +`KIROCREW_PROVIDER_BIN_STRICT` precedent +(`github_runner.py:validate_provider_executable`) records that requiring a +root-owned copy made every stock package-manager install fail.