How the safe.directory Configuration Works in actions/checkout
The actions/checkout action automatically configures Git's safe.directory setting to prevent "fatal: unsafe repository" errors when running in Docker containers or under different user UIDs.
The actions/checkout action configures Git's safe.directory setting to prevent ownership-related failures in containerized workflows. When Git 2.35+ detects a repository directory owned by a different user, it aborts operations with a fatal error. The action automatically handles this security feature by adding the repository path to Git's safe directory list, ensuring reliable checkouts across diverse execution environments.
Understanding Git's safe.directory Requirement
Git 2.35 introduced stricter ownership checks that treat repositories owned by different users as potentially unsafe. When running jobs inside Docker containers, the mounted workspace often has a UID that differs from the container's default user, triggering the "fatal: unsafe repository" error. The safe.directory configuration tells Git to trust specific paths regardless of ownership, allowing operations to proceed securely.
How actions/checkout Implements safe.directory
The implementation spans three core components that parse inputs, configure Git, and persist state across the job lifecycle.
Input Parsing in input-helper.ts
In src/input-helper.ts (lines 74-77), the action reads the boolean input set-safe-directory, which defaults to true. This value is stored in result.setSafeDirectory and passed to the git source provider.
Temporary Global Configuration in git-source-provider.ts
When setSafeDirectory is enabled, src/git-source-provider.ts (lines 45-63) executes git config --global to add the repository path to the safe directory list. This creates a temporary global Git configuration that applies to the current job. The helper also calls stateHelper.setSafeDirectory() to record that the configuration was applied.
State Persistence in state-helper.ts
The src/state-helper.ts module (lines 14-22) uses core.saveState() to persist the set-safe-directory flag in the GitHub Actions state bag. This allows the POST-action cleanup phase to detect whether the safe directory configuration was applied, ensuring proper cleanup and idempotency.
Configuring safe.directory in Your Workflows
You can control this behavior through the set-safe-directory input or handle it manually.
Default Behavior
steps:
- uses: actions/checkout@v4
With set-safe-directory defaulting to true, the action automatically adds $GITHUB_WORKSPACE to Git's safe directories.
Disabling Automatic Configuration
steps:
- uses: actions/checkout@v4
with:
set-safe-directory: false
Setting this to false skips the automatic configuration. Only use this when the job runs with the same UID as the runner or when you manage the configuration separately.
Manual Configuration
steps:
- name: Add safe directory manually
run: |
git config --global --add safe.directory $GITHUB_WORKSPACE
- uses: actions/checkout@v4
with:
set-safe-directory: false
This approach gives you full control over Git's configuration while preventing duplicate entries.
Summary
actions/checkoutautomatically configuressafe.directoryto prevent Git ownership errors in containerized environments.- The
set-safe-directoryinput (defaulttrue) controls whether the action modifies Git's global configuration. - Implementation spans
src/input-helper.ts,src/git-source-provider.ts, andsrc/state-helper.tsto handle parsing, configuration, and state persistence. - Git 2.35+ requires this configuration when the repository owner differs from the current user, which is common in Docker workflows.
Frequently Asked Questions
What is the safe.directory configuration in Git?
The safe.directory configuration is a Git security feature introduced in version 2.35 that specifies directories Git should consider safe regardless of ownership. By default, Git refuses to operate on repositories owned by users other than the current process owner to prevent security risks from malicious .git directories.
Why does actions/checkout need to configure safe.directory?
Containerized workflows often mount the workspace directory with a UID different from the container's default user. Without adding the path to safe.directory, Git would abort with "fatal: unsafe repository" errors. The action automatically configures this to ensure checkout operations succeed regardless of the user context.
Can I disable the safe.directory configuration?
Yes. Set set-safe-directory: false in the action inputs. This skips the automatic configuration in src/git-source-provider.ts. Only disable this if you are certain the job runs with matching UIDs or if you configure the safe directory manually before the checkout step.
Where is the safe.directory state stored between action phases?
The action uses core.saveState() in src/state-helper.ts to store a flag in the GitHub Actions state bag. This persists the configuration status between the main action and POST-action phases, allowing the cleanup process to reference the original settings.
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 →