git submodule
error handling
repository ownership
git troubleshooting
version control issues

git submodule update failed with 'fatal detected dubious ownership in repository at...'

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Git 2.35.2+ introduced a security check that refuses to operate on repositories owned by a different user than the current one. When running git submodule update, this check applies to each submodule directory, and if the submodule is owned by a different OS user (common in Docker containers, CI/CD pipelines, and shared file systems), Git throws fatal: detected dubious ownership in repository at. The fix is to add the directory to Git's safe.directory list or fix the actual file ownership.

The Error

bash
1$ git submodule update --init --recursive
2fatal: detected dubious ownership in repository at '/path/to/repo/submodule'
3To add an exception for this directory, call:
4    git config --global --add safe.directory /path/to/repo/submodule

This error means the submodule directory is owned by a different user than the one running the git command.

Why This Exists

Git added this check in response to CVE-2022-24765. Without it, a malicious user could place a .git directory in a shared location (like /tmp) and configure Git hooks that execute arbitrary code when another user runs git commands in that directory. The ownership check prevents Git from trusting repositories owned by other users.

bash
1# Check who owns the directory vs who you are
2ls -la /path/to/repo/submodule
3#   owner: root
4
5whoami
6#   developer
7# Mismatch → dubious ownership error

Fix 1: Add safe.directory (Quick Fix)

bash
1# Add the specific submodule path
2git config --global --add safe.directory /path/to/repo/submodule
3
4# Or allow all directories (less secure)
5git config --global --add safe.directory '*'
6
7# For multiple submodules, add each one
8git config --global --add safe.directory /path/to/repo/sub1
9git config --global --add safe.directory /path/to/repo/sub2
10git config --global --add safe.directory /path/to/repo/sub3

This tells Git to trust the directory even though it is owned by another user.

Fix 2: Fix File Ownership (Proper Fix)

bash
1# Change ownership to the current user
2sudo chown -R $(whoami) /path/to/repo
3
4# Or change ownership of just the submodule
5sudo chown -R $(whoami) /path/to/repo/submodule
6
7# Verify
8ls -la /path/to/repo/submodule/.git

This is the correct fix when you actually own the repository and the ownership was wrong (e.g., after extracting an archive as root).

Fix 3: Docker Containers

This error is extremely common in Docker because files mounted from the host or created by different users inside the container have mismatched ownership.

dockerfile
1# Option 1: Run Git commands as the file owner
2FROM ubuntu:22.04
3RUN apt-get update && apt-get install -y git
4
5# Add safe.directory in the Dockerfile
6RUN git config --global --add safe.directory /app
7WORKDIR /app
8COPY . .
9RUN git submodule update --init --recursive
dockerfile
1# Option 2: Fix ownership in the entrypoint
2FROM ubuntu:22.04
3COPY entrypoint.sh /entrypoint.sh
4ENTRYPOINT ["/entrypoint.sh"]
bash
1#!/bin/bash
2# entrypoint.sh
3chown -R $(id -u):$(id -g) /app
4git submodule update --init --recursive
5exec "$@"
yaml
1# Option 3: Docker Compose — set user to match host
2services:
3  app:
4    build: .
5    user: "${UID}:${GID}"
6    volumes:
7      - .:/app

Fix 4: CI/CD Pipelines

GitHub Actions

yaml
1jobs:
2  build:
3    runs-on: ubuntu-latest
4    steps:
5      - uses: actions/checkout@v4
6        with:
7          submodules: recursive
8      # If the error persists:
9      - run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
10      - run: git submodule update --init --recursive

GitLab CI

yaml
1before_script:
2  - git config --global --add safe.directory "${CI_PROJECT_DIR}"
3  - git submodule sync --recursive
4  - git submodule update --init --recursive

Jenkins

groovy
1pipeline {
2    agent any
3    stages {
4        stage('Checkout') {
5            steps {
6                sh 'git config --global --add safe.directory "${WORKSPACE}"'
7                checkout scmGit(
8                    branches: [[name: 'main']],
9                    extensions: [submodule(recursiveSubmodules: true)]
10                )
11            }
12        }
13    }
14}

Automating safe.directory for All Submodules

bash
1# Add safe.directory for every submodule in the repo
2git submodule foreach --recursive \
3  'git config --global --add safe.directory $toplevel/$sm_path'
4
5# Then update
6git submodule update --init --recursive

Checking Your Git Version

The ownership check was introduced in Git 2.35.2. If you cannot fix the ownership and safe.directory is not available:

bash
1git --version
2# git version 2.35.1  ← no ownership check
3# git version 2.35.2+ ← has ownership check
4
5# Downgrading Git is NOT recommended — the check exists for security

Common Pitfalls

  • Using safe.directory '*' in production: The wildcard disables ownership checks globally, defeating the security purpose. Use it only in ephemeral environments like CI containers. In production, add specific paths.
  • Forgetting recursive submodules: If submodule A contains submodule B, you must add both paths to safe.directory. Use git submodule foreach --recursive to add all of them automatically.
  • Setting safe.directory in the wrong Git config scope: --global sets it for the current user. In Docker containers running as root, this configures root's gitconfig. If the container later switches users, the setting is lost. Use --system for container-wide settings.
  • Fixing ownership in a mounted volume: chown inside a Docker container does not change ownership on the host when using bind mounts on Linux. The files remain owned by the host user. Use user: in docker-compose.yml to match the host UID instead.
  • Not understanding the security implication: The error exists to prevent code execution attacks via malicious .git directories. Before adding safe.directory, verify that the repository is actually trusted and the ownership mismatch is benign (Docker, CI) rather than a sign of compromise.

Summary

  • Git 2.35.2+ refuses to operate on repositories owned by a different user (CVE-2022-24765 fix)
  • Quick fix: git config --global --add safe.directory /path/to/repo
  • Proper fix: chown -R $(whoami) /path/to/repo to correct ownership
  • Docker containers: add safe.directory in the Dockerfile or match UIDs with user: in compose
  • CI/CD: add safe.directory for $GITHUB_WORKSPACE or $CI_PROJECT_DIR in pipeline config
  • Avoid safe.directory '*' outside of ephemeral, trusted environments

Course illustration
Course illustration

All Rights Reserved.