PRD 0011: Trust boundary for cwd-supplied manifests #15

Closed
didericis wants to merge 2 commits from cwd-manifest-trust into main

2 Commits

Author SHA1 Message Date
didericis ccfdb141dd feat(manifest)!: enforce cwd-manifest trust boundary (PRD 0011)
test / unit (pull_request) Successful in 13s
test / integration (pull_request) Successful in 22s
Splits `Manifest.resolve` into a two-phase load:

1. $HOME/claude-bottle.json parses under the full schema as today.
   This file owns bottle infrastructure (cred_proxy.routes, git,
   env, egress).
2. $CWD/claude-bottle.json parses under the new CwdExtension schema
   — agents-only. Any `bottles:` section dies at parse with a
   pointer at the home file. Each cwd agent's `bottle:` must
   resolve against a home-defined bottle name.

When CWD == HOME (running from $HOME directly) the resolver
short-circuits to home-only — no false trust-boundary error from
parsing the same file twice.

Closes the exfil vector documented in PRD 0011: a cloned repo's
claude-bottle.json can no longer redefine cred-proxy routes, and
therefore can't redirect $CLAUDE_BOTTLE_OAUTH_TOKEN /
$GITHUB_TOKEN / etc. to an attacker-named upstream on first
launch.

Preflight surfaces the boundary positively: print() shows
`bottle: <name>  (from $HOME/claude-bottle.json)`, and to_dict
emits `"bottle_source": "home"`. README + the existing dry-run
integration test pick that up.

BREAKING: existing cwd manifests that define bottles now fail.
The error message names the file path, the offending field, and
the fix ("move bottles section to $HOME/claude-bottle.json").

Tests:
- tests/unit/test_manifest_trust_boundary.py — 10 cases covering
  PRD 0011's success criteria (bottles rejected, agents allowed,
  cwd overrides agent fields, no silent fallback, home-only
  unchanged, etc.).
- tests/integration/test_dry_run_plan.py picks up the
  bottle_source assertion.
2026-05-24 15:22:58 -04:00
didericis 579a9dae3e docs: add PRD 0011 for cwd-manifest trust boundary
test / unit (pull_request) Successful in 12s
test / integration (pull_request) Successful in 23s
Bottles defined in $CWD/claude-bottle.json can redefine
cred_proxy.routes / git / env / egress on key conflict, which
gives a cloned repo's manifest the ability to redirect a host
env var (CLAUDE_BOTTLE_OAUTH_TOKEN, GITHUB_TOKEN, ...) to an
attacker-controlled upstream on first launch — no agent
compromise required.

This PRD proposes drawing the trust boundary at the bottle
level: $HOME owns bottle definitions; $CWD can only declare
agents that reference home-defined bottles. Six success
criteria + the resolver-split design.

PRD-only; no code in this commit.
2026-05-24 14:59:11 -04:00