diff options
author | Johannes Schindelin <johannes.schindelin@gmx.de> | 2024-03-30 19:12:50 +0100 |
---|---|---|
committer | Johannes Schindelin <johannes.schindelin@gmx.de> | 2024-04-19 12:38:24 +0200 |
commit | 20f3588efc6cbcae5bbaabf65ee12df87b51a9ea (patch) | |
tree | f3121b1e7181c1a7f8fd2b5e8d1faf07342e87db /config.c | |
parent | init.templateDir: consider this config setting protected (diff) | |
download | git-20f3588efc6cbcae5bbaabf65ee12df87b51a9ea.tar.xz git-20f3588efc6cbcae5bbaabf65ee12df87b51a9ea.zip |
core.hooksPath: add some protection while cloning
Quite frequently, when vulnerabilities were found in Git's (quite
complex) clone machinery, a relatively common way to escalate the
severity was to trick Git into running a hook which is actually a script
that has just been laid on disk as part of that clone. This constitutes
a Remote Code Execution vulnerability, the highest severity observed in
Git's vulnerabilities so far.
Some previously-fixed vulnerabilities allowed malicious repositories to
be crafted such that Git would check out files not in the worktree, but
in, say, a submodule's `<git>/hooks/` directory.
A vulnerability that "merely" allows to modify the Git config would
allow a related attack vector, to manipulate Git into looking in the
worktree for hooks, e.g. redirecting the location where Git looks for
hooks, via setting `core.hooksPath` (which would be classified as
CWE-427: Uncontrolled Search Path Element and CWE-114: Process Control,
for more details see https://cwe.mitre.org/data/definitions/427.html and
https://cwe.mitre.org/data/definitions/114.html).
To prevent that attack vector, let's error out and complain loudly if an
active `core.hooksPath` configuration is seen in the repository-local
Git config during a `git clone`.
There is one caveat: This changes Git's behavior in a slightly
backwards-incompatible manner. While it is probably a rare scenario (if
it exists at all) to configure `core.hooksPath` via a config in the Git
templates, it _is_ conceivable that some valid setup requires this to
work. In the hopefully very unlikely case that a user runs into this,
there is an escape hatch: set the `GIT_CLONE_PROTECTION_ACTIVE=false`
environment variable. Obviously, this should be done only with utmost
caution.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Diffstat (limited to 'config.c')
-rw-r--r-- | config.c | 13 |
1 files changed, 12 insertions, 1 deletions
@@ -1525,8 +1525,19 @@ static int git_default_core_config(const char *var, const char *value, void *cb) if (!strcmp(var, "core.attributesfile")) return git_config_pathname(&git_attributes_file, var, value); - if (!strcmp(var, "core.hookspath")) + if (!strcmp(var, "core.hookspath")) { + if (current_config_scope() == CONFIG_SCOPE_LOCAL && + git_env_bool("GIT_CLONE_PROTECTION_ACTIVE", 0)) + die(_("active `core.hooksPath` found in the local " + "repository config:\n\t%s\nFor security " + "reasons, this is disallowed by default.\nIf " + "this is intentional and the hook should " + "actually be run, please\nrun the command " + "again with " + "`GIT_CLONE_PROTECTION_ACTIVE=false`"), + value); return git_config_pathname(&git_hooks_path, var, value); + } if (!strcmp(var, "core.bare")) { is_bare_repository_cfg = git_config_bool(var, value); |