Re: Security of .git/config and .git/hooks
From: Junio C Hamano <hidden>
Date: 2017-10-03 01:12:25
Jonathan Nieder [off-list ref] writes:
Proposed fix: because of case (1), I would like a way to tell Git to
stop trusting any files in .git. That is:
1. Introduce a (configurable) list of "safe" configuration items that
can be set in .git/config and don't respect any others.The list of "safe" things are configurable by having something in ~/.gitconfig, perhaps? How would this work, from the end-user's point of view, with "git config --global" and "git config --local"?
2. But what if I want to set a different pager per-repository?
I think we could do this using configuration "profiles".
My ~/.config/git/profiles/ directory would contain git-style
config files for repositories to include. Repositories could
then contain
[include]
path = ~/.config/git/profiles/fancy-log-pager
to make use of those settings. The facility (1) would
special-case this directory to allow it to set "unsafe" settings
since files there are assumed not to be under the control of an
attacker.Meaning, "include" is not in "safe" category, but a value that begins with "~/.config/git/" are excempt???
3. Likewise for hooks: my ~/.config/git/hooks/ directory would
contain hooks for repositories to make use of. Repositories could
symlink to hook files from there to make use of them.I am not sure what this means. .git/hooks/pre-commit being a symbolic link to "~/.config/git/hooks/pre-commit-fancy" (i.e. readlink gives the path with tilde unexpanded), so that the attacked sysadmin will not run it from ~attacker/.config/git/hooks? And the code that finds a hook to run sees .git/hooks/pre-commit, resolves the symlink manually and makes sure it leads to somewhere inside ~/.config/... (otherwise it rejects) and then uses the pointed-at copy? At that point, we are not taking any advantage of symbolic-link-ness of the entity, so .git/hooks/pre-commit being a text file that has a single like, e.g. # safe-hook: pre-commit-fancy may be sufficient (and we do not have to worry about systems without symbolic links)? The machinery that used to manually resolved symlink instead reads it, finds "pre-commit-fancy" in ~/.config/git/hooks/ and runs it, and you get the same behaviour, no?
One downside of (3) is its reliance on symlinks. Some alternatives:
3b. Use core.hooksPath configuration instead. Rely on (2).
3c. Introduce new hook.* configuration to be used instead of hook
scripts. Rely on (2).I guess I invented 3d. without reading ahead X-<. None of the 3x variants other than 3 proper will not work for scripts and existing code that sees that .git/hooks/pre-commit is an executable and runs it, and 3 proper will not work without symbolic links, so this means we'd need "git locate-hook pre-commit" (and underlying locate_hook() helper API) that returns "/home/me/.git/config/hook/pre-commit-fancy" or fails when we do this transition. In an unconverted repository, it may return $PWD/.git/hooks/pre-commit, or failure if we are running under the paranoid mode. Sounds workable.