Summary
The Revoke app token post-step in action.yml runs an unbounded curl -L -X DELETE against ${GITHUB_API_URL:-https://api.github.com}/installation/token with no --max-time, no --connect-timeout, and no || true. When that endpoint hangs or is slow, the curl call waits out the runner timeout and the whole workflow is marked failed even though the main Run Claude Code Action step already posted its review comment(s) successfully.
Failure signature (canonical)
claude Run Claude Code No buffered inline comments
claude Run Claude Code ##[group]Run curl -L \
claude Run Claude Code -X DELETE \
claude Run Claude Code -H "Accept: application/vnd.github+json" \
claude Run Claude Code -H "Authorization: ***" \
claude Run Claude Code ${GITHUB_API_URL:-https://api.github.com}/installation/token
claude Run Claude Code 0 0 0 0 0 0 0 0 --:--:--
The progress meter (0 0 0 0 0 0 0 0 --:--:--) confirms curl is open and waiting on bytes from the endpoint.
Impact in caller's workflow
On the M365 Migration Planner repo, we observed:
- 5/20 success rate (25%) across one day of runs on 2026-06-24
- 100% failure rate from 2026-06-24 21:19Z onward (across multiple PRs)
- Each failure pattern is identical: main step posts the verdict comment, post-step crashes during cleanup, workflow marked failed
- Our review-gate keys off comment content (not workflow status), so the gate works — but downstream consumers that key off workflow conclusion see a red status
Affected location
action.yml (verified at v1 SHA 428971d2ecd6e3a7cb0ee0da2a3a8b33fdb3678d, 2026-06-24):
- name: Revoke app token
if: always() && inputs.github_token == '' && steps.run.outputs.github_token != '' && steps.run.outputs.skipped_due_to_workflow_validation_mismatch != 'true'
shell: bash
run: |
curl -L \
-X DELETE \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${{ steps.run.outputs.github_token }}" \
-H "X-GitHub-Api-Version: 2022-11-28" \
${GITHUB_API_URL:-https://api.github.com}/installation/token
Suggested fix
Either of these resolves the cleanup-shadowing-success failure mode:
Option A (minimal):
curl -L \
--max-time 10 \
--connect-timeout 5 \
-X DELETE \
...
${GITHUB_API_URL:-https://api.github.com}/installation/token || true
Option B: add continue-on-error: true at the step level.
Both keep the security intent (best-effort revoke of the temp installation token) without letting cleanup hide a successful review. The temp token has a 1-hour TTL — failing-to-revoke is a soft signal, not a security gap.
Reproduction
Cannot deterministically reproduce; the underlying /installation/token slowness appears upstream-of-action. But the failure mode (one slow endpoint hanging a curl with no timeout → workflow marked failed) is deterministic given those conditions.
Workaround consumers can apply
Set continue-on-error: true on the action step in the calling workflow. Tradeoff: also masks any future legitimate failure of the main step, so it's a temporary unblock, not a fix.
Related
Summary
The
Revoke app tokenpost-step inaction.ymlruns an unboundedcurl -L -X DELETEagainst${GITHUB_API_URL:-https://api.github.com}/installation/tokenwith no--max-time, no--connect-timeout, and no|| true. When that endpoint hangs or is slow, the curl call waits out the runner timeout and the whole workflow is marked failed even though the mainRun Claude Code Actionstep already posted its review comment(s) successfully.Failure signature (canonical)
The progress meter (
0 0 0 0 0 0 0 0 --:--:--) confirms curl is open and waiting on bytes from the endpoint.Impact in caller's workflow
On the M365 Migration Planner repo, we observed:
Affected location
action.yml(verified atv1SHA428971d2ecd6e3a7cb0ee0da2a3a8b33fdb3678d, 2026-06-24):Suggested fix
Either of these resolves the cleanup-shadowing-success failure mode:
Option A (minimal):
Option B: add
continue-on-error: trueat the step level.Both keep the security intent (best-effort revoke of the temp installation token) without letting cleanup hide a successful review. The temp token has a 1-hour TTL — failing-to-revoke is a soft signal, not a security gap.
Reproduction
Cannot deterministically reproduce; the underlying
/installation/tokenslowness appears upstream-of-action. But the failure mode (one slow endpoint hanging a curl with no timeout → workflow marked failed) is deterministic given those conditions.Workaround consumers can apply
Set
continue-on-error: trueon the action step in the calling workflow. Tradeoff: also masks any future legitimate failure of the main step, so it's a temporary unblock, not a fix.Related