fix(tier2): deny %TEMP% writes - use app-data dir for temp files

The Tier 2 agent wrote audit_exception_handling.py output to
C:\\Users\\Ed\\AppData\\Local\\Temp\\audit_initial.json via shell
redirection. This is OUTSIDE the sandbox allowlist (which is
C:\\projects\\manual_slop_tier2 + C:\\Users\\Ed\\AppData\\Local\\
manual_slop\\tier2 + C:\\Users\\Ed\\AppData\\Local\\manual_slop\\
tier2_failures). The OpenCode session-level guard fires the 'ask'
prompt for paths outside the project root, which has no answer in an
autonomous session, so ops halted mid-track.

Fix (3 layers):

1. opencode.json.fragment: add bash deny rule
   '*AppData\\Local\\Temp\\*': 'deny' to BOTH the top-level
   permission.bash (for default agents) and the tier2-autonomous
   agent's permission.bash. The agent physically cannot run shell
   commands that target the global Temp dir.

2. conductor/tier2/agents/tier2-autonomous.md: add 'Temp files'
   convention telling the agent to use
   C:\\Users\\Ed\\AppData\\Local\\manual_slop\\tier2\\ for scratch
   / audit-output / intermediate files, NOT %TEMP%.

3. conductor/tier2/commands/tier-2-auto-execute.md: same convention
   in the slash command so the agent sees it at slash-command time.

Tests (default-on):
- test_agent_denies_temp_writes: agent prompt has the Temp deny in
  frontmatter bash + the app-data dir note
- test_config_fragment_denies_temp_writes: both top-level and agent
  bash have the deny rule

All 16 tier 2 slash command tests pass.

Also: cleaned up the leaked audit_initial.json + audit.json +
audit_after*.json from %TEMP% (they were leftovers from a prior
run). Re-ran setup against the live clone; opencode.json's agent
bash and top-level bash both have the deny rule.
This commit is contained in:
ed
2026-06-17 16:13:19 -04:00
parent 3ec601d4da
commit 03c9df8450
4 changed files with 32 additions and 0 deletions
+27
View File
@@ -79,6 +79,18 @@ def test_agent_denies_destructive_git() -> None:
assert '"git reset*": deny' in content
def test_agent_denies_temp_writes() -> None:
"""Regression test (2026-06-17): the agent wrote an audit JSON to
C:\\Users\\Ed\\AppData\\Local\\Temp\\, which is outside the sandbox
allowlist, triggering the OpenCode session-level 'ask' prompt and
halting ops. The agent's bash MUST now deny commands targeting
AppData\\Local\\Temp\\, and the agent prompt MUST tell the agent
to use the sandbox's app-data dir for temp files."""
content = AGENT_PATH.read_text(encoding="utf-8")
assert 'AppData\\Local\\Temp' in content, "agent prompt must include Temp deny rule in frontmatter bash"
assert 'AppData\\Local\\manual_slop\\tier2' in content or 'app-data' in content.lower(), "agent prompt must point agent at the app-data dir for temp files"
def test_config_fragment_valid_json() -> None:
data = json.loads(CONFIG_PATH.read_text(encoding="utf-8"))
assert data["default_agent"] == "tier2-autonomous"
@@ -122,3 +134,18 @@ def test_config_fragment_has_top_level_permission() -> None:
assert top["bash"].get("git checkout*") == "deny"
assert top["bash"].get("git restore*") == "deny"
assert top["bash"].get("git reset*") == "deny"
def test_config_fragment_denies_temp_writes() -> None:
"""Regression test (2026-06-17): the agent wrote audit output to
C:\\Users\\Ed\\AppData\\Local\\Temp\\ which is outside the sandbox.
Both the top-level and the tier2-autonomous agent's bash MUST deny
commands targeting AppData\\Local\\Temp\\ so the agent cannot write
there, and so the session-level 'ask' prompt is never triggered."""
data = json.loads(CONFIG_PATH.read_text(encoding="utf-8"))
top_bash = data["permission"]["bash"]
agent_bash = data["agent"]["tier2-autonomous"]["permission"]["bash"]
temp_deny_keys = [k for k in top_bash if "Temp" in k and top_bash[k] == "deny"]
assert temp_deny_keys, "top-level bash must have a deny rule for AppData\\Local\\Temp\\ paths"
temp_deny_keys_agent = [k for k in agent_bash if "Temp" in k and agent_bash[k] == "deny"]
assert temp_deny_keys_agent, "tier2-autonomous agent bash must have a deny rule for AppData\\Local\\Temp\\ paths"