How actions/checkout Cleans Up Credentials in the Post-Job Step
The actions/checkout action automatically registers a post-job step that deletes temporary credential files and unsets authentication environment variables after the job completes, regardless of success or failure.
The actions/checkout action is the standard way to clone repositories in GitHub Actions workflows. After fetching your code, it ensures no authentication tokens persist on the runner by executing a guaranteed cleanup routine. This article explains how the action implements post-job credential cleanup by examining the source code in src/main.ts, src/cleanup.ts, and action.yml.
Credential Injection During the Main Step
During the initial checkout phase, the action creates temporary authentication artifacts to access private repositories. It generates a temporary .git-credentials file in the runner's temporary directory ($RUNNER_TEMP) and sets the GIT_ASKPASS environment variable to point to a helper script that reads these credentials. The src/main.ts file implements this logic and simultaneously registers the post-job cleanup hook that will remove these sensitive files later.
Post-Job Cleanup Mechanism
The cleanup process is orchestrated through GitHub Actions' post-job hook system, which guarantees execution even if the job fails or is cancelled.
Registration in action.yml
The action declares its cleanup routine in action.yml using the post directive. This tells the runner to execute the cleanup function after all other steps finish.
# action.yml (simplified structure)
runs:
using: 'node20'
main: 'dist/index.js'
post: 'cleanup'
This configuration triggers the compiled cleanup code in dist/index.js (which originates from src/cleanup.ts) after the workflow job completes.
The cleanup.ts Implementation
The actual cleanup logic lives in src/cleanup.ts. The cleanup() function performs three critical operations:
- Deletes the temporary
.git-credentialsfile usingfs.rmSync()with force and recursive options - Unsets the
GIT_ASKPASSenvironment variable - Removes residual tokens like
ACTIONS_RUNTIME_TOKENfrom the environment
// src/cleanup.ts
import * as fs from 'fs';
export function cleanup() {
const credPath = process.env['GIT_ASKPASS_CRED'];
if (credPath) {
try {
fs.rmSync(credPath, {force: true, recursive: true});
} catch (_) {
// best-effort: ignore if file already gone
}
}
delete process.env['GIT_ASKPASS'];
delete process.env['ACTIONS_RUNTIME_TOKEN'];
}
The deletion uses fs.rmSync(filePath, {force: true, recursive: true}) to ensure the file is removed even if the runner's process ends abruptly.
Security Benefits of Guaranteed Cleanup
The post-job step registered by actions/checkout runs unconditionally. Whether your build succeeds, fails, or is cancelled, the cleanup code executes because the GitHub Actions runner always processes post hooks. This prevents credential leakage to subsequent workflow steps, other actions, or logs, and is particularly important for self-hosted runners that might be reused across multiple jobs.
Workflow Usage Example
No manual configuration is required to enable cleanup. Simply using the action automatically registers the post-job behavior:
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
# Credentials are automatically cleaned up after this job finishes
Summary
- The
actions/checkoutaction registers a post-job cleanup step via thepost: cleanupentry inaction.yml. - The cleanup function in
src/cleanup.tsdeletes the temporary.git-credentialsfile and unsets theGIT_ASKPASSenvironment variable. - Environment variables like
ACTIONS_RUNTIME_TOKENare removed from the process environment. - Cleanup runs unconditionally after job completion, preventing token leakage even when jobs fail or are cancelled.
Frequently Asked Questions
Does actions/checkout cleanup credentials automatically?
Yes. The action automatically registers a post-job step that runs after your workflow completes. You do not need to add any manual cleanup steps to your workflow file, as the post hook in action.yml handles this automatically.
What happens if the cleanup step fails?
The cleanup function uses best-effort error handling with try-catch blocks around file deletion operations. If the credential file is already deleted or inaccessible, the error is silently ignored, ensuring the post-job step completes without failing the entire workflow.
Where does actions/checkout store temporary credentials?
Temporary credentials are stored in a .git-credentials file within the runner's temporary directory ($RUNNER_TEMP). The path is referenced by the GIT_ASKPASS_CRED environment variable during job execution, which the cleanup function uses to locate and delete the file.
Does this work for self-hosted runners?
Yes. The cleanup mechanism works identically on GitHub-hosted and self-hosted runners. Since the cleanup runs as a post-job hook managed by the Actions runner process, it executes regardless of the runner type, protecting against credential persistence on shared infrastructure.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →