studio: regression tests for sandbox hardening patches A / B / D
124 tests across 7 classes:
* TestPatchA_DynamicPaths — open() with concatenated literals + f-strings.
Pins 7 attack patterns BLOCKED, 6 legitimate dynamic paths ALLOWED,
12-level deep concat doesn't crash.
* TestPatchB_FindSensitivePathsHomeAnchored — ~/.ssh/id_*, ~/.aws/,
~/.docker/, ~/.kube/, ~/.pypirc/.npmrc, ~/.netrc, ~/.password-store,
~/.gnupg/private-keys-v1.d across ~, $HOME, /home/<u>, /root,
/Users/<u>. Pins 21 attack paths BLOCKED, 15 legitimate paths
(~/.gitconfig, ~/.bashrc, ~/.ssh/{config,known_hosts}, ~/.npm,
project-local rc files, /tmp/.npmrc) ALLOWED.
* TestPatchB_FindSensitivePathsAbsolute — /etc/shadow, /etc/sudoers,
/etc/ssh/ssh_host_*, /proc/{self,<pid>}/{environ,mem,maps,auxv},
/proc/kcore, /proc/kallsyms, /var/spool/cron/. Pins 12 attacks
BLOCKED, 11 legit paths (/etc/hosts, /etc/resolv.conf, /proc/cpuinfo,
/proc/meminfo, …) ALLOWED.
* TestPatchB_PythonShellExec — same surface flows through os.system /
subprocess.run. 6 attacks BLOCKED, 11 legitimate tool-calls ALLOWED.
* TestPatchD_EvalExecLiteralPayload — exec/eval with a literal payload
parsed and re-checked. 5 attack payloads BLOCKED, 6 legit
expressions (eval('1+2'), exec('print("hi")'), nested innocuous
exec) ALLOWED.
* TestPatchD_EvalExecDynamicPayload — non-literal eval/exec args
flagged as dynamic shell escape. 4 patterns BLOCKED.
* TestPatchD_NestedDepthCap — 10-level nested exec(exec(...)) caps
at depth 3, doesn't crash, doesn't false-positive.
* TestCrossCuttingNoRegression — 6 pre-existing BLOCK patterns still
fire (sudo, signal tampering, /etc/passwd literal, untrusted host,
metadata host); 7 pre-existing ALLOW patterns still pass (print,
json.loads, trusted host, dataclass, legitimate open()).
Result on the rebuilt scaffold:
131/131 pre-existing tests in test_sandbox_tools.py pass
124/124 new hardening tests pass
255/255 combined, zero regressions
The "must remain ALLOWED" cases form the non-regression floor that
prevents the patches from making LLM tool calling dumber.