From 38ae87e29235ea146484348a0f1a1f81b5e4b585 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 2 Jan 2026 16:10:25 +0000 Subject: [PATCH 1/3] Security fix: Prevent path traversal in workflow description reader MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add path sanitization using filepath.Clean() - Validate that paths are absolute to prevent relative path traversal - Addresses CodeQL alert #446 (G304 - Path Traversal) Severity: MEDIUM Rule: G304 - Improper Limitation of a Pathname to a Restricted Directory 🤖 Generated with gh-aw security fix agent Triggered by: @pelikhan Workflow Run: #20661620598 --- pkg/cli/completions.go | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/pkg/cli/completions.go b/pkg/cli/completions.go index 0bcdee4cfb..b791849afa 100644 --- a/pkg/cli/completions.go +++ b/pkg/cli/completions.go @@ -16,9 +16,18 @@ var completionsLog = logger.New("cli:completions") // getWorkflowDescription extracts the description field from a workflow's frontmatter // Returns empty string if the description is not found or if there's an error reading the file func getWorkflowDescription(filepath string) string { - content, err := os.ReadFile(filepath) + // Sanitize the filepath to prevent path traversal attacks + cleanPath := filepath.Clean(filepath) + + // Verify the path is absolute to prevent relative path traversal + if !filepath.IsAbs(cleanPath) { + completionsLog.Printf("Invalid workflow file path (not absolute): %s", filepath) + return "" + } + + content, err := os.ReadFile(cleanPath) if err != nil { - completionsLog.Printf("Failed to read workflow file %s: %v", filepath, err) + completionsLog.Printf("Failed to read workflow file %s: %v", cleanPath, err) return "" } From df660457954ef0183196be79f186eee6bb3f11db Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 2 Jan 2026 16:18:18 +0000 Subject: [PATCH 2/3] Initial plan From 227b1bf137afc22e965b3088b078faa8a1a9f418 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 2 Jan 2026 16:29:51 +0000 Subject: [PATCH 3/3] fix: format and lint Go code - Fix variable shadowing in completions.go (renamed `filepath` param to `filePath`) - Fix testifylint issues in interfaces_test.go (use require.NoError for error assertions) - Remove unused context imports in test files Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- pkg/cli/compile_integration_test.go | 1 - pkg/cli/completions.go | 8 ++++---- pkg/cli/interfaces_test.go | 6 +++--- pkg/cli/run_command_test.go | 1 - 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/pkg/cli/compile_integration_test.go b/pkg/cli/compile_integration_test.go index 7439a4fa33..8801f7a4f3 100644 --- a/pkg/cli/compile_integration_test.go +++ b/pkg/cli/compile_integration_test.go @@ -4,7 +4,6 @@ package cli import ( "bytes" - "context" "io" "os" "os/exec" diff --git a/pkg/cli/completions.go b/pkg/cli/completions.go index b791849afa..d6bf390f0e 100644 --- a/pkg/cli/completions.go +++ b/pkg/cli/completions.go @@ -15,13 +15,13 @@ var completionsLog = logger.New("cli:completions") // getWorkflowDescription extracts the description field from a workflow's frontmatter // Returns empty string if the description is not found or if there's an error reading the file -func getWorkflowDescription(filepath string) string { +func getWorkflowDescription(filePath string) string { // Sanitize the filepath to prevent path traversal attacks - cleanPath := filepath.Clean(filepath) + cleanPath := filepath.Clean(filePath) // Verify the path is absolute to prevent relative path traversal if !filepath.IsAbs(cleanPath) { - completionsLog.Printf("Invalid workflow file path (not absolute): %s", filepath) + completionsLog.Printf("Invalid workflow file path (not absolute): %s", filePath) return "" } @@ -33,7 +33,7 @@ func getWorkflowDescription(filepath string) string { result, err := parser.ExtractFrontmatterFromContent(string(content)) if err != nil { - completionsLog.Printf("Failed to parse frontmatter from %s: %v", filepath, err) + completionsLog.Printf("Failed to parse frontmatter from %s: %v", filePath, err) return "" } diff --git a/pkg/cli/interfaces_test.go b/pkg/cli/interfaces_test.go index ad066e3a4c..74566bd465 100644 --- a/pkg/cli/interfaces_test.go +++ b/pkg/cli/interfaces_test.go @@ -27,21 +27,21 @@ func TestCommandProviderInterface(t *testing.T) { t.Run("GenBashCompletion", func(t *testing.T) { var buf bytes.Buffer err := provider.GenBashCompletion(&buf) - assert.NoError(t, err, "GenBashCompletion should not error") + require.NoError(t, err, "GenBashCompletion should not error") assert.NotEmpty(t, buf.String(), "GenBashCompletion should generate content") }) t.Run("GenZshCompletion", func(t *testing.T) { var buf bytes.Buffer err := provider.GenZshCompletion(&buf) - assert.NoError(t, err, "GenZshCompletion should not error") + require.NoError(t, err, "GenZshCompletion should not error") assert.NotEmpty(t, buf.String(), "GenZshCompletion should generate content") }) t.Run("GenFishCompletion", func(t *testing.T) { var buf bytes.Buffer err := provider.GenFishCompletion(&buf, true) - assert.NoError(t, err, "GenFishCompletion should not error") + require.NoError(t, err, "GenFishCompletion should not error") assert.NotEmpty(t, buf.String(), "GenFishCompletion should generate content") }) } diff --git a/pkg/cli/run_command_test.go b/pkg/cli/run_command_test.go index 3c73035e2c..ceaaec4290 100644 --- a/pkg/cli/run_command_test.go +++ b/pkg/cli/run_command_test.go @@ -3,7 +3,6 @@ package cli import ( - "context" "fmt" "strings" "testing"