Commit Graph

16 Commits

Author SHA1 Message Date
didericis e7e72c4833 feat(cli): wire pipelock sidecar + internal network into start flow
PRD 0001 cli.sh integration:

- Source the new lib/network.sh and lib/pipelock.sh.
- During plan resolution: generate the per-bottle pipelock YAML into
  the existing mktemp stage dir (mode 600, hostnames only) and
  resolve a one-line "<N> hosts allowed (...)" summary.
- Add the egress summary as a sub-bullet under the bottle in the y/N
  preflight, alongside the existing ssh hosts line.
- After the y/N gate (and after build_image): create the per-agent
  --internal Docker network with a slug-derived name, then start the
  pipelock sidecar attached to it.
- docker run argv: agent attaches to the internal network with
  HTTPS_PROXY / HTTP_PROXY pointing at the sidecar by service name on
  that network. NO_PROXY only covers loopback. The internal network
  has no default gateway, so any path that ignores the proxy env
  hits no-route-to-host rather than leaking.
- Exit trap: tear down the agent container, then the sidecar (so the
  network is empty), then remove the network, then run the existing
  stage cleanup. Order matters — docker refuses to remove a network
  with attached containers.
- --dry-run continues to exit before any docker network/run/cp/exec
  call; the YAML write into the mktemp dir is the only new
  side-effect inside the dry-run path.

Verified against a temp fixture: defaults-only bottle shows
"7 hosts allowed", a bottle with two extra entries shows
"9 hosts allowed (api.anthropic.com, api.openai.com, claude.ai,
+6 more)", and dry-run exits before any docker calls.

Refs: docs/prds/0001-per-agent-egress-proxy-via-pipelock.md

Assisted-by: Claude Code
2026-05-08 01:01:20 -04:00
didericis 4c51ba422e feat(manifest): document egress object + add allowlist accessor
Extends the manifest schema doc-comment to include the new
bottles.<name>.egress.allowlist field added in PRD 0001, and
introduces manifest_bottle_egress_allowlist alongside
manifest_bottle_ssh — same shape as the existing per-bottle
helper, returns one hostname per line, empty for missing field.
The accessor performs only top-level array-type validation;
per-element string typing happens in lib/pipelock.sh next to the
YAML generator that consumes it.

Refs: docs/prds/0001-per-agent-egress-proxy-via-pipelock.md

Assisted-by: Claude Code
2026-05-08 00:59:13 -04:00
didericis 18e34af583 feat(pipelock): add lib/pipelock.sh sidecar lifecycle + YAML generator
Adds the pipelock half of the PRD 0001 egress topology:

- Pins the pipelock image by digest (sha256:3b1a39...) for the
  multi-arch ghcr.io/luckypipewrench/pipelock:2.3.0 manifest list,
  resolved on 2026-05-08. The registry uses unprefixed tags, so the
  v2.3.0 GitHub release maps to the 2.3.0 Docker tag.
- Bakes in the default allowlist for Claude Code's required hosts
  (api.anthropic.com, statsig.anthropic.com, sentry.io, claude.ai,
  platform.claude.com, downloads.claude.ai, raw.githubusercontent.com)
  and unions it with the bottle's egress.allowlist for the effective
  list.
- Generates a minimum-viable YAML config at mode 600: strict mode +
  enforce + api_allowlist + forward_proxy.enabled + DLP defaults +
  scan_env. No env values, no secrets, hostnames only. Schema keys
  cite pipelock's docs/configuration.md inline.
- Sidecar lifecycle: docker create → docker cp the YAML in → connect
  to the default bridge for upstream egress → docker start. Avoids
  bind mounts (Docker Desktop ownership quirks). Stop is idempotent
  for use in cli.sh's exit trap.
- Helper for the y/N preflight: one-line summary "<N> hosts allowed
  (host1, host2, host3 +M more)".

Refs: docs/prds/0001-per-agent-egress-proxy-via-pipelock.md
Refs: docs/research/pipelock-assessment.md

Assisted-by: Claude Code
2026-05-08 00:58:37 -04:00
didericis b0d8987c68 feat(network): add lib/network.sh for per-agent --internal Docker networks
Adds the network half of the PRD 0001 egress topology: per-agent
--internal Docker networks with a slug-derived name and a numeric
conflict suffix that mirrors the container-name scheme in cli.sh.
Helpers cover create / attach / remove and are pipelock-agnostic, so
a future PRD can layer a different sidecar on top without entangling
the two concerns.

Refs: docs/prds/0001-per-agent-egress-proxy-via-pipelock.md

Assisted-by: Claude Code
2026-05-08 00:56:51 -04:00
didericis 39059f69b9 docs(prd): scaffold PRD 0001 — Per-agent egress proxy via pipelock
Assisted-by: Claude Code
2026-05-08 00:52:21 -04:00
didericis 08597ebcf8 docs: add redundancy analysis to pipelock assessment
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-08 00:25:01 -04:00
didericis 5607dce611 docs(journal): 2026-05-08 00:15 2026-05-08 00:16:14 -04:00
didericis b36e6da0b3 docs: add research note assessing pipelock for egress/exfil control
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-08 00:15:11 -04:00
didericis c74bd5cf26 docs: add research note on multi-encoding secret exfil tripwires
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-08 00:00:51 -04:00
didericis bc7f506311 docs: add research note on isolating tea token via proxy
Investigates whether the Gitea `tea` CLI can be authenticated via a
header-injecting proxy so the token never enters the container — even as
an env var. Parallels the OAuth-token research note. Recommends an
in-container root-owned reverse proxy as the lowest-friction shape, and
flags the unavoidable tradeoff that the agent retains the token's full
API scope (no exfil ≠ no harm).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-07 23:30:06 -04:00
didericis edf79b3880 docs: add research note on container network egress guards
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-07 23:27:18 -04:00
didericis 7a38b8da23 docs: add research note on OAuth token exposure to claude
Walks the current `docker run -e CLAUDE_CODE_OAUTH_TOKEN` flow, why claude
can read the token trivially via its Bash tool, why no Linux primitive
hides an env var from its own process, and why a root-owned localhost
auth-injecting reverse proxy (paired with an egress allowlist) is the
realistic mitigation. Documents `ANTHROPIC_BASE_URL` caveats (SSE,
header passthrough, issue #36998, out-of-band traffic).
2026-05-07 23:24:39 -04:00
didericis adaaa2c0e8 chore: enforce Conventional Commits via .githooks/commit-msg
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-07 23:14:39 -04:00
didericis 9b4ff29f49 docs: add research note on revoking Claude Code OAuth tokens
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-07 23:13:42 -04:00
didericis 74a2c7a32a refactor: rename box/boxes to bottle/bottles in config schema and code
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-07 23:02:34 -04:00
didericis c45f384fb8 Initial commit 2026-05-07 22:45:36 -04:00