Skip to content

[aw-compat] Add gh aw fix codemods for strict-mode secret leaks in step run and engine.env#26919

Open
Copilot wants to merge 5 commits intomainfrom
copilot/aw-compat-fix-secrets-strict-mode
Open

[aw-compat] Add gh aw fix codemods for strict-mode secret leaks in step run and engine.env#26919
Copilot wants to merge 5 commits intomainfrom
copilot/aw-compat-fix-secrets-strict-mode

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 17, 2026

Recurring aw-compat failures showed two strict-mode breakages: secrets interpolated directly in step run: commands, and secret-bearing entries in engine.env. This PR adds two codemods so gh aw fix --write can remediate both patterns automatically.

  • What changed

    • Added codemod: steps-run-secrets-to-env
      • Targets pre-steps, steps, post-steps, pre-agent-steps
      • Rewrites inline ${{ secrets.NAME }} in run: to $NAME
      • Adds/merges step-level env bindings (NAME: ${{ secrets.NAME }})
    • Added codemod: engine-env-secrets-to-engine-config
      • Removes secret-bearing engine.env keys that are unsafe under strict mode
      • Preserves required engine credential override keys
      • Removes empty engine.env blocks after pruning
  • Registry integration

    • Registered both codemods in GetAllCodemods()
    • Updated codemod count/order/registry expectations in tests
  • Example transformation

    # before
    steps:
      - name: Clone runtime
        run: git clone https://x:${{ secrets.RUNTIME_TRIAGE_TOKEN }}@github.com/org/repo.git
    
    # after
    steps:
      - name: Clone runtime
        env:
          RUNTIME_TRIAGE_TOKEN: ${{ secrets.RUNTIME_TRIAGE_TOKEN }}
        run: git clone ******github.com/org/repo.git

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • https://api.github.com/graphql
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw 6379199/b215/vetrev-parse ache/go/1.25.8/x--show-toplevel git rev-�� --show-toplevel ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet /usr/bin/git -buildid EjXw-bZiDcnvohS5rev-parse e/git git (http block)
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw sh ache/go/1.25.8/x--show-toplevel git rev-�� --show-toplevel t.wasm && \ mv gh-aw.opt.wasm gh-aw.wasm; \ AFrev-parse /usr/bin/git -json GO111MODULE ache/go/1.25.8/x--show-toplevel git (http block)
  • https://api.github.com/orgs/test-owner/actions/secrets
    • Triggering command: /usr/bin/gh gh api /orgs/test-owner/actions/secrets --jq .secrets[].name -json GO111MODULE x_amd64/compile -Oz --enable-bu/opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/vet GOMOD GOMODCACHE x_amd64/compile env -json 1.5.0/jsonrpc/js-ifaceassert x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile (http block)
    • Triggering command: /usr/bin/gh gh api /orgs/test-owner/actions/secrets --jq .secrets[].name -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env i-lint >/dev/nulGOINSECURE GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/actions/ai-inference/git/ref/tags/v1
    • Triggering command: /usr/bin/gh gh api /repos/actions/ai-inference/git/ref/tags/v1 --jq [.object.sha, .object.type] | @tsv --git-dir 64/pkg/tool/linu--jq /usr/bin/infocmp rtcfg .cfg 64/pkg/tool/linu--show-toplevel infocmp -1 xterm-color 64/pkg/tool/linu/tmp/go-build2326379199/b114/vet.cfg /usr/bin/git 126812741/.githugit .cfg 64/pkg/tool/linu--show-toplevel git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/ai-inference/git/ref/tags/v1 --jq [.object.sha, .object.type] | @tsv user.email test@example.com (http block)
  • https://api.github.com/repos/actions/checkout/git/ref/tags/v3
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v3 --jq [.object.sha, .object.type] | @tsv runs/20260417-175637-38644/test-1894266478 SPu62hh/wUwm7E1C/tmp/go-build2326379199/b272/vet-test.run=^Test ache/node/24.14.1/x64/bin/node -json GO111MODULE x_amd64/compile git t-18�� k/gh-aw/gh-aw/.github/workflows/ace-editor.md x_amd64/compile /opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/vet -json GO111MODULE x_amd64/vet /opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v3 --jq [.object.sha, .object.type] | @tsv /tmp/TestHashConsistency_GoAndJavaScript3572635073/001/test-fron.github/workflows/test.md go /usr/bin/infocmp on' --ignore-patgit GO111MODULE 64/bin/go infocmp -1 xterm-color go /usr/bin/git led-with-body-cogit GO111MODULE 64/bin/go git (http block)
  • https://api.github.com/repos/actions/checkout/git/ref/tags/v5
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq [.object.sha, .object.type] | @tsv se 6379199/b035/vet.cfg .cfg -p internal/goarch -lang=go1.25 ache/go/1.25.8/x64/pkg/tool/linustatus -o /001/inlined-a.md -trimpath ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet -p io/fs -lang=go1.25 ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq [.object.sha, .object.type] | @tsv --show-toplevel 64/pkg/tool/linux_amd64/vet /usr/bin/git 085455/b231/_pkggit 7LFx/9x5EhNlMwHDrev-parse .cfg git rev-�� --show-toplevel ache/go/1.25.8/x64/pkg/tool/linuremote /usr/bin/git RCYu/ay_SjJUFVsegit GOPROXY x_amd64/compile git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq [.object.sha, .object.type] | @tsv --show-toplevel 64/pkg/tool/linux_amd64/vet /usr/bin/git -bool .cfg /usr/bin/git git rev-�� --show-toplevel git /usr/bin/git --show-toplevel -tests ache/node/24.14.--show-toplevel git (http block)
  • https://api.github.com/repos/actions/github-script/git/ref/tags/v8
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq [.object.sha, .object.type] | @tsv --show-toplevel ger.test /usr/bin/git se 6379199/b156/vetrev-parse .cfg git rev-�� --show-toplevel ache/go/1.25.8/x-trimpath /usr/bin/git CompiledOutput32git 6379199/b254/vetrev-parse ache/go/1.25.8/x--show-toplevel git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq [.object.sha, .object.type] | @tsv --get-regexp ^remote\..*\.gh-resolved$ /usr/bin/git npx prettier --cgit GOPROXY ache/go/1.25.8/xHEAD git rev-�� --show-toplevel node /usr/bin/git --check scripts/**/*.js .cfg git (http block)
  • https://api.github.com/repos/actions/github-script/git/ref/tags/v9
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v9 --jq [.object.sha, .object.type] | @tsv -json GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile env -json GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v9 --jq [.object.sha, .object.type] | @tsv -json 1.5.0/internal/jsonrpc2/conn.go x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile env -json GO111MODULE x_amd64/vet GOINSECURE xcontext GOMODCACHE x_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v9 --jq [.object.sha, .object.type] | @tsv -json gset/set.go x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile env -json GO111MODULE x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet (http block)
  • https://api.github.com/repos/actions/setup-go/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-go/git/ref/tags/v4 --jq [.object.sha, .object.type] | @tsv --show-toplevel _3VA1bELNvSY /usr/bin/git _.a nLaxVxxol 64/pkg/tool/linu--show-toplevel git conf�� user.name Test User /usr/bin/gh le-frontmatter.mgit .cfg 64/pkg/tool/linu--show-toplevel gh (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-go/git/ref/tags/v4 --jq [.object.sha, .object.type] | @tsv --get remote.origin.url /usr/bin/git /workflows GO111MODULE 64/bin/go git rev-�� --git-dir go /usr/bin/git -json GO111MODULE 64/bin/go git (http block)
  • https://api.github.com/repos/actions/setup-node/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v4 --jq [.object.sha, .object.type] | @tsv --git-dir /tmp/go-build2326379199/b442/_testmain.go /opt/hostedtoolcache/node/24.14.1/x64/bin/node _.a GO111MODULE 64/pkg/tool/linu--show-toplevel node /tmp�� /home/REDACTED/work/gh-aw/gh-aw/.github/workflows/api-consumption-report.md 64/pkg/tool/linux_amd64/vet /usr/bin/git -json .cfg x_amd64/link /usr/bin/git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v4 --jq [.object.sha, .object.type] | @tsv add myorg /usr/bin/git /workflows GO111MODULE 64/bin/go git conf�� user.name Test User /usr/bin/git -json GO111MODULE 64/bin/go git (http block)
  • https://api.github.com/repos/actions/upload-artifact/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/upload-artifact/git/ref/tags/v4 --jq [.object.sha, .object.type] | @tsv ithub/workflows/agent-persona-explorer.md --jq (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/upload-artifact/git/ref/tags/v4 --jq [.object.sha, .object.type] | @tsv runs/20260417-181504-91024/test-1418465664/.github/workflows blob /usr/bin/git GOSUMDB GOWORK 64/bin/go git init�� --bare --initial-branch=develop e/git -json GO111MODULE 64/bin/go e/git (http block)
  • https://api.github.com/repos/github/gh-aw-actions/git/ref/tags/v0.1.2
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v0.1.2 --jq [.object.sha, .object.type] | @tsv --show-toplevel x_amd64/vet /usr/bin/git _.a LvhFNvMoO x_amd64/compile git rev-�� --show-toplevel x_amd64/compile /usr/bin/git rtcfg .cfg 64/pkg/tool/linu--show-toplevel git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v0.1.2 --jq [.object.sha, .object.type] | @tsv remove origin /usr/bin/git ub/workflows GO111MODULE 64/bin/go git rev-�� --show-toplevel go /usr/bin/git -json GO111MODULE 64/bin/go git (http block)
  • https://api.github.com/repos/github/gh-aw-actions/git/ref/tags/v1.0.0
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v1.0.0 --jq [.object.sha, .object.type] | @tsv --show-toplevel l ache/node/24.14.1/x64/bin/node -json GO111MODULE x_amd64/compile git t-37�� sistency_InlinedImports449707998/001/inlined-a.md rev-parse /usr/bin/git -json GO111MODULE x_amd64/compile git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v1.0.0 --jq [.object.sha, .object.type] | @tsv ithub-script/git/ref/tags/v9 GOPROXY bject.type] | @tsv GOSUMDB GOWORK odules/npm/node_--show-toplevel git-upload-pack /tmp�� GOMODCACHE (http block)
  • https://api.github.com/repos/github/gh-aw-actions/git/ref/tags/v1.2.3
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v1.2.3 --jq [.object.sha, .object.type] | @tsv sistency_GoAndJavaScript3666599040/001/test-frontmatter-with-nes-s -tests ache/node/24.14.1/x64/bin/node sm-opt -Oz (sizegit GO111MODULE nch,headSha,disp--show-toplevel git t-31�� sistency_KeyOrdering451067035/001/test1.md x_amd64/asm /usr/bin/git -json oken.go x_amd64/asm git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v1.2.3 --jq [.object.sha, .object.type] | @tsv runs/20260417-181504-91024/test-3925285523/custom/workflows log /usr/bin/git -n1 --format=format:rev-parse --end-of-options--show-toplevel git ls-r�� --symref origin /usr/bin/git json' --ignore-pgit GO111MODULE 64/bin/go git (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/1/artifacts
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/1/artifacts --jq .artifacts[].name GO111MODULE 64/pkg/tool/linu-nolocalimports GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linuTest User env 2825186426 hxms/bWOB0OjYPOs06SIChxms .cfg GOINSECURE g/x/text/unicoderev-parse GOMODCACHE ache/go/1.25.8/x64/pkg/tool/linu-buildtags (http block)
    • Triggering command: /usr/bin/gh gh run download 1 --dir test-logs/run-1 .cfg 64/pkg/tool/linux_amd64/vet OUTPUT hlite 085455/b013/symabis 64/pkg/tool/linux_amd64/vet env 085455/b245/_pkg_.a _zAe/m6K4S-499xrKjIdi_zAe ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet GOINSECURE t/internal/strinrev-parse GOMODCACHE ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/1/artifacts --jq .artifacts[].name GOPROXY ache/go/1.25.8/x64/bin/go GOSUMDB GOWORK 64/bin/go go env 1504-91024/test-704403190/.github/workflows GO111MODULE ache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/12345/artifacts
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/12345/artifacts --jq .artifacts[].name .cfg 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet env 085455/b202/_pkg_.a GO111MODULE ache/go/1.25.8/x64/pkg/tool/linux_amd64/compile GOINSECURE GOMOD 085455/b078/syma--show-toplevel ache/go/1.25.8/x64/pkg/tool/linux_amd64/compile (http block)
    • Triggering command: /usr/bin/gh gh run download 12345 --dir test-logs/run-12345 GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE (http block)
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/12345/artifacts --jq .artifacts[].name GOPROXY ache/go/1.25.8/x64/bin/go GOSUMDB GOWORK 64/bin/go sh -c "prettier" --check 'scripts/**/*.js' --ignore-path .prettierignoGOINSECURE sh ache/go/1.25.8/x64/bin/go tierignore go 64/bin/go go (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/12346/artifacts
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/12346/artifacts --jq .artifacts[].name .cfg 64/pkg/tool/linux_amd64/vet GOINSECURE 085455/b078/ GOMODCACHE 64/pkg/tool/linux_amd64/vet env 085455/b201/_pkg_.a GO111MODULE x_amd64/vet GOINSECURE fips140/hkdf 085455/b078/syma--show-toplevel x_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh run download 12346 --dir test-logs/run-12346 .cfg 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet env 1099620598 d2UJ/DbmGN00V4XBV3gqgd2UJ 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/12346/artifacts --jq .artifacts[].name GOPROXY 64/pkg/tool/linux_amd64/vet GOSUMDB GOWORK 64/bin/go 64/pkg/tool/linux_amd64/vet -c "prettier" --check 'scripts/**/*--detach sh d01f7065bbd23e8e35d0c85e80709bf24ecf317f372edee51bc230b601a94425-d tierignore go 64/bin/go go (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/2/artifacts
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/2/artifacts --jq .artifacts[].name .cfg 64/pkg/tool/linux_amd64/vet GOINSECURE 085455/b092/ GOMODCACHE 64/pkg/tool/linutest@example.com env 2825186426 GO111MODULE x_amd64/compile GOINSECURE g/x/net/http2/hprev-parse 085455/b092/syma--show-toplevel x_amd64/compile (http block)
    • Triggering command: /usr/bin/gh gh run download 2 --dir test-logs/run-2 .cfg 64/pkg/tool/linux_amd64/vet OUTPUT -d 168.63.129.16 64/pkg/tool/linux_amd64/vet env 085455/b178/_pkg_.a 7Ps3/Xuna8G_bMUX3GMM57Ps3 ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/2/artifacts --jq .artifacts[].name GOPROXY ache/go/1.25.8/x64/bin/go GOSUMDB GOWORK 64/bin/go go env 1504-91024/test-704403190/.github/workflows GO111MODULE .cfg GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/3/artifacts
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/3/artifacts --jq .artifacts[].name .cfg 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet env 2825186426 3cxW/IBlaqeSprCJhOYFQ3cxW 64/pkg/tool/linux_amd64/compile GOINSECURE g/x/text/secure/rev-parse GOMODCACHE 64/pkg/tool/linux_amd64/compile (http block)
    • Triggering command: /usr/bin/gh gh run download 3 --dir test-logs/run-3 .cfg 64/pkg/tool/linux_amd64/vet OUTPUT -d 085455/b007/symauser.email 64/pkg/tool/linutest@example.com ache�� 3537593456/.github/workflows GO111MODULE ck GOINSECURE b/gh-aw/pkg/semv/tmp/js-hash-test-2676963344/test-hash.js GOMODCACHE ache/go/1.25.8/x64/pkg/tool/linurev-parse (http block)
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/3/artifacts --jq .artifacts[].name efaultBranchFromLsRemoteWithRealGitmaster_branch1475764923/001' 1/x64/bin/node GOSUMDB GOWORK 64/bin/go go t-ha�� vaScript3572635073/001/test-frontmatter-with-arrays.md GO111MODULE /opt/hostedtoolcache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/4/artifacts
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/4/artifacts --jq .artifacts[].name .cfg 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet env 2825186426 GO111MODULE 64/pkg/tool/linux_amd64/link GOINSECURE able 085455/b092/syma--git-dir 64/pkg/tool/linux_amd64/link (http block)
    • Triggering command: /usr/bin/gh gh run download 4 --dir test-logs/run-4 .cfg 64/pkg/tool/linux_amd64/vet OUTPUT -d 168.63.129.16 64/pkg/tool/linux_amd64/vet env 3537593456/.github/workflows oYmy/n_pwg_VDfKQLamLkoYmy ache/go/1.25.8/x64/pkg/tool/linu-test.short=true GOINSECURE b/gh-aw/pkg/actirev-parse GOMODCACHE ache/go/1.25.8/x64/pkg/tool/linuconfig (http block)
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/4/artifacts --jq .artifacts[].name sRemoteWithRealGitmaster_branch1475764923/002/work ache/go/1.25.8/x64/bin/go GOSUMDB GOWORK run-script/lib/n--show-toplevel go env -json GO111MODULE /opt/hostedtoolcache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/5/artifacts
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/5/artifacts --jq .artifacts[].name GO111MODULE 64/pkg/tool/linu-importcfg GOINSECURE fips140 GOMODCACHE 64/pkg/tool/linu/home/REDACTED/work/gh-aw/gh-aw/pkg/timeutil/format_test.go env 2825186426 i2Jk/kxQktkbJrdZm0O72i2Jk .cfg GOINSECURE l GOMODCACHE ache/go/1.25.8/x64/pkg/tool/linu-goversion (http block)
    • Triggering command: /usr/bin/gh gh run download 5 --dir test-logs/run-5 .cfg 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linuTest User env 3537593456/.github/workflows r73k/ZR15bOYtzO_sNGC5r73k ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet GOINSECURE /semver GOMODCACHE ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/5/artifacts --jq .artifacts[].name GOPROXY ache/go/1.25.8/x64/bin/go GOSUMDB GOWORK 64/bin/go go env 1504-91024/test-3975127605/.github/workflows GO111MODULE /opt/hostedtoolcache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/github/gh-aw/actions/workflows
    • Triggering command: /usr/bin/gh gh workflow list --json name,state,path -json GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile env -json GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile (http block)
    • Triggering command: /usr/bin/gh gh run list --json databaseId,number,url,status,conclusion,workflowName,createdAt,startedAt,updatedAt,event,headBranch,headSha,displayTitle --workflow nonexistent-workflow-12345 --limit 100 GOMOD GOMODCACHE x_amd64/vet env -json GO111MODULE x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh run list --json databaseId,number,url,status,conclusion,workflowName,createdAt,startedAt,updatedAt,event,headBranch,headSha,displayTitle --workflow nonexistent-workflow-12345 --limit 6 085455/b011/ GOMODCACHE 64/pkg/tool/linux_amd64/vet env 085455/b176/_pkg_.a .cfg 64/pkg/tool/linux_amd64/vet GOINSECURE fips140/nistec/fremote ache/go/1.25.8/x64/src/runtime/iuser.name 64/pkg/tool/linux_amd64/vet (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v0.47.4
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v0.47.4 --jq [.object.sha, .object.type] | @tsv --show-toplevel x_amd64/link /usr/bin/git e-analyzer.md 6379199/b036/vetrev-parse x_amd64/link git rev-�� --show-toplevel x_amd64/link /usr/bin/git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v0.47.4 --jq [.object.sha, .object.type] | @tsv --show-toplevel go /usr/bin/git 719828201 GO111MODULE ck /usr/bin/git conf�� --get-regexp ^remote\..*\.gh-resolved$ /usr/bin/git "prettier" --chels GOPROXY ache/go/1.25.8/x/tmp/gh-aw/aw-feature-branch.patch git (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v1.0.0
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.0.0 --jq [.object.sha, .object.type] | @tsv 085455/b189/_pkg_.a GO111MODULE util.test GOINSECURE GOMOD 085455/b006/symauser.email util.test 3263�� se 6379199/b043/vet.cfg .cfg GOINSECURE GOMOD GOMODCACHE ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.0.0 --jq [.object.sha, .object.type] | @tsv -json GO111MODULE 64/bin/go GOINSECURE GOMOD erignore go m/_n�� 73/001/test-fron.github/workflows/test.md GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v1.2.3
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.2.3 --jq [.object.sha, .object.type] | @tsv -json GO111MODULE x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet env -json GO111MODULE x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.2.3 --jq [.object.sha, .object.type] | @tsv -json GO111MODULE ache/go/1.25.8/x-nilfunc GOINSECURE GOMOD GOMODCACHE go env */*.ts' '**/*.js-errorsas GO111MODULE 64/pkg/tool/linu-nilfunc GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linu-tests (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v2.0.0
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v2.0.0 --jq [.object.sha, .object.type] | @tsv -json GO111MODULE x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet env -json GO111MODULE x_amd64/vet GOINSECURE GOMOD GOMODCACHE SLlQ1ZG/V_z3kiodThbFBmRphbkm (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v2.0.0 --jq [.object.sha, .object.type] | @tsv -json GO111MODULE x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet env _.a GO111MODULE x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v2.0.0 --jq [.object.sha, .object.type] | @tsv -json GO111MODULE x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet env lGitmain_branch3--repo lGitmain_branch3owner/repo x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v3.0.0
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v3.0.0 --jq [.object.sha, .object.type] | @tsv -json GO111MODULE x_amd64/vet GOINSECURE xcontext GOMODCACHE x_amd64/vet env -json GO111MODULE x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v3.0.0 --jq [.object.sha, .object.type] | @tsv -json GO111MODULE tions/node_modul-nilfunc GOINSECURE GOMOD GOMODCACHE go 4271�� */*.ts' '**/*.json' --ignore-patGOINSECURE GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/nonexistent/action/git/ref/tags/v999.999.999
    • Triggering command: /usr/bin/gh gh api /repos/nonexistent/action/git/ref/tags/v999.999.999 --jq [.object.sha, .object.type] | @tsv thub/workflows o 64/pkg/tool/linux_amd64/compile GOINSECURE (http block)
    • Triggering command: /usr/bin/gh gh api /repos/nonexistent/action/git/ref/tags/v999.999.999 --jq [.object.sha, .object.type] | @tsv ck '**/*.cjs' '**/*.ts' '**/*.js-errorsas GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env (http block)
  • https://api.github.com/repos/nonexistent/repo/actions/runs/12345
    • Triggering command: /usr/bin/gh gh run view 12345 --repo nonexistent/repo --json status,conclusion GOINSECURE g/x/net/dns/dnsmrev-parse GOMODCACHE 64/pkg/tool/linu/home/REDACTED/work/gh-aw/gh-aw/pkg/typeutil/convert_test.go env 085455/b161/_pkg_.a jfLv/0caWgwAWMGdke8fejfLv ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet GOINSECURE th2 GOMODCACHE ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh run view 12345 --repo nonexistent/repo --json status,conclusion GOINSECURE GOMOD GOMODCACHE go env 1504-91024/test-3711360203/.github/workflows GO111MODULE /opt/hostedtoolcache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/owner/repo/actions/workflows
    • Triggering command: /usr/bin/gh gh workflow list --json name,state,path --repo owner/repo x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile env -json gset/set.go x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile (http block)
    • Triggering command: /usr/bin/gh gh workflow list --json name,state,path --repo owner/repo x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile env -json GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile (http block)
    • Triggering command: /usr/bin/gh gh workflow list --json name,state,path --repo owner/repo 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/owner/repo/contents/file.md
    • Triggering command: /tmp/go-build2326379199/b400/cli.test /tmp/go-build2326379199/b400/cli.test -test.testlogfile=/tmp/go-build2326379199/b400/testlog.txt -test.paniconexit0 -test.v=true -test.parallel=4 -test.timeout=10m0s -test.run=^Test -test.short=true GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE 6AWy9kr/rVG28oB_-buildtags (http block)
    • Triggering command: /tmp/go-build2975740689/b400/cli.test /tmp/go-build2975740689/b400/cli.test -test.testlogfile=/tmp/go-build2975740689/b400/testlog.txt -test.paniconexit0 -test.v=true -test.parallel=4 -test.timeout=10m0s -test.run=^Test -test.short=true GOINSECURE GOMOD GOMODCACHE go env on' --ignore-patGOINSECURE GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile (http block)
  • https://api.github.com/repos/test-owner/test-repo/actions/secrets
    • Triggering command: /usr/bin/gh gh api /repos/test-owner/test-repo/actions/secrets --jq .secrets[].name 76822675/001' 76822675/001' -nolocalimports -importcfg /tmp/go-build2326379199/b400/importcfg -pack /tmp/go-build2326379199/b400/_testmain.go env -json GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile (http block)
    • Triggering command: /usr/bin/gh gh api /repos/test-owner/test-repo/actions/secrets --jq .secrets[].name -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go ules�� -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI changed the title [WIP] Fix recurring syntax error for secrets in strict-mode workflows [aw-compat] Add gh aw fix codemods for strict-mode secret leaks in step run and engine.env Apr 17, 2026
Copilot AI requested a review from pelikhan April 17, 2026 18:31
@pelikhan pelikhan marked this pull request as ready for review April 17, 2026 19:01
Copilot AI review requested due to automatic review settings April 17, 2026 19:01
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds two new gh aw fix codemods intended to remediate strict-mode secret leak patterns in workflow frontmatter (inline ${{ secrets.* }} usage in step run: commands, and secret-bearing entries under engine.env), and registers them in the codemod registry with accompanying tests.

Changes:

  • Registered two new codemods in GetAllCodemods() and updated registry expectations/tests.
  • Added steps-run-secrets-to-env codemod + tests to rewrite inline secret expressions in step run: into $VARS and add step-level env bindings.
  • Added engine-env-secrets-to-engine-config codemod + tests to remove unsafe secret-bearing engine.env keys and delete empty engine.env blocks after pruning.
Show a summary per file
File Description
pkg/cli/fix_codemods.go Registers the two new codemods in the global codemod registry.
pkg/cli/fix_codemods_test.go Updates codemod count and expected registry IDs/order.
pkg/cli/codemod_steps_run_secrets_env.go Implements the step run secret-to-env rewrite codemod.
pkg/cli/codemod_steps_run_secrets_env_test.go Adds unit tests for step run secret rewriting across step sections.
pkg/cli/codemod_engine_env_secrets.go Implements the engine env secret pruning codemod and empty-env cleanup.
pkg/cli/codemod_engine_env_secrets_test.go Adds unit tests for pruning unsafe engine.env secret-bearing keys.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comments suppressed due to low confidence (3)

pkg/cli/codemod_steps_run_secrets_env.go:239

  • If a step already uses inline env-map syntax (e.g. env: { FOO: bar }) this codemod won’t detect the existing env keys (it only matches block-style env: with no trailing value). In that case it will insert a second env: block, producing duplicate YAML keys and potentially invalid/ambiguous YAML. Consider supporting inline env maps (or, at minimum, skipping insertion when an env: key already exists in the step) and add a test that covers env: { FOO: bar } + run: echo ${{ secrets.TEST }}.
		if strings.HasPrefix(trimmed, "env:") && len(indent) > len(stepIndent) && strings.TrimSpace(strings.TrimPrefix(trimmed, "env:")) == "" {
			envStart = i
			envIndent = indent
			envEnd = i
			for j := i + 1; j < len(stepLines); j++ {
				t := strings.TrimSpace(stepLines[j])
				if len(t) == 0 {
					envEnd = j
					continue
				}
				if len(getIndentation(stepLines[j])) <= len(envIndent) {
					break
				}
				envEnd = j
				key := parseYAMLMapKey(t)
				if key != "" {
					existingEnvKeys[key] = true
				}
			}
		}

		if !strings.HasPrefix(trimmed, "run:") || len(indent) <= len(stepIndent) {
			continue
		}
		if firstRunLine == -1 {
			firstRunLine = i
		}

		runValue := strings.TrimSpace(strings.TrimPrefix(trimmed, "run:"))
		if runValue == "|" || runValue == "|-" || runValue == ">" || runValue == ">-" {
			runIndent := indent
			for j := i + 1; j < len(stepLines); j++ {
				t := strings.TrimSpace(stepLines[j])
				if len(t) == 0 {
					continue
				}
				if len(getIndentation(stepLines[j])) <= len(runIndent) {
					break
				}
				updatedLine, names := replaceStepSecretRefs(stepLines[j])
				if len(names) > 0 {
					stepLines[j] = updatedLine
					modified = true
				}
				for _, name := range names {
					if !seen[name] {
						seen[name] = true
						orderedSecrets = append(orderedSecrets, name)
					}
				}
			}
			continue
		}

		newLine, names := replaceStepSecretRefs(line)
		if len(names) > 0 {
			stepLines[i] = newLine
			modified = true
		}
		for _, name := range names {
			if !seen[name] {
				seen[name] = true
				orderedSecrets = append(orderedSecrets, name)
			}
		}
	}

	if len(orderedSecrets) == 0 {
		return stepLines, modified
	}

	missingSecrets := make([]string, 0, len(orderedSecrets))
	for _, name := range orderedSecrets {
		if !existingEnvKeys[name] {
			missingSecrets = append(missingSecrets, name)
		}
	}
	if len(missingSecrets) == 0 {
		return stepLines, true
	}

	if envStart != -1 {
		insertAt := envEnd + 1
		envValueIndent := envIndent + "  "
		insertLines := make([]string, 0, len(missingSecrets))
		for _, name := range missingSecrets {
			insertLines = append(insertLines, fmt.Sprintf("%s%s: ${{ secrets.%s }}", envValueIndent, name, name))
		}
		stepLines = append(stepLines[:insertAt], append(insertLines, stepLines[insertAt:]...)...)
		return stepLines, true
	}

pkg/cli/codemod_engine_env_secrets.go:142

  • removeUnsafeEngineEnvKeys only enters the env block for block-style env: lines with no inline value. If engine.env is written in inline-map form (e.g. env: { OPENAI_BASE_URL: ... }), unsafeKeys can be detected from parsed frontmatter but the line-based transformer won’t remove anything, so the codemod silently fails to remediate the strict-mode issue. Please handle inline-map env: syntax (or fall back to a safer transformation strategy) and add a test for this formatting.
		if inEngine && !inEnv && strings.HasPrefix(trimmed, "env:") && strings.TrimSpace(strings.TrimPrefix(trimmed, "env:")) == "" {
			inEnv = true
			envIndent = indent
			removingKey = false
			result = append(result, line)
			continue
		}

pkg/cli/codemod_engine_env_secrets.go:204

  • removeEmptyEngineEnvBlock currently removes any empty env: block anywhere in the frontmatter, not just under engine:. Since this codemod is scoped to engine.env, this can cause unrelated formatting/semantic changes (e.g. deleting an intentionally-empty step env: block) whenever unsafe engine env keys are pruned. Please scope the empty-env cleanup to engine.env only by tracking whether you’re inside the engine: block and its env: sub-block before removing the header line.
func removeEmptyEngineEnvBlock(lines []string) []string {
	result := make([]string, 0, len(lines))
	for i := range lines {
		line := lines[i]
		trimmed := strings.TrimSpace(line)
		if trimmed == "env:" {
			envIndent := getIndentation(line)
			hasValues := false
			j := i + 1
			for ; j < len(lines); j++ {
				t := strings.TrimSpace(lines[j])
				if len(t) == 0 {
					continue
				}
				if len(getIndentation(lines[j])) <= len(envIndent) {
					break
				}
				hasValues = true
				break
			}
			if !hasValues {
				continue
			}
		}
		result = append(result, line)
	}
	return result
  • Files reviewed: 6/6 changed files
  • Comments generated: 2

Comment on lines +149 to +176
if strings.HasPrefix(trimmed, "env:") && len(indent) > len(stepIndent) && strings.TrimSpace(strings.TrimPrefix(trimmed, "env:")) == "" {
envStart = i
envIndent = indent
envEnd = i
for j := i + 1; j < len(stepLines); j++ {
t := strings.TrimSpace(stepLines[j])
if len(t) == 0 {
envEnd = j
continue
}
if len(getIndentation(stepLines[j])) <= len(envIndent) {
break
}
envEnd = j
key := parseYAMLMapKey(t)
if key != "" {
existingEnvKeys[key] = true
}
}
}

if !strings.HasPrefix(trimmed, "run:") || len(indent) <= len(stepIndent) {
continue
}
if firstRunLine == -1 {
firstRunLine = i
}

Comment on lines +64 to +71
func extractEngineIDForCodemod(frontmatter map[string]any, engineMap map[string]any) string {
if id, ok := engineMap["id"].(string); ok && id != "" {
return id
}
if id, ok := frontmatter["engine"].(string); ok && id != "" {
return id
}
return ""
…n codemods

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

Commit pushed: 22a7ab5

🏗️ ADR gate enforced by Design Decision Gate 🏗️

@github-actions
Copy link
Copy Markdown
Contributor

🏗️ Design Decision Gate — ADR Required

This PR makes significant changes to core business logic (756 new lines in pkg/cli/) but does not have a linked Architecture Decision Record (ADR).

AI has analyzed the PR diff and generated a draft ADR to help you get started:

📄 Draft ADR: docs/adr/26919-automated-codemods-for-strict-mode-secret-leak-remediation.md

What to do next

  1. Review the draft ADR committed to your branch — it was generated from the PR diff
  2. Complete the missing sections — add context the AI couldn't infer, refine the decision rationale, and list real alternatives you considered
  3. Commit the finalized ADR to docs/adr/ on your branch
  4. Reference the ADR in this PR body by adding a line such as:

    ADR: ADR-26919: Automated Codemods for Strict-Mode Secret Leak Remediation

Once an ADR is linked in the PR body, this gate will re-run and verify the implementation matches the decision.

What the draft covers

The draft ADR captures three key design decisions inferred from the diff:

  • Automated remediation via codemods rather than requiring manual migration — the gh aw fix --write codemod registry is extended with two new entries
  • Step run secrets strategy$\{\{ secrets.NAME }} expressions in run: fields are replaced with $NAME shell references and a corresponding env: binding is injected (rather than masking or removing the secret)
  • Engine env secrets strategy — unsafe secret-bearing engine.env keys are removed using an allowlist of required engine credential overrides, and empty env: blocks are pruned

Why ADRs Matter

"AI made me procrastinate on key design decisions. Because refactoring was cheap, I could always say 'I'll deal with this later.' Deferring decisions corroded my ability to think clearly."

ADRs create a searchable, permanent record of why the codebase looks the way it does. Future contributors (and your future self) will thank you.


📋 Michael Nygard ADR Format Reference

An ADR must contain these four sections to be considered complete:

  • Context — What is the problem? What forces are at play?
  • Decision — What did you decide? Why?
  • Alternatives Considered — What else could have been done?
  • Consequences — What are the trade-offs (positive and negative)?

All ADRs are stored in docs/adr/ as Markdown files numbered by PR number (e.g., 26919-automated-codemods-for-strict-mode-secret-leak-remediation.md for PR #26919).

🔒 This PR cannot merge until an ADR is linked in the PR body.

References: §24581919524

Note

🔒 Integrity filter blocked 1 item

The following item were blocked because they don't meet the GitHub integrity level.

To allow these resources, lower min-integrity in your GitHub frontmatter:

tools:
  github:
    min-integrity: approved  # merged | approved | unapproved | none

🏗️ ADR gate enforced by Design Decision Gate 🏗️ · ● 191.4K ·

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[aw-compat] Recurring syntax error: secrets in strict-mode workflows (2 repos)

3 participants