Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 22 additions & 14 deletions .github/workflows/smoke-agent-all-merged.lock.yml

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions .github/workflows/smoke-agent-all-merged.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ permissions:
sandbox:
agent:
id: awf
runtime: cloud-hypervisor
sudo: false
name: "Smoke Agent: all/merged"
engine: claude
Expand Down
107 changes: 58 additions & 49 deletions .github/workflows/smoke-gemini.lock.yml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion .github/workflows/smoke-gemini.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ engine:
id: gemini
strict: true
imports:
- shared/gh.md
- shared/reporting-otlp.md
- shared/otlp.md
- shared/token-telemetry-check.md
Expand Down Expand Up @@ -79,6 +78,7 @@ evals:
sandbox:
agent:
id: awf
runtime: cloud-hypervisor
sudo: false
---

Expand Down
29 changes: 16 additions & 13 deletions .github/workflows/smoke-test-tools.lock.yml

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions .github/workflows/smoke-test-tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ features:
sandbox:
agent:
id: awf
runtime: cloud-hypervisor
sudo: false
---

Expand Down
1 change: 1 addition & 0 deletions pkg/workflow/compiler_orchestrator_engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,7 @@ func (c *Compiler) runPostEngineValidations(
enableFirewallByDefaultForCopilot(engineSetting, networkPermissions, sandboxConfig)
enableFirewallByDefaultForClaude(engineSetting, networkPermissions, sandboxConfig)
enableFirewallByDefaultForPi(engineSetting, networkPermissions, sandboxConfig)
enableFirewallByDefaultForGemini(engineSetting, networkPermissions, sandboxConfig)
return c.withEffectiveStrictMode(frontmatter, func() error {
orchestratorEngineLog.Printf("Validating strict firewall (strict=%v)", c.strictMode)
if err := c.validateStrictFirewall(engineSetting, networkPermissions, sandboxConfig); err != nil {
Expand Down
16 changes: 16 additions & 0 deletions pkg/workflow/firewall.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,22 @@ func enableFirewallByDefaultForPi(engineID string, networkPermissions *NetworkPe
enableFirewallByDefaultForEngine(engineID, networkPermissions, sandboxConfig)
}

// enableFirewallByDefaultForGemini enables firewall by default for Gemini engine
// when network restrictions are present but no explicit firewall configuration exists
// and sandbox.agent is not explicitly set to false
//
// The firewall is enabled by default for Gemini UNLESS:
// - allowed contains "*" (unrestricted network access)
// - sandbox.agent is explicitly set to false
func enableFirewallByDefaultForGemini(engineID string, networkPermissions *NetworkPermissions, sandboxConfig *SandboxConfig) {
// Only apply to gemini engine
if engineID != string(constants.GeminiEngine) {
return
}

enableFirewallByDefaultForEngine(engineID, networkPermissions, sandboxConfig)
}

// enableFirewallByDefaultForEngine enables firewall by default for a given engine
// when network restrictions are present but no explicit firewall configuration exists
// and no SRT sandbox is configured (SRT and AWF are mutually exclusive)
Expand Down
51 changes: 51 additions & 0 deletions pkg/workflow/firewall_default_enablement_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,57 @@ func TestEnableFirewallByDefaultForCopilot(t *testing.T) {
})
}

// TestEnableFirewallByDefaultForGemini tests the automatic firewall enablement for the gemini engine.
func TestEnableFirewallByDefaultForGemini(t *testing.T) {
t.Run("gemini engine with network restrictions enables firewall by default", func(t *testing.T) {
networkPerms := &NetworkPermissions{
Allowed: []string{"example.com"},
ExplicitlyDefined: true,
}

enableFirewallByDefaultForGemini("gemini", networkPerms, nil)

if networkPerms.Firewall == nil {
t.Fatal("Expected firewall to be enabled by default for gemini engine with network restrictions")
}

if !networkPerms.Firewall.Enabled {
t.Error("Expected firewall.Enabled to be true")
}
})

t.Run("non-gemini engine does not enable firewall", func(t *testing.T) {
networkPerms := &NetworkPermissions{
Allowed: []string{"example.com"},
ExplicitlyDefined: true,
}

enableFirewallByDefaultForGemini("claude", networkPerms, nil)

if networkPerms.Firewall != nil {
t.Error("Expected firewall to remain nil for non-gemini engine")
}
})

t.Run("wildcard allowed domain skips auto-enablement", func(t *testing.T) {
networkPerms := &NetworkPermissions{
Allowed: []string{"*"},
ExplicitlyDefined: true,
}

enableFirewallByDefaultForGemini("gemini", networkPerms, nil)

if networkPerms.Firewall != nil {
t.Error("Expected firewall to remain nil when wildcard '*' is in allowed domains")
}
})

t.Run("nil network permissions does not cause error", func(t *testing.T) {
// Should not panic
enableFirewallByDefaultForGemini("gemini", nil, nil)
})
}

// TestCopilotFirewallDefaultIntegration tests the integration with workflow compilation
func TestCopilotFirewallDefaultIntegration(t *testing.T) {
t.Run("copilot workflow with network restrictions includes AWF installation", func(t *testing.T) {
Expand Down
7 changes: 5 additions & 2 deletions pkg/workflow/testdata/TestWasmGolden_AllEngines/gemini.golden
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ jobs:
GH_AW_SETUP_WORKFLOW_NAME: "engine-gemini-test"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/workflow.lock.yml@${{ github.ref }}
GH_AW_INFO_VERSION: "0.55.1"
GH_AW_INFO_AWF_VERSION: "vAWF_VERSION"
GH_AW_INFO_ENGINE_ID: "gemini"
- name: Generate agentic run info
id: generate_aw_info
Expand All @@ -78,8 +79,8 @@ jobs:
GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true"
GH_AW_INFO_STAGED: "false"
GH_AW_INFO_ALLOWED_DOMAINS: '["defaults"]'
GH_AW_INFO_FIREWALL_ENABLED: "false"
GH_AW_INFO_AWF_VERSION: ""
GH_AW_INFO_FIREWALL_ENABLED: "true"
GH_AW_INFO_AWF_VERSION: "vAWF_VERSION"
GH_AW_INFO_AWMG_VERSION: ""
GH_AW_INFO_FIREWALL_TYPE: "squid"
GH_AW_INFO_AGENT_RUNTIME: ""
Expand Down Expand Up @@ -327,6 +328,7 @@ jobs:
GH_AW_SETUP_WORKFLOW_NAME: "engine-gemini-test"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/workflow.lock.yml@${{ github.ref }}
GH_AW_INFO_VERSION: "0.55.1"
GH_AW_INFO_AWF_VERSION: "vAWF_VERSION"
GH_AW_INFO_ENGINE_ID: "gemini"
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
Expand Down Expand Up @@ -663,6 +665,7 @@ jobs:
GH_AW_SETUP_WORKFLOW_NAME: "engine-gemini-test"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/workflow.lock.yml@${{ github.ref }}
GH_AW_INFO_VERSION: "0.55.1"
GH_AW_INFO_AWF_VERSION: "vAWF_VERSION"
GH_AW_INFO_ENGINE_ID: "gemini"
- name: Check team membership for workflow
id: check_membership
Expand Down
Loading