git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: "brian m. carlson" <sandals@crustytoothpaste.net>,
	Jeff King <peff@peff.net>,
	Johannes Schindelin <johannes.schindelin@gmx.de>,
	Johannes Schindelin <johannes.schindelin@gmx.de>
Subject: [PATCH v3 5/6] clone: drop the protections where hooks aren't run
Date: Mon, 20 May 2024 20:22:04 +0000	[thread overview]
Message-ID: <0044a35567417a552cc518576670b43f7141a02e.1716236526.git.gitgitgadget@gmail.com> (raw)
In-Reply-To: <pull.1732.v3.git.1716236526.gitgitgadget@gmail.com>

From: Johannes Schindelin <johannes.schindelin@gmx.de>

As part of the security bug-fix releases v2.39.4, ..., v2.45.1, I
introduced logic to safeguard `git clone` from running hooks that were
installed _during_ the clone operation.

The rationale was that Git's CVE-2024-32002, CVE-2021-21300,
CVE-2019-1354, CVE-2019-1353, CVE-2019-1352, and CVE-2019-1349 should
have been low-severity vulnerabilities but were elevated to
critical/high severity by the attack vector that allows a weakness where
files inside `.git/` can be inadvertently written during a `git clone`
to escalate to a Remote Code Execution attack by virtue of installing a
malicious `post-checkout` hook that Git will then run at the end of the
operation without giving the user a chance to see what code is executed.

Unfortunately, Git LFS uses a similar strategy to install its own
`post-checkout` hook during a `git clone`; In fact, Git LFS is
installing four separate hooks while running the `smudge` filter.

While this pattern is probably in want of being improved by introducing
better support in Git for Git LFS and other tools wishing to register
hooks to be run at various stages of Git's commands, let's undo the
clone protections to unbreak Git LFS-enabled clones.

This reverts commit 8db1e8743c0 (clone: prevent hooks from running
during a clone, 2024-03-28).

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 builtin/clone.c  | 12 +-----------
 hook.c           | 34 --------------------------------
 t/t5601-clone.sh | 51 ------------------------------------------------
 3 files changed, 1 insertion(+), 96 deletions(-)

diff --git a/builtin/clone.c b/builtin/clone.c
index e7721f5c22c..9ec500d427e 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -937,8 +937,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 	int err = 0, complete_refs_before_fetch = 1;
 	int submodule_progress;
 	int filter_submodules = 0;
-	const char *template_dir;
-	char *template_dir_dup = NULL;
 
 	struct transport_ls_refs_options transport_ls_refs_options =
 		TRANSPORT_LS_REFS_OPTIONS_INIT;
@@ -958,13 +956,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 		usage_msg_opt(_("You must specify a repository to clone."),
 			builtin_clone_usage, builtin_clone_options);
 
-	xsetenv("GIT_CLONE_PROTECTION_ACTIVE", "true", 0 /* allow user override */);
-	template_dir = get_template_dir(option_template);
-	if (*template_dir && !is_absolute_path(template_dir))
-		template_dir = template_dir_dup =
-			absolute_pathdup(template_dir);
-	xsetenv("GIT_CLONE_TEMPLATE_DIR", template_dir, 1);
-
 	if (option_depth || option_since || option_not.nr)
 		deepen = 1;
 	if (option_single_branch == -1)
@@ -1112,7 +1103,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 		}
 	}
 
-	init_db(git_dir, real_git_dir, template_dir, GIT_HASH_UNKNOWN, NULL,
+	init_db(git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN, NULL,
 		INIT_DB_QUIET);
 
 	if (real_git_dir) {
@@ -1430,7 +1421,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 	free(unborn_head);
 	free(dir);
 	free(path);
-	free(template_dir_dup);
 	UNLEAK(repo);
 	junk_mode = JUNK_LEAVE_ALL;
 
diff --git a/hook.c b/hook.c
index fc974cee1d8..22b274b60b1 100644
--- a/hook.c
+++ b/hook.c
@@ -3,32 +3,6 @@
 #include "run-command.h"
 #include "config.h"
 
-static int identical_to_template_hook(const char *name, const char *path)
-{
-	const char *env = getenv("GIT_CLONE_TEMPLATE_DIR");
-	const char *template_dir = get_template_dir(env && *env ? env : NULL);
-	struct strbuf template_path = STRBUF_INIT;
-	int found_template_hook, ret;
-
-	strbuf_addf(&template_path, "%s/hooks/%s", template_dir, name);
-	found_template_hook = access(template_path.buf, X_OK) >= 0;
-#ifdef STRIP_EXTENSION
-	if (!found_template_hook) {
-		strbuf_addstr(&template_path, STRIP_EXTENSION);
-		found_template_hook = access(template_path.buf, X_OK) >= 0;
-	}
-#endif
-	if (!found_template_hook) {
-		strbuf_release(&template_path);
-		return 0;
-	}
-
-	ret = do_files_match(template_path.buf, path);
-
-	strbuf_release(&template_path);
-	return ret;
-}
-
 const char *find_hook(const char *name)
 {
 	static struct strbuf path = STRBUF_INIT;
@@ -64,14 +38,6 @@ const char *find_hook(const char *name)
 		}
 		return NULL;
 	}
-	if (!git_hooks_path && git_env_bool("GIT_CLONE_PROTECTION_ACTIVE", 0) &&
-	    !identical_to_template_hook(name, path.buf))
-		die(_("active `%s` hook found during `git clone`:\n\t%s\n"
-		      "For security reasons, this is disallowed by default.\n"
-		      "If this is intentional and the hook should actually "
-		      "be run, please\nrun the command again with "
-		      "`GIT_CLONE_PROTECTION_ACTIVE=false`"),
-		    name, path.buf);
 	return path.buf;
 }
 
diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh
index 20deca0231b..fd029843307 100755
--- a/t/t5601-clone.sh
+++ b/t/t5601-clone.sh
@@ -771,57 +771,6 @@ test_expect_success 'batch missing blob request does not inadvertently try to fe
 	git clone --filter=blob:limit=0 "file://$(pwd)/server" client
 '
 
-test_expect_success 'clone with init.templatedir runs hooks' '
-	git init tmpl/hooks &&
-	write_script tmpl/hooks/post-checkout <<-EOF &&
-	echo HOOK-RUN >&2
-	echo I was here >hook.run
-	EOF
-	git -C tmpl/hooks add . &&
-	test_tick &&
-	git -C tmpl/hooks commit -m post-checkout &&
-
-	test_when_finished "git config --global --unset init.templateDir || :" &&
-	test_when_finished "git config --unset init.templateDir || :" &&
-	(
-		sane_unset GIT_TEMPLATE_DIR &&
-		NO_SET_GIT_TEMPLATE_DIR=t &&
-		export NO_SET_GIT_TEMPLATE_DIR &&
-
-		git -c core.hooksPath="$(pwd)/tmpl/hooks" \
-			clone tmpl/hooks hook-run-hookspath 2>err &&
-		! grep "active .* hook found" err &&
-		test_path_is_file hook-run-hookspath/hook.run &&
-
-		git -c init.templateDir="$(pwd)/tmpl" \
-			clone tmpl/hooks hook-run-config 2>err &&
-		! grep "active .* hook found" err &&
-		test_path_is_file hook-run-config/hook.run &&
-
-		git clone --template=tmpl tmpl/hooks hook-run-option 2>err &&
-		! grep "active .* hook found" err &&
-		test_path_is_file hook-run-option/hook.run &&
-
-		git config --global init.templateDir "$(pwd)/tmpl" &&
-		git clone tmpl/hooks hook-run-global-config 2>err &&
-		git config --global --unset init.templateDir &&
-		! grep "active .* hook found" err &&
-		test_path_is_file hook-run-global-config/hook.run &&
-
-		# clone ignores local `init.templateDir`; need to create
-		# a new repository because we deleted `.git/` in the
-		# `setup` test case above
-		git init local-clone &&
-		cd local-clone &&
-
-		git config init.templateDir "$(pwd)/../tmpl" &&
-		git clone ../tmpl/hooks hook-run-local-config 2>err &&
-		git config --unset init.templateDir &&
-		! grep "active .* hook found" err &&
-		test_path_is_missing hook-run-local-config/hook.run
-	)
-'
-
 . "$TEST_DIRECTORY"/lib-httpd.sh
 start_httpd
 
-- 
gitgitgadget


  parent reply	other threads:[~2024-05-20 20:22 UTC|newest]

