fix(pipelock): disable bip39 detector by default
This commit is contained in:
+10
-16
@@ -84,14 +84,13 @@ def pipelock_effective_allowlist(bottle: Bottle) -> list[str]:
|
|||||||
|
|
||||||
|
|
||||||
def pipelock_seed_phrase_detection_enabled(bottle: Bottle) -> bool:
|
def pipelock_seed_phrase_detection_enabled(bottle: Bottle) -> bool:
|
||||||
"""Whether pipelock's BIP-39 seed-phrase detector stays on for
|
"""Whether pipelock's BIP-39 seed-phrase detector stays on.
|
||||||
this bottle.
|
|
||||||
|
|
||||||
LLM conversation bodies legitimately trip the detector — any 12+
|
LLM conversation bodies legitimately trip the detector — any 12+
|
||||||
English words that pass the BIP-39 checksum match — so any
|
English words that pass the BIP-39 checksum match — so agents can
|
||||||
bottle that routes claude through pipelock's body scanner gets
|
get blocked on ordinary prompts/responses regardless of provider
|
||||||
blocked on the first real chat. We tried two narrower knobs
|
(Claude, Codex/OpenAI, or future harnesses). We tried two narrower
|
||||||
first:
|
knobs first:
|
||||||
|
|
||||||
- `suppress: [{rule, path}]` — pipelock accepts the schema
|
- `suppress: [{rule, path}]` — pipelock accepts the schema
|
||||||
but the entry only silences the alert; the body_dlp block
|
but the entry only silences the alert; the body_dlp block
|
||||||
@@ -102,16 +101,11 @@ def pipelock_seed_phrase_detection_enabled(bottle: Bottle) -> bool:
|
|||||||
Empirically only `seed_phrase_detection.enabled: false`
|
Empirically only `seed_phrase_detection.enabled: false`
|
||||||
actually stops the block (verified by sending a 12-word BIP-39
|
actually stops the block (verified by sending a 12-word BIP-39
|
||||||
body through three pipelock instances). It is a global toggle —
|
body through three pipelock instances). It is a global toggle —
|
||||||
no per-path / per-host knob in pipelock 2.3.0 — so we turn the
|
no per-path / per-host knob in pipelock 2.3.0 — so we turn off
|
||||||
detector off for the entire bottle when the bottle declares an
|
only this detector for every bottle. The rest of pipelock's DLP
|
||||||
egress route to `api.anthropic.com`. The trade-off is
|
defaults and request-body/header scanning remain enabled."""
|
||||||
accepted: BIP-39 detection has little value in bot-bottle's
|
del bottle # kept for call-site stability and future policy knobs.
|
||||||
threat model (the agent has no access to a user's crypto wallet
|
return False
|
||||||
seeds; the patterns that matter — gh*_, sk-ant-, AKIA, etc. —
|
|
||||||
keep firing)."""
|
|
||||||
return not any(
|
|
||||||
r.Host == "api.anthropic.com" for r in bottle.egress.routes
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def pipelock_effective_tls_passthrough(bottle: Bottle) -> list[str]:
|
def pipelock_effective_tls_passthrough(bottle: Bottle) -> list[str]:
|
||||||
|
|||||||
@@ -98,25 +98,23 @@ class TestBuildConfig(unittest.TestCase):
|
|||||||
self.assertIn("ssrf", cfg)
|
self.assertIn("ssrf", cfg)
|
||||||
self.assertEqual({"ip_allowlist": ["172.20.0.0/16"]}, cfg["ssrf"])
|
self.assertEqual({"ip_allowlist": ["172.20.0.0/16"]}, cfg["ssrf"])
|
||||||
|
|
||||||
def test_seed_phrase_detection_left_at_default_when_no_anthropic_route(self):
|
def test_seed_phrase_detection_disabled_by_default(self):
|
||||||
# No override emitted -> pipelock keeps its built-in default
|
# Only the broad BIP-39 detector is disabled. The rest of
|
||||||
# (BIP-39 detection enabled). Bottles that don't carry an
|
# DLP remains enabled via the `dlp` and request-body sections.
|
||||||
# Anthropic route don't need the false-positive workaround.
|
|
||||||
cfg = pipelock_build_config(fixture_minimal().bottles["dev"])
|
cfg = pipelock_build_config(fixture_minimal().bottles["dev"])
|
||||||
self.assertNotIn("seed_phrase_detection", cfg)
|
self.assertEqual({"enabled": False}, cfg["seed_phrase_detection"])
|
||||||
|
|
||||||
def test_seed_phrase_detection_disabled_for_anthropic_route(self):
|
def test_seed_phrase_detection_disabled_for_openai_route(self):
|
||||||
# claude-code's chat bodies trip pipelock's BIP-39 detector
|
# OpenAI/Codex chat bodies trip pipelock's BIP-39 detector
|
||||||
# (12+ English words that pass the checksum). pipelock 2.3.0
|
# (12+ English words that pass the checksum). pipelock 2.3.0
|
||||||
# has no per-path knob for this detector, and both `suppress`
|
# has no per-path knob for this detector, and both `suppress`
|
||||||
# and `rules.disabled` only silence alerts — the block still
|
# and `rules.disabled` only silence alerts — the block still
|
||||||
# fires. The only knob that actually skips the block is the
|
# fires. The only knob that actually skips the block is the
|
||||||
# global on/off, so we flip it off whenever the bottle is set
|
# global on/off.
|
||||||
# up to route claude through pipelock.
|
|
||||||
from bot_bottle.manifest import Manifest
|
from bot_bottle.manifest import Manifest
|
||||||
bottle = Manifest.from_json_obj({
|
bottle = Manifest.from_json_obj({
|
||||||
"bottles": {"dev": {"egress": {"routes": [
|
"bottles": {"dev": {"egress": {"routes": [
|
||||||
{"host": "api.anthropic.com",
|
{"host": "api.openai.com",
|
||||||
"auth": {"scheme": "Bearer", "token_ref": "T"}},
|
"auth": {"scheme": "Bearer", "token_ref": "T"}},
|
||||||
]}}},
|
]}}},
|
||||||
"agents": {"demo": {"skills": [], "prompt": "", "bottle": "dev"}},
|
"agents": {"demo": {"skills": [], "prompt": "", "bottle": "dev"}},
|
||||||
@@ -207,16 +205,10 @@ class TestRenderAndWrite(unittest.TestCase):
|
|||||||
self.assertIn("ip_allowlist:", text)
|
self.assertIn("ip_allowlist:", text)
|
||||||
self.assertIn('- "172.20.0.0/16"', text)
|
self.assertIn('- "172.20.0.0/16"', text)
|
||||||
|
|
||||||
def test_render_emits_seed_phrase_off_for_anthropic_route(self):
|
def test_render_emits_seed_phrase_off_by_default(self):
|
||||||
from bot_bottle.manifest import Manifest
|
text = pipelock_render_yaml(
|
||||||
bottle = Manifest.from_json_obj({
|
pipelock_build_config(fixture_minimal().bottles["dev"])
|
||||||
"bottles": {"dev": {"egress": {"routes": [
|
)
|
||||||
{"host": "api.anthropic.com",
|
|
||||||
"auth": {"scheme": "Bearer", "token_ref": "T"}},
|
|
||||||
]}}},
|
|
||||||
"agents": {"demo": {"skills": [], "prompt": "", "bottle": "dev"}},
|
|
||||||
}).bottles["dev"]
|
|
||||||
text = pipelock_render_yaml(pipelock_build_config(bottle))
|
|
||||||
self.assertIn("seed_phrase_detection:", text)
|
self.assertIn("seed_phrase_detection:", text)
|
||||||
self.assertIn("enabled: false", text)
|
self.assertIn("enabled: false", text)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user