Documentation: clarify Git's security boundary
Subsystems (2)
PATCH 1/1 Documentation: clarify Git's security boundary
From: Toon Claes <[email protected]>
Like so many other open source projects, the Git project has seen an ever-increasing flood of security reports. Many of those reports describe valid bugs yet are redirected from the git-security mailing list because they are deemed "not vulnerabilities". While some Git contributors seem to have a very concrete idea how to discern between bugs that constitute vulnerabilities (and hence must be fixed in secret, to keep Git users safe) from bugs that can be fixed in the open, most reporters must be quite puzzled because the Git project provides no clear document to help define the security boundaries Git tries to guarantee.
Of course, there _are_ hints and bits and pieces of documentation: Git's security guidance has accumulated across individual fixes. Some might be tempted to describe the boundary as "before clone" versus "after clone", but history establishes a more precise distinction. e69ac42fcc8 (docs:
document security issues around untrusted .git dirs, 2024-04-16) explains why cloned content can generally be inspected with git log:
repository-local hooks and configuration are not copied, whereas an untrusted .git directory remains unsafe. 779ea9303a7 (Documentation:
define protected configuration, 2022-07-14) likewise ties trust to configuration scope rather than timing alone.
State the governing principle in one place: Git's security boundary concerns unexpected or implicit execution of attacker-controlled code. A theoretical opportunity to inspect repository contents is not consent to execute them. Conversely, explicitly choosing an execution-capable mechanism is materially different. Execution after clone is therefore not inherently a vulnerability.
This distinction underlies 4cd1cf31efe (Git 2.20.2, 2019-12-04), which describes CVE-2019-19604 as code running during recursive clone plus a submodule update "without the user explicitly having asked for that". a1d4f67c12ac (transport: make protocol.file.allow be user by default, 2022-07-29) likewise contrasts direct user action with recursion lacking user input. e4930e86c0d (t5510: verify that D/F confusion cannot lead to an RCE, 2024-03-24) similarly frames remote code execution as code run by an operation not expected to run it.
Timing remains relevant when it removes any meaningful choice. 873a466ea3f (clone: drop the protections where hooks aren't run, 2024-05-20) notes that clone-time hook execution leaves no chance to inspect first. Conversely, 8d1a7448206 (setup.c: create safe.bareRepository, 2022-07-14) addresses post-clone use of embedded bare repositories. Together these cases show why timing alone cannot define the boundary.
---
Documentation: clarify Git's security boundary
This documents Git's security boundary, a topic that came up on the git-security mailing list. Since the discussion there has run its course and nobody objected to making it public, here it is as a regular series.
Toon rewrote the document almost from scratch after reviewing it, and Patrick and Junio both shaped it substantially; the trailers carry the formal credit.
Patrick floated the idea of a git --safe mode. I think this is a good idea, but since this document describes the status quo, it deliberately leaves that idea out.
It is related to a discussion that Stolee tried to start on the git-security list years ago (but which unfortunately did not get any traction, something that now bites us with the onslaught of AI-assisted, reports, and I don't mean the easily dismissed slop, I mean well-crafted, well-argued reports that would have benefited from a clear documentation of Git's security boundary, something that I hereby aim to provide).
A --safe flag would have to enumerate every execution-capable mechanism -- hooks, core.fsmonitor, core.sshCommand, core.pager, core.editor, core.hooksPath, uploadpack.packObjectsHook, protocol.*.allow, safe.bareRepository, safe.directory, submodule recursion, include.path/includeIf, aliases, and so on. That list would be a snapshot of today's attack surface, and it would rot as new mechanisms appear; the failure mode therefore would provide a false sense of safety. Instead, the --safe mode would require substantial refactoring so that there is a central registry of config settings and hooks, all with documented safety levels.
Git's history bears this out: the set of execution-capable things is discovered incrementally (CVE-2019-19604, protocol.file.allow, safe.bareRepository, the clone-time hook protections dropped in 873a466ea3f), so a flag promising safety would need re-auditing each time one is found.
An alternative would be a narrower variant that is more defensible:
per-operation switches that refuse execution-capable configuration, each with a narrow, auditable contract. The LOCAL DISK ACCESS and PROTECTED CONFIGURATION sections already point at what a user can do today (--no-local, safe.directory, safe.bareRepository).
I am sure that listing these options invites a lengthy discussion, and I hope that it will not distract from getting this security boundary documentation from being finalized in a timely manner so that we have firmer ways to deal with security reports. It is easier to point to an official document stating that a Git config modified in one's worktree by an attacker is outside of what Git promises (if such a document exists) than trying to argue based on historical (public) record what constitutes a vulnerability in Git or not. Therefore having this document will be quite helpful, I expect, in dealing with the reports on the git-security mailing list.
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-2286%2Fdscho%2Fgit-security-boundary-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-2286/dscho/git-security-boundary-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/2286
Documentation/Makefile | 1 + Documentation/git.adoc | 3 + Documentation/gitsecurityboundary.adoc | 184 +++++++++++++++++++++++++ Documentation/meson.build | 1 + SECURITY.md | 4 + command-list.txt | 1 + 6 files changed, 194 insertions(+) create mode 100644 Documentation/gitsecurityboundary.adoc
Documentation/Makefile +1 -0
@@ -62,6 +62,7 @@ MAN7_TXT += gitpacking.adoc MAN7_TXT += gitnamespaces.adoc MAN7_TXT += gitremote-helpers.adoc MAN7_TXT += gitrevisions.adoc +MAN7_TXT += gitsecurityboundary.adoc MAN7_TXT += gitsubmodules.adoc MAN7_TXT += gittutorial-2.adoc MAN7_TXT += gittutorial.adoc
Documentation/git.adoc +3 -0
@@ -1124,6 +1124,9 @@ unmerged version of a file when a merge is in progress. SECURITY -------- +See linkgit:gitsecurityboundary[7] for a broader discussion of Git's +security model. + Some configuration options and hook files may cause Git to run arbitrary shell commands. Because configuration and hooks are not copied using `git clone`, it is generally safe to clone remote repositories with
Documentation/gitsecurityboundary.adoc new file +184 -0
184 lines not on this page · raw message
Documentation/meson.build +1 -0
@@ -205,6 +205,7 @@ manpages = { 'gitnamespaces.adoc' : 7, 'gitremote-helpers.adoc' : 7, 'gitrevisions.adoc' : 7, + 'gitsecurityboundary.adoc' : 7, 'gitsubmodules.adoc' : 7, 'gittutorial-2.adoc' : 7, 'gittutorial.adoc' : 7,
SECURITY.md +4 -0
@@ -10,6 +10,10 @@ vulnerability, it is recommended to send the report to [email protected] (and obviously not to discuss the issue anywhere else). +See the [security boundary +documentation](https://git-scm.com/docs/gitsecurityboundary) for a +discussion of what Git considers to be within its security boundary. + Vulnerabilities are expected to be discussed _only_ on that list, and not in public, until the official announcement on the Git mailing list on the release date.
command-list.txt +1 -0
@@ -242,6 +242,7 @@ gitprotocol-v2 developerinterfaces gitremote-helpers guide gitrepository-layout userinterfaces gitrevisions userinterfaces +gitsecurityboundary guide gitsubmodules guide gittutorial guide gittutorial-2 guide
base-commit: a018953688f1b10bddf91bff8747068f5f4746a4
Signature · 1 line
gitgitgadget
"Johannes Schindelin via GitGitGadget" <[email protected]>
Documentation/gitsecurityboundary.adoc line 60
Quoted 3 lines · writes:
Documentation/gitsecurityboundary.adoc new file +3
-0+Serving an untrusted repository to `git clone` still exposes +linkgit:git-upload-pack[1] to that repository. For additional isolation, +`upload-pack` can be run as an unprivileged user where the platform permits it.
This tricky thing is often forgotten, but it is nice to see it mentioned. 'git help upload-pack' also mentions this facility. Overall the document was a pleasant read.
Thanks.