Thread overview: 54+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-05-17 23:15 [PATCH 0/8] Various fixes for v2.45.1 and friends Johannes Schindelin via GitGitGadget
2024-05-17 23:15 ` [PATCH 1/8] hook: plug a new memory leak Johannes Schindelin via GitGitGadget
2024-05-17 23:15 ` [PATCH 2/8] init: use the correct path of the templates directory again Johannes Schindelin via GitGitGadget
2024-05-17 23:15 ` [PATCH 3/8] Revert "core.hooksPath: add some protection while cloning" Johannes Schindelin via GitGitGadget
2024-05-17 23:15 ` [PATCH 4/8] tests: verify that `clone -c core.hooksPath=/dev/null` works again Johannes Schindelin via GitGitGadget
2024-05-18  0:10   ` Junio C Hamano
2024-05-18 18:58     ` Johannes Schindelin
2024-05-17 23:15 ` [PATCH 5/8] hook(clone protections): add escape hatch Johannes Schindelin via GitGitGadget
2024-05-18  0:21   ` Junio C Hamano
2024-05-17 23:15 ` [PATCH 6/8] hooks(clone protections): special-case current Git LFS hooks Johannes Schindelin via GitGitGadget
2024-05-18  0:20   ` Junio C Hamano
2024-05-17 23:15 ` [PATCH 7/8] hooks(clone protections): simplify templates hooks validation Johannes Schindelin via GitGitGadget
2024-05-17 23:15 ` [PATCH 8/8] Revert "Add a helper function to compare file contents" Johannes Schindelin via GitGitGadget
2024-05-17 23:52 ` [PATCH 0/8] Various fixes for v2.45.1 and friends Junio C Hamano
2024-05-18  0:02   ` Johannes Schindelin
2024-05-18 10:32 ` [PATCH v2 " Johannes Schindelin via GitGitGadget
2024-05-18 10:32   ` [PATCH v2 1/8] hook: plug a new memory leak Johannes Schindelin via GitGitGadget
2024-05-18 10:32   ` [PATCH v2 2/8] init: use the correct path of the templates directory again Johannes Schindelin via GitGitGadget
2024-05-18 10:32   ` [PATCH v2 3/8] Revert "core.hooksPath: add some protection while cloning" Johannes Schindelin via GitGitGadget
2024-05-18 10:32   ` [PATCH v2 4/8] tests: verify that `clone -c core.hooksPath=/dev/null` works again Johannes Schindelin via GitGitGadget
2024-05-18 10:32   ` [PATCH v2 5/8] hook(clone protections): add escape hatch Johannes Schindelin via GitGitGadget
2024-05-18 18:14     ` Jeff King
2024-05-18 18:54       ` Junio C Hamano
2024-05-18 19:35         ` Jeff King
2024-05-18 19:37         ` Johannes Schindelin
2024-05-18 19:32       ` Johannes Schindelin
2024-05-18 19:47         ` Jeff King
2024-05-18 20:06           ` Johannes Schindelin
2024-05-18 21:12             ` Jeff King
2024-05-19  1:15               ` Junio C Hamano
2024-05-20 16:05                 ` Johannes Schindelin
2024-05-20 18:18                   ` Junio C Hamano
2024-05-20 19:38                     ` Johannes Schindelin
2024-05-20 20:07                       ` Junio C Hamano
2024-05-20 21:03                       ` Johannes Schindelin
2024-05-18 10:32   ` [PATCH v2 6/8] hooks(clone protections): special-case current Git LFS hooks Johannes Schindelin via GitGitGadget
2024-05-18 10:32   ` [PATCH v2 7/8] hooks(clone protections): simplify templates hooks validation Johannes Schindelin via GitGitGadget
2024-05-18 10:32   ` [PATCH v2 8/8] Revert "Add a helper function to compare file contents" Johannes Schindelin via GitGitGadget
2024-05-18 17:07   ` [PATCH v2 0/8] Various fixes for v2.45.1 and friends Junio C Hamano
2024-05-18 19:22     ` Johannes Schindelin
2024-05-18 20:13       ` Johannes Schindelin
2024-05-20 20:21   ` [PATCH v3 0/6] " Johannes Schindelin via GitGitGadget
2024-05-20 20:22     ` [PATCH v3 1/6] hook: plug a new memory leak Johannes Schindelin via GitGitGadget
2024-05-20 20:22     ` [PATCH v3 2/6] init: use the correct path of the templates directory again Johannes Schindelin via GitGitGadget
2024-05-20 20:22     ` [PATCH v3 3/6] Revert "core.hooksPath: add some protection while cloning" Johannes Schindelin via GitGitGadget
2024-05-20 20:22     ` [PATCH v3 4/6] tests: verify that `clone -c core.hooksPath=/dev/null` works again Johannes Schindelin via GitGitGadget
2024-05-20 20:22     ` Johannes Schindelin via GitGitGadget [this message]
2024-05-20 20:22     ` [PATCH v3 6/6] Revert "Add a helper function to compare file contents" Johannes Schindelin via GitGitGadget
2024-05-20 23:56     ` [PATCH v3 0/6] Various fixes for v2.45.1 and friends Junio C Hamano
2024-05-21  5:33       ` Junio C Hamano
2024-05-21 18:14         ` Junio C Hamano
2024-05-21 22:33     ` brian m. carlson
2024-05-21 22:40       ` Junio C Hamano
2024-05-21 23:04       ` Junio C Hamano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=0044a35567417a552cc518576670b43f7141a02e.1716236526.git.gitgitgadget@gmail.com \
    --to=gitgitgadget@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=johannes.schindelin@gmx.de \
    --cc=peff@peff.net \
    --cc=sandals@crustytoothpaste.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).