Merge branch 'tc/security-boundary-doc' into jch
A new document, gitsecurityboundary(7), has been added to clarify the security boundaries Git guarantees and the responsibilities of the user, aiming to provide a clear reference for what constitutes a security vulnerability in Git. * tc/security-boundary-doc: Documentation: clarify Git's security boundary
This commit is contained in:
commit
d8cb9befcd
6 files changed
+194
No files matched your search
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 <untrusted-repository> <clean-copy>
|
||||
------------
|
||||
|
||||
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
|
||||
@@ -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,
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -243,6 +243,7 @@ gitprotocol-v2 developerinterfaces
|
||||
gitremote-helpers guide
|
||||
gitrepository-layout userinterfaces
|
||||
gitrevisions userinterfaces
|
||||
gitsecurityboundary guide
|
||||
gitsubmodules guide
|
||||
gittutorial guide
|
||||
gitweb ancillaryinterrogators
|
||||
|
||||
Reference in new issue
Block a user