diff --git a/docs/src/content/docs/reference/sandbox.md b/docs/src/content/docs/reference/sandbox.md index 0495a0b622..9cba687f66 100644 --- a/docs/src/content/docs/reference/sandbox.md +++ b/docs/src/content/docs/reference/sandbox.md @@ -89,7 +89,7 @@ network: #### Chroot Mode -AWF v0.13.1+ uses **chroot mode** (`--enable-chroot`) to provide transparent host filesystem access while maintaining network isolation via iptables. This eliminates explicit volume mounts and environment variable configuration. +AWF v0.15.0+ uses **chroot mode by default** to provide transparent host filesystem access while maintaining network isolation via iptables. This eliminates explicit volume mounts and environment variable configuration. ```text ┌─────────────────────────────────────────────┐ diff --git a/pkg/workflow/claude_engine.go b/pkg/workflow/claude_engine.go index f2741d943d..8dcf71639b 100644 --- a/pkg/workflow/claude_engine.go +++ b/pkg/workflow/claude_engine.go @@ -270,12 +270,10 @@ func (e *ClaudeEngine) GetExecutionSteps(workflowData *WorkflowData, logFile str // Get allowed domains (Claude defaults + network permissions + HTTP MCP server URLs + runtime ecosystem domains) allowedDomains := GetClaudeAllowedDomainsWithToolsAndRuntimes(workflowData.NetworkPermissions, workflowData.Tools, workflowData.Runtimes) - // Build AWF arguments: enable-chroot mode + standard flags + custom args from config - // AWF v0.13.1+ chroot mode provides transparent access to host binaries and environment - // while maintaining network isolation, eliminating the need for explicit mounts and env flags + // Build AWF arguments: standard flags + custom args from config + // AWF v0.15.0+ uses chroot mode by default, providing transparent access to host binaries + // and environment while maintaining network isolation var awfArgs []string - awfArgs = append(awfArgs, "--enable-chroot") - claudeLog.Print("Enabled chroot mode for transparent host access") // TTY is required for Claude Code CLI awfArgs = append(awfArgs, "--tty") diff --git a/pkg/workflow/codex_engine.go b/pkg/workflow/codex_engine.go index 876a789e51..fc93bac545 100644 --- a/pkg/workflow/codex_engine.go +++ b/pkg/workflow/codex_engine.go @@ -194,12 +194,10 @@ func (e *CodexEngine) GetExecutionSteps(workflowData *WorkflowData, logFile stri // Get allowed domains (Codex defaults + network permissions + HTTP MCP server URLs + runtime ecosystem domains) allowedDomains := GetCodexAllowedDomainsWithToolsAndRuntimes(workflowData.NetworkPermissions, workflowData.Tools, workflowData.Runtimes) - // Build AWF arguments: enable-chroot mode + standard flags + custom args from config - // AWF v0.13.1+ chroot mode provides transparent access to host binaries and environment - // while maintaining network isolation, eliminating the need for explicit mounts and env flags + // Build AWF arguments: standard flags + custom args from config + // AWF v0.15.0+ uses chroot mode by default, providing transparent access to host binaries + // and environment while maintaining network isolation var awfArgs []string - awfArgs = append(awfArgs, "--enable-chroot") - codexEngineLog.Print("Enabled chroot mode for transparent host access") // Pass all environment variables to the container awfArgs = append(awfArgs, "--env-all") @@ -279,7 +277,7 @@ func (e *CodexEngine) GetExecutionSteps(workflowData *WorkflowData, logFile stri // INSTRUCTION reading is done inside the AWF command to avoid Docker Compose interpolation // issues with $ characters in the prompt. // - // AWF with --enable-chroot and --env-all handles most PATH setup natively: + // AWF v0.15.0+ with --env-all handles most PATH setup natively (chroot mode is default): // - GOROOT, JAVA_HOME, etc. are handled via AWF_HOST_PATH and entrypoint.sh // However, npm-installed CLIs (like codex) need hostedtoolcache bin directories in PATH. npmPathSetup := GetNpmBinPathSetup() diff --git a/pkg/workflow/copilot_engine_execution.go b/pkg/workflow/copilot_engine_execution.go index ac2270e4fa..592d75c627 100644 --- a/pkg/workflow/copilot_engine_execution.go +++ b/pkg/workflow/copilot_engine_execution.go @@ -255,12 +255,10 @@ func (e *CopilotEngine) GetExecutionSteps(workflowData *WorkflowData, logFile st // Get allowed domains (copilot defaults + network permissions + HTTP MCP server URLs + runtime ecosystem domains) allowedDomains := GetCopilotAllowedDomainsWithToolsAndRuntimes(workflowData.NetworkPermissions, workflowData.Tools, workflowData.Runtimes) - // Build AWF arguments: enable-chroot mode + standard flags + custom args from config - // AWF v0.13.1+ chroot mode provides transparent access to host binaries and environment - // while maintaining network isolation, eliminating the need for explicit mounts and env flags + // Build AWF arguments: standard flags + custom args from config + // AWF v0.15.0+ uses chroot mode by default, providing transparent access to host binaries + // and environment while maintaining network isolation var awfArgs []string - awfArgs = append(awfArgs, "--enable-chroot") - copilotExecLog.Print("Enabled chroot mode for transparent host access") // Pass all environment variables to the container awfArgs = append(awfArgs, "--env-all") @@ -340,7 +338,7 @@ func (e *CopilotEngine) GetExecutionSteps(workflowData *WorkflowData, logFile st // AWF v0.2.0 uses -- to separate AWF args from the actual command // The command arguments should be passed as individual shell arguments, not as a single string // - // AWF with --enable-chroot and --env-all handles PATH natively: + // AWF v0.15.0+ with --env-all handles PATH natively (chroot mode is default): // 1. Captures host PATH → AWF_HOST_PATH (already has correct ordering from actions/setup-*) // 2. Passes ALL host env vars including JAVA_HOME, DOTNET_ROOT, GOROOT // 3. entrypoint.sh exports PATH="${AWF_HOST_PATH}" and tool-specific vars diff --git a/pkg/workflow/firewall_args_test.go b/pkg/workflow/firewall_args_test.go index 1aece4e90c..09c548ed14 100644 --- a/pkg/workflow/firewall_args_test.go +++ b/pkg/workflow/firewall_args_test.go @@ -33,9 +33,9 @@ func TestFirewallArgsInCopilotEngine(t *testing.T) { stepContent := strings.Join(steps[0], "\n") - // Check that the command contains --enable-chroot for AWF v0.13.1+ chroot mode - if !strings.Contains(stepContent, "awf --enable-chroot") { - t.Error("Expected command to contain 'awf --enable-chroot'") + // Check that the command contains awf (AWF v0.15.0+ uses chroot mode by default) + if !strings.Contains(stepContent, "sudo -E awf") { + t.Error("Expected command to contain 'sudo -E awf'") } if !strings.Contains(stepContent, "--allow-domains") { @@ -150,15 +150,15 @@ func TestFirewallArgsInCopilotEngine(t *testing.T) { stepContent := strings.Join(steps[0], "\n") - // Check that --enable-chroot is used for transparent host access (AWF v0.13.1+) - // This replaces the need for explicit binary mounts like --mount /usr/bin/gh:/usr/bin/gh:ro - if !strings.Contains(stepContent, "--enable-chroot") { - t.Error("Expected AWF command to contain '--enable-chroot' for transparent host access") + // Check that AWF is used for transparent host access (AWF v0.15.0+) + // Chroot mode is now the default, so no --enable-chroot flag is needed + if !strings.Contains(stepContent, "sudo -E awf") { + t.Error("Expected AWF command for transparent host access") } - // Verify that individual binary mounts are no longer used (replaced by chroot) + // Verify that individual binary mounts are not used (chroot mode is default) if strings.Contains(stepContent, "--mount /usr/bin/gh:/usr/bin/gh:ro") { - t.Error("Individual binary mounts should be replaced by --enable-chroot mode") + t.Error("Individual binary mounts should not be present with default chroot mode") } }) diff --git a/pkg/workflow/gh_cli_mount_test.go b/pkg/workflow/gh_cli_mount_test.go index d1e5ac92ba..e15e190857 100644 --- a/pkg/workflow/gh_cli_mount_test.go +++ b/pkg/workflow/gh_cli_mount_test.go @@ -7,9 +7,9 @@ import ( "testing" ) -// TestChrootModeInAWFContainer tests that AWF uses --enable-chroot mode for transparent host access +// TestChrootModeInAWFContainer tests that AWF uses chroot mode (default in v0.15.0+) for transparent host access func TestChrootModeInAWFContainer(t *testing.T) { - t.Run("chroot mode is enabled when firewall is enabled", func(t *testing.T) { + t.Run("chroot mode is enabled by default when firewall is enabled", func(t *testing.T) { workflowData := &WorkflowData{ Name: "test-workflow", EngineConfig: &EngineConfig{ @@ -31,9 +31,9 @@ func TestChrootModeInAWFContainer(t *testing.T) { stepContent := strings.Join(steps[0], "\n") - // Check that --enable-chroot is used instead of individual binary mounts - if !strings.Contains(stepContent, "--enable-chroot") { - t.Error("Expected AWF command to contain '--enable-chroot' for transparent host access") + // Check that AWF is used (chroot mode is default in v0.15.0+) + if !strings.Contains(stepContent, "sudo -E awf") { + t.Error("Expected AWF command for transparent host access") } }) @@ -63,11 +63,6 @@ func TestChrootModeInAWFContainer(t *testing.T) { if strings.Contains(stepContent, "awf") { t.Error("Expected no AWF command when firewall is disabled") } - - // Check that --enable-chroot is not present - if strings.Contains(stepContent, "--enable-chroot") { - t.Error("Expected no --enable-chroot when firewall is disabled") - } }) t.Run("chroot mode replaces individual binary mounts", func(t *testing.T) { @@ -92,12 +87,12 @@ func TestChrootModeInAWFContainer(t *testing.T) { stepContent := strings.Join(steps[0], "\n") - // Verify --enable-chroot is present - if !strings.Contains(stepContent, "--enable-chroot") { - t.Error("Expected --enable-chroot to be present") + // Verify AWF is present (chroot mode is default in v0.15.0+) + if !strings.Contains(stepContent, "sudo -E awf") { + t.Error("Expected AWF to be present") } - // Verify individual binary mounts are NOT present (replaced by chroot) + // Verify individual binary mounts are NOT present (replaced by default chroot mode) individualMounts := []string{ "--mount /usr/bin/gh:/usr/bin/gh:ro", "--mount /usr/bin/cat:/usr/bin/cat:ro", @@ -108,7 +103,7 @@ func TestChrootModeInAWFContainer(t *testing.T) { for _, mount := range individualMounts { if strings.Contains(stepContent, mount) { - t.Errorf("Individual mount '%s' should be replaced by --enable-chroot mode", mount) + t.Errorf("Individual mount '%s' should be replaced by default chroot mode", mount) } } }) @@ -136,9 +131,9 @@ func TestChrootModeInAWFContainer(t *testing.T) { stepContent := strings.Join(steps[0], "\n") - // Verify both --enable-chroot and custom args are present - if !strings.Contains(stepContent, "--enable-chroot") { - t.Error("Expected --enable-chroot to be present with custom firewall args") + // Verify AWF is present with custom args (chroot mode is default in v0.15.0+) + if !strings.Contains(stepContent, "sudo -E awf") { + t.Error("Expected AWF to be present with custom firewall args") } if !strings.Contains(stepContent, "--custom-flag") { @@ -174,12 +169,7 @@ func TestChrootModeInAWFContainer(t *testing.T) { stepContent := strings.Join(steps[0], "\n") - // Verify --enable-chroot is present - if !strings.Contains(stepContent, "--enable-chroot") { - t.Error("Expected --enable-chroot to be present when using AWF") - } - - // Verify AWF is being used + // Verify AWF is being used (chroot mode is default in v0.15.0+) if !strings.Contains(stepContent, "awf") { t.Error("Expected AWF to be used when firewall is enabled") } @@ -210,9 +200,9 @@ func TestChrootModeEnvFlags(t *testing.T) { stepContent := strings.Join(steps[0], "\n") - // Verify --enable-chroot is present (provides transparent host access) - if !strings.Contains(stepContent, "--enable-chroot") { - t.Error("Expected --enable-chroot to be present") + // Verify AWF is present (chroot mode is default in v0.15.0+) + if !strings.Contains(stepContent, "sudo -E awf") { + t.Error("Expected AWF to be present") } // Verify --env-all IS used (required for AWF to receive host environment variables) diff --git a/pkg/workflow/sandbox_mounts_test.go b/pkg/workflow/sandbox_mounts_test.go index 17e0022d4c..30e224d640 100644 --- a/pkg/workflow/sandbox_mounts_test.go +++ b/pkg/workflow/sandbox_mounts_test.go @@ -279,9 +279,9 @@ func TestCopilotEngineWithCustomMounts(t *testing.T) { t.Error("Expected command to contain custom mount '--mount /usr/local/bin/custom-tool:/usr/local/bin/custom-tool:ro'") } - // Verify --enable-chroot is present (replaces standard mounts) - if !strings.Contains(stepContent, "--enable-chroot") { - t.Error("Expected command to contain '--enable-chroot' for transparent host access") + // Verify AWF is present (chroot mode is default in v0.15.0+) + if !strings.Contains(stepContent, "sudo -E awf") { + t.Error("Expected AWF command for transparent host access") } }) @@ -307,9 +307,9 @@ func TestCopilotEngineWithCustomMounts(t *testing.T) { stepContent := strings.Join(steps[0], "\n") - // Verify --enable-chroot is present (provides transparent host access) - if !strings.Contains(stepContent, "--enable-chroot") { - t.Error("Expected command to contain '--enable-chroot' for transparent host access") + // Verify AWF is present (chroot mode is default in v0.15.0+) + if !strings.Contains(stepContent, "sudo -E awf") { + t.Error("Expected AWF command for transparent host access") } // Custom mount should not be present