Background & Root Cause
You just mounted a code directory from your host machine into a Docker container. You run git status and are immediately greeted with a cold splash of reality:
fatal: detected dubious ownership in repository at '/workspace/my-app'
To add an exception for this directory, call:
git config --global --add safe.directory /workspace/my-app
This scenario is also very familiar when you SSH into a staging server shared by 4-5 developers.
The repository is not corrupted. Git is not broken either. This is a security mechanism introduced in the patch for CVE-2022-24765 (April 2022).
Prior to this patch, Git would traverse up parent directories looking for a .git directory. On a multi-user server, an attacker could plant a malicious repository in a shared directory such as /tmp or /var/www. Inside that .git/config file, they could insert malicious hooks or configure core.fsmonitor to point to a malicious script. Whenever you navigated into a subdirectory and ran any Git command, the malicious code would execute with your user privileges.
To close this loophole, Git introduced a new rule: The user running the command must own the repository directory itself.
The issue arises when using Docker. The source code on the host machine is owned by a regular user (typically UID 1000). However, the container runs as root (UID 0) by default. The two UIDs mismatch completely, causing Git to immediately block the operation as a safety precaution.
Check Your Git Version
The safe.directory mechanism is available starting from Git 2.35.2. First, check the version on your machine or inside the container:
git --version
If your version is older, you need to upgrade the package. On Ubuntu/Debian:
sudo apt update && sudo apt install -y git
On Alpine Linux (a common base image for Docker):
apk update && apk add --no-cache git
4 Ways to Fix It: From Safe to Definitive
Don’t blindly copy commands from the internet. Choose the solution that best fits your actual environment.
1. Whitelist Specific Directories (Recommended)
The simplest approach is to inform Git that this directory is completely safe:
git config --global --add safe.directory /workspace/my-app
This command writes an entry to the current user’s ~/.gitconfig file. Inside a container running as root, this file is written to /root/.gitconfig.
2. Pre-configure in Dockerfile or Compose
When building dev containers or CI/CD runners (such as GitLab CI or Jenkins), newly spun-up containers will lose runtime configs. Add it directly into your Dockerfile:
FROM node:20-alpine
WORKDIR /app
# Install git and whitelist the working directory
RUN apk add --no-cache git \
&& git config --global --add safe.directory /app
CMD ["npm", "run", "dev"]
If you use docker-compose.yml for local development, you can run this command in the entrypoint or command section:
version: '3.8'
services:
api:
image: python:3.11-slim
working_dir: /code
volumes:
- .:/code
command: >
sh -c "git config --global --add safe.directory /code &&
python main.py"
3. Sync UIDs Between Host and Container (Best Practice for Devs)
The root cause lies in the UID mismatch (1000 vs. 0). Fix it definitively by running the container with your own UID/GID:
docker run -it --rm \
-u $(id -u):$(id -g) \
-v $(pwd):/workspace \
-w /workspace \
node:20-alpine sh
A double benefit: Git no longer flags dubious ownership errors, and files generated inside the container (such as node_modules or caches) won’t end up owned by root on your host machine.
4. Fix Directory Ownership on Linux
On shared servers, the error often happens when a teammate accidentally runs sudo git clone or sudo git pull. You simply need to reassign ownership back to your user account:
sudo chown -R $USER:$USER /var/www/my-app
Warning: Avoid the ‘*’ Wildcard
Many answers on Stack Overflow recommend running this for convenience:
# DANGEROUS: NEVER RUN THIS ON A REAL HOST MACHINE
git config --global --add safe.directory '*'
The * wildcard completely disables the protections of CVE-2022-24765 across the entire system. You should only consider using it inside temporary, short-lived CI/CD containers (ephemeral runners). Never apply this on your personal workstation or a production server.
Verification and Cleanup
Once configured, verify that Git has picked up the changes.
View the Current safe.directory List
git config --global --get-all safe.directory
To check where the configuration is saved (system, global, or local), add the --show-origin flag:
git config --list --show-origin | grep safe.directory
Confirm Repository Status
Run the usual command inside your project directory:
git status
If Git displays your branch and commit status normally without throwing an error, you’re all set.
Remove Obsolete Paths
When deleting old projects, clean up your configuration to keep ~/.gitconfig tidy:
git config --global --unset-all safe.directory /workspace/my-app
Understanding how UIDs and safe.directory work allows you to resolve permission issues in 30 seconds without compromising system security.
