@@ -250,6 +250,126 @@ func TestSandboxManagerDegradesUnavailableCommandPlan(t *testing.T) {
250250 }
251251}
252252
253+ func TestSandboxManagerRejectsUnavailableBackendForProtectedToken (t * testing.T ) {
254+ workspace , _ := protectedTokenFixture (t )
255+ policy := DefaultPolicy ()
256+ backend := Backend {Name : BackendUnavailable , Platform : "linux" , Fallback : true , Message : "native sandbox unavailable" }
257+ _ , err := NewSandboxManager (SandboxManagerOptions {GOOS : "linux" , Backend : backend }).BuildCommandPlan (SandboxManagerRequest {
258+ WorkspaceRoot : workspace ,
259+ Command : CommandSpec {Name : "/bin/sh" , Args : []string {"-c" , "true" }, Dir : workspace },
260+ Policy : policy ,
261+ Profile : PermissionProfileFromPolicy (workspace , policy , nil ),
262+ Preference : SandboxPreferenceAuto ,
263+ ValidateExecution : true ,
264+ })
265+ if err == nil || ! strings .Contains (err .Error (), "protected credentials cannot be enforced" ) {
266+ t .Fatalf ("BuildCommandPlan error = %v, want protected-credential enforcement failure" , err )
267+ }
268+ }
269+
270+ func TestSandboxManagerRejectsMacOSTokenInsideWritableWorkspace (t * testing.T ) {
271+ t .Setenv (daemonRemoteTokenEnv , "" )
272+ t .Setenv (daemonRemoteTokenFileEnv , "/workspace/bridge-token" )
273+ workspace := "/workspace"
274+ policy := DefaultPolicy ()
275+ backend := Backend {
276+ Name : BackendMacOSSeatbelt ,
277+ Available : true ,
278+ Executable : "/usr/bin/sandbox-exec" ,
279+ Platform : "darwin" ,
280+ CommandWrapping : true ,
281+ NativeIsolation : true ,
282+ }
283+ _ , err := NewSandboxManager (SandboxManagerOptions {GOOS : "darwin" , Backend : backend }).BuildCommandPlan (SandboxManagerRequest {
284+ WorkspaceRoot : workspace ,
285+ Command : CommandSpec {Name : "/bin/sh" , Args : []string {"-c" , "true" }, Dir : workspace },
286+ Policy : policy ,
287+ Profile : PermissionProfileFromPolicy (workspace , policy , nil ),
288+ Preference : SandboxPreferenceAuto ,
289+ ValidateExecution : true ,
290+ })
291+ if err == nil || ! strings .Contains (err .Error (), "inside a shell-writable root" ) {
292+ t .Fatalf ("BuildCommandPlan error = %v, want macOS writable-token failure" , err )
293+ }
294+ }
295+
296+ func TestProtectedCredentialInWritableMacOSRootMatchesSeatbeltWrites (t * testing.T ) {
297+ restricted := PermissionProfile {FileSystem : FileSystemPolicy {
298+ Kind : FileSystemRestricted ,
299+ WriteRoots : []WritableRoot {{Root : "/Users/Test/Workspace" }},
300+ }}
301+ if ! protectedCredentialInWritableMacOSRoot (restricted , []string {"/users/test/workspace/token" }) {
302+ t .Fatal ("case-variant token under a macOS write root should be rejected" )
303+ }
304+ if protectedCredentialInWritableMacOSRoot (restricted , []string {"/Users/Test/Credentials/token" }) {
305+ t .Fatal ("token outside every macOS write root should remain allowed" )
306+ }
307+ restricted .FileSystem .AllowTemp = true
308+ if ! protectedCredentialInWritableMacOSRoot (restricted , []string {"/private/tmp/bridge-token" }) {
309+ t .Fatal ("token under an allowed temporary root should be rejected" )
310+ }
311+ unrestricted := PermissionProfile {FileSystem : FileSystemPolicy {Kind : FileSystemUnrestricted }}
312+ if ! protectedCredentialInWritableMacOSRoot (unrestricted , []string {"/credentials/token" }) {
313+ t .Fatal ("an unrestricted macOS filesystem makes every token path shell-writable" )
314+ }
315+
316+ writable := t .TempDir ()
317+ targetDir := t .TempDir ()
318+ target := filepath .Join (targetDir , "token" )
319+ if err := os .WriteFile (target , []byte ("secret" ), 0o600 ); err != nil {
320+ t .Fatal (err )
321+ }
322+ link := filepath .Join (writable , "token-link" )
323+ if err := os .Symlink (target , link ); err != nil {
324+ t .Skipf ("symlinks unavailable: %v" , err )
325+ }
326+ symlinkProfile := PermissionProfile {FileSystem : FileSystemPolicy {
327+ Kind : FileSystemRestricted ,
328+ WriteRoots : []WritableRoot {{Root : writable }},
329+ }}
330+ if ! protectedCredentialInWritableMacOSRoot (symlinkProfile , []string {link , target }) {
331+ t .Fatal ("selected symlink inside a write root must be rejected even when its target is outside" )
332+ }
333+ }
334+
335+ func TestSandboxManagerLeavesProtectedTokenShellOpenWhenSandboxDisabled (t * testing.T ) {
336+ t .Setenv (daemonRemoteTokenEnv , "" )
337+ t .Setenv (daemonRemoteTokenFileEnv , "/workspace/bridge-token" )
338+ policy := DefaultPolicy ()
339+ policy .Mode = ModeDisabled
340+ backend := Backend {Name : BackendUnavailable , Platform : "darwin" , Fallback : true , Message : "native sandbox unavailable" }
341+ request , err := NewSandboxManager (SandboxManagerOptions {GOOS : "darwin" , Backend : backend }).BuildExecutionRequest (SandboxManagerRequest {
342+ WorkspaceRoot : "/workspace" ,
343+ Command : CommandSpec {Name : "/bin/sh" , Args : []string {"-c" , "true" }, Dir : "/workspace" },
344+ Policy : policy ,
345+ Profile : PermissionProfileFromPolicy ("/workspace" , policy , nil ),
346+ Preference : SandboxPreferenceAuto ,
347+ ValidateExecution : true ,
348+ })
349+ if err != nil {
350+ t .Fatalf ("BuildExecutionRequest disabled policy: %v" , err )
351+ }
352+ if request .EnforcementLevel != EnforcementDisabled || request .CommandWrapped {
353+ t .Fatalf ("disabled request = %#v, want intentionally open shell" , request )
354+ }
355+
356+ policy = DefaultPolicy ()
357+ request , err = NewSandboxManager (SandboxManagerOptions {GOOS : "darwin" , Backend : backend }).BuildExecutionRequest (SandboxManagerRequest {
358+ WorkspaceRoot : "/workspace" ,
359+ Command : CommandSpec {Name : "/bin/sh" , Args : []string {"-c" , "true" }, Dir : "/workspace" },
360+ Policy : policy ,
361+ Profile : PermissionProfileFromPolicy ("/workspace" , policy , nil ),
362+ Preference : SandboxPreferenceForbid ,
363+ ValidateExecution : true ,
364+ })
365+ if err != nil {
366+ t .Fatalf ("BuildExecutionRequest forbidden sandbox preference: %v" , err )
367+ }
368+ if request .EnforcementLevel != EnforcementDisabled || request .CommandWrapped {
369+ t .Fatalf ("forbidden-sandbox request = %#v, want intentionally open shell" , request )
370+ }
371+ }
372+
253373func TestSandboxManagerSelectsPlatformBackend (t * testing.T ) {
254374 tests := []struct {
255375 name string
0 commit comments