From beaa09a154684325800de969c14f8ef86a31ea8a Mon Sep 17 00:00:00 2001 From: vikingowl <26+vikingowl@noreply.somegit.dev> Date: Tue, 19 May 2026 16:21:53 +0200 Subject: [PATCH] test(permission): lock in elf safety-pattern inheritance Audit finding H2 hypothesised that spawn_elfs/agent's safetyCheck exemption could be reached as a bypass route if the spawned elf failed to enforce the same patterns. Verified by inspection that: 1. WithDenyPrompt copies safetyDenyPatterns into the elf checker. 2. Check() runs safetyCheck (Step 2) before ModeBypass (Step 3), so bypass cannot skip safety. 3. main.go always passes the parent permChecker to the elf Manager. H2 is not exploitable in current code. This test pins the contract so future refactors of WithDenyPrompt cannot silently drop pattern inheritance. --- internal/permission/permission_test.go | 29 ++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/internal/permission/permission_test.go b/internal/permission/permission_test.go index d3bfc33..7c174d4 100644 --- a/internal/permission/permission_test.go +++ b/internal/permission/permission_test.go @@ -202,6 +202,35 @@ func TestChecker_SafetyCheck(t *testing.T) { }) } +func TestChecker_ElfInheritsSafetyPatterns(t *testing.T) { + // Audit H2: spawn_elfs/agent are exempt from safetyCheck at the orchestration + // layer, with the rationale that the spawned elf will be checked when it + // actually accesses files. That contract requires the elf checker (built via + // WithDenyPrompt) to inherit the parent's safetyDenyPatterns AND for those + // patterns to still fire even in ModeBypass. + parent := NewChecker(ModeBypass, nil, nil) + elfChecker := parent.WithDenyPrompt() + + safetyCases := []struct { + name string + toolName string + args string + }{ + {"env file", "fs.read", `{"path":".env"}`}, + {"ssh key", "fs.read", `{"path":"id_rsa"}`}, + {"aws creds", "fs.read", `{"path":".aws/credentials"}`}, + {"bash on env", "bash", `{"command":"cat .env"}`}, + } + for _, tt := range safetyCases { + t.Run(tt.name, func(t *testing.T) { + err := elfChecker.Check(context.Background(), ToolInfo{Name: tt.toolName}, json.RawMessage(tt.args)) + if !errors.Is(err, ErrDenied) { + t.Errorf("elf checker must still block %s on %s, got: %v", tt.args, tt.toolName, err) + } + }) + } +} + func TestChecker_SafetyCheck_OrchestrationToolsExempt(t *testing.T) { // spawn_elfs and agent carry elf PROMPT TEXT as args — arbitrary instruction // text that may legitimately mention .env, credentials, etc.