Commit Graph

46 Commits

Author SHA1 Message Date
didericis 2c2af47d3e docs(demo): switch to prompt-driven probes; BirdsOfParadise theme
test / unit (push) Successful in 15s
test / integration (push) Successful in 32s
Each of the four probes is now a natural-language prompt to claude
instead of a bash escape via `!`. The agent uses its Bash tool, runs
the literal curl/git command, and narrates what pipelock or git-gate
returned. More authentic to actual product use, at the cost of a
longer recording (59s vs 26s) and a non-deterministic narration.

To keep claude on-task, the demo agent now ships a system prompt
that frames the bottle as a security-testing sandbox: synthetic
credentials, intentional probes, and an instruction to invoke curl
with `--proxy "$HTTPS_PROXY"` since curl ignores the uppercase
HTTP_PROXY env var (an upstream curl quirk — the env var is set, but
only the explicit flag actually routes through pipelock).

Theme moves to BirdsOfParadise (warmer palette against Claude TUI's
red accents). README copy updated to describe the prompt flow.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-13 02:28:04 -04:00
didericis c47356c728 docs(demo): decimate dead time; bake the pass into demo-record.sh
test / unit (push) Successful in 16s
test / integration (push) Successful in 21s
VHS records in real time, so the GIF spent ~30s of its 82s on static
frames (bottle launch wait, command-output wait between probes). Run
mpdecimate to drop duplicate consecutive frames and re-time at 12 fps;
tpad clones the final frame for 4s so the gitleaks rejection holds
long enough to read on each GIF loop. Result: 25.8s, 1.87 MB.

scripts/demo-record.sh now does the decimation pass automatically
after vhs, so re-records stay compressed without manual ffmpeg.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-13 01:50:19 -04:00
didericis 5d88523ac6 docs(demo): switch to brogrammer theme; open with hello there
test / unit (push) Successful in 15s
test / integration (push) Successful in 27s
Two changes:

