Fix APM GitHub App token never invalidated after use#21508
Merged
Conversation
6 tasks
The GitHub App installation token minted for APM cross-org repository access was never revoked after use, leaving it valid for up to 1 hour. - Add buildAPMAppTokenInvalidationStep() in apm_dependencies.go that targets the apm-app-token step with always() condition for cleanup even on failure - Call buildAPMAppTokenInvalidationStep() in compiler_activation_job.go after the APM bundle artifact upload, guarded by GitHubApp != nil - Add unit tests for the new invalidation function - Add activation job integration tests asserting invalidation step order Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] [plan] Fix APM GitHub App token revocation after use
Fix APM GitHub App token never invalidated after use
Mar 18, 2026
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes the APM GitHub App installation token lifecycle by adding an explicit token revocation step to the activation job so the apm-app-token is invalidated after APM dependency packing.
Changes:
- Added
buildAPMAppTokenInvalidationStep()to revoke the APM GitHub App installation token viagh api DELETE /installation/tokenwithif: always(). - Wired the invalidation step into the activation job after the APM bundle artifact upload (only when
APMDependencies.GitHubAppis configured). - Added unit and activation-job tests to verify the invalidation step presence, condition, and ordering.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| pkg/workflow/apm_dependencies.go | Adds a new workflow-step generator to revoke the APM GitHub App token. |
| pkg/workflow/compiler_activation_job.go | Appends the APM token invalidation step after the APM bundle upload when a GitHub App is configured. |
| pkg/workflow/apm_dependencies_test.go | Adds unit coverage for the invalidation step contents/conditions. |
| pkg/workflow/compiler_activation_jobs_test.go | Adds activation job coverage ensuring the invalidation step is present and ordered after APM artifact upload. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
|
|
||
| // Invalidation step should appear after the APM bundle upload | ||
| uploadIdx := strings.Index(stepsStr, "Upload APM bundle artifact") | ||
| invalidateIdx := strings.Index(stepsStr, "Invalidate GitHub App token for APM") |
Contributor
|
@copilot review comments |
…e positives Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Contributor
Author
pelikhan
approved these changes
Mar 18, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The GitHub App token minted for APM cross-org dependency access (
apm-app-token) was never revoked post-pack, leaving it live for up to 60 minutes — a token lifecycle violation. All five other token-minting paths in the codebase correctly invalidate their tokens; APM was the only exception.Changes
pkg/workflow/apm_dependencies.go: AddedbuildAPMAppTokenInvalidationStep()targetingapm-app-tokenwithif: always()to ensure cleanup even on step failure, callingDELETE /installation/tokenviagh api.pkg/workflow/compiler_activation_job.go: Calls the invalidation step after the APM bundle artifact upload, guarded byAPMDependencies.GitHubApp != nil.TestBuildAPMAppTokenInvalidationStep(unit) andTestBuildActivationJob_APMTokenInvalidation(activation job) verifying the step is present withalways(), targets the correct step ID, and is ordered after the artifact upload.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/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 GO111MODULE 64/bin/go git rev-�� --show-toplevel go /usr/bin/git -json GO111MODULE 64/pkg/tool/linu--show-toplevel git(http block)https://api.github.com/orgs/test-owner/actions/secrets/usr/bin/gh gh api /orgs/test-owner/actions/secrets --jq .secrets[].name g/logger/exampleGOINSECURE GO111MODULE 64/bin/go GOINSECURE GOMOD erignore ache/go/1.25.0/xGO111MODULE env 1820674/b398/_pkGOINSECURE GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go(http block)/usr/bin/gh gh api /orgs/test-owner/actions/secrets --jq .secrets[].name "prettier" --wriGOINSECURE git 64/bin/go --show-toplevel ortcfg /usr/bin/git node /opt�� prettier --write 64/bin/go !../../../pkg/wonode --ignore-path ../../../.pretti--check go(http block)https://api.github.com/repos/actions/ai-inference/git/ref/tags/v1/usr/bin/gh gh api /repos/actions/ai-inference/git/ref/tags/v1 --jq .object.sha run --auto /usr/bin/git --detach k/gh-aw/gh-aw/pkrev-parse nch,headSha,disp--show-toplevel git rev-�� --show-toplevel /opt/hostedtoolcache/go/1.25.0/xGO111MODULE /usr/bin/git b/workflows -trimpath 64/bin/go git(http block)https://api.github.com/repos/actions/checkout/git/ref/tags/v3/usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v3 --jq .object.sha 9646443/b421/_pkg_.a GO111MODULE 9646443/b421=> GOINSECURE b/gh-aw/pkg/stylrev-parse GOMODCACHE /opt/hostedtoolcache/go/1.25.0/x64/pkg/tool/linux_amd64/vet -ato�� r-test929750792/existing.md -buildtags /usr/bin/git -errorsas -ifaceassert -nilfunc 9646443/b421/importcfg(http block)https://api.github.com/repos/actions/checkout/git/ref/tags/v5/usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq .object.sha -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env 90/001/test-frontmatter-with-env-template-expressions.md GO111MODULE 64/pkg/tool/linux_amd64/link GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/link(http block)/usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq .object.sha --show-toplevel go /usr/bin/gh -json GO111MODULE 64/bin/go gh run view 12345 /usr/bin/git nonexistent/repogit --json status,conclusio--show-toplevel git(http block)/usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq .object.sha --show-toplevel go /usr/bin/git -json GO111MODULE ache/go/1.25.0/x--show-toplevel git rev-�� --show-toplevel go /usr/bin/git -json GO111MODULE ache/go/1.25.0/x--show-toplevel git(http block)https://api.github.com/repos/actions/checkout/git/ref/tags/v6/usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v6 --jq .object.sha user.name Test User /usr/bin/git -json GO111MODULE 64/bin/go git conf�� user.name Test User /usr/bin/git tions-lock.json git GOPROXY 64/bin/go git(http block)/usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v6 --jq .object.sha user.name Test User /usr/bin/git -json GO111MODULE At,event,headBra--show-toplevel git conf�� user.email test@example.com /usr/bin/git "prettier" --chegit om/owner/repo.girev-parse lone-3379788206 git(http block)/usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v6 --jq .object.sha --show-toplevel go /usr/bin/git -json GO111MODULE ache/go/1.25.0/x--show-toplevel git rev-�� --show-toplevel go /usr/bin/git -json GO111MODULE ache/go/1.25.0/x--show-toplevel git(http block)https://api.github.com/repos/actions/github-script/git/ref/tags/v8/usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq .object.sha GOSUMDB GOWORK 64/bin/go GOINSECURE GOMOD GOMODCACHE ache/go/1.25.0/xGO111MODULE env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go(http block)/usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq .object.sha ck 'scripts/**/*GOINSECURE GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE sh(http block)/usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq .object.sha -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE node(http block)https://api.github.com/repos/actions/setup-go/git/ref/tags/v4/usr/bin/gh gh api /repos/actions/setup-go/git/ref/tags/v4 --jq .object.sha --get remote.origin.url ache/go/1.25.0/x64/pkg/tool/linux_amd64/vet -json GO111MODULE 64/bin/go ache/go/1.25.0/x64/pkg/tool/linux_amd64/vet main�� run --auto /usr/bin/git --detach GOPROXY 64/bin/go git(http block)https://api.github.com/repos/actions/setup-node/git/ref/tags/v4/usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v4 --jq .object.sha --get remote.origin.url /usr/bin/git -json GO111MODULE 64/bin/go git add test.txt sh /usr/bin/git(http block)https://api.github.com/repos/actions/upload-artifact/git/ref/tags/v4/usr/bin/gh gh api /repos/actions/upload-artifact/git/ref/tags/v4 --jq .object.sha -json GO111MODULE .cfg GOINSECURE GOMOD GOMODCACHE go env runs/20260318-015811-28265/test-790291533/.github/workflows GO111MODULE /opt/hostedtoolcache/go/1.25.0/x64/bin/go GOINSECURE GOMOD GOMODCACHE go(http block)https://api.github.com/repos/github/gh-aw-actions/git/ref/tags/v1.0.0/usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v1.0.0 --jq .object.sha 9646443/b405/_pkg_.a GO111MODULE 9646443/b405=> GOINSECURE GOMOD GOMODCACHE go env wlHC/eMdwFO3cBOLj36ZOwlHC l ache/go/1.25.0/x64/pkg/tool/linux_amd64/compile GOINSECURE GOMOD GOMODCACHE ache/go/1.25.0/x64/pkg/tool/linux_amd64/compile(http block)https://api.github.com/repos/github/gh-aw-actions/git/ref/tags/v1.2.3/usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v1.2.3 --jq .object.sha -json GO111MODULE /opt/hostedtoolcache/go/1.25.0/x64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE /opt/hostedtoolcache/go/1.25.0/x64/bin/go GOINSECURE GOMOD GOMODCACHE go(http block)https://api.github.com/repos/github/gh-aw/actions/runs/1/artifacts/usr/bin/gh gh run download 1 --dir test-logs/run-1 GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go(http block)https://api.github.com/repos/github/gh-aw/actions/runs/12345/artifacts/usr/bin/gh gh run download 12345 --dir test-logs/run-12345 GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go(http block)/usr/bin/gh gh run download 12345 --dir test-logs/run-12345 GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE oFiles,IgnoredOtherFiles,CFiles,CgoFiles,CXXFiles,MFiles,HFiles,FFiles,SFiles,SwigFiles,SwigCXXFiles,SysoFiles,T--get GOINSECURE GOMOD GOMODCACHE go(http block)https://api.github.com/repos/github/gh-aw/actions/runs/12346/artifacts/usr/bin/gh gh run download 12346 --dir test-logs/run-12346 GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go(http block)https://api.github.com/repos/github/gh-aw/actions/runs/2/artifacts/usr/bin/gh gh run download 2 --dir test-logs/run-2 GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env hub/workflows GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go(http block)/usr/bin/gh gh run download 2 --dir test-logs/run-2 GO111MODULE x_amd64/asm GOINSECURE GOMOD GOMODCACHE x_amd64/asm env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go(http block)https://api.github.com/repos/github/gh-aw/actions/runs/3/artifacts/usr/bin/gh gh run download 3 --dir test-logs/run-3 GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go(http block)/usr/bin/gh gh run download 3 --dir test-logs/run-3 GO111MODULE x_amd64/cgo GOINSECURE GOMOD GOMODCACHE x_amd64/cgo env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go(http block)https://api.github.com/repos/github/gh-aw/actions/runs/4/artifacts/usr/bin/gh gh run download 4 --dir test-logs/run-4 GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env hub/workflows GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go(http block)/usr/bin/gh gh run download 4 --dir test-logs/run-4 GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go(http block)https://api.github.com/repos/github/gh-aw/actions/runs/5/artifacts/usr/bin/gh gh run download 5 --dir test-logs/run-5 GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go(http block)/usr/bin/gh gh run download 5 --dir test-logs/run-5 GO111MODULE x_amd64/link GOINSECURE GOMOD GOMODCACHE x_amd64/link env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go(http block)https://api.github.com/repos/github/gh-aw/actions/workflows/usr/bin/gh gh workflow list --json name,state,path 5a8a5bbe22444b35GOINSECURE GO111MODULE 64/bin/go GOINSECURE GOMOD erignore ache/go/1.25.0/xGO111MODULE env 1820674/b408/_pkGOINSECURE GO111MODULE 64/bin/go GOINSECURE b/gh-aw/pkg/stri-c GOMODCACHE go(http block)/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 b/gh-aw/pkg/teststatus GOMODCACHE go env pAbU/df2Fx0C0xZwGOSUMDB GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE 1820674/b412/imp^remote\..*\.gh-resolved$(http block)/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 GOMOD GOMODCACHE x_amd64/compile env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go(http block)https://api.github.com/repos/github/gh-aw/git/ref/tags/v1.0.0/usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.0.0 --jq .object.sha -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE oJ/UGKM_FbdUZ8dYmy4ud1P/9VAygHAMrev-parse env -json GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile(http block)https://api.github.com/repos/github/gh-aw/git/ref/tags/v1.2.3/usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.2.3 --jq .object.sha -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE node /opt�� run lint:cjs 64/bin/go GOSUMDB GOWORK 64/bin/go ls(http block)/usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.2.3 --jq .object.sha --write ../../../**/*.js**/*.json 64/bin/go --ignore-path ../../../.prettienv /usr/bin/git go env h ../../../.prettierignore GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go(http block)https://api.github.com/repos/github/gh-aw/git/ref/tags/v2.0.0/usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v2.0.0 --jq .object.sha -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE node /opt�� run lint:cjs 64/bin/go GOSUMDB GOWORK 64/bin/go ls(http block)/usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v2.0.0 --jq .object.sha -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE sh -c npx prettier --c-errorsas GOPROXY 64/bin/go GOSUMDB GOWORK run-script/lib/n--show-toplevel sh(http block)/usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v2.0.0 --jq .object.sha -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE sh -c npx prettier --c-errorsas GOPROXY 64/bin/go GOSUMDB GOWORK 64/bin/go sh(http block)https://api.github.com/repos/github/gh-aw/git/ref/tags/v3.0.0/usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v3.0.0 --jq .object.sha -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE sh -c npx prettier --c-errorsas GOPROXY 64/bin/go GOSUMDB GOWORK 64/bin/go node(http block)/usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v3.0.0 --jq .object.sha --write ../../../**/*.js**/*.json /node --ignore-path ../../../.prettilist /usr/bin/git go /pre�� orts,XTestImpor GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go(http block)https://api.github.com/repos/nonexistent/action/git/ref/tags/v999.999.999/usr/bin/gh gh api /repos/nonexistent/action/git/ref/tags/v999.999.999 --jq .object.sha -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env 2262399815/.github/workflows GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE ns-lock.json does not exist yet"test@example.com(http block)https://api.github.com/repos/nonexistent/repo/actions/runs/12345/usr/bin/gh gh run view 12345 --repo nonexistent/repo --json status,conclusion GOINSECURE GOMOD GOMODCACHE x_amd64/vet env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go(http block)https://api.github.com/repos/owner/repo/actions/workflows/usr/bin/gh gh workflow list --json name,state,path --repo owner/repo 64/bin/go GOINSECURE GOMOD erignore ache/go/1.25.0/xGO111MODULE env 1820674/b413/_pkGOINSECURE GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go(http block)/usr/bin/gh gh workflow list --json name,state,path --repo owner/repo 64/bin/go GOINSECURE GOMOD erignore ache/go/1.25.0/xGO111MODULE env 1820674/b415/_pkGOINSECURE GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go(http block)/usr/bin/gh gh workflow list --json name,state,path --repo owner/repo 64/bin/go --show-toplevel go /usr/bin/git node /opt�� prettier --write 64/bin/go !../../../pkg/wonode --ignore-path ../../../.prettiprettier go(http block)https://api.github.com/repos/owner/repo/contents/file.md/tmp/go-build1869646443/b383/cli.test /tmp/go-build1869646443/b383/cli.test -test.testlogfile=/tmp/go-build1869646443/b383/testlog.txt -test.paniconexit0 -test.v=true -test.parallel=4 -test.timeout=10m0s -test.run=^Test -test.short=true GOINSECURE GOMOD GOMODCACHE erignore m/_n�� -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go(http block)/tmp/go-build4131226733/b383/cli.test /tmp/go-build4131226733/b383/cli.test -test.testlogfile=/tmp/go-build4131226733/b383/testlog.txt -test.paniconexit0 -test.v=true -test.parallel=4 -test.timeout=10m0s -test.run=^Test -test.short=true **/*.ts **/*.json --ignore-path node /opt�� run format:pkg-json 64/bin/go ; \ else \ echo "golangci-lint is not installed. Run 'make deps-dev' to install dependencies." go /usr/bin/git go(http block)https://api.github.com/repos/test-owner/test-repo/actions/secrets/usr/bin/gh gh api /repos/test-owner/test-repo/actions/secrets --jq .secrets[].name GOSUMDB GOWORK 64/bin/go GOINSECURE GOMOD GOMODCACHE ache/go/1.25.0/xGO111MODULE env 1820674/b394/_pkGOINSECURE GO111MODULE 64/bin/go GOINSECURE b/gh-aw/pkg/fileenv GOMODCACHE go(http block)/usr/bin/gh gh api /repos/test-owner/test-repo/actions/secrets --jq .secrets[].name "prettier" --wriGOINSECURE git 64/bin/go --show-toplevel go /usr/bin/git npx pret�� --write ../../../**/*.jsGOMOD 64/bin/go --ignore-path ../../../.pretti/home/REDACTED/work/gh-aw/gh-aw/actions/setup/js/node_modules/.bin/prettier /usr/bin/git go(http block)If you need me to access, download, or install something from one of these locations, you can either:
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.