diff --git a/Documentation/Makefile b/Documentation/Makefile index b574ca2044..11208591d0 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -63,6 +63,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 diff --git a/Documentation/git.adoc b/Documentation/git.adoc index e3374a2fcc..1aa0608bae 100644 --- a/Documentation/git.adoc +++ b/Documentation/git.adoc @@ -1142,6 +1142,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 diff --git a/Documentation/gitsecurityboundary.adoc b/Documentation/gitsecurityboundary.adoc new file mode 100644 index 0000000000..fd67824d23 --- /dev/null +++ b/Documentation/gitsecurityboundary.adoc @@ -0,0 +1,184 @@ +gitsecurityboundary(7) +====================== + +NAME +---- +gitsecurityboundary - Git's security boundary + +SYNOPSIS +-------- +gitsecurityboundary + +DESCRIPTION +----------- + +Git encounters data in repositories that is not controlled by the user. That +data must be treated as untrusted. It is considered safe to clone an untrusted +Git repository and inspect its contents using Git commands like +linkgit:git-log[1]. + +Git repository configuration and hooks are not covered by this guarantee: the +user is responsible for reviewing them to determine whether they are trusted. + +Crucially, copies of untrusted repositories (e.g. obtained via `.zip` or other +archives) **must** be sanitized first and Git commands must only be run on this +sanitized clone. + +SANITIZED CLONE +--------------- + +A `.git` directory contains active metadata, not merely repository content. It +may contain configuration and hooks that cause Git to run arbitrary commands. +Most Git commands should therefore *not* be run in an untrusted `.git` directory +or the working tree that surrounds it. + +This distinction matters for repositories retrieved as filesystem copies or +archives. A repository obtained through git-clone(1) sanitizes this metadata, +while extracting an archive that contains a `.git` directory doesn't have these +protections. To create a sanitized copy, clone the untrusted repository with: + +------------ +git clone --no-local +------------ + +This creates a full clone of the untrusted repository, but excludes all +configuration and hooks that might cause harmful code to run when some Git +commands are executed. + +Note that `--no-local` is required here: a local clone (the default when the +source is given as a path) bypasses the transport layer and hardlinks the +source repository's object database instead of copying it, so it does not +sanitize the repository. + +This is also the way to turn an untrusted local repository into a trusted one: +there is no way to verify by inspection that the binary files in an untrusted +object database are safe, so the repository must be re-cloned through the +transport layer rather than trusted in place. + +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. + +REPOSITORY CONTENTS UNTRUSTED +----------------------------- + +Creating a sanitized clone avoids copying configuration and hooks from the +potentially evil repository. But it does not make contents in the repository +trustworthy. The user is still responsible for inspecting the repository data +before executing or installing any of the data inside. + +After cloning, Git commands intended to inspect repository contents should not +unexpectedly execute those contents. If the user reviews and explicitly enables +a hook, filter, helper, or other program supplied by the repository, the user +has extended trust to that program. + +UNEXPECTED CODE EXECUTION +------------------------- + +Git protects against remote code execution, thus an attacker shall not be able +to run malicious code as part of a Git operation (that is not expected to run +that code). For example, it is considered a security vulnerability when a bug in +git-clone(1) writes an executable hook into the new repository and runs that +hook. + +It doesn't matter at which point this code runs. Whether it's at the end of the +clone, or another Git command that's used on the repository. + +By using Git commands on a repository to inspect its contents, the user does not +consent to execute that content. Explicitly running a checked-out script is +different from passing a repository-supplied filename to a Git command that is +expected only to inspect it. + +This principle is not new; it has guided individual fixes over the years: + +* 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) ties + trust to configuration scope rather than to when the code runs. + +* 4cd1cf31efe (Git 2.20.2, 2019-12-04) 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) contrasts direct user action with recursion lacking user input. + +* e4930e86c0d (t5510: verify that D/F confusion cannot lead to an RCE, + 2024-03-24) frames remote code execution as code run by an operation not + expected to run it. + +* 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. + +* 8d1a7448206 (setup.c: create `safe.bareRepository`, 2022-07-14) addresses + post-clone use of embedded bare repositories. + +Together these cases show why the point at which code runs cannot by itself +define the boundary. + +READING AND WRITING OUTSIDE THE REPOSITORY +------------------------------------------ + +Git also protects against repository contents causing Git to read from or write +to paths outside the repository's working tree. This is not about files the user +or platform explicitly asks Git to use, such as configuration files or paths +given on the command line. It is about paths stored in the repository payload +that lead Git outside the worktree, for example through a symlink or a +path-traversing filename. + +This differs from LOCAL DISK ACCESS: there, the attacker already controls the +local disk. Here, the attacker uses Git's processing of untrusted repository +contents to reach paths the user did not intend to expose. + +By inspecting repository contents, the user does not consent to these side +effects. + +USER INTENT AND RECURSION +------------------------- + +Some potentially dangerous mechanisms are allowed when selected directly by the +user but restricted when reached indirectly. For example, a protocol may be +configured with the `user` policy so that it can be used directly but not by +recursive submodule initialization, which runs clone or fetch operations +without additional user input. See `protocol.allow` in linkgit:git-config[1]. +User input establishes intent only when the user selects the mechanism that can +execute code. A repository-controlled argument does not become trusted merely +because it is passed through a command the user invoked. + +PROTECTED CONFIGURATION +----------------------- + +Git treats system, global, and command-scope configuration as protected +configuration, and assumes that the user or a trusted administrator controls +these scopes. Repository-local configuration does not receive that +presumption, so options that affect security may be respected only in +protected configuration and ignored otherwise. See "Protected configuration" +in linkgit:git-config[1] for the authoritative list. + +LOCAL DISK ACCESS +----------------- + +Git does not consider an adversary who can already write to the local disk to +be within its security boundary. Such an attacker can modify the Git +executable, the user's configuration, or the repository itself, and can +therefore cause harm without exploiting Git. The boundary described here +concerns data that Git consumes from a repository the user does not control, +not data that an attacker can place on the user's own filesystem. + +SEE ALSO +-------- + +linkgit:git[1], +linkgit:git-clone[1], +linkgit:git-config[1], +linkgit:git-upload-pack[1], +linkgit:githooks[5], +linkgit:gitmodules[5] + +GIT +--- + +Part of the linkgit:git[1] suite diff --git a/Documentation/meson.build b/Documentation/meson.build index b290557834..c7469df1f8 100644 --- a/Documentation/meson.build +++ b/Documentation/meson.build @@ -206,6 +206,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, diff --git a/SECURITY.md b/SECURITY.md index c720c2ae7f..1a21e4c9d1 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -10,6 +10,10 @@ vulnerability, it is recommended to send the report to git-security@googlegroups.com (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. diff --git a/command-list.txt b/command-list.txt index 56d0d7ed9b..bc361aac8c 100644 --- a/command-list.txt +++ b/command-list.txt @@ -243,6 +243,7 @@ gitprotocol-v2 developerinterfaces gitremote-helpers guide gitrepository-layout userinterfaces gitrevisions userinterfaces +gitsecurityboundary guide gitsubmodules guide gittutorial guide gitweb ancillaryinterrogators