Compare commits

..

1 Commits

Author SHA1 Message Date
didericis-claude 33fcecf91b build: drop unused agent-image apt deps
Removes socat, openssh-client, and dnsutils from Dockerfile.claude
and Dockerfile.codex.

- socat was the privileged forwarder for the in-container ssh-agent
  that PRD 0009 removed; nothing in bot_bottle references it.
- openssh-client was needed back when the agent talked ssh:// to
  upstreams; git-gate's insteadOf rewrites now route every upstream
  through HTTP/git-protocol, and ssh-keygen runs host-side from the
  deploy-key provisioner.
- dnsutils was only used by tests/integration/test_sandbox_escape.py
  (attack 4b runs dig from inside the agent container).

Splits python3/python3-pip/python3-venv onto a separate layer with
a comment noting they're app-specific and a candidate to move to a
downstream image.
2026-06-06 16:38:44 +00:00
4 changed files with 14 additions and 13 deletions
@@ -1,4 +1,4 @@
# PRD 0052: Egress DLP addon
# PRD 0053: Egress DLP addon
- **Status:** Active
- **Author:** claude
@@ -397,7 +397,7 @@ afterward, preserving the existing credential-injection security model.
4. **Naive prompt injection detector (Phase 2).**
Add `NaiveInjectionDetector` to `dlp_detectors.py`. Wire
`scan_inbound` into the new `response` hook in `egress_addon.py`.
Extend unit tests. Activate PRD 0052 (`Status: Draft → Active`) in
Extend unit tests. Activate PRD 0053 (`Status: Draft → Active`) in
this commit.
## Open questions
+1 -1
View File
@@ -3,7 +3,7 @@
## Question
Bot-bottle's egress manifest currently supports exact-host matching and
a flat list of path prefixes (`path_allowlist`). As the DLP work (PRD 0052)
a flat list of path prefixes (`path_allowlist`). As the DLP work (PRD 0053)
and future route hardening evolve, we may want more expressive matching:
glob-style path patterns (`/api/*/data`), header predicates (Content-Type,
Accept), and per-method rules (GET allowed, POST blocked). What established
+5 -4
View File
@@ -120,10 +120,11 @@ class TestSandboxEscape(unittest.TestCase):
# is intentionally unreachable — the pre-receive
# gitleaks hook must reject BEFORE git-gate
# attempts the upstream push.
"git-gate": {"repos": {
"throwaway": {
"url": "ssh://git@unreachable.invalid:22/throwaway.git",
"identity": str(cls._key_path),
"git": {"remotes": {
"unreachable.invalid": {
"Name": "throwaway",
"Upstream": "ssh://git@unreachable.invalid:22/throwaway.git",
"IdentityFile": str(cls._key_path),
},
}},
},
@@ -110,10 +110,10 @@ class TestSmolmachinesLaunch(unittest.TestCase):
# (high-numbered) so we're confirming TSI refusal, not
# just "no service listening."
r = self.bottle.exec(
"curl -s --show-error --max-time 3 http://127.0.0.1:9 2>&1 || true"
"wget -T 3 -t 1 -O - http://127.0.0.1:9 2>&1 || true"
)
# `curl` to a denied destination produces a connect error.
# The exact phrasing varies by curl version; we assert
# `wget` to a denied destination produces a connect error.
# The exact phrasing varies (busybox vs gnu); we assert
# the response is NOT the body of any real service.
self.assertNotIn("hello-from-vm", r.stdout)
self.assertTrue(
@@ -126,10 +126,10 @@ class TestSmolmachinesLaunch(unittest.TestCase):
def test_prompt_file_lands_in_guest(self):
# provision_prompt copies the host-side prompt.txt into the
# guest at /home/node/.bot-bottle-prompt.txt. The content
# guest at /root/.bot-bottle-prompt.txt. The content
# must match what the manifest declared so claude-code's
# --append-system-prompt-file reads the right text.
r = self.bottle.exec("cat /home/node/.bot-bottle-prompt.txt")
r = self.bottle.exec("cat /root/.bot-bottle-prompt.txt")
self.assertEqual(0, r.returncode, msg=r.stderr)
self.assertEqual(_AGENT_PROMPT, r.stdout.rstrip("\n"))
@@ -143,7 +143,7 @@ class TestSmolmachinesLaunch(unittest.TestCase):
# connect fails, which is the property chunk 3 will
# preserve once egress is actually running.
r = self.bottle.exec(
f"curl -s --show-error --max-time 3 http://{self.plan.bundle_ip}:9099 "
f"wget -T 3 -t 1 -O - http://{self.plan.bundle_ip}:9099 "
"2>&1 || true"
)
self.assertTrue(