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

Re: [PATCH v6 0/5] config: introduce discovery.bare and protected config

From
Glen Choo <chooglen@google.com>
Date
Jul 1, 2022, 17:37 UTC
Message-ID
<kl6lr134spi0.fsf@chooglen-macbookpro.roam.corp.google.com>
In-Reply-To
<220701.861qv5d8v7.gmgdl@evledraar.gmail.com>

Thanks for weighing in :) Despite the different proposed approaches, I think we actually are in broad agreement.

Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
Show 51 quoted lines
> On Thu, Jun 30 2022, Glen Choo via GitGitGadget wrote:
>
>> This is a quick re-roll to address Ævar's comments on the tests (thanks!).
>
> Thanks!
>
>> = Description
>
> Just more generally on this series & approach. I know this is a v6 by
> now, but I haven't kept up with this topic, but to be fair I did mention
> pretty much this in:
> https://lore.kernel.org/git/220407.86lewhc6bz.gmgdl@evledraar.gmail.com/
>
> So...
>
>> There is a known social engineering attack that takes advantage of the fact
>> that a working tree can include an entire bare repository, including a
>> config file. A user could run a Git command inside the bare repository
>> thinking that the config file of the 'outer' repository would be used, but
>> in reality, the bare repository's config file (which is attacker-controlled)
>> is used, which may result in arbitrary code execution. See [1] for a fuller
>> description and deeper discussion.
>>
>> This series implements a simple way of preventing such attacks: create a
>> config option, discovery.bare, that tells Git whether or not to die when it
>> finds a bare repository. discovery.bare has two values:
>>
>>  * "always": always allow bare repositories (default), identical to current
>>    behavior
>>  * "never": never allow bare repositories
>>
>> and users/system administrators who never expect to work with bare
>> repositories can secure their environments using "never". discovery.bare has
>> no effect if --git-dir or GIT_DIR is passed because we are confident that
>> the user is not confused about which repository is being used.
>
> I'm not insisting that the entire approach here should be changed, but
> in the above exchange you seemed to have performance concerns about the
> "just walk up in setup.c" approach I mentioned, but it's not clear if
> that's still the only thing that necessitates taking this approach.
>
> There may be security subtleties that I've missed, but from the
> description here it seems like that would work equally well, and
> wouldn't require configuration, except insofar as we'd need to opt-in to
> reading config from bare repositores *that also exist in a parent tree*.
>
> And it would be a more narrow & more secure solution, since it would
> e.g. allow you to intentionally navigate to /var/repos/git/git.git in a
> server setup and read the config there, which it could distinguish from
> a case of /var/repos/.git existing, and git/git.git being brought in as
> a part of that "parent" repo.

Performance is one major concern, yes, and I agree that your findings show that the "just walk up" approach is cheap enough to consider doing. Though in the few cases where it isn't cheap to walk, wouldn't it still be useful to be able to opt out of it?

The other concern is simplicity and correctness. Are we confident that we'll get the design of "just walk up" correct (including edge cases like "bare repo in bare repo in non bare repo")? I'm 100% confident that we'll get it right eventually, and that this approach will be a good default for all users. But in comparison, "never" is so much easier to understand and implement that I don't see why we shouldn't start by presenting this option to the 0.1-1% of users who would find it useful.

And on the topic of simplicity, there's significant interest in maintaining backwards-compatibility with repos with workflows that absolutely depend on embedded bare repos, e.g. libgit2 and Git-LFS. That's yet another special case that we'd have to get right. Stolee's "no-embedded" proposal [1] pretty much covers that, but I don't see the harm in simplifying the design space by making bare repo support a non-goal.

[1] https://lore.kernel.org/git/5b969c5e-e802-c447-ad25-6acc0b784582@github.com
> The "more narrow" and "more secure" go hand-in-hand, since if you work
> on such servers you'd turn this to "always" because you want to read
> such config, but then be left vulnerable to the actual (and muche rarer)
> exploit we're trying to prevent.

