Permanently Fix ‘fatal: detected dubious ownership in repository’ with Git safe.directory

Git tutorial - IT technology blog
Git tutorial - IT technology blog

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.

Share: