mirror of
https://github.com/Twigpine/zero.git
synced 2026-11-08 09:49:34 -10:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8b5c1535bc |
No files matched your search
@@ -93,6 +93,40 @@ func TestSandboxedBashAutoAllowDoesNotAffectNonShell(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Forged re-entrancy markers (ambient ZERO_SANDBOXED=1 + ZERO_SANDBOX_BACKEND at
|
||||
// an unsandboxed process boundary) must NOT let a shell command combine an
|
||||
// auto-allow decision with an unwrapped pass-through plan (issue #727). The
|
||||
// runner skips wrapping when the markers are present, so the policy must stop
|
||||
// auto-allowing on the basis of an "active sandbox" — the command takes the
|
||||
// normal prompt instead. Without the markers the identical setup auto-allows
|
||||
// (TestSandboxedBashAutoAllowedWhenSandboxActive), so this is the before/after.
|
||||
func TestForgedReentrancyMarkersDoNotAutoAllowUnwrappedShell(t *testing.T) {
|
||||
t.Setenv(EnvSandboxed, "1")
|
||||
t.Setenv(EnvSandboxBackend, string(BackendLinuxBwrap))
|
||||
root := t.TempDir()
|
||||
engine := NewEngine(EngineOptions{
|
||||
WorkspaceRoot: root,
|
||||
Policy: DefaultPolicy(),
|
||||
Backend: nativeWrappingBackend,
|
||||
})
|
||||
|
||||
// Policy side: the shell command must NOT be auto-allowed.
|
||||
decision := engine.Evaluate(context.Background(), bashRequest())
|
||||
if decision.Action != ActionPrompt || decision.AutoAllowed {
|
||||
t.Fatalf("forged markers must not auto-allow the shell command, got %#v", decision)
|
||||
}
|
||||
|
||||
// Planning side: the same command is an unwrapped pass-through. Together with
|
||||
// the prompt above, this proves auto-allow and unwrapped can no longer combine.
|
||||
plan, err := engine.BuildCommandPlan(CommandSpec{Name: "/bin/sh", Args: []string{"-c", "echo hi"}, Dir: root})
|
||||
if err != nil {
|
||||
t.Fatalf("BuildCommandPlan: %v", err)
|
||||
}
|
||||
if plan.Wrapped {
|
||||
t.Fatalf("re-entrancy plan must be an unwrapped pass-through, got wrapped=%v", plan.Wrapped)
|
||||
}
|
||||
}
|
||||
|
||||
// TestShellSandboxActive reports correctly across backends and policy modes.
|
||||
func TestShellSandboxActive(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
|
||||
@@ -232,6 +232,15 @@ func (engine *Engine) shellSandboxActive(policy Policy) bool {
|
||||
if policy.Mode == ModeDisabled {
|
||||
return false
|
||||
}
|
||||
// Re-entrancy skips wrapping: when the process carries the sandbox markers,
|
||||
// the runner returns a pass-through (unwrapped) plan, so the native sandbox
|
||||
// is NOT the boundary for THIS command. Because the markers are ambient and
|
||||
// forgeable at an unsandboxed process boundary (issue #727), auto-allowing a
|
||||
// shell command on that basis would run it unwrapped with no prompt. Mirror
|
||||
// the runner: report inactive so the command takes the normal approval path.
|
||||
if IsAlreadySandboxed() {
|
||||
return false
|
||||
}
|
||||
backend := engine.backend
|
||||
if !(backend.Available && backend.Executable != "" && backend.CommandWrapping && backend.NativeIsolation) {
|
||||
return false
|
||||
|
||||
Reference in new issue
Block a user