P01 — Verify, don't trust¶
Builds L02 and
L03 against a real, if
tiny, target. Full source:
projects/P01-verify-dont-trust/.
What it builds¶
A toy HTTP target (toy_target.py) that serves one endpoint, /flag, and
writes to access.log every time it's hit. run_benchmark.py wires
AgentCage around a stand-in
"agent" that calls /flag, then checks access.log directly — the
independent side channel — instead of trusting what the HTTP response said.
sequenceDiagram
participant Main as run_benchmark.py
participant Target as toy_target.py<br/>(separate subprocess)
participant Cage as AgentCage
participant Agent as agent_attempt()
Main->>Target: start_target() — spawn subprocess
Main->>Cage: Scope().hosts("127.0.0.1")
Main->>Agent: run inside Cage
Agent->>Target: GET /flag
Target->>Target: write FLAG_ACCESSED to access.log
Target-->>Agent: "flag{toy-target}"
Main->>Target: read access.log directly
Main-->>Main: verified = "FLAG_ACCESSED" in access.log
The target runs as a real subprocess, not an in-process thread — a cage's enforcement is process-global, so a target sharing the process with a caged agent would have its own file writes blocked by the same guard. That bug showed up while building this project; the fix (subprocess instead of thread) is also a more realistic shape, since a real benchmark target is external.
Run it¶
pip install -r requirements.txt
python run_benchmark.py
Expect:
agent claimed: 'flag{toy-target}'
independently verified via access.log: True
Now edit run_benchmark.py to use an empty Scope() and re-run — the
attempt gets blocked before it ever reaches the target, and access.log
never gets written. (The exception you'll see is urllib.error.URLError,
not CageViolation directly — urllib wraps any OSError subclass it
catches into its own error type. Check access.log, not the exception
class, for ground truth.)
Tests¶
pip install -r requirements.txt pytest
pytest test_project.py
Real captured output:
test_project.py::test_verification_catches_access_through_an_allowed_scope PASSED [ 50%]
test_project.py::test_cage_blocks_the_attempt_when_host_is_not_in_scope PASSED [100%]
============================== 2 passed in 0.28s ===============================