Bug: WIF OIDC token refresh can recreate credentials on disk after handle.stop()
Author: SparshM8Created Sep 15, 2026Updated Sep 15, 2026
Labelsbugduplicateprovider:1pp3
Summary
In base-action/src/workload-identity.ts, the asynchronous background token refresh interval (setInterval) does not cancel in-flight HTTP requests when stop() is called. If the action concludes and src/entrypoints/run.ts executes workloadIdentity?.stop() in its finally block, a pending getIDToken() request can still resolve later, recreating the deleted .claude/ credential directory and token file on disk.
Problem & Failure Scenario
- Pending Token Request Continues: The 4-minute token refresh interval triggers an asynchronous OIDC request (
getIDToken()). - Orchestrator Shutdown: The agent run finishes while that request is still pending.
src/entrypoints/run.tsexecutesworkloadIdentity?.stop()in itsfinallyblock. - Post-Cleanup Write:
clearInterval()stops future intervals but cannot cancel an in-flight promise. WhengetIDToken()resolves, execution continues pastawaitand executesmkdirSyncandwriteFileSync, recreating the credential files after cleanup. - Partial Initialization Leak: If profile generation throws after the identity token has been written, orphaned token files remain without an exported cleanup handle.
Steps to Reproduce
- Configure workload identity federation with a delayed or mocked asynchronous
getIDToken()response. - Call
handle.stop()while the refresh request is still in flight. - Observe that
stop()clears the directory and token file. - Let the pending
getIDToken()promise resolve. - Notice that the credential directory and token file are recreated on disk.
Expected Behavior
Once handle.stop() is invoked, any in-flight or subsequent token resolution must be discarded synchronously without performing disk mutations, ensuring no credential remnants persist on the runner.
Proposed Fix / Pull Request
Resolved by #1831.
Source: anthropics/claude-code-action