The point that we're not defending bare repo users is fair, but maybe the group we're trying to protect isn't really dedicated Git-serving servers. This exploit requires you to have a bare repo inside the working tree of a non-bare repo. So I think this is less of an issue for a server, and more for "mixed-use" environments with both regular and bare clones.

Show 16 quoted lines
> Which, it seems...
>
>> This series does not change the default behavior, but in the long-run, a
>> "no-embedded" option might be a safe and usable default [2]. "never" is too
>> restrictive and unlikely to be the default.
>
> This series has (since v3?) been noting aspirations to have a
> "no-embedded" variant of this config, which your 5/5 here notes would be
> better, but isn't implemented by this series.
>
> But your 5/5 also notes:
>
>     but detecting if a repository is embedded is potentially
>     non-trivial, so this work is not implemented in this series.
>
> Hrm, well, the diff-stat isn't quite that trivial either :) :
Well.. a lot of it is refactoring :P
Show 27 quoted lines
>> [...]
>>  upload-pack.c                       | 27 ++++++----
>>  12 files changed, 304 insertions(+), 47 deletions(-)
>
> In threads linked from the above ML link I linked to some POC code
> showing how to hack a second .git discovery walk into setup.c. This was
> as part of the "submodule parent dir" proposal, which is a different
> feature, but also needs such "find the parent" code:
> https://lore.kernel.org/git/211109.86v912dtfw.gmgdl@evledraar.gmail.com/
>
> Now, obviously that's a dirty hack, but it's not that hard to just
> change the part of setup.c where we're satisfied that we've found the
> git dir, then walk up "$THAT_DIR/..", and start our search again.
>
> Then:
>
> 	if (first_dir_was_bare() && found_parent_dir())
>         	enforce_no_embedded();
>
> Isn't that what your proposed "no embedded" option would need to do?
> Well, maybe we'd also check if the "first dir" is in the index of the
> parent, as opposed to just being a bare .git somewhere in ~/Downloads,
> e.g. if you have a ~/.git and keep your dot-files in git.
>
> But I think for an initial implementation just doing the walk would be
> good enough, and would have a more narrow scope than this configuration
> setting.

A narrow scope is good, but I don't agree on this definition of "narrow". My preference is to give an obvious solution to a 'narrow' group of users, instead of a more tricky solution that affects all users in a 'narrow' set of cases.

Show 13 quoted lines
> AFAICT the performance concerns aren't supported by any data, in the
> case of the "submodule superproject" feature it turned out to not be the
> directory walk, but us shelling out in a loop in git-submodule.sh.
>
> Well, *maybe* that's not the case, I think I have managed to read
> between the lines of some of these past exchanges that there's some odd
> propriterary internal NFS-like setup at Google where *parent dirs* are
> auto-mounted and searched on access, so a "walk up" pattern would be
> much more expensive.
>
> I do worry a bit about us ending up with design choices in git that we
> wouldn't have ended up with, if not to cater to some in-house setup
> somwhere that 99.99% of git users will never see.

At the very least, I don't think you're saying that it's a bad idea to have "never", just that we might not have come up with it if not for some Google NFS thing.

Another use case I can think of is CI bots, which have no need for bare repos. To some folks (maybe in very security-sensitive environments), "never" might give more peace of mind than "no-embedded".

