# Land Retirement Path Hardening

audience: AI coding agents first.

status: IDLE
task IDs: owner request 2026-08-13 land-retirement critical finding
source request: Independently verify whether `operation.receipt.root` controls executable path passed to `bash` in `controller/src/land-retirement.ts`. If confirmed, apply smallest robust fix: fixed trusted installed conductor script; resolve repository roots and queue directories server-side from trusted IDs/config; canonical realpath component-boundary allowlist; reject symlinks and outside roots. Add focused adversarial tests for malicious absolute paths, symlink escapes, valid allowed roots, and fixed executable selection. Do not touch Factory/k3s files. Run focused controller tests and typecheck cleanly. Commit locally. Do not install, push, or land.

## Acceptance criteria

- Independently trace untrusted receipt fields to process execution; record confirmed or refuted verdict.
- Executable path MUST be fixed from trusted installed controller configuration, never receipt data.
- Repository root and queue directory MUST resolve server-side from trusted operation identity/config.
- Canonical paths MUST remain within component-boundary allowlisted roots.
- Symlink components and paths outside allowlisted roots MUST be rejected.
- Tests MUST cover malicious absolute receipt paths, symlink escapes, valid allowed roots, and fixed executable selection.
- Focused controller tests and controller typecheck MUST pass without warnings.
- Commit locally only. NEVER install, push, land, or touch Factory/k3s files.

## Preserved WIP

- Worktree: `/home/user/Projects/overdeck/.worktrees/land-retirement-path-hardening`.
- Branch: `wt/land-retirement-path-hardening` from `origin/main` at `6c6657b00806f59192cf29c446c4129468319528`.
- Scope restricted to controller implementation/tests and this plan/index.

## Constraints

- Make smallest robust change.
- Validate at trust boundary; fail closed.
- Use canonical `realpath` checks plus path-component boundary checks, not string prefixes.
- Do not trust datastore receipt fields merely because schema-valid.

## Execution steps

1. Trace `operation.receipt.root`, operation identity, trusted config, and process spawn.
2. Reproduce exploit in focused test.
3. Add trusted server-side path resolver and fixed executable selection.
4. Add adversarial and valid-path tests.
5. Run focused controller tests and typecheck; address every signal.
6. Update receipt, commit locally, report exact outputs.

## Current receipt

- Automated CRITICAL finding confirmed: hostile `receipt.root` selected `finish-branch.sh` passed to `bash`.
- Fixed executable now resolves from deployed controller source, independent of receipt data.
- Exact configured repository roots are canonicalized; hostile roots must equal an entry, not merely descend from a parent.
- Queue directory is derived from canonical Git metadata and used for claim/verdict I/O; receipt queue path is assertion-only and symlink-free.
- Independent adversarial review found three residual gaps; all addressed before final verification.
- Verification: `bun test src/land-retirement.test.ts src/config.test.ts src/server.test.ts` → 48 pass, 0 fail. `bun run typecheck` → exit 0, no output beyond command.
- No Factory/k3s files touched. No install, push, or land performed.

## Next executable action

Commit verified changes locally; hand commit and exact receipts to main orchestrator.
