From 6bab5dc0f63096cda5d14c85004981d030fa1b83 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 25 Mar 2026 10:47:17 +0000 Subject: [PATCH 1/2] Initial plan From 51bdac203227e48b3449a378ccf6def6a52aef56 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 25 Mar 2026 11:02:57 +0000 Subject: [PATCH 2/2] fix: exclude proxy-tls directory from agent artifact upload to prevent EACCES error The DIFC proxy creates a TLS private key at /tmp/gh-aw/proxy-logs/proxy-tls/server.key with root-only permissions (mode 600). When the agent artifact tried to upload /tmp/gh-aw/proxy-logs/, it failed with EACCES because the runner could not read this file, preventing the detection job from downloading the agent artifact. Fix: Add !/tmp/gh-aw/proxy-logs/proxy-tls/ exclusion pattern to difcProxyLogPaths() so the TLS key/cert directory is never included in the artifact upload. The TLS private key is ephemeral, not needed for debugging, and should not be uploaded. Also update isPathScannedBySecretRedaction() in the step order validator to recognize exclusion patterns (paths starting with !) as valid - they are not themselves uploaded, so they don't need to be covered by secret redaction. Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> Agent-Logs-Url: https://github.com/github/gh-aw/sessions/d543c36a-17a4-4716-ad17-fb5149cabfc1 --- .github/workflows/contribution-check.lock.yml | 1 + .github/workflows/daily-issues-report.lock.yml | 1 + .github/workflows/discussion-task-miner.lock.yml | 1 + .github/workflows/grumpy-reviewer.lock.yml | 1 + .github/workflows/issue-arborist.lock.yml | 1 + .github/workflows/issue-monster.lock.yml | 1 + .github/workflows/issue-triage-agent.lock.yml | 1 + .github/workflows/org-health-report.lock.yml | 1 + .github/workflows/plan.lock.yml | 1 + .github/workflows/pr-triage-agent.lock.yml | 1 + .github/workflows/q.lock.yml | 1 + .github/workflows/refiner.lock.yml | 1 + .github/workflows/scout.lock.yml | 1 + .github/workflows/smoke-agent-all-merged.lock.yml | 1 + .github/workflows/smoke-agent-all-none.lock.yml | 1 + .github/workflows/smoke-agent-public-approved.lock.yml | 1 + .github/workflows/smoke-agent-public-none.lock.yml | 1 + .github/workflows/smoke-agent-scoped-approved.lock.yml | 1 + .github/workflows/stale-repo-identifier.lock.yml | 1 + .github/workflows/weekly-blog-post-writer.lock.yml | 1 + .github/workflows/weekly-issue-summary.lock.yml | 1 + .../workflows/weekly-safe-outputs-spec-review.lock.yml | 1 + .github/workflows/workflow-generator.lock.yml | 1 + pkg/workflow/compiler_difc_proxy.go | 8 +++++++- pkg/workflow/compiler_difc_proxy_test.go | 5 +++-- pkg/workflow/step_order_validation.go | 6 ++++++ pkg/workflow/step_order_validation_test.go | 10 ++++++++++ 27 files changed, 49 insertions(+), 3 deletions(-) diff --git a/.github/workflows/contribution-check.lock.yml b/.github/workflows/contribution-check.lock.yml index 39499b44174..3147f34ed38 100644 --- a/.github/workflows/contribution-check.lock.yml +++ b/.github/workflows/contribution-check.lock.yml @@ -778,6 +778,7 @@ jobs: /tmp/gh-aw/redacted-urls.log /tmp/gh-aw/mcp-logs/ /tmp/gh-aw/proxy-logs/ + !/tmp/gh-aw/proxy-logs/proxy-tls/ /tmp/gh-aw/agent-stdio.log /tmp/gh-aw/agent/ /tmp/gh-aw/safeoutputs.jsonl diff --git a/.github/workflows/daily-issues-report.lock.yml b/.github/workflows/daily-issues-report.lock.yml index b31cc3594f3..cdb48e0b571 100644 --- a/.github/workflows/daily-issues-report.lock.yml +++ b/.github/workflows/daily-issues-report.lock.yml @@ -881,6 +881,7 @@ jobs: /tmp/gh-aw/redacted-urls.log /tmp/gh-aw/mcp-logs/ /tmp/gh-aw/proxy-logs/ + !/tmp/gh-aw/proxy-logs/proxy-tls/ /tmp/gh-aw/agent-stdio.log /tmp/gh-aw/agent/ /tmp/gh-aw/safeoutputs.jsonl diff --git a/.github/workflows/discussion-task-miner.lock.yml b/.github/workflows/discussion-task-miner.lock.yml index f5d9c6e7723..ec82d7f05f1 100644 --- a/.github/workflows/discussion-task-miner.lock.yml +++ b/.github/workflows/discussion-task-miner.lock.yml @@ -815,6 +815,7 @@ jobs: /tmp/gh-aw/redacted-urls.log /tmp/gh-aw/mcp-logs/ /tmp/gh-aw/proxy-logs/ + !/tmp/gh-aw/proxy-logs/proxy-tls/ /tmp/gh-aw/agent-stdio.log /tmp/gh-aw/agent/ /tmp/gh-aw/safeoutputs.jsonl diff --git a/.github/workflows/grumpy-reviewer.lock.yml b/.github/workflows/grumpy-reviewer.lock.yml index 71053a78916..ca85638d3fd 100644 --- a/.github/workflows/grumpy-reviewer.lock.yml +++ b/.github/workflows/grumpy-reviewer.lock.yml @@ -847,6 +847,7 @@ jobs: /tmp/gh-aw/redacted-urls.log /tmp/gh-aw/mcp-logs/ /tmp/gh-aw/proxy-logs/ + !/tmp/gh-aw/proxy-logs/proxy-tls/ /tmp/gh-aw/agent-stdio.log /tmp/gh-aw/agent/ /tmp/gh-aw/safeoutputs.jsonl diff --git a/.github/workflows/issue-arborist.lock.yml b/.github/workflows/issue-arborist.lock.yml index 0d663c8058b..456848ea156 100644 --- a/.github/workflows/issue-arborist.lock.yml +++ b/.github/workflows/issue-arborist.lock.yml @@ -808,6 +808,7 @@ jobs: /tmp/gh-aw/redacted-urls.log /tmp/gh-aw/mcp-logs/ /tmp/gh-aw/proxy-logs/ + !/tmp/gh-aw/proxy-logs/proxy-tls/ /tmp/gh-aw/agent-stdio.log /tmp/gh-aw/agent/ /tmp/gh-aw/safeoutputs.jsonl diff --git a/.github/workflows/issue-monster.lock.yml b/.github/workflows/issue-monster.lock.yml index 80f9e5fb243..3a4b29f10ff 100644 --- a/.github/workflows/issue-monster.lock.yml +++ b/.github/workflows/issue-monster.lock.yml @@ -1127,6 +1127,7 @@ jobs: /tmp/gh-aw/redacted-urls.log /tmp/gh-aw/mcp-logs/ /tmp/gh-aw/proxy-logs/ + !/tmp/gh-aw/proxy-logs/proxy-tls/ /tmp/gh-aw/agent-stdio.log /tmp/gh-aw/agent/ /tmp/gh-aw/safeoutputs.jsonl diff --git a/.github/workflows/issue-triage-agent.lock.yml b/.github/workflows/issue-triage-agent.lock.yml index b0ff3e98a62..1c536a92e30 100644 --- a/.github/workflows/issue-triage-agent.lock.yml +++ b/.github/workflows/issue-triage-agent.lock.yml @@ -727,6 +727,7 @@ jobs: /tmp/gh-aw/redacted-urls.log /tmp/gh-aw/mcp-logs/ /tmp/gh-aw/proxy-logs/ + !/tmp/gh-aw/proxy-logs/proxy-tls/ /tmp/gh-aw/agent-stdio.log /tmp/gh-aw/agent/ /tmp/gh-aw/safeoutputs.jsonl diff --git a/.github/workflows/org-health-report.lock.yml b/.github/workflows/org-health-report.lock.yml index 3cd34a5f5ab..ef1da2fd790 100644 --- a/.github/workflows/org-health-report.lock.yml +++ b/.github/workflows/org-health-report.lock.yml @@ -817,6 +817,7 @@ jobs: /tmp/gh-aw/redacted-urls.log /tmp/gh-aw/mcp-logs/ /tmp/gh-aw/proxy-logs/ + !/tmp/gh-aw/proxy-logs/proxy-tls/ /tmp/gh-aw/agent-stdio.log /tmp/gh-aw/agent/ /tmp/gh-aw/safeoutputs.jsonl diff --git a/.github/workflows/plan.lock.yml b/.github/workflows/plan.lock.yml index dc9e24ae9cc..bdb5a18a97a 100644 --- a/.github/workflows/plan.lock.yml +++ b/.github/workflows/plan.lock.yml @@ -819,6 +819,7 @@ jobs: /tmp/gh-aw/redacted-urls.log /tmp/gh-aw/mcp-logs/ /tmp/gh-aw/proxy-logs/ + !/tmp/gh-aw/proxy-logs/proxy-tls/ /tmp/gh-aw/agent-stdio.log /tmp/gh-aw/agent/ /tmp/gh-aw/safeoutputs.jsonl diff --git a/.github/workflows/pr-triage-agent.lock.yml b/.github/workflows/pr-triage-agent.lock.yml index e63ccc14b35..09770a545dc 100644 --- a/.github/workflows/pr-triage-agent.lock.yml +++ b/.github/workflows/pr-triage-agent.lock.yml @@ -805,6 +805,7 @@ jobs: /tmp/gh-aw/redacted-urls.log /tmp/gh-aw/mcp-logs/ /tmp/gh-aw/proxy-logs/ + !/tmp/gh-aw/proxy-logs/proxy-tls/ /tmp/gh-aw/agent-stdio.log /tmp/gh-aw/agent/ /tmp/gh-aw/safeoutputs.jsonl diff --git a/.github/workflows/q.lock.yml b/.github/workflows/q.lock.yml index e4f42a55ef9..008cc0edd42 100644 --- a/.github/workflows/q.lock.yml +++ b/.github/workflows/q.lock.yml @@ -986,6 +986,7 @@ jobs: /tmp/gh-aw/redacted-urls.log /tmp/gh-aw/mcp-logs/ /tmp/gh-aw/proxy-logs/ + !/tmp/gh-aw/proxy-logs/proxy-tls/ /tmp/gh-aw/agent-stdio.log /tmp/gh-aw/agent/ /tmp/gh-aw/safeoutputs.jsonl diff --git a/.github/workflows/refiner.lock.yml b/.github/workflows/refiner.lock.yml index 0d2a5ad0d8b..53257537d42 100644 --- a/.github/workflows/refiner.lock.yml +++ b/.github/workflows/refiner.lock.yml @@ -788,6 +788,7 @@ jobs: /tmp/gh-aw/redacted-urls.log /tmp/gh-aw/mcp-logs/ /tmp/gh-aw/proxy-logs/ + !/tmp/gh-aw/proxy-logs/proxy-tls/ /tmp/gh-aw/agent-stdio.log /tmp/gh-aw/agent/ /tmp/gh-aw/safeoutputs.jsonl diff --git a/.github/workflows/scout.lock.yml b/.github/workflows/scout.lock.yml index 432471cffe1..49e20732f56 100644 --- a/.github/workflows/scout.lock.yml +++ b/.github/workflows/scout.lock.yml @@ -1053,6 +1053,7 @@ jobs: /tmp/gh-aw/aw-prompts/prompt.txt /tmp/gh-aw/mcp-logs/ /tmp/gh-aw/proxy-logs/ + !/tmp/gh-aw/proxy-logs/proxy-tls/ /tmp/gh-aw/agent-stdio.log /tmp/gh-aw/agent/ /tmp/gh-aw/safeoutputs.jsonl diff --git a/.github/workflows/smoke-agent-all-merged.lock.yml b/.github/workflows/smoke-agent-all-merged.lock.yml index 5d804edadf2..b52601edffe 100644 --- a/.github/workflows/smoke-agent-all-merged.lock.yml +++ b/.github/workflows/smoke-agent-all-merged.lock.yml @@ -756,6 +756,7 @@ jobs: /tmp/gh-aw/redacted-urls.log /tmp/gh-aw/mcp-logs/ /tmp/gh-aw/proxy-logs/ + !/tmp/gh-aw/proxy-logs/proxy-tls/ /tmp/gh-aw/agent-stdio.log /tmp/gh-aw/agent/ /tmp/gh-aw/safeoutputs.jsonl diff --git a/.github/workflows/smoke-agent-all-none.lock.yml b/.github/workflows/smoke-agent-all-none.lock.yml index b6a4bbfd3c7..0520a2c453b 100644 --- a/.github/workflows/smoke-agent-all-none.lock.yml +++ b/.github/workflows/smoke-agent-all-none.lock.yml @@ -756,6 +756,7 @@ jobs: /tmp/gh-aw/redacted-urls.log /tmp/gh-aw/mcp-logs/ /tmp/gh-aw/proxy-logs/ + !/tmp/gh-aw/proxy-logs/proxy-tls/ /tmp/gh-aw/agent-stdio.log /tmp/gh-aw/agent/ /tmp/gh-aw/safeoutputs.jsonl diff --git a/.github/workflows/smoke-agent-public-approved.lock.yml b/.github/workflows/smoke-agent-public-approved.lock.yml index 39b07e76b8d..43b4f3ed76b 100644 --- a/.github/workflows/smoke-agent-public-approved.lock.yml +++ b/.github/workflows/smoke-agent-public-approved.lock.yml @@ -782,6 +782,7 @@ jobs: /tmp/gh-aw/redacted-urls.log /tmp/gh-aw/mcp-logs/ /tmp/gh-aw/proxy-logs/ + !/tmp/gh-aw/proxy-logs/proxy-tls/ /tmp/gh-aw/agent-stdio.log /tmp/gh-aw/agent/ /tmp/gh-aw/safeoutputs.jsonl diff --git a/.github/workflows/smoke-agent-public-none.lock.yml b/.github/workflows/smoke-agent-public-none.lock.yml index 95ad608b214..bf5ea2d9108 100644 --- a/.github/workflows/smoke-agent-public-none.lock.yml +++ b/.github/workflows/smoke-agent-public-none.lock.yml @@ -756,6 +756,7 @@ jobs: /tmp/gh-aw/redacted-urls.log /tmp/gh-aw/mcp-logs/ /tmp/gh-aw/proxy-logs/ + !/tmp/gh-aw/proxy-logs/proxy-tls/ /tmp/gh-aw/agent-stdio.log /tmp/gh-aw/agent/ /tmp/gh-aw/safeoutputs.jsonl diff --git a/.github/workflows/smoke-agent-scoped-approved.lock.yml b/.github/workflows/smoke-agent-scoped-approved.lock.yml index b5bb023a529..191cb949935 100644 --- a/.github/workflows/smoke-agent-scoped-approved.lock.yml +++ b/.github/workflows/smoke-agent-scoped-approved.lock.yml @@ -760,6 +760,7 @@ jobs: /tmp/gh-aw/redacted-urls.log /tmp/gh-aw/mcp-logs/ /tmp/gh-aw/proxy-logs/ + !/tmp/gh-aw/proxy-logs/proxy-tls/ /tmp/gh-aw/agent-stdio.log /tmp/gh-aw/agent/ /tmp/gh-aw/safeoutputs.jsonl diff --git a/.github/workflows/stale-repo-identifier.lock.yml b/.github/workflows/stale-repo-identifier.lock.yml index 882a8bd9ddb..e86db2f98e6 100644 --- a/.github/workflows/stale-repo-identifier.lock.yml +++ b/.github/workflows/stale-repo-identifier.lock.yml @@ -883,6 +883,7 @@ jobs: /tmp/gh-aw/redacted-urls.log /tmp/gh-aw/mcp-logs/ /tmp/gh-aw/proxy-logs/ + !/tmp/gh-aw/proxy-logs/proxy-tls/ /tmp/gh-aw/agent-stdio.log /tmp/gh-aw/agent/ /tmp/gh-aw/safeoutputs.jsonl diff --git a/.github/workflows/weekly-blog-post-writer.lock.yml b/.github/workflows/weekly-blog-post-writer.lock.yml index c72690b2a4b..5cad7a53b11 100644 --- a/.github/workflows/weekly-blog-post-writer.lock.yml +++ b/.github/workflows/weekly-blog-post-writer.lock.yml @@ -918,6 +918,7 @@ jobs: /tmp/gh-aw/redacted-urls.log /tmp/gh-aw/mcp-logs/ /tmp/gh-aw/proxy-logs/ + !/tmp/gh-aw/proxy-logs/proxy-tls/ /tmp/gh-aw/agent-stdio.log /tmp/gh-aw/agent/ /tmp/gh-aw/safeoutputs.jsonl diff --git a/.github/workflows/weekly-issue-summary.lock.yml b/.github/workflows/weekly-issue-summary.lock.yml index b2513f76177..bb20a7e4d05 100644 --- a/.github/workflows/weekly-issue-summary.lock.yml +++ b/.github/workflows/weekly-issue-summary.lock.yml @@ -797,6 +797,7 @@ jobs: /tmp/gh-aw/redacted-urls.log /tmp/gh-aw/mcp-logs/ /tmp/gh-aw/proxy-logs/ + !/tmp/gh-aw/proxy-logs/proxy-tls/ /tmp/gh-aw/agent-stdio.log /tmp/gh-aw/agent/ /tmp/gh-aw/safeoutputs.jsonl diff --git a/.github/workflows/weekly-safe-outputs-spec-review.lock.yml b/.github/workflows/weekly-safe-outputs-spec-review.lock.yml index 2813d479876..f2eca75fee3 100644 --- a/.github/workflows/weekly-safe-outputs-spec-review.lock.yml +++ b/.github/workflows/weekly-safe-outputs-spec-review.lock.yml @@ -737,6 +737,7 @@ jobs: /tmp/gh-aw/redacted-urls.log /tmp/gh-aw/mcp-logs/ /tmp/gh-aw/proxy-logs/ + !/tmp/gh-aw/proxy-logs/proxy-tls/ /tmp/gh-aw/agent-stdio.log /tmp/gh-aw/agent/ /tmp/gh-aw/safeoutputs.jsonl diff --git a/.github/workflows/workflow-generator.lock.yml b/.github/workflows/workflow-generator.lock.yml index 2e11528e1bd..9790125d430 100644 --- a/.github/workflows/workflow-generator.lock.yml +++ b/.github/workflows/workflow-generator.lock.yml @@ -814,6 +814,7 @@ jobs: /tmp/gh-aw/redacted-urls.log /tmp/gh-aw/mcp-logs/ /tmp/gh-aw/proxy-logs/ + !/tmp/gh-aw/proxy-logs/proxy-tls/ /tmp/gh-aw/agent-stdio.log /tmp/gh-aw/agent/ /tmp/gh-aw/safeoutputs.jsonl diff --git a/pkg/workflow/compiler_difc_proxy.go b/pkg/workflow/compiler_difc_proxy.go index c7a2846b231..23bb0d23039 100644 --- a/pkg/workflow/compiler_difc_proxy.go +++ b/pkg/workflow/compiler_difc_proxy.go @@ -276,5 +276,11 @@ func difcProxyLogPaths(data *WorkflowData) []string { } // proxy-logs/ contains TLS certs and container stderr from the proxy // (mcp-logs/ is already collected as part of standard MCP logging) - return []string{"/tmp/gh-aw/proxy-logs/"} + // Exclude proxy-tls/ because it contains the TLS private key (server.key) which is + // created by the Docker container with root-only permissions, causing artifact upload + // to fail with EACCES. The private key is ephemeral and should not be uploaded. + return []string{ + "/tmp/gh-aw/proxy-logs/", + "!/tmp/gh-aw/proxy-logs/proxy-tls/", + } } diff --git a/pkg/workflow/compiler_difc_proxy_test.go b/pkg/workflow/compiler_difc_proxy_test.go index 98823ec0ccc..03954809e1f 100644 --- a/pkg/workflow/compiler_difc_proxy_test.go +++ b/pkg/workflow/compiler_difc_proxy_test.go @@ -362,8 +362,9 @@ func TestDIFCProxyLogPaths(t *testing.T) { CustomSteps: "steps:\n - name: Fetch\n env:\n GH_TOKEN: ${{ github.token }}\n run: gh issue list", } paths := difcProxyLogPaths(data) - require.Len(t, paths, 1, "should return exactly one path") - assert.Contains(t, paths[0], "proxy-logs", "path should include proxy-logs directory") + require.Len(t, paths, 2, "should return inclusion path and proxy-tls exclusion path") + assert.Contains(t, paths[0], "proxy-logs", "first path should include proxy-logs directory") + assert.Equal(t, "!/tmp/gh-aw/proxy-logs/proxy-tls/", paths[1], "second path should exclude proxy-tls directory") }) } diff --git a/pkg/workflow/step_order_validation.go b/pkg/workflow/step_order_validation.go index d1f2d9d7764..b2e9b202a29 100644 --- a/pkg/workflow/step_order_validation.go +++ b/pkg/workflow/step_order_validation.go @@ -178,6 +178,12 @@ func (t *StepOrderTracker) findUnscannablePaths(artifactUploads []StepRecord) [] // isPathScannedBySecretRedaction checks if a path would be scanned by the secret redaction step // or is otherwise safe to upload (known engine-controlled diagnostic paths). func isPathScannedBySecretRedaction(path string) bool { + // Exclusion patterns (paths starting with !) are not uploaded - they tell the artifact + // action to skip matching files. They do not need to be scanned by secret redaction. + if strings.HasPrefix(path, "!") { + return true + } + // Paths must be under /tmp/gh-aw/ or ${RUNNER_TEMP}/gh-aw/ to be scanned. // Accept both literal paths and environment variable references. // Engines that produce output outside /tmp/gh-aw/ must move their files into /tmp/gh-aw/ diff --git a/pkg/workflow/step_order_validation_test.go b/pkg/workflow/step_order_validation_test.go index cbf977bca34..b42d1ed06de 100644 --- a/pkg/workflow/step_order_validation_test.go +++ b/pkg/workflow/step_order_validation_test.go @@ -128,6 +128,16 @@ func TestIsPathScannedBySecretRedaction_ScannableFiles(t *testing.T) { path: "${{ env.GH_AW_SAFE_OUTPUTS }}", expected: true, }, + { + name: "Exclusion pattern (proxy-tls directory)", + path: "!/tmp/gh-aw/proxy-logs/proxy-tls/", + expected: true, + }, + { + name: "Exclusion pattern (file outside /tmp/gh-aw/)", + path: "!/some/other/path/file.key", + expected: true, + }, } for _, tt := range tests {