git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH] fsck: detect bare repos in trees and warn

From
Glen Choo <chooglen@google.com>
Date
Apr 6, 2022, 23:22 UTC
Message-ID
<20220406232231.47714-1-chooglen@google.com>
In-Reply-To
<kl6lsfqpygsj.fsf@chooglen-macbookpro.roam.corp.google.com>

Git tries not to distribute configs in-repo because they are a security risk. However, an attacker can do exactly this if they embed a bare repo inside of another repo.

Teach fsck to detect whether a tree object contains a bare repo (as determined by setup.c) and warn. This will help hosting sites detect and prevent transmission of such malicious repos.

See [1] for a more in-depth discussion, including future steps and alternatives.

[1] https://lore.kernel.org/git/kl6lsfqpygsj.fsf@chooglen-macbookpro.roam.corp.google.com/
Signed-off-by: Glen Choo <chooglen@google.com>
---
 fsck.c          | 19 +++++++++++++++++++
 fsck.h          |  1 +
 setup.c         |  4 ++++
 t/t1450-fsck.sh | 36 ++++++++++++++++++++++++++++++++++++
 4 files changed, 60 insertions(+)
diff --git a/fsck.c b/fsck.c
index 3ec500d707..11c11c348a 100644
--- a/fsck.c
+++ b/fsck.c
@@ -573,6 +573,9 @@ static int fsck_tree(const struct object_id *tree_oid,
 	int has_bad_modes = 0;
 	int has_dup_entries = 0;
 	int not_properly_sorted = 0;
+	int has_head = 0;
+	int has_refs_entry = 0;
+	int has_objects_entry = 0;
 	struct tree_desc desc;
 	unsigned o_mode;
 	const char *o_name;
@@ -602,6 +605,12 @@ static int fsck_tree(const struct object_id *tree_oid,
 		has_dotdot |= !strcmp(name, "..");
 		has_dotgit |= is_hfs_dotgit(name) || is_ntfs_dotgit(name);
 		has_zero_pad |= *(char *)desc.buffer == '0';
+		has_head |= !strcasecmp(name, "HEAD")
+			&& (S_ISLNK(mode) || S_ISREG(mode));
+		has_refs_entry |= !strcasecmp(name, "refs")
+			&& (S_ISLNK(mode) || S_ISDIR(mode));
+		has_objects_entry |= !strcasecmp(name, "objects")
+			&& (S_ISLNK(mode) || S_ISDIR(mode));
 
 		if (is_hfs_dotgitmodules(name) || is_ntfs_dotgitmodules(name)) {
 			if (!S_ISLNK(mode))
@@ -739,6 +748,16 @@ static int fsck_tree(const struct object_id *tree_oid,
 		retval += report(options, tree_oid, OBJ_TREE,
 				 FSCK_MSG_TREE_NOT_SORTED,
 				 "not properly sorted");
+	/*
+	 * Determine if this tree looks like a bare repository according
+	 * to the rules of setup.c. If those are changed, this should be
+	 * changed too.
+	 */
+	if (has_head && has_refs_entry && has_objects_entry)
+		retval += report(options, tree_oid, OBJ_TREE,
+				 FSCK_MSG_EMBEDDED_BARE_REPO,
+				 "contains bare repository");
+
 	return retval;
 }
 
diff --git a/fsck.h b/fsck.h
index d07f7a2459..3f0f73b0f3 100644
--- a/fsck.h
+++ b/fsck.h
@@ -65,6 +65,7 @@ enum fsck_msg_type {
 	FUNC(NULL_SHA1, WARN) \
 	FUNC(ZERO_PADDED_FILEMODE, WARN) \
 	FUNC(NUL_IN_COMMIT, WARN) \
+	FUNC(EMBEDDED_BARE_REPO, WARN) \
 	/* infos (reported as warnings, but ignored by default) */ \
 	FUNC(GITMODULES_PARSE, INFO) \
 	FUNC(GITIGNORE_SYMLINK, INFO) \
diff --git a/setup.c b/setup.c
index 04ce33cdcd..2600548776 100644
--- a/setup.c
+++ b/setup.c
@@ -336,6 +336,10 @@ int get_common_dir_noenv(struct strbuf *sb, const char *gitdir)
  *  - either a HEAD symlink or a HEAD file that is formatted as
  *    a proper "ref:", or a regular file HEAD that has a properly
  *    formatted sha1 object name.
+ *
+ * fsck.c checks for bare repositories in trees using similar rules, but a
+ * duplicated implementation. If these are changed, the correspnding code in
+ * fsck.c should change too.
  */
 int is_git_directory(const char *suspect)
 {
diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh
index de50c0ea01..a65827bc03 100755
--- a/t/t1450-fsck.sh
+++ b/t/t1450-fsck.sh
@@ -563,6 +563,42 @@ dot-backslash-case .\\\\.GIT\\\\foobar
 dotgit-case-backslash .git\\\\foobar
 EOF
 
+test_expect_success "fsck notices bare repo" '
+(
+	mkdir -p embedded-bare-repo/bare &&
+	git init embedded-bare-repo &&
+	(
+		cd embedded-bare-repo/bare &&
+		echo content >HEAD &&
+		mkdir refs/ objects/ &&
+		echo content >refs/foo &&
+		echo content >objects/foo &&
+		git add . &&
+		git commit -m base &&
+		bad_tree=$(git rev-parse HEAD:bare) &&
+		git fsck 2>out &&
+		test_i18ngrep "warning.*tree $bad_tree: embeddedBareRepo: contains bare repository" out
+	)
+)'
+
+test_expect_success "fsck notices bare repo with odd casing" '
+(
+	mkdir -p embedded-bare-repo-case/bare &&
+	git init embedded-bare-repo-case &&
+	(
+		cd embedded-bare-repo-case/bare &&
+		echo content >heAD &&
+		mkdir Refs/ objectS/ &&
+		echo content >Refs/foo &&
+		echo content >objectS/foo &&
+		git add . &&
+		git commit -m base &&
+		bad_tree=$(git rev-parse HEAD:bare) &&
+		git fsck 2>out &&
+		test_i18ngrep "warning.*tree $bad_tree: embeddedBareRepo: contains bare repository" out
+	)
+)'
+
 test_expect_success 'fsck allows .Ňit' '
 	(
 		git init not-dotgit &&

base-commit: 805e0a68082a217f0112db9ee86a022227a9c81b
-- 
2.33.GIT
Previous: Glen ChooNext: Johannes Schindelin
Message 2 of 50 in “Bare repositories in the working tree are a security risk”
  1. Glen ChooApr 6, 2022
  2. fsck: detect bare repos in trees and warnGlen Choo, Apr 6, 2022
  3. Johannes SchindelinApr 7, 2022
  4. Derrick StoleeApr 7, 2022
  5. Ævar Arnfjörð BjarmasonApr 7, 2022
  6. Glen ChooApr 14, 2022
  7. Ævar Arnfjörð BjarmasonApr 15, 2022
  8. Junio C HamanoApr 7, 2022
  9. Glen ChooApr 13, 2022
  10. Ævar Arnfjörð BjarmasonApr 7, 2022
  11. Junio C HamanoApr 7, 2022
  12. John CaiApr 7, 2022
  13. brian m. carlsonApr 7, 2022
  14. Justin StevenApr 7, 2022
  15. brian m. carlsonApr 7, 2022
  16. rsbecker@nexbridge.comApr 7, 2022
  17. Junio C HamanoApr 8, 2022
  18. Junio C HamanoApr 14, 2022
  19. Glen ChooApr 14, 2022
  20. Glen ChooApr 13, 2022
  21. Glen ChooApr 13, 2022
  22. Junio C HamanoApr 13, 2022
  23. Glen ChooApr 14, 2022
  24. Junio C HamanoApr 14, 2022
  25. Junio C HamanoApr 14, 2022
  26. Glen ChooApr 15, 2022
  27. Junio C HamanoApr 15, 2022
  28. Taylor BlauApr 16, 2022
  29. Glen ChooApr 15, 2022
  30. Junio C HamanoApr 15, 2022
  31. Glen ChooApr 15, 2022
  32. Glen ChooApr 15, 2022
  33. Taylor BlauApr 16, 2022
  34. Junio C HamanoApr 16, 2022
  35. Taylor BlauApr 16, 2022
  36. Glen ChooApr 16, 2022
  37. Taylor BlauApr 16, 2022
  38. Emily ShafferApr 21, 2022
  39. Emily ShafferApr 21, 2022
  40. Junio C HamanoApr 21, 2022
  41. Taylor BlauApr 21, 2022
  42. Taylor BlauApr 21, 2022
  43. Emily ShafferApr 21, 2022
  44. Taylor BlauApr 21, 2022
  45. Glen ChooApr 29, 2022
  46. Taylor BlauApr 30, 2022
  47. Glen ChooMay 2, 2022
  48. Philip OakleyMay 2, 2022
  49. Junio C HamanoMay 2, 2022
  50. Glen ChooApr 16, 2022

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.