mirror of
https://github.com/Byron/gitoxide
synced 2025-10-06 01:52:40 +02:00
Merge pull request #2192 from EliahKagan/irp
Add IRP and threat model outline
This commit is contained in:
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
@@ -533,7 +533,7 @@ jobs:
|
||||
os:
|
||||
- ubuntu-latest
|
||||
# We consider this script read-only and its effect is the same everywhere.
|
||||
# However, when changes are made to `etc/copy-packetline.sh`, re-enable the other platforms for testing.
|
||||
# However, when changes are made to `etc/scripts/copy-packetline.sh`, re-enable the other platforms for testing.
|
||||
# - macos-latest
|
||||
# - windows-latest
|
||||
|
||||
@@ -554,7 +554,7 @@ jobs:
|
||||
git status
|
||||
git diff --exit-code
|
||||
- name: Regenerate gix-packetline-blocking/src
|
||||
run: etc/copy-packetline.sh
|
||||
run: etc/scripts/copy-packetline.sh
|
||||
- name: Check that gix-packetline-blocking/src was already up to date
|
||||
run: |
|
||||
set -x
|
||||
|
18
etc/security/README.md
Normal file
18
etc/security/README.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# Security process documents
|
||||
|
||||
> [!NOTE]
|
||||
> To *report* a vulnerablity, see the [**security policy**](https://github.com/GitoxideLabs/gitoxide/security/policy), which can also be read in the top-level [`SECURITY.md`](https://github.com/GitoxideLabs/gitoxide/blob/main/SECURITY.md).
|
||||
|
||||
## Table of Contents
|
||||
|
||||
The documents in this directory are things we use when managing vulnerabilities:
|
||||
|
||||
### Incident Repsonse Plan
|
||||
|
||||
- [*`irp.md`*](irp.md) is our incident response plan.
|
||||
|
||||
### Threat Model
|
||||
|
||||
- [*`threat-model.md`*](threat-model.md) is our provisional threat model outline.
|
||||
|
||||
- [*`threat-model-notes.md`*](threat-model-notes.md) are some notes in a different form that have informed it. It overlaps significantly with `threat-model.md`, but it may also occasionally be useful to refer to.
|
122
etc/security/irp.md
Normal file
122
etc/security/irp.md
Normal file
@@ -0,0 +1,122 @@
|
||||
# Gitoxide Incident Response Plan (IRP) for Vulnerabilities
|
||||
|
||||
This document outlines the procedure for responding to security incidents, with a primary focus on the discovery and handling of vulnerabilities in Gitoxide. It is a living document that will be updated as we learn and refine our processes.
|
||||
|
||||
The primary goal during any incident is to remain calm and methodical to ensure a thorough and effective response.
|
||||
|
||||
This plan supports two disclosure strategies:
|
||||
|
||||
- **Issue Advisory With Patch:** The standard and most common path, where a fix is prepared privately and released at the same time the vulnerability is publicly disclosed in an advisory.
|
||||
- **Issue Advisory Early:** The less common path, where we publish an advisory to disclose the vulnerability publicly *before* a fix is available.
|
||||
|
||||
The following steps are written for the standard "Issue Advisory With Patch" path, with notes indicating how the process changes for the "Issue Advisory Early" path.
|
||||
|
||||
## Phase One: Initial Triage and Assessment
|
||||
|
||||
This phase begins when a potential vulnerability is reported to us. Usually this is either by a member of the GitoxideLabs org itself via a draft GitHub Security Advisory, by anyone by Private Vulnerability Reporting (PVR) on GitHub or by email, as outlined in `SECURITY.md`. However, this also applies if a vulnerability is communicated in some other way, such as by being publicly disclosed. (Immediate public disclosure is plausible even if the reporter values coordinated disclosure, because a bug that the reporter believes is not a vulnerability, or whose security implications are unknown to the reporter, might be reported initially in a GitHub issue or other public post.)
|
||||
|
||||
1. **Acknowledge the Report**: Aim to provide an initial response to the reporter within 72 hours, acknowledging receipt of the report.
|
||||
|
||||
2. **Understand the Report**: Carefully review the report to ensure a full understanding of the claimed vulnerability. If any part is unclear, request clarification from the reporter.
|
||||
|
||||
3. **Validate the Vulnerability**:
|
||||
|
||||
- Assess whether the described behavior, if accurate, constitutes a security vulnerability. It must be plausibly exploitable and have a negative impact on confidentiality, integrity, or availability (C/I/A).
|
||||
- Confirm that the vulnerability lies within Gitoxide rather than exclusively in third-party code or the surrounding environment, or that the vulnerability arises from a specific way Gitoxide interacts with other software that can be fixed in Gitoxide more feasibly than in other software.
|
||||
- If a Proof-of-Concept (PoC) is provided, attempt to reproduce the issue as described. If the PoC fails, investigate further to determine if a vulnerability still exists. Work with the reporter to refine the PoC if necessary. If no PoC is included, write one and test it.
|
||||
|
||||
4. **Initiate Advisory**:
|
||||
|
||||
- If the report was submitted by email, create a new draft GitHub Security Advisory for the vulnerability.
|
||||
- Alternatively, we can request that the reporter create the draft advisory via Private Vulnerability Reporting, unless they express a preference for us to manage it.
|
||||
|
||||
5. **Triage Severity**: Perform an initial severity assessment. Determine the potential impact on confidentiality, integrity, and availability, and either calculate a CVSS score or validate/adjust the score suggested by the reporter.
|
||||
|
||||
6. **Choose Disclosure Strategy**: Based on the assessment, decide which disclosure path to follow. While "Issue Advisory With Patch" is the default, choose "Issue Advisory Early" if it is determined that we should publish an advisory before a fix is ready. Reasons for this include, but are not limited to:
|
||||
|
||||
- The vulnerability is confirmed to be actively exploited in the wild.
|
||||
- The vulnerability has already been disclosed publicly, by the original reporter or by another party.
|
||||
- The vulnerability is low risk, the fix is expected to be lengthy, and we believe that awareness of the issue would benefit users more than withholding it.
|
||||
|
||||
This step can sometimes be deferred. That is, sometimes we may further investigate or coordinate before deciding to issue an advisory prior to making a fix available.
|
||||
|
||||
## Phase Two: Investigation and Coordination
|
||||
|
||||
Once a vulnerability is validated, a deeper investigation is required to understand its full scope and impact.
|
||||
|
||||
1. **Scope the Impact within Gitoxide**:
|
||||
|
||||
- Identify which specific crate(s) are affected.
|
||||
- If possible, identify which versions are affected, or otherwise when the vulnerability was introduced.
|
||||
- Determine the use cases or APIs that trigger the vulnerability.
|
||||
- Ascertain if the vulnerability is platform-specific (e.g., Windows only, Unix-like only) or affects all operating systems.
|
||||
|
||||
2. **Assess Risk and Ecosystem Impact**:
|
||||
|
||||
- Make a rough estimate of the likelihood of exploitation.
|
||||
- Assess the potential impact on Gitoxide users and the broader ecosystem of dependent libraries and applications.
|
||||
|
||||
3. **Analyze for Broader Implications**:
|
||||
|
||||
- Investigate if the vulnerability is similar to previously discovered issues in Gitoxide. If so, determine if this is a new, independent flaw or the result of an incomplete fix.
|
||||
- Research if the vulnerability is similar to known issues in other Git implementations, especially Git itself or Git for Windows.
|
||||
- Consider if the vulnerability stems from a flaw in widely accepted semantics of Git repositories or common implementation patterns. If feasible, and on a best-effort basis, check experimentally if other Git implementations are affected.
|
||||
|
||||
4. **Coordinate with External Parties (if necessary)**:
|
||||
|
||||
- **Other Git Projects**: If the vulnerability is confirmed or likely to affect other Git implementations, triage whether coordination is needed. For vulnerabilities in Git itself (including Git for Windows), the git-security mailing list is the correct communication channel. We will investigate if this list is also appropriate for broader coordination and update this IRP accordingly.
|
||||
|
||||
- **Consumers**: For severe vulnerabilities, consider if direct coordination with critical applications or libraries that use Gitoxide is warranted. This is expected to be rare.
|
||||
|
||||
- **Downstream Packagers**: Coordination with downstream packagers is not currently a required step, as there are few. However, this may be a consideration in the future for high-risk issues.
|
||||
|
||||
5. **Update Advisory and Request CVE**:
|
||||
|
||||
- Update the draft GitHub Security Advisory with all relevant findings, analysis, and references.
|
||||
- Once the nature of the vulnerability is understood, request a CVE identifier through the GitHub advisory interface.
|
||||
- *Note for "Issue Advisory Early": When following this strategy, we publish the initial public advisory once we fully understand the vulnerability, usually around the same time as we request the CVE. We may then update it with further findings to ensure it remains as useful as possible, and to maintain transparency.*
|
||||
|
||||
## Phase Three: Remediation and Disclosure
|
||||
|
||||
This phase covers developing and releasing a fix.
|
||||
|
||||
1. **Plan the Fix**: Design a code-level solution to address the vulnerability.
|
||||
|
||||
2. **Establish a Timeline**: If the fix is complex, break it down into manageable steps and establish a realistic timeline for implementation and release.
|
||||
|
||||
3. **Implement and Test**: Write the code for the fix. Ensure comprehensive tests are added to prevent regressions. Test any changes required in other Gitoxide crates to adapt to the fix.
|
||||
|
||||
4. **Finalize Advisory**: Perform a final review of the security advisory. Add the version numbers of all crates that will be released in the fix.
|
||||
|
||||
5. **Publish and Release**:
|
||||
|
||||
- Publish the GitHub Security Advisory (GHSA).
|
||||
- Simultaneously, release new versions of all affected crates and any other crates whose dependencies need to be bumped.
|
||||
- *Note for "Issue Advisory Early": This step becomes **updating the existing public advisory** with details about the fix, along with the release of the new crate versions.*
|
||||
|
||||
6. **Create RUSTSEC Advisory**: Author one or more advisories for the `rustsec/advisory-db` repository. The content should be consistent with the GHSA. Open a pull request to submit them.
|
||||
|
||||
- *Note for "Issue Advisory Early": A preliminary RUSTSEC advisory should be published along with the public GHSA or immediately thereafter, and likewise updated later with information about the fix.*
|
||||
|
||||
## Phase Four: Post-Disclosure Follow-up
|
||||
|
||||
After the fix is public, monitor its rollout and ensure information is accurate.
|
||||
|
||||
1. **Monitor for Breakages**: Keep an eye on user reports (e.g., GitHub issues) to see if the fix has introduced any breaking changes.
|
||||
|
||||
2. **Verify Public Advisories**: A few days after publication, check the global GHSA in the GitHub Advisory Database and the published RUSTSEC advisory. Ensure their content and formatting are correct and consistent with the original repository advisory.
|
||||
|
||||
3. **Update Advisories**: Update all advisories as needed with any new information, such as adding the CVE number if it was not available at the time of initial publication.
|
||||
|
||||
## Phase Five: Post-Incident Review
|
||||
|
||||
After the incident is fully resolved, it is crucial to learn from it.
|
||||
|
||||
1. **Process Retrospective**: Discuss the handling of the incident. Identify what went well and what could be improved in our response process. Such discussion may be brief or extensive, depending on the vulnerability and how involved it was to handle and remedy. Update this IRP with any lessons learned.
|
||||
|
||||
2. **Root Cause Analysis**:
|
||||
|
||||
- Examine how the vulnerability was introduced and whether process or tooling changes could prevent similar issues in the future.
|
||||
- Assess if the vulnerability is a symptom of a broader architectural or design pattern in the software that needs to be reconsidered.
|
||||
- Consider if the vulnerability represents a condition previously thought to be benign, but whose security implications have grown due to evolving use cases and expectations. This may give insight into how to prioritize existing issues and requested features.
|
||||
- If the vulnerability arose from incorrect assumptions about portability, examine whether there are other areas of the code that embody the same or similar assumptions and can be improved.
|
93
etc/security/threat-model-notes.md
Normal file
93
etc/security/threat-model-notes.md
Normal file
@@ -0,0 +1,93 @@
|
||||
# Threat modeling notes
|
||||
|
||||
*These are fragmentary thoughts about our threat model. They are currently incomplete in many ways, but especially in that they do not examine the ecosystem of software that uses gitoxide.*
|
||||
|
||||
## Similar, but not identical, to Git security considerations
|
||||
|
||||
The security considerations and threat landscape for Gitoxide is similar to that of Git, with several of the most important differences being:
|
||||
|
||||
1. Gitoxide is primarily a library project. Used as a library, it contains a the `gix` crate (which most users declare as their dependency) and numerous more special-purpose `gix-*` crates.
|
||||
|
||||
2. Gitoxide does not ship a Unix-like environment on Windows. We prefer instead to treat Windows as a "first-class" platform, and because we are primarily a library, there is no clear reasonable way to ship an MSYS2 or similar environment of our own. However, typical operations on Git repositories often include running shell scripts and other commands that expect Unix-like tools and some aspects of Unix-like path semantics. We try to accommodate this on Windows, and we also search for a suitable POSIX-compatible shell to run shell scripts in, preferring one that accompanies a Git for Windows installation when it is present and when we can find it. The uncertainty associated with the environment in which users may configure some custom commands to run makes it so that some assumptions that might seem safe for us to make are not.
|
||||
|
||||
3. We do not carry our own installation-scoped configuration. Instead, we use the one that Git provides, when present. The Git installation scoped configuration is usually the `system` scope, but some `git` builds (specifically, Apple Git on macOS) have a higher `unknown` scope. When not set or suppressed by an environment variable, the `system` scope configuration file, if present, is usually `/etc/gitconfig` except on Windows, but that is not guaranteed. We do not require that `git` be installed, but if it is then we want to respect the values of any variables in its installation-level configuration scope except where overridden in a narrower scope. To do this, we attempt to invoke `git` to ascertain the appropriate path. We have to make sure the program we're running is `git` and not an attacker-controlled decoy, and that we parse the output correctly even on systems with unexpected configurations.
|
||||
|
||||
4. We model trust for local repositories differently: while `git` refuses to read the configuration file at all when a repository has "dubious ownership," we will read the configuration file but report variables from it as untrusted to the caller, and always refrain from performing actions such as running commands based on them. One reason for this difference is to allow broader use as a library, while avoiding a scenario where a user or application would dangerously mark untrusted local files or directories as safe (by taking ownership of them or listing them as a value of `safe.directory`) in order to read a configuration without attempting to follow it.
|
||||
|
||||
Aside from the subtle differences in point (4) above (and also that we do not yet have our own implementation of `upload-pack`), [the SECURITY section of the git(1) manual page](https://git-scm.com/docs/git#_security) applies fully.
|
||||
|
||||
The rest of these notes are, therefore, not unique to Gitoxide, though they are presented in the context of Gitoxide, and they emphasize areas we have found we need to be especially careful about.
|
||||
|
||||
## What data do we trust?
|
||||
|
||||
### Users should be able to safely clone untrusted repositories
|
||||
|
||||
Remote repositories that we clone or otherwise fetch from are untrusted. Although there are numerous exceptions to this in practice--where users know they are cloning a repository they control fully--we never actually know that this is the case and we rarely if ever would benefit from knowing:
|
||||
|
||||
- We always treat remote repostiories as untrusted and we never install or run hooks based on any valid or malformed configuration or other content in them.
|
||||
|
||||
- We always check that files we would create in a checkout, whether the checkout is done as part of a clone or subsequently, cannot carry out a directory traversal attack. We need to prevent upward traversal, where cloning a repository would create files outside of the directory where the repository working tree would be checked out. We also need to prevent downward traversal, where cloning a respository would create files in "holes" in the repository that are not considered part of the working tree and that may be sensitive, such as the repository's own `.git` dir, the working trees of submodules, and the `.git` dirs of submodules. Preventing directory traversal involves some checks that always apply and others that apply on particular operating systems or filesystems, related to case folding, other forms of equivalence, NTFS alternate data streams, Windows 8.3 short names, and what characters are directory separators (in particular, both `/` and `\` are directory separators on Windows, while on Unix-like systems a tree or blob can be checked out to a location with `\` in its name).
|
||||
|
||||
- On Windows, we always check that files we would create in a fetch (including refs) and checkout do not have names that are treated as legacy DOS devices on any Windows systems (e.g., `COM1`, `CON`, `CON.txt`, `CONIN$`, and numerous others), at least for devices that can in practice exist (i.e., it is probably okay to fail to block the COMn and LPTn where n is a Unicode superscript, since those are distinct from the ones where it is an actual digit and the superscript device names never in practice actually exist; other than that, everything that is a reserved name, plus `CONIN$` and `CONOUT$` which behave as reserved names even though technically they are not, must be blocked.
|
||||
|
||||
- We always check that refs have valid names according to the Git rules for how a ref can be named, before performing operations based on them that have known security implications. This especially includes the operation of creating a loose ref for it in the object database.
|
||||
|
||||
Remote repositories cannot be trusted to pass any `git fsck` or other validation checks or otherwise to satisfy the technical requirements of "being a Git repository."
|
||||
|
||||
### Users should be able to clone from untrusted servers
|
||||
|
||||
The servers that host remote repositories cloned via network transport must be assumed untrusted as well:
|
||||
|
||||
- The server may send us specially crafted malicious data that do not conform to expected protocols. For HTTP this includes the possibility of an attacker-controlled web server.
|
||||
|
||||
- More straightforwardly, the server may have malicious (or even just malfunctioning) implementations of `git-*-pack` commands that are used when cloning.
|
||||
|
||||
- The exception is that we cannot protect users who trust a malicious server in ways that rely on the server preserving integrity of data that pass through it. Specifically, if a user pushes to a server and relies on that server providing the same data back, and then fetches from it elsewhere, then we cannot protect the user from that loss of integrity.
|
||||
|
||||
### Transport over untrusted networks should be as secure as possible
|
||||
|
||||
The network over which transport occurs must not be trusted unless a protocol is being used that inherently trusts the network:
|
||||
|
||||
- SSH, and HTTP with SSL/TLS (`https://`), must ensure authenticity, unless the user has explicitly allowed connections to proceed otherwise.
|
||||
|
||||
- HTTP without SSL/TLS (http), to the extent to which it is permitted at all, cannot ensure authenticity, nor can the Git protocol (`git://`).
|
||||
|
||||
- However, even if the user explicitly chooses to use a protocol that is vulnerable to man-in-the-middle attacks, we still need to preserve authenticity expectations related to other functionality, e.g., ensuring that SHA-1 OIDs are processed with collision detection (against collisions produced in the known feasible ways of doing so) and working toward supporting repositories with SHA256 OIDs.
|
||||
|
||||
### Users should be able to sanitize by cloning via the filesystem
|
||||
|
||||
One way to neutralize a potentially malicious configuration in a locally present repository, such as a repository that was downloaded and unpacked from a .tar archive or made available by another user in share location, is to clone it (leveraging the sanitization performed by `git-upload-pack`), and this is sometimes done via the filesystem. So remote repositories where the remote is the same machine, even if they are cloned through the filesystem rather than via network transport, are *just as untrusted*.
|
||||
|
||||
### Working trees and current working directories are unsafe search paths
|
||||
|
||||
The current working directory is an untrusted search path in nearly all cases, both because it may be the checked-out working tree of a repository (or branch) whose content on the remote was attacker-controlled and that was faithfully cloned, and more generally because the CWD can be anywhere (e.g., `/tmp`) and need not be trusted.
|
||||
|
||||
### Contents in a git-dir are trusted, and that directory must be protected…
|
||||
|
||||
Files like a repository's `.git/config` and its `.git/hooks` directory are trusted in ordinary use, and we are responsible for ensuring that nothing untrusted gets in there.
|
||||
|
||||
### …But we must only trust it if user-"owned" or allowlisted
|
||||
|
||||
Because we trust files in a repository's `.git` dir (or just in the repository directory if it is a bare repository), we must refuse to perform most operations on local repositories whose filesystem metadata (on the relevant files and directories of/in them) do not indicate that the user who owns the process is also the owner of the repository, unless the user has explicitly configured the relevant path(s) as trusted:
|
||||
|
||||
- On Unix-like systems, this sense of ownership of a file/directory corresponds to the ownership model supported by the filesystem and operating system, because every filesystem entry on a Unix-like system has a user (or UID) as its owner (with a *separate* group ownership mechanism).
|
||||
|
||||
- On Windows, this only partially coincides with the ownership model supported by the filesystem and operating system, because filesystem entries (like securable objects in general) may be owned by any SID (security identifier), not necessarily a user. There are major important situations where the owner is not a user but where usability degrades greatly if we refuse to trust the local repository, so we have various special cases. These are intended to be the same or almost the same as those in Git for Windows, and are intended in any case never to be any less secure.
|
||||
|
||||
- As in Git, the `safe.directory` configuration variable must be ignored in any non-protected scopes (local and worktree scopes) but honored in protected scopes as an allowlist of paths that can be trusted as if owned by the current user even when they are not.
|
||||
|
||||
### Being investigated: Gitoxide in installers run from from partly untrusted directories
|
||||
|
||||
In some use cases, an application's own containing directory is an untrusted search path. On Windows, that may be relevant if gitoxide library crates are used as part of an installer. If the user downloads the installer to their `Downloads` directory, then through our use of `std::process::Command`, subprocesses of the installer will be searched for in that directory, possibly picking up malicious programs that have been downloaded but not examined or previously run.
|
||||
|
||||
- This is slighly mitigated by how programs in `Downloads` often have the "mark of the web" alternate data stream data, prompting the user; but the user may intepret the prompt as pertaining to the installer they deliberately just ran and allow it. This is entirely separate from the issue where we must not trust the current working directory--this is about the directory that contains the executable itself.
|
||||
|
||||
- We are still evaluating the likelihood and impact of this use case.
|
||||
|
||||
- Implementing path search ourselves in more (or all) cases may be a solution, but this carries its own risks that we may make mistakes ourselves that would otherwise be avoided by using `std::process::Command`'s own path search logic for Windows. (We already face this to some extent, in that there are already circumstnaces where we have to reimplement path search on Windows, in order to find and run files that would not otherwise be found, such as shell scripts with `#!` lines that make them "executable.")
|
||||
|
||||
### Being investigated: Can we select CodeQL queries to reflect these subtleties?
|
||||
|
||||
In CodeQL, a combination of queries, including all those from "remote only" and a hand-picked selection of those from from "remote and local" could be used.
|
||||
|
||||
(This is separate from the goal of accurately *stating* in a threat modeling document what the threat model is. But hopefully either one, if done, would help figure out how to do the other.)
|
73
etc/security/threat-model.md
Normal file
73
etc/security/threat-model.md
Normal file
@@ -0,0 +1,73 @@
|
||||
# Threat Model for Gitoxide - *Provisional*
|
||||
|
||||
This document outlines the current understanding of the threat model for the Gitoxide project.
|
||||
|
||||
**Note on Scope:** This document is a work in progress and currently provisional in nature. While it will be updated as we learn and refine our processes, a more comprehensive threat model awaits a deeper, component-by-component analysis of all crates and their features.
|
||||
|
||||
## 1. Core Security Philosophy & Assets
|
||||
|
||||
The primary goal of the Gitoxide project is to provide a safe, correct, and high-performance implementation of Git, in Rust. Our security posture is built on the assumption that we must safely handle untrusted data from multiple sources.
|
||||
|
||||
The key assets we aim to protect are:
|
||||
|
||||
- **Integrity and Confidentiality of the Host System:** Preventing Gitoxide from being used as a vector to execute arbitrary code, or to read or write files outside of intended directories.
|
||||
- **Availability of the Host Application:** Ensuring that processing malicious data does not cause the application using Gitoxide to crash, hang, or suffer from resource exhaustion.
|
||||
- **Integrity of Git Operations:** Ensuring all operations are correct and that an attacker cannot corrupt the repository state in a way that violates Git's security model (e.g., via hash collisions).
|
||||
- **The Trust of our Users:** The trust of our users is built on designing and implementing Gitoxide as robustly as we can, continuously improving it, and on a commitment to transparency when issues are found and fixed.
|
||||
|
||||
## 2. The Gitoxide Threat Landscape
|
||||
|
||||
The security considerations for Gitoxide are similar to those of Git itself, and [the SECURITY section of the git(1) manual page](https://git-scm.com/docs/git#_security) is a key reference. However, there are important distinctions arising from Gitoxide's nature as a library. The following sections detail the core principles and specific areas of concern that shape our threat model.
|
||||
|
||||
### 2.1. Data Trust Boundaries
|
||||
|
||||
#### 2.1.1. Untrusted Remote Repositories and Servers
|
||||
Remote repositories and the servers that host them are generally treated as untrusted. We assume they may serve malicious, malformed, or unexpected data.
|
||||
|
||||
- **Sanitization:** Gitoxide must sanitize all data from remotes. We never automatically install or run hooks provided by a repository we clone. We must also protect against directory traversal attacks during checkout, which includes handling sensitive tree entry filenames (e.g., `..`, `.git`), and malformed or platform-unsupported filenames containing separators or prohibited characters (e.g., `a/../b`, `a\..\b`, `C:x`). Similarly, ref names must be validated to conform to Git's naming rules, and on Windows, they must be prohibited from having reserved names (e.g., `COM1`).
|
||||
- **Protocol-Level Attacks:** The server may send malicious data that does not conform to expected protocols (e.g., `git-upload-pack` commands or HTTP responses).
|
||||
- **Data Transported via Insecure Protocols:** Data transported via protocols that inherently do not guarantee integrity (like `http://` or `git://`) is vulnerable to MITM attacks. While we cannot secure the underlying protocol, we must preserve other security guarantees, such as SHA-1 collision detection.
|
||||
|
||||
#### 2.1.2. Untrusted Local Repositories
|
||||
A local repository on the filesystem is not inherently more trustworthy than a remote one. For example, a user might unpack a malicious repository from an archive. Cloning such a repository (even via the filesystem) is a valid way to sanitize it, as the clone operation itself is designed to be safe. Therefore, any repository used as a *source* for a clone must be treated with the same level of scrutiny as a network remote.
|
||||
|
||||
- **"Dubious Ownership":** For "dubiously owned" repos, unless allowlisted in a value of `safe.directory` set in a protected scope, Gitoxide must operate in a restricted mode. Our model differs slightly from Git: we will read the repository's `.git/config` file but treat its contents as **untrusted**, refusing to execute any commands or perform other dangerous actions based on its configuration. This allows for broader library use cases without requiring users to unsafely take ownership of untrusted files.
|
||||
|
||||
#### 2.1.3. Untrusted Environment & Filesystem Locations
|
||||
The environment in which Gitoxide runs is not fully trusted.
|
||||
|
||||
- **Working Tree:** The contents of a repository's working tree are untrusted, as they are derived from (untrusted) repository history.
|
||||
- **Current Working Directory (CWD):** The CWD is an untrusted search path for executing external programs. We do not execute programs from the CWD unless their path explicitly indicates a local execution (e.g., prefixed with `./`).
|
||||
- **Application Directory (on Windows):** In some scenarios (e.g., an installer in the `Downloads` directory), the directory containing the executable is also an untrusted search path. This poses a risk when invoking subprocesses (e.g., `git`), as a malicious executable with the same name could be found and run from that directory.
|
||||
|
||||
### 2.2. Trusted Data and Responsibilities
|
||||
|
||||
- **The `.git` Directory:** In a trusted repository (i.e., one that passes ownership checks), files within the `.git` directory (like `config` and `hooks`) are considered trusted. Our responsibility is to ensure that untrusted data can never tamper with the contents of this directory.
|
||||
|
||||
## 3. Formal Threat Analysis (STRIDE Summary)
|
||||
|
||||
The following table summarizes the primary threats to Gitoxide using the STRIDE framework. The "Details" column references the relevant section in the narrative landscape above.
|
||||
|
||||
| Interaction / Component | Threat & Summary | STRIDE Category | Details |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| **Cloning/Fetching an Untrusted Repository** | A crafted repository causes writes outside the working tree. | **T**ampering, **E**levation of Privilege | 2.1.1 |
|
||||
| | A malformed packfile or "git bomb" exhausts memory/CPU. | **D**enial of Service | 2.1.1 |
|
||||
| | An object with a colliding SHA-1 hash is injected into the repo. | **S**poofing, **T**ampering | 2.1.1 |
|
||||
| **Reading Local Repository Configuration** | A malicious `.git/config` in a "dubiously-owned" repo executes code. | **E**levation of Privilege | 2.1.2 |
|
||||
| | A malformed `.git/config` file causes the library to panic. | **D**enial of Service | 2.1.2 |
|
||||
| **Invoking External Processes (`git`, shells)** | A malicious executable (`git`, `sh`) is found first in an untrusted search path. | **S**poofing, **E**levation of Privilege | 2.1.3 |
|
||||
| | A malicious external process hangs, causing the host app to hang. | **D**enial of Service | 2.1.3 |
|
||||
| **File Checkout** | A file path in the index targets a reserved device name on Windows. | **D**enial of Service | 2.1.1 |
|
||||
| | A file path uses case-folding or equivalent names to overwrite another file. | **T**ampering | 2.1.1 |
|
||||
|
||||
## 4. Mitigation Strategies
|
||||
|
||||
This section outlines our primary countermeasures for the threats identified above.
|
||||
|
||||
| Threat Category | Mitigation Strategy |
|
||||
| :--- | :--- |
|
||||
| **Filesystem Tampering & EoP (Traversal, Special Filenames)** | - Rigorous path sanitization before all filesystem writes. <br> - Block traversal (`../`), git-dir writes (`.git/`), and special Windows device names. <br> - Prohibit patterns that can alias sensitive directories via OS-specific equivalences (e.g., case-folding, 8.3 names, NTFS streams, HFS+ ignorable characters). |
|
||||
| **EoP via Malicious Local Configuration** | - Implement ownership checks on local repositories. <br> - For "dubiously owned" repos, unless allowlisted, treat all configuration values as untrusted and never execute commands based on them. |
|
||||
| **EoP via Spoofed External Processes** | - Use secure, well-defined search paths when invoking external commands. Do not execute programs from the CWD unless explicitly requested (e.g., `./program`). <br> - *Being Investigated:* The risks of using `std::process::Command` in scenarios like installers on Windows. |
|
||||
| **SHA-1 Collision Attacks** | - Implement detection for known SHA-1 collision methods. <br> - We hope to support SHA-256 repositories in the near future. |
|
||||
| **Denial of Service (Resource Exhaustion)** | - Write panic-safe parsing logic for all Git data structures. <br> - Apply sensible resource limits during resource-intensive operations like packfile decompression. |
|
6
justfile
6
justfile
@@ -239,7 +239,7 @@ cross-test-android: (cross-test 'armv7-linux-androideabi' '--no-default-features
|
||||
|
||||
# Run `cargo diet` on all crates to see that they are still in bounds
|
||||
check-size:
|
||||
etc/check-package-size.sh
|
||||
etc/scripts/check-package-size.sh
|
||||
|
||||
# Report the Minimum Supported Rust Version (the `rust-version` of `gix`) in X.Y.Z form
|
||||
msrv: (query-meta '''
|
||||
@@ -295,11 +295,11 @@ check-mode:
|
||||
|
||||
# Delete `gix-packetline-blocking/src` and regenerate from `gix-packetline/src`
|
||||
copy-packetline:
|
||||
etc/copy-packetline.sh
|
||||
etc/scripts/copy-packetline.sh
|
||||
|
||||
# Get the unique `v*` tag at `HEAD`, or fail with an error
|
||||
unique-v-tag:
|
||||
etc/unique-v-tag.sh
|
||||
etc/scripts/unique-v-tag.sh
|
||||
|
||||
# Trigger the `release.yml` workflow on the current `v*` tag
|
||||
run-release-workflow repo='':
|
||||
|
Reference in New Issue
Block a user