git-for-windows / git

A fork of Git containing Windows-specific patches.
http://gitforwindows.org/
Other
8.39k stars 2.54k forks source link

Disabling safe directory checks (safe.directory = *) is not working #3809

Closed DigNative closed 2 years ago

DigNative commented 2 years ago

The issue seems very similar to #3786, however, the suggested solutions there do not solve the issue for me.

Setup

$ git --version --build-options

git version 2.35.3.windows.1
cpu: x86_64
built from commit: b952ed2af65bd726a4d21270bc3911db79873fe2
sizeof-long: 4
sizeof-size_t: 8
shell-path: /bin/sh
feature: fsmonitor--daemon
$ cmd.exe /c ver

Microsoft Windows [Version 10.0.19043.1645]
> type "C:\Program Files\Git\etc\install-options.txt"

Editor Option: Notepad++
Custom Editor Path:
Default Branch Option:
Path Option: Cmd
SSH Option: OpenSSH
Tortoise Option: false
CURL Option: OpenSSL
CRLF Option: CRLFCommitAsIs
Bash Terminal Option: MinTTY
Git Pull Behavior Option: Merge
Use Credential Manager: Enabled
Performance Tweaks FSCache: Enabled
Enable Symlinks: Disabled
Enable Pseudo Console Support: Disabled
Enable FSMonitor: Disabled

Almost all of the repositories I am working with are located on network shares, which are mapped as drives on Windows.

Details

CMD (used for everything below), Cygwin, and TortoiseGit

git config --global --add safe.directory "*"
git pull

Fetch and integrate the latest commits of a remote repository.

fatal: unsafe repository ('//server.local/Path/to/repo' is owned by someone else)
To add an exception for this directory, call:

        git config --global --add safe.directory '%(prefix)///server.local/Path/to/repo'

The safe.directory = "*" setting seems not to be effective. I also tried all possible variations with the specific repository path which made sense to me:

git config --global --add safe.directory '%(prefix)///server.local/*'
git config --global --add safe.directory '%(prefix)///server.local/Path/to/repo'

None of them worked and I was always getting the fatal error reported above.

No, since the issue seems to be related to the storage path of the local repository.

dscho commented 2 years ago

git config --global --add safe.directory "*"

Can you please make sure that it was added correctly? Run git config --global --get-all safe.directory to see the entries.

DigNative commented 2 years ago

git config --global --add safe.directory "*"

Can you please make sure that it was added correctly? Run git config --global --get-all safe.directory to see the entries.

Yes, I did cross-check the configuration file before filing this issue report. The configuration options seem to be properly applied.

Following is my current configuration:

> git config --global --get-all safe.directory
'*'
'%(prefix)///server.local/*'
'%(prefix)///server.local/Path/to/repo'
DigNative commented 2 years ago

I was able to figure out why it was not working: The enclosing single quotation marks for the path specification seem to be the issue. If they are removed or replaced by double quotation marks, it works for me.

does not work:

[safe]
    directory = '*'

does work:

[safe]
    directory = "*"

I actually used single quotation marks as the error message from git suggests to do so (I simply copied & pasted the suggested command line in the beginning):

fatal: unsafe repository ('//server.local/Path/to/repo' is owned by someone else)
To add an exception for this directory, call:

        git config --global --add safe.directory '%(prefix)///server.local/Path/to/repo'

Having said this, the following would be working:

# not working, but suggested by git
git config --global --add safe.directory '%(prefix)///server.local/Path/to/repo'

# working
git config --global --add safe.directory "%(prefix)///server.local/Path/to/repo"

Also the global disabling for all directories using the asterisk works for me.

I don't know if this issue with the single quotation marks is specific to my environment.

dscho commented 2 years ago

does not work:

[safe]
  directory = '*'

As https://git-scm.com/docs/git-config#_syntax explains, single quotes are not treated as quoting characters, only double quotes are.

'%(prefix)///server.local/*'

Git's handling of * in safe.directory values is not actually a globbing mechanism. It is merely a special value * that is handled in a specific way, all other values are handled verbatim (including the casing!).

DigNative commented 2 years ago

As https://git-scm.com/docs/git-config#_syntax explains, single quotes are not treated as quoting characters, only double quotes are.

'%(prefix)///server.local/*'

Git's handling of * in safe.directory values is not actually a globbing mechanism. It is merely a special value * that is handled in a specific way, all other values are handled verbatim (including the casing!).

Thank you for the clarifications. The issue then actually is that the suggested command by git in the error message is erroneous since it uses single quotation marks, while these should be double quotation marks.

rimrul commented 2 years ago

the suggested command by git in the error message is erroneous since it uses single quotation marks

Kinda. It isn't really erroneous, it just falls into a pattern that git often (always?) uses when suggesting commands. It assumes you're running it from a POSIX shell, which would treat * as a globbing pattern.

It would be great if we could reliably detect being run from cmd or powershell and suggest the appropriate syntax in these situations, but I don't see a good way of doing that.

viceice commented 2 years ago

Having somehow same issue. I'm using Jenkins with docker containers on windows.

  1. So jenkins is checking out the git repo on host with jenkins-agent user
  2. jenkins is starting docker container
  3. jenkins is running my commands as container user

So i tried to add safe.directory which results to

> git config --global --add safe.directory "%WORKSPACE%"
> git config --global --get-all safe.directory
c:\jenkins\workspace\repo_folder
> git log -n 3
fatal: unsafe repository ('C:/jenkins/workspace/repo_folder' is owned by someone else)
To add an exception for this directory, call:

    git config --global --add safe.directory C:/jenkins/workspace/repo_folder

Is there any workaround? It seems to be caused by the wrong backslashes. 🤔

dscho commented 2 years ago

You could use cygpath -am %WORKSPACE% to convert the path.

viceice commented 2 years ago

You could use cygpath -am %WORKSPACE% to convert the path.

🤔 this would require to run from git bash, otherwise command isn't found. also not easily doable on Jenkins.

I'm now disable with *, i don't see any security issues on CI with ephemeral docker containers.

dscho commented 2 years ago

🤔 this would require to run from git bash, otherwise command isn't found. also not easily doable on Jenkins.

You could run it via git -c alias.cygpath="!cygpath" cygpath -am "%WORKSPACE".

But then it would make more sense to do the substitution in an alias right away:

git -c alias.xyz="!git config --global --add safe.directory $(cygpath -am $WORKSPACE)" xyz
Diogo-Rossi commented 2 months ago

Hello @dscho

Git's handling of * in safe.directory values is not actually a globbing mechanism. It is merely a special value * that is handled in a specific way, all other values are handled verbatim (including the casing!).

So, this last phrase in https://git-scm.com/docs/git-config#Documentation/git-config.txt-safedirectory :

To completely opt-out of this security check, set safe.directory to the string *. [...]. *Giving a directory with `/` appended to it will allow access to all repositories under the named directory.**

is not right?

rimrul commented 2 months ago

Git's handling of * in safe.directory values is not actually a globbing mechanism. It is merely a special value * that is handled in a specific way, all other values are handled verbatim (including the casing!).

That was accurate at the time of writing, but since Git 2.46.0 safe.directory allows leading path matching.

So, this last phrase in https://git-scm.com/docs/git-config#Documentation/git-config.txt-safedirectory :

To completely opt-out of this security check, set safe.directory to the string *. [...]. *Giving a directory with `/` appended to it will allow access to all repositories under the named directory.**

is not right?

That documentation is correct, but that sentence (and that behaviour) didn't exist in 2022.

Diogo-Rossi commented 2 months ago

@rimrul Thanks!