- VHS theme moves from Catppuccin Mocha to Brogrammer (slightly higher
  contrast against the Claude TUI's red accents).
- First probe is now a plain `hello there` prompt to claude instead of
  a curl to an allowlisted host. The reply proves api.anthropic.com is
  reachable through pipelock end-to-end (bumped TLS, DLP scan,
  forward) -- a stronger baseline than a static curl, and a more
  honest "the agent works" beat before the three block scenarios.

README copy updated to match. GIF re-recorded and re-encoded
(960px / 10fps / 64-color palette, 2.2 MB).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-13 01:41:33 -04:00
didericis 030a6bc793 refactor(demo): drive recording through real cli.py instead of a harness
test / unit (push) Successful in 14s
test / integration (push) Successful in 29s
The previous demo harness called the backend Python API directly,
which didn't match what a user typing `./cli.py start <agent>` would
actually see. The recording now goes through the real CLI surface:

- claude-bottle.demo.json + scripts/demo-setup.sh stage a demo
  manifest (one bottle, FAKE_TOKEN env, one unreachable git upstream)
  alongside a dummy SSH identity at ~/.cache/claude-bottle-demo/.
- docs/demo.tape types `./cli.py start demo`, answers the y/N
  preflight, and runs four bash probes via claude's `!` prefix
  (curl x3 + git push), so the recording shows real preflight output
  and real probe results.
- scripts/demo.sh wraps setup -> cli.py -> teardown for human use;
  scripts/demo-record.sh does the same around `vhs docs/demo.tape`.
- .gitignore picks up claude-bottle.json so a user's local manifest
  doesn't get tracked alongside .example / .demo siblings.

scripts/demo_harness.py is removed -- its behavior is fully replaced
by the cli.py + `!` flow.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-13 01:26:41 -04:00
didericis 4ef1cc58df docs: add end-to-end demo with recorded GIF
test / unit (push) Successful in 12s
test / integration (push) Successful in 19s
scripts/demo.sh + scripts/demo_harness.py drive a real bottle through
four probes (pipelock allow, host-allowlist block, DLP body-scan
block, git-gate gitleaks rejection). docs/demo.tape is the VHS source
that renders docs/demo.gif, embedded at the top of the README as a
working proof of the security model the prose describes.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-13 00:55:58 -04:00
didericis 30d92bef48 docs: drop ssh from README/example, supersede PRD 0007 (PRD 0009)
test / unit (pull_request) Successful in 13s
test / integration (pull_request) Successful in 21s
- README architecture diagram drops the socat/ssh image box and
  the agent's ~/.ssh/config; the prose-bullets section drops the
  ssh image; the manifest example swaps `ssh:` for `git:` so
  someone copy-pasting it picks up the new shape.
- claude-bottle.example.json: `default` bottle's `"ssh": []` is
  gone (now just an empty bottle); the gitea-dev example already
  uses `git:` since the ExtraHosts work.
- PRD 0007 carries a "Superseded by PRD 0009" header at the top
  with a one-paragraph block explaining why; the file stays so
  the rationale of the prior design is still in-tree.
- git_gate.py: drop the now-stale shadow-route mention from a
  docstring (the validator went away in the manifest layer).
2026-05-12 23:57:50 -04:00
didericis efcafae810 docs(prds): add PRD 0009 to remove ssh-gate and bottle.ssh
test / unit (pull_request) Successful in 18s
test / integration (pull_request) Successful in 34s
ssh-gate was built for non-git SSH (PRD 0007), but every
upstream currently declared in any bottle is a git remote, and
those now flow through git-gate (PRD 0008) with credential
isolation, gitleaks scanning, and `insteadOf` URL rewrites.
ssh-gate is left doing L4 forwarding with no gating value over
git-gate's path; carrying it means a redundant sidecar lifecycle,
a shadow-route validator between bottle.ssh and bottle.git, and
a third place to keep an SSH identity in sync.

Goal is straightforward deletion: bottle.ssh becomes a parse
error pointing at bottle.git, the SshEntry / SSHGate / socat
provisioner / pipelock allowlist branch all go away, and PRD
0007 carries a "Superseded by PRD 0009" header so the rationale
of the prior design stays in the tree.
2026-05-12 23:34:11 -04:00
didericis 00649d27e9 docs(research): add credential-proxy landscape and DLP-minimization framing
test / unit (push) Successful in 14s
test / integration (push) Successful in 29s
Consolidates oauth-token-exposure-to-claude.md and
tea-token-isolation-via-proxy.md into agent-credential-proxy-landscape.md,
adding a May-2026 survey of existing tools (Docker AI Sandboxes,
Cloudflare Sandbox Auth, Infisical Agent Vault, nono, Aembit, LiteLLM
CVE-2026-42208, Portkey, Helicone, etc.) and a build-vs-adopt verdict.

Adds secret-minimization-over-dlp.md explaining why pipelock's body
DLP and gitleaks's pre-receive scan cannot stop encoding/splitting
exfil, and why moving credentials out of the bottle (the git-gate
pattern, generalized) is the only robust answer.

Updates git-secret-scanning-hardening.md's reference to point at
the new consolidated landscape doc.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-12 23:25:12 -04:00
didericis 9b7bcc0149 docs(git-gate): document ExtraHosts on bottle.git entries
test / unit (pull_request) Successful in 12s
test / integration (pull_request) Successful in 19s
- example manifest swaps the gitea-dev bottle from ssh: to git:
  and shows ExtraHosts pinning gitea.dideric.is to its Tailscale IP
- README's git-gate paragraph names the field and the case it
  solves (upstream resolvable on the host but not from the gate
  container's default DNS)
- PRD 0008's manifest-field bullet mentions the field for parity
2026-05-12 23:18:46 -04:00
didericis ae7e22065f docs(prds): expand PRD 0008 to bidirectional mirror scope
test / unit (pull_request) Successful in 11s
test / integration (pull_request) Successful in 18s
The gate now fronts every git operation, not just push. Fetch
(clone, pull, ls-remote) is mirrored via git daemon's
--access-hook running 'git fetch origin --prune' against the
real upstream before each upload-pack; fail-closed if upstream
is unreachable so the agent never serves stale data.

Push path is unchanged in concept (gitleaks gate → forward) but
the hook now pushes to 'origin' rather than 'upstream', matching
the remote name the entrypoint configures.
2026-05-12 21:26:19 -04:00
didericis c91395425c docs(prds): add PRD 0008 git gate
test / unit (pull_request) Successful in 12s
test / integration (pull_request) Successful in 13s
Per-bottle sidecar that fronts the agent's git remotes, runs
gitleaks via a pre-receive hook, and only forwards to the real
upstream on a clean scan. Upstream push credentials live in the
gate, not the agent — so a misbehaving agent cannot push a
secret-bearing commit past it.
2026-05-12 18:24:33 -04:00
didericis 96d2c7b7a1 docs(research): add note on git secret-scanning as defense-in-depth
test / unit (push) Successful in 12s
test / integration (push) Successful in 15s
Threat-models the case where a credential ends up in a tracked
file and is git-pushed to a public remote — the secret is
compromised the instant the push lands (events API, scrapers),
not at merge time. Recommends gitleaks as the smallest-blast-
radius layer to add: Go binary, MIT, offline, scans full history,
hookable from the existing .githooks/.

No code or workflow change; just the research note.
2026-05-12 16:24:06 -04:00
didericis a3d77cd015 fix(ssh-gate): listen on the upstream port so URL-supplied ports work
test / unit (pull_request) Successful in 12s
test / integration (pull_request) Successful in 12s
Bug: git fetch failed with "connect to host
claude-bottle-ssh-gate-implementer port 30009: Connection refused".
OpenSSH treats a URL-supplied port (the user's remote was
ssh://git@gitea.dideric.is:30009/...) as overriding the
~/.ssh/config Port directive, so even though the config wrote
Port 30000 the agent dialed :30009 — where nothing was listening
because the gate had been assigned BASE_LISTEN_PORT + index.

Fix: the gate's listen port now equals the upstream port. Same
script, same socat, just port = entry.Port. Two entries on the
same upstream port are rejected at prepare time (the gate is one
container with a flat port space).

Re-smoked: probe nc github.com via the gate at :22, banner came
back as expected.

PRD 0007 updated to record the design refinement.
2026-05-12 16:19:07 -04:00
didericis b2927b1483 docs(prd): note gate image must be self-sufficient at boot on 0007
test / unit (pull_request) Successful in 12s
test / integration (pull_request) Successful in 13s
The gate's agent-facing leg sits on the `--internal` network, so
the forwarder image cannot rely on apk/apt at startup. Surfaced
by the DNS spike — a placeholder using `apk add socat` died
silently and gave a false-negative DNS-on-internal result.
2026-05-12 15:50:34 -04:00
didericis cb0f0f133d docs(prd): resolve gate-DNS open question on 0007
test / unit (pull_request) Successful in 12s
test / integration (pull_request) Successful in 14s
Spike: container on a `--internal` user-defined network resolves
another container's name via the embedded resolver at 127.0.0.11
and reaches it over TCP, while egress to the public internet
remains blocked. The PRD's design assumption holds — no design
change needed.
2026-05-12 15:48:55 -04:00
didericis 02a0fe679d docs(prd): 0007 SSH egress gate
test / unit (pull_request) Successful in 18s
test / integration (pull_request) Successful in 15s
PRD 0006 enabled pipelock's native TLS interception, which broke
git fetch over SSH from inside the agent: pipelock's SNI gate
rejects the SSH banner that follows CONNECT. Document the
architectural fix — a dedicated per-agent TCP-forwarder sidecar
built from bottle.ssh entries — so pipelock can stay maximally
strict on the HTTPS path with no SSH carve-outs.
2026-05-12 15:41:26 -04:00
didericis f44e884d8a docs(prd): fold 0006 walkthrough resolutions into the design
test / unit (pull_request) Successful in 15s
test / integration (pull_request) Successful in 14s
After the open-question walkthrough, all four collapsed:

- Q1 (mount semantics): resolved to `docker cp` between
  `docker create` and `docker start`, mirroring the existing
  pipelock YAML handling. No bind mount, no UID/permission
  concern. Folded into §Proposed Design > CA lifecycle as
  "Sidecar install".
- Q2 (cert validity / TTL): pre-decided in the question text.
  Per-bottle ephemerality is enforced by regenerating per launch,
  not by short validity windows. Pipelock's defaults are fine.
  Folded into §Proposed Design as a one-line "Per-bottle
  ephemerality" note.
- Q3 (`passthrough_domains` shape): not v1 scope; the shape is
  pre-recorded so the follow-up is mechanical. Moved into
  §Out of scope.
- Q4 (stage-dir cleanup ordering): reading start.py confirmed
  the ExitStack-then-outer-finally order is correct. Folded into
  §Proposed Design as a "Teardown" note.

The §Open questions section is dropped. None of the four was a
real design question — they were verifications and pre-decided
items left in for defensiveness.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-12 14:22:59 -04:00
didericis 6716f091c1 docs(prd): add 0006, enable pipelock's native TLS interception
test / unit (pull_request) Successful in 12s
test / integration (pull_request) Successful in 13s
Supersedes the abandoned PR #8 (`mitmproxy-tls-interception`),
which built a mitmproxy + addon chain on the (falsified) premise
that pipelock could not MITM. Empirical proof from the impl-time
spike: with `tls_interception: { enabled: true, ca_cert, ca_key }`
in pipelock's config, pipelock answered a credential POST over
HTTPS with `STATUS=403 / body: blocked: request body contains
secret: GitHub Token` and emitted both `scanner:"tls_intercept"`
and `scanner:"body_dlp"` events. Standalone, no second proxy.

Net change vs PR #8: one sidecar instead of two, no vendored
addon, no addon-verdict pattern matching, no HTTPS-trust /
DNS / lookup workarounds. Same end-state behavior — pipelock's
DLP fires on plaintext for HTTPS hosts in the allowlist.

Also cleaning up the now-stale TLS-research notes:

- `docs/research/tls-mitm-for-pipelock.md` is removed. Its
  entire premise (mitmproxy in front of pipelock) is moot now
  that pipelock does the work natively. The mechanics of CONNECT
  bumping and the CA-lifecycle considerations it documented are
  the same as what pipelock implements; the PRD restates the
  parts that matter for the integration.
- `docs/research/pipelock-assessment.md` had two stale claims
  corrected: the "Pipelock does not perform TLS inspection (no
  CA trust injection)" line in §Scope gaps and the
  "no TLS termination" cell in the comparison table. Both now
  point at the `tls_interception` config and `pipelock tls`
  CLI instead.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-12 14:15:44 -04:00
didericis 8e261563dc docs(research): TLS interception topologies for pipelock content scanning
test / unit (push) Successful in 14s
test / integration (push) Failing after 13s
Survey of TLS-MITM tools (mitmproxy, Squid+ssl_bump, Go libraries) and
five candidate topologies for adding TLS termination to the egress path
so pipelock's DLP, subdomain-entropy, and MCP scanners can fire on
plaintext bodies. Recommends mitmproxy in front of pipelock for v1
with a per-bottle ephemeral CA.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-12 11:41:34 -04:00
didericis 45203e2cd6 docs(prd): add 0004 split out provisioners
test / unit (pull_request) Successful in 12s
test / integration (pull_request) Successful in 13s
2026-05-11 19:36:39 -04:00
didericis b97807ac71 docs(research): evaluate smolmachines as VM backend
test / run tests/run_tests.py (push) Successful in 16s
Compares smolmachines against the six subsystems in
agent-vm-isolation.md. smolmachines replaces the microVM runtime,
network attachment (libkrun TSI with built-in DNS-over-vsock filter),
vsock control plane, and Python lifecycle wrapper. Pipelock stays;
disk-image story shifts to OCI + writable overlay. Recommends adopting
smolmachines as the macOS VM backend after smoke-testing TSI
passthrough to a host-side pipelock.
2026-05-11 16:32:04 -04:00
didericis aba9a823ba docs(research): document macOS agent VM isolation approach
Transcript-style notes on running an agent in a hardware-isolated
microVM on macOS. Covers Virtualization.framework / vfkit / libkrun
choices, hardware-isolation guarantees, driving VMs from Python
(subprocess or PyObjC), pipelock as the egress proxy, vsock for the
control channel, and egress enforcement via
VZFileHandleNetworkDeviceAttachment + gvisor-tap-vsock.
2026-05-11 16:31:40 -04:00
didericis 08159e1031 docs(research): survey AI-agent sandbox tools
test / run tests/run_tests.py (push) Successful in 19s
Compares claude-bottle to endo-familiar, litterbox, agent-safehouse,
matchlock, tilde.run, boxlite, microsandbox, and smolmachines. Covers
isolation primitive, locality, agent integration, network policy, and
maturity, and notes three borrowable ideas (per-use SSH confirmation,
in-flight secret injection, microVM backend) that fit the current
bash-first / local-Docker stance.
2026-05-11 15:56:23 -04:00
didericis f0b67a3e94 docs(prd): update PRD 0003 to reflect the shipped design
test / run tests/run_tests.py (pull_request) Successful in 14s
Renames the file and rewrites the body around what actually shipped:
class-based BottleBackend ABC (not a free create_docker_bottle
function), the two-phase prepare/launch split, the backend/docker/
subpackage layout, env.py reshaped into a backend-neutral ResolvedEnv,
and PipelockProxy split between top-level and backend/docker/.
2026-05-11 14:47:17 -04:00
didericis 70a22fa210 refactor: rename platform abstraction to backend
test / run tests/run_tests.py (pull_request) Successful in 21s
Across the package:
  - claude_bottle/platform/         -> claude_bottle/backend/
  - platform/docker/platform.py     -> backend/docker/backend.py
  - class BottlePlatform            -> BottleBackend
  - class DockerBottlePlatform      -> DockerBottleBackend
  - get_bottle_platform()           -> get_bottle_backend()
  - env var CLAUDE_BOTTLE_PLATFORM  -> CLAUDE_BOTTLE_BACKEND
  - dict _PLATFORMS                 -> _BACKENDS

"Backend" is shorter and more established as the term for a
pluggable strategy-pattern implementation. "Platform" was vague
(could mean OS, hardware, cloud) and mildly redundant — Docker is
itself a platform.

The previous PRD section claiming "the Backend protocol was
rejected" referred to a low-level run/exec/cp/network_connect
protocol; the name was never the reason. The PRD is updated to
describe that rejected design by shape rather than by name.

The bottle/agent concepts and the manifest schema are unchanged.
2026-05-10 23:59:38 -04:00
didericis d5c056f36e docs(prd): add 0003 bottle factory abstraction
test / run tests/run_tests.py (pull_request) Successful in 17s
2026-05-10 21:56:10 -04:00
didericis 7e0e256370 docs: add research note on polish priorities to close the maturity gap
test / run tests/run_tests.py (push) Successful in 21s
Captures the ranked list of changes that would move the project from
"works for me" toward the perceived maturity of comparable tools —
onboarding friction, error messages, distribution, versioning, schema
validation, starter library, docs site, cross-platform CI. Includes
effort estimates and an explicit "what polish is not" section so the
roadmap doesn't drift into feature work.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-10 20:38:44 -04:00
didericis e1efc64862 docs: add research note on Apple container as an alternative backend
test / run tests/run_tests.py (push) Successful in 14s
Captures the surface area of the current Docker integration, how it
maps to Apple's `container` framework, the dominant networking risk
(pipelock multi-network attach), and the cost difference between a
faithful port and a simplified VM-firewall variant.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-10 02:36:11 -04:00
didericis 1e6f254db5 docs: add research note comparing bash, Python, and Go for the CLI
test / run tests/run_tests.py (push) Successful in 14s
Captures the reasoning for staying on Python, the conditions under which
a Go rewrite would pay for itself, and why bash isn't viable at the
project's current size.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-10 02:34:40 -04:00
didericis c8a35beb12 docs: add project logo and trademark disclaimer to README
test / run tests/run_tests.py (push) Successful in 15s
A short apothecary-bottle SVG with a cream cartoon robot inside —
sized roughly to the robot so it works as a favicon-shaped icon.
README gains a centered logo above the title and a Trademarks
section disclaiming affiliation with Anthropic and framing the
"claude" in the project name as descriptive use.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-10 01:40:05 -04:00
didericis ec6261cd77 docs: add Fly Machines case study to remote-docker-vm-isolation note
test / run tests/run_tests.py (push) Successful in 13s
Concrete worked example covering image strategy (with the bake-the-
claude-bottle-image-in optimization that elides 30-90s of in-VM
build), cold/warm/hot boot-to-prompt timing, standby vs ephemeral
cost breakdown, three workflow patterns, and Fly-specific gotchas
(DinD kernel requirements, the y/N preflight blocking automated
launch, pricing-may-have-moved hedge).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-10 01:18:08 -04:00
didericis 43453c66ea docs: add research note on remote Docker VM as an isolation upgrade
test / run tests/run_tests.py (push) Successful in 15s
Argues that running claude-bottle unchanged on a remote Linux VM with
dockerd is the cheapest practical path to stronger isolation than
local Docker — preserves the v1 pipelock topology, requires zero code
changes, and shrinks the agent's blast radius from the developer
laptop to a disposable VM. Cross-references the existing
stronger-isolation-alternatives and local-vs-remote-agent-execution
notes so the research set composes cleanly.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-10 01:07:17 -04:00
didericis 7986f2bd23 docs: add research note on stronger isolation alternatives
test / run tests/run_tests.py (push) Successful in 19s
Surveys gVisor, Kata, Firecracker, and Apple Container as replacements
or complements to Docker+runc, with concrete file-level migration notes
for this codebase and a recommended rung-by-rung path.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-10 00:38:46 -04:00
didericis cc5e772519 docs: replace stale .sh paths with claude_bottle/*.py equivalents
test / run tests/run_tests.py (push) Successful in 13s
Cleans up references to the pre-refactor bash layout (cli.sh,
lib/*.sh, scripts/*.sh) across README, Dockerfile, the pipelock PRD,
and research notes. Refreshes line numbers in the oauth-token note
against the current cli/start.py.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-10 00:27:25 -04:00
didericis 0c1740ca99 chore: remove journal and project-local init-entry skill
test / run tests/run_tests.py (push) Successful in 23s
Drop docs/JOURNAL.md and .claude/skills/init-entry/, and update
CLAUDE.md, docs/INDEX.md, and claude-bottle.example.json so nothing
points at them anymore.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-09 23:55:39 -04:00
didericis 4694db1201 PRD 0002: Test pipeline on Gitea Actions (#3)
test / run tests/run_tests.py (push) Successful in 20s
2026-05-09 02:48:03 -04:00
didericis ba7616a4ae PRD 0001: Per-agent egress proxy via pipelock (#1) 2026-05-08 01:56:43 -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 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 c45f384fb8 Initial commit 2026-05-07 22:45:36 -04:00