Skip to content

ggshield ignores users global git configuration fileΒ #1055

@PinkSheep

Description

@PinkSheep

Environment

  • ggshield version: 1.36.0
  • Operating system (Linux, macOS, Windows): Linux
  • Operating system version: Ubuntu 24.04.2 LTS
  • Python version: 3.11.6

Describe the bug

Global Git user configuration is ignored/overwritten when running a ggshield scan, leading to dubious ownership errors.

Steps to reproduce:

mkdir ggshield_test
cd ggshield_test
git init
ggshield secret scan repo . # Works as expected with no errors
chown <different user>:<different group> /path/to/ggshield_test/ # change ownership of the repo to another user
ggshield secret scan repo . # ggshield complains about dubious ownership in the repo
git rev-parse --git-dir # git complains about dubious onwership in the repo
git config --global --add safe.directory /path/to/ggshield_test
git rev-parse --git-dir # git no longer complains about dubious ownership
ggshield secret scan repo . # ggshield still complains about dubious ownership in the repo

Actual result:

(ggshield) oli@K57252:~/tmp/ggshield_test$ ggshield secret scan repo .
Traceback (most recent call last):
  File "/home/oli/.pyenv/versions/3.11.6/envs/ggshield/lib/python3.11/site-packages/ggshield/utils/git_shell.py", line 206, in git
    result = subprocess.run(
             ^^^^^^^^^^^^^^^
  File "/home/oli/.pyenv/versions/3.11.6/lib/python3.11/subprocess.py", line 571, in run
    raise CalledProcessError(retcode, process.args,
subprocess.CalledProcessError: Command '['/usr/bin/git', 'rev-parse', '--git-dir']' returned non-zero exit status 128.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/oli/.pyenv/versions/ggshield/bin/ggshield", line 8, in <module>
    sys.exit(main())
             ^^^^^^
  File "/home/oli/.pyenv/versions/3.11.6/envs/ggshield/lib/python3.11/site-packages/ggshield/__main__.py", line 205, in main
    return cli.main(args, prog_name="ggshield", standalone_mode=not show_crash_log)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/oli/.pyenv/versions/3.11.6/envs/ggshield/lib/python3.11/site-packages/click/core.py", line 1078, in main
    rv = self.invoke(ctx)
         ^^^^^^^^^^^^^^^^
  File "/home/oli/.pyenv/versions/3.11.6/envs/ggshield/lib/python3.11/site-packages/click/core.py", line 1685, in invoke
    super().invoke(ctx)
  File "/home/oli/.pyenv/versions/3.11.6/envs/ggshield/lib/python3.11/site-packages/click/core.py", line 1434, in invoke
    return ctx.invoke(self.callback, **ctx.params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/oli/.pyenv/versions/3.11.6/envs/ggshield/lib/python3.11/site-packages/click/core.py", line 783, in invoke
    return __callback(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/oli/.pyenv/versions/3.11.6/envs/ggshield/lib/python3.11/site-packages/click/decorators.py", line 33, in new_func
    return f(get_current_context(), *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/oli/.pyenv/versions/3.11.6/envs/ggshield/lib/python3.11/site-packages/ggshield/__main__.py", line 91, in cli
    ctx_obj.config = Config(config_path)
                     ^^^^^^^^^^^^^^^^^^^
  File "/home/oli/.pyenv/versions/3.11.6/envs/ggshield/lib/python3.11/site-packages/ggshield/core/config/config.py", line 66, in __init__
    self.user_config, self._config_path = UserConfig.load(config_path=config_path)
                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/oli/.pyenv/versions/3.11.6/envs/ggshield/lib/python3.11/site-packages/ggshield/core/config/user_config.py", line 143, in load
    local_config_path = find_local_config_path()
                        ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/oli/.pyenv/versions/3.11.6/envs/ggshield/lib/python3.11/site-packages/ggshield/core/config/utils.py", line 108, in find_local_config_path
    project_root_dir = get_project_root_dir(Path())
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/oli/.pyenv/versions/3.11.6/envs/ggshield/lib/python3.11/site-packages/ggshield/core/dirs.py", line 52, in get_project_root_dir
    return get_git_root(wd=path).resolve()
           ^^^^^^^^^^^^^^^^^^^^^
  File "/home/oli/.pyenv/versions/3.11.6/envs/ggshield/lib/python3.11/site-packages/ggshield/utils/git_shell.py", line 165, in get_git_root
    check_git_dir(wd)
  File "/home/oli/.pyenv/versions/3.11.6/envs/ggshield/lib/python3.11/site-packages/ggshield/utils/git_shell.py", line 179, in check_git_dir
    if not is_git_dir(wd):
           ^^^^^^^^^^^^^^
  File "/home/oli/.pyenv/versions/3.11.6/envs/ggshield/lib/python3.11/site-packages/ggshield/utils/git_shell.py", line 145, in is_git_dir
    return _git_rev_parse("--git-dir", Path(wd)) is not None
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/oli/.pyenv/versions/3.11.6/envs/ggshield/lib/python3.11/site-packages/ggshield/utils/git_shell.py", line 96, in _git_rev_parse
    return _git_rev_parse_absolute(option=option, wd_absolute=wd.resolve())
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/oli/.pyenv/versions/3.11.6/envs/ggshield/lib/python3.11/site-packages/ggshield/utils/git_shell.py", line 90, in _git_rev_parse_absolute
    return git(["rev-parse", option], cwd=wd_absolute, log_stderr=False)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/oli/.pyenv/versions/3.11.6/envs/ggshield/lib/python3.11/site-packages/ggshield/utils/git_shell.py", line 226, in git
    raise GitError(
ggshield.utils.git_shell.GitError: Git command failed because of a dubious ownership in repository.
If you still want to run ggshield, make sure you mark the current repository as safe for git with:
   git config --global --add safe.directory <YOUR_REPO>

Expected result:

ggshield respects the global git configuration by the user, who executes the ggshield scan.

The root cause of this error seems to be the following line in the code: https://github.com/GitGuardian/ggshield/blob/main/ggshield/utils/git_shell.py#L198 This sets the GIT_CONFIG_GLOBAL env var even if it was not set before. As a result, the path to the global git config is now an empty string. Therefore the git command ignores the users global git configuration file. As a workaround we now have to additionally set the GG_GIT_CONFIG env var to the path of the users global git config.

Based on the comment above the specific code it seems like this is intended? However I fail to see why ggshield would want to ignore/owerwrite the users global git configuration?

As a ggshield user I would expect ggshield to respect my global git configuration without the user having to set a specific env var that is not documented (as far as I know).

Metadata

Metadata

Assignees

No one assigned

    Labels

    status:newThis issue needs to be reviewedtype:bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions