git “fatal: detected dubious ownership in repository”: what it means and the safe fix
Git can be told to run programs from a repository’s own config file. So if someone else owns a repository you step into, they could make your git run their commands. Since 2022 git checks that the repository belongs to you, and stops with <i>dubious ownership</i> if it doesn’t.
The full message
fatal: detected dubious ownership in repository at '/srv/app'
To add an exception for this directory, call:
git config --global --add safe.directory /srv/app
On Windows the message also says who owns it, for example 'C:/code/app' is owned by: 'BUILTIN/Administrators' but the current user is: 'PC/sam'.
Why git checks
A repository’s .git/config can name programs git will run, such as a pager, an editor or a file-system monitor. Before the check, anyone who could create a .git folder in a shared or parent directory could get other users’ git commands, or a shell prompt that runs git status, to run their code. Checking ownership closes that hole. That’s why the exception lives in your own global config and is ignored if placed in the repository’s config.
Find out who owns it
ls -ld /srv/app /srv/app/.git # owner of the folder and of .git
id -u; id -un # who you are
stat -c '%u %U %n' /srv/app # numeric owner (handy inside containers)
Causes and fixes
| Situation | Fix |
|---|---|
You once ran sudo git clone or sudo git pull, so root owns it | sudo chown -R "$(id -u):$(id -g)" /path/to/repo, then stop using sudo with git |
| A web server or deploy user owns the checkout | Run git as that user: sudo -u www-data git -C /srv/app pull, or add a safe.directory entry for that exact path |
| Docker bind mount: the host user ID differs from the container’s | Run the container as your ID (--user "$(id -u):$(id -g)"), or inside it run git config --global --add safe.directory /app |
| CI job inside a container (git commands after checkout fail) | Add a step: git config --global --add safe.directory "$PWD". Many checkout actions now do this for you |
WSL working on /mnt/c/..., or an external, FAT or exFAT drive | These drives report a fixed owner. Add safe.directory for the path, or move the repo into your Linux home folder (also much faster) |
| Windows: repo created by an admin prompt or another account | Take ownership in the folder’s Security settings, or add the path in the form git prints: git config --global --add safe.directory C:/code/app |
| A submodule inside the repo | Each submodule path is checked separately; add each one or fix ownership for the whole tree |
About safe.directory '*'
git config --global --add safe.directory '*' turns the check off for every folder. It’s reasonable inside a throwaway container or CI job that only ever sees its own code. On a laptop or a shared server, list the paths you actually mean. To see or undo entries: git config --global --get-all safe.directory and git config --global --unset-all safe.directory.
Related
Git saying not a git repository instead? See fatal: not a git repository. Fixing ownership often goes with fixing modes: chmod 755, 644 and 600 explained. Docker permissions in general: docker.sock permission denied. Not allowed to use sudo at all? See user is not in the sudoers file.
Questions
What does detected dubious ownership in repository mean?
The repository folder belongs to a different user than the one running git. Git stops because a repository's config can make git run programs, so it only trusts repositories you own or have listed in safe.directory.
How do I fix dubious ownership after using sudo?
Give the folder back to yourself with sudo chown -R $(id -u):$(id -g) /path/to/repo and run git without sudo from then on.
Is git config --global --add safe.directory '*' safe?
It disables the check everywhere. That's acceptable in a throwaway container or CI job, but on a personal or shared machine add only the specific paths you trust.
Why can't I put safe.directory in the repository's own .git/config?
Because the point of the check is not to trust that repository's config yet. Git only reads safe.directory from system, global or command-line config.
Published .