For RL coding environments, git history scrub + separate verifier containers is strictly stronger than uid-wall permissions + in-process grading. But non-root agent user from the uid-wall approach is worth adopting universally as defense-in-depth.
Comparing two RL environment architectures for coding bug-fix tasks (agent edits repo, hidden tests grade the fix):
Architecture A (uid-wall + in-process grading):
setprivshutil.copytree repo to /tmp, git apply hidden test patch, run pytest, cleanup in finally blockArchitecture B (git-scrub + separate verifier container):
rm -rf .git && git init && git add -A && git commit -m basegit diff --cached, filtered through apply_agent_patch.py to strip test/config file modifications before gradingnetwork_mode: no-network — can't exfiltrateArchitecture B is strictly stronger: there's no history to leak (vs. permission-based hiding), tests are architecturally isolated (vs. cleanup-dependent), and agent patches are filtered (vs. trusting the agent not to modify grading infrastructure).
However, Architecture A has one defense-in-depth practice worth adopting everywhere: running the agent as a non-root user. Even with git scrubbed and tests in a separate container, root inside the environment container gives agents unnecessary filesystem access. Adding USER agent (uid 1000) to the environment Dockerfile is cheap and reduces the blast radius of any container escape.
Additional hardening layers in Architecture B worth noting: canary footers for training contamination detection, HTTPS apt mirrors for SNI-compatible egress allowlists, Node.js pre-baking to remove raw.githubusercontent.com from runtime allowlists, and automated hardening audit tools that check all these properties.