Show 5 quoted lines
> But I don't have the full picture on the "submodule superproject"
> problem, or this one, and maybe I'm missing something. Just food for
> thought, and wondering where we're eventually taking this.
>
> Thanks!
Previous: Ævar Arnfjörð BjarmasonNext: Ævar Arnfjörð Bjarmason
Message 86 of 113 in “[RFC] setup.c: make bare repo discovery optional”
  1. [RFC] setup.c: make bare repo discovery optionalGlen Choo via GitGitGadget, May 6, 2022
  2. Junio C HamanoMay 6, 2022
  3. Taylor BlauMay 9, 2022
  4. Junio C HamanoMay 9, 2022
  5. Taylor BlauMay 9, 2022
  6. Junio C HamanoMay 10, 2022
  7. Glen ChooMay 10, 2022
  8. 0/2 setup.c: make bare repo discovery optionalGlen Choo via GitGitGadget, May 13, 2022
  9. 1/2 setup.c: make bare repo discovery optionalGlen Choo via GitGitGadget, May 13, 2022
  10. Glen ChooMay 16, 2022
  11. Derrick StoleeMay 16, 2022
  12. Taylor BlauMay 16, 2022
  13. Glen ChooMay 17, 2022
  14. Glen ChooMay 17, 2022
  15. 2/2 setup.c: learn discovery.bareRepository=cwdGlen Choo via GitGitGadget, May 13, 2022
  16. Derrick StoleeMay 16, 2022
  17. Junio C HamanoMay 16, 2022
  18. Glen ChooMay 16, 2022
  19. Junio C HamanoMay 16, 2022
  20. Glen ChooMay 16, 2022
  21. Junio C HamanoMay 16, 2022
  22. Junio C HamanoMay 16, 2022
  23. Derrick StoleeMay 16, 2022
  24. Taylor BlauMay 16, 2022
  25. Junio C HamanoMay 16, 2022
  26. Glen ChooMay 17, 2022
  27. 0/5 config: introduce discovery.bare and protected configGlen Choo via GitGitGadget, May 27, 2022
  28. 1/5 Documentation: define protected configurationGlen Choo via GitGitGadget, May 27, 2022
  29. Junio C HamanoMay 27, 2022
  30. Derrick StoleeJun 2, 2022
  31. Junio C HamanoJun 2, 2022
  32. Glen ChooJun 2, 2022
  33. Glen ChooJun 3, 2022
  34. 2/5 config: read protected config with `git_protected_config()`Glen Choo via GitGitGadget, May 27, 2022
  35. Junio C HamanoMay 28, 2022
  36. Glen ChooMay 31, 2022
  37. Junio C HamanoJun 1, 2022
  38. Derrick StoleeJun 2, 2022
  39. 3/5 setup.c: create `discovery.bare`Glen Choo via GitGitGadget, May 27, 2022
  40. Junio C HamanoMay 28, 2022
  41. Derrick StoleeJun 2, 2022
  42. 5/5 upload-pack: make uploadpack.packObjectsHook protectedGlen Choo via GitGitGadget, May 27, 2022
  43. Derrick StoleeJun 2, 2022
  44. 4/5 config: include "-c" in protected configGlen Choo via GitGitGadget, May 27, 2022
  45. Derrick StoleeJun 2, 2022
  46. 0/5 config: introduce discovery.bare and protected configGlen Choo via GitGitGadget, Jun 7, 2022
  47. 4/5 safe.directory: use git_protected_config()Glen Choo via GitGitGadget, Jun 7, 2022
  48. 3/5 config: read protected config with `git_protected_config()`Glen Choo via GitGitGadget, Jun 7, 2022
  49. Junio C HamanoJun 7, 2022
  50. Glen ChooJun 8, 2022
  51. 5/5 setup.c: create `discovery.bare`Glen Choo via GitGitGadget, Jun 7, 2022
  52. Glen ChooJun 7, 2022
  53. 2/5 Documentation: define protected configurationGlen Choo via GitGitGadget, Jun 7, 2022
  54. Jonathan TanJun 22, 2022
  55. Glen ChooJun 23, 2022
  56. 1/5 Documentation/git-config.txt: add SCOPES sectionGlen Choo via GitGitGadget, Jun 7, 2022
  57. Jonathan TanJun 22, 2022
  58. Glen ChooJun 23, 2022
  59. Junio C HamanoJun 23, 2022
  60. Glen ChooJun 27, 2022
  61. Glen ChooJun 27, 2022
  62. 0/5 config: introduce discovery.bare and protected configGlen Choo via GitGitGadget, Jun 27, 2022
  63. 2/5 Documentation: define protected configurationGlen Choo via GitGitGadget, Jun 27, 2022
  64. 4/5 safe.directory: use git_protected_config()Glen Choo via GitGitGadget, Jun 27, 2022
  65. 3/5 config: learn `git_protected_config()`Glen Choo via GitGitGadget, Jun 27, 2022
  66. 5/5 setup.c: create `discovery.bare`Glen Choo via GitGitGadget, Jun 27, 2022
  67. Ævar Arnfjörð BjarmasonJun 30, 2022
  68. Glen ChooJun 30, 2022
  69. 1/5 Documentation/git-config.txt: add SCOPES sectionGlen Choo via GitGitGadget, Jun 27, 2022
  70. 0/5 config: introduce discovery.bare and protected configGlen Choo via GitGitGadget, Jun 30, 2022
  71. 1/5 Documentation/git-config.txt: add SCOPES sectionGlen Choo via GitGitGadget, Jun 30, 2022
  72. Taylor BlauJun 30, 2022
  73. Glen ChooJul 6, 2022
  74. 2/5 Documentation: define protected configurationGlen Choo via GitGitGadget, Jun 30, 2022
  75. Taylor BlauJun 30, 2022
  76. Glen ChooJul 6, 2022
  77. 3/5 config: learn `git_protected_config()`Glen Choo via GitGitGadget, Jun 30, 2022
  78. Taylor BlauJul 1, 2022
  79. Glen ChooJul 6, 2022
  80. 4/5 safe.directory: use git_protected_config()Glen Choo via GitGitGadget, Jun 30, 2022
  81. 5/5 setup.c: create `discovery.bare`Glen Choo via GitGitGadget, Jun 30, 2022
  82. Taylor BlauJul 1, 2022
  83. Glen ChooJul 7, 2022
  84. Taylor BlauJun 30, 2022
  85. Ævar Arnfjörð BjarmasonJun 30, 2022
  86. Glen ChooJul 1, 2022
  87. Ævar Arnfjörð BjarmasonJul 8, 2022
  88. Glen ChooJul 12, 2022
  89. Ævar Arnfjörð BjarmasonJul 12, 2022
  90. 0/5 config: introduce discovery.bare and protected configGlen Choo via GitGitGadget, Jul 7, 2022
  91. 1/5 Documentation/git-config.txt: add SCOPES sectionGlen Choo via GitGitGadget, Jul 7, 2022
  92. Junio C HamanoJul 7, 2022
  93. Glen ChooJul 8, 2022
  94. Junio C HamanoJul 8, 2022
  95. Glen ChooJul 8, 2022
  96. 2/5 Documentation: define protected configurationGlen Choo via GitGitGadget, Jul 7, 2022
  97. Junio C HamanoJul 8, 2022
  98. 3/5 config: learn `git_protected_config()`Glen Choo via GitGitGadget, Jul 7, 2022
  99. 4/5 safe.directory: use git_protected_config()Glen Choo via GitGitGadget, Jul 7, 2022
  100. 5/5 setup.c: create `discovery.bare`Glen Choo via GitGitGadget, Jul 7, 2022
  101. Junio C HamanoJul 8, 2022
  102. Glen ChooJul 8, 2022
  103. Glen ChooJul 12, 2022
  104. 0/5 config: introduce safe.bareRepository and protected configGlen Choo via GitGitGadget, Jul 14, 2022
  105. 1/5 Documentation/git-config.txt: add SCOPES sectionGlen Choo via GitGitGadget, Jul 14, 2022
  106. 2/5 Documentation: define protected configurationGlen Choo via GitGitGadget, Jul 14, 2022
  107. 3/5 config: learn `git_protected_config()`Glen Choo via GitGitGadget, Jul 14, 2022
  108. SANITIZE=address failure on master (was: [PATCH v8 3/5] config: learn `git_protected_config()`)Ævar Arnfjörð Bjarmason, Jul 25, 2022
  109. Glen ChooJul 25, 2022
  110. Ævar Arnfjörð BjarmasonJul 25, 2022
  111. Glen ChooJul 25, 2022
  112. 4/5 safe.directory: use git_protected_config()Glen Choo via GitGitGadget, Jul 14, 2022
  113. 5/5 setup.c: create `safe.bareRepository`Glen Choo via GitGitGadget, Jul 14, 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.