Skip to content
Closed
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
8 changes: 8 additions & 0 deletions .changeset/patch-add-tests-smoke-copilot-safe-inputs.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .changeset/patch-test-smoke-copilot-safe-inputs.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions .github/workflows/daily-team-status.lock.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14,590 changes: 7,510 additions & 7,080 deletions .github/workflows/go-file-size-reduction-project64.campaign.g.lock.yml

Large diffs are not rendered by default.

14,590 changes: 7,510 additions & 7,080 deletions .github/workflows/go-file-size-reduction.campaign.g.lock.yml

Large diffs are not rendered by default.

1,689 changes: 188 additions & 1,501 deletions .github/workflows/smoke-copilot-safe-inputs.lock.yml

Large diffs are not rendered by default.

8 changes: 0 additions & 8 deletions .github/workflows/smoke-copilot-safe-inputs.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ network:
- defaults
- node
- github
sandbox:
agent: false # Firewall disabled (migrated from network.firewall)
imports:
- shared/gh.md
tools:
Expand All @@ -31,10 +29,6 @@ tools:
safe-outputs:
add-comment:
hide-older-comments: true
create-issue:
expires: 1d
add-labels:
allowed: [smoke-copilot]
strict: true
---

Expand All @@ -56,5 +50,3 @@ Add a **very brief** comment (max 5-10 lines) to the current pull request with:
- PR titles only (no descriptions)
- ✅ or ❌ for each test result
- Overall status: PASS or FAIL

If all tests pass, add the label `smoke-copilot` to the pull request.
5 changes: 5 additions & 0 deletions pkg/workflow/compiler_parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,11 @@ func (c *Compiler) ParseWorkflowFile(markdownPath string) (*WorkflowData, error)
workflowData.SafeInputs = c.mergeSafeInputs(workflowData.SafeInputs, importsResult.MergedSafeInputs)
}

// NOTE: Do NOT inject proxy environment variables for safe-inputs tools when firewall is enabled.
// Safe-inputs tools run inside the AWF container and should access allowed domains directly.
// AWF handles domain filtering, and setting HTTP_PROXY/HTTPS_PROXY would force tools to
// route through Squid proxy even for allowed domains, causing TLS handshake failures.

// Extract safe-jobs from safe-outputs.jobs location
topSafeJobs := extractSafeJobsFromFrontmatter(result.Frontmatter)

Expand Down
26 changes: 26 additions & 0 deletions pkg/workflow/safe_inputs.go
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,32 @@ func collectSafeInputsSecrets(safeInputs *SafeInputsConfig) map[string]string {
return secrets
}

// injectFirewallProxyEnv adds proxy environment variables to all safe-inputs tools
// when the firewall is enabled. This allows tools to use the Squid proxy explicitly.
func injectFirewallProxyEnv(safeInputs *SafeInputsConfig, squidIP string, squidPort string) {
if safeInputs == nil || len(safeInputs.Tools) == 0 {
return
}

proxyURL := "http://" + squidIP + ":" + squidPort

// Add proxy environment variables to each tool
for _, toolConfig := range safeInputs.Tools {
if toolConfig.Env == nil {
toolConfig.Env = make(map[string]string)
}

// Add uppercase variants only to avoid GitHub Actions env block conflicts
// (GitHub Actions treats env var names as case-insensitive)
// The MCP server will pass these to tools, which will have both uppercase
// and lowercase variants available in their process environment
toolConfig.Env["HTTP_PROXY"] = proxyURL
toolConfig.Env["HTTPS_PROXY"] = proxyURL
}

safeInputsLog.Printf("Injected firewall proxy environment variables (%s) into %d safe-inputs tools", proxyURL, len(safeInputs.Tools))
}

// renderSafeInputsMCPConfigWithOptions generates the Safe Inputs MCP server configuration with engine-specific options
// Supports both HTTP and stdio transport modes
func renderSafeInputsMCPConfigWithOptions(yaml *strings.Builder, safeInputs *SafeInputsConfig, isLast bool, includeCopilotFields bool) {
Expand Down
85 changes: 85 additions & 0 deletions pkg/workflow/safe_inputs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -671,6 +671,91 @@ func TestGenerateSafeInputsMCPServerScript(t *testing.T) {
}
}

func TestInjectFirewallProxyEnv(t *testing.T) {
t.Run("injects proxy env vars into all tools", func(t *testing.T) {
config := &SafeInputsConfig{
Tools: map[string]*SafeInputToolConfig{
"gh": {
Name: "gh",
Description: "GitHub CLI",
Env: map[string]string{
"GH_TOKEN": "${{ secrets.GITHUB_TOKEN }}",
},
},
"npm": {
Name: "npm",
Description: "NPM tool",
Env: map[string]string{},
},
},
}

injectFirewallProxyEnv(config, "172.30.0.10", "3128")

// Check gh tool has proxy vars (uppercase only) plus original env var
ghTool := config.Tools["gh"]
if ghTool.Env["HTTP_PROXY"] != "http://172.30.0.10:3128" {
t.Errorf("Expected HTTP_PROXY to be set, got %s", ghTool.Env["HTTP_PROXY"])
}
if ghTool.Env["HTTPS_PROXY"] != "http://172.30.0.10:3128" {
t.Errorf("Expected HTTPS_PROXY to be set, got %s", ghTool.Env["HTTPS_PROXY"])
}
// Lowercase variants should NOT be set (to avoid GitHub Actions env conflicts)
if _, exists := ghTool.Env["http_proxy"]; exists {
t.Error("Expected http_proxy NOT to be set (lowercase conflicts with uppercase in GitHub Actions)")
}
if _, exists := ghTool.Env["https_proxy"]; exists {
t.Error("Expected https_proxy NOT to be set (lowercase conflicts with uppercase in GitHub Actions)")
}
if ghTool.Env["GH_TOKEN"] != "${{ secrets.GITHUB_TOKEN }}" {
t.Error("Expected original GH_TOKEN env var to be preserved")
}

// Check npm tool has proxy vars (uppercase only)
npmTool := config.Tools["npm"]
if npmTool.Env["HTTP_PROXY"] != "http://172.30.0.10:3128" {
t.Errorf("Expected HTTP_PROXY to be set, got %s", npmTool.Env["HTTP_PROXY"])
}
if npmTool.Env["HTTPS_PROXY"] != "http://172.30.0.10:3128" {
t.Errorf("Expected HTTPS_PROXY to be set, got %s", npmTool.Env["HTTPS_PROXY"])
}
})

t.Run("handles nil config", func(t *testing.T) {
injectFirewallProxyEnv(nil, "172.30.0.10", "3128")
// Should not panic
})

t.Run("handles empty tools", func(t *testing.T) {
config := &SafeInputsConfig{
Tools: map[string]*SafeInputToolConfig{},
}
injectFirewallProxyEnv(config, "172.30.0.10", "3128")
// Should not panic
})

t.Run("initializes env map if nil", func(t *testing.T) {
config := &SafeInputsConfig{
Tools: map[string]*SafeInputToolConfig{
"test": {
Name: "test",
Env: nil, // No env map
},
},
}

injectFirewallProxyEnv(config, "172.30.0.10", "3128")

testTool := config.Tools["test"]
if testTool.Env == nil {
t.Error("Expected Env map to be initialized")
}
if testTool.Env["HTTP_PROXY"] != "http://172.30.0.10:3128" {
t.Error("Expected HTTP_PROXY to be set after initializing Env map")
}
})
}

func TestGenerateSafeInputsToolsConfigWithEnv(t *testing.T) {
config := &SafeInputsConfig{
Tools: map[string]*SafeInputToolConfig{
Expand Down
Loading