Skip to main content

gitoxide (gix-fs) CVE-2026-44471

HIGH
Improper Link Resolution Before File Access (CWE-59)
2026-05-07 https://github.com/GitoxideLabs/gitoxide GHSA-f89h-2fjh-2r9q
7.8
CVSS 3.1 · GitHub Advisory
Share

Severity by source

GitHub Advisory PRIMARY
7.8 HIGH
AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

Primary rating from GitHub Advisory · only source for this CVE.

CVSS VectorGitHub Advisory

CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
Attack Vector
Local
Attack Complexity
Low
Privileges Required
None
User Interaction
Required
Scope
Unchanged
Confidentiality
High
Integrity
High
Availability
High

Lifecycle Timeline

3
Source Code Evidence Fetched
May 07, 2026 - 00:31 vuln.today
Analysis Generated
May 07, 2026 - 00:31 vuln.today
CVE Published
May 07, 2026 - 00:01 nvd
HIGH 7.8

DescriptionGitHub Advisory

Summary

A malicious tree can be constructed that will, when checked out with gitoxide, permit writing an attacker-controlled symlink into any existing directory the user has write access to.

Details

During checkout, all symlink index entries are deferred and created after regular files using a single shared gix_worktree::Stack. Internally, this uses a gix_fs::Stack.

gix_fs::Stack::make_relative_path_current() caches validated path prefixes: when the previously-processed leaf component exactly matches the leading component(s) of the next path, the leaf-to-directory transition at gix-fs/src/stack.rs:195-197 invokes only delegate.push_directory(), never delegate.push().

In gix_worktree::stack::delegate::StackDelegate, when the state member is State::CreateDirectoryAndAttributesStack, Attributes::push_directory() only loads attributes (from the ODB, in the clone case), and does not perform any other checks. The on-disk symlink_metadata() check and unlink-on-collision live in StackDelegate::push()'s invocation of create_leading_directory(), which is therefore bypassed for the cached prefix. The final symlink is created with plain std::os::unix::fs::symlink, which follows symlinks in parent directories.

Therefore, it's possible to provide a tree with duplicate symlink and directory entries that exploits this. If a tree is constructed with:

  1. A 120000 (symlink) entry a that points to .git/hooks.
  2. A 040000 (directory) entry a with a subtree that contains a symlink from post-checkout to ../../payload.
  3. A 100755 (executable file) entry payload.

This is converted by gix_index::State::from_tree() into index entries ["a" (SYMLINK), "a/post-checkout" (SYMLINK)].

Then, during the delayed symlink phase:

  1. a is created as a symlink to e.g. .git/hooks.
  2. When processing a/post-checkout, the a prefix is reused from the just-processed leaf entry without re-running the intermediate-directory check, after which…
  3. symlink(target, "<wt>/a/post-checkout") resolves through the just-created symlink to write .git/hooks/post-checkout.

Although this example uses .git/hooks for simplicity, there's no actual requirement to write within the repo checkout. This can be fairly easily chained into code execution by writing to something that is known to be executed - for example, by writing to .git/hooks/post-checkout if the attacker knows that a hook-aware Git implementation will be used later, or by writing to something like ~/.local/bin.

PoC

Attached is build-bad-repo.sh, which builds a repo with the aforementioned tree structure. Cloning it with gix will set up the malicious .git/hooks/post-checkout, at which point anything that normally invokes the post-checkout hook will result in its execution, such as git checkout -b new-branch.

Impact

Arbitrary symlink creation into any existing directory the user can write to.

Disclosure

This vulnerability was found by AI (specifically, Claude Mythos) as part of Project Glasswing. This advisory was written and verified by a human.

AnalysisAI

Path traversal via symlink prefix reuse in gitoxide's gix-fs crate allows arbitrary code execution when cloning malicious repositories. Attackers can construct Git trees with duplicate symlink/directory entries that escape the worktree during checkout, writing controlled files to sensitive locations like .git/hooks or ~/.local/bin on Unix systems. Publicly available exploit code exists (PoC script provided in advisory). CVSS 7.8 reflects local attack vector with required user interaction (cloning the malicious repo), but real-world impact is high given code execution potential.

Technical ContextAI

The vulnerability (CWE-59: Improper Link Resolution Before File Access) exists in the Rust-based gitoxide Git implementation, specifically in the gix-fs crate (pkg:rust/gix-fs versions ≤0.21.0). During checkout operations, gix_fs::Stack caches validated path prefixes to optimize directory traversal. When processing symlink entries deferred until after regular files, the cached prefix mechanism bypasses critical security checks. The gix_fs::Stack::make_relative_path_current() method reuses leaf-to-directory transitions without re-invoking delegate.push(), which normally performs symlink_metadata() validation and unlink-on-collision handling in create_leading_directory(). When Attributes::push_directory() is called instead for cached prefixes, only attribute loading occurs-no filesystem collision detection. The final symlink creation uses std::os::unix::fs::symlink, which follows symlinks in parent directories, enabling directory traversal. The flaw allows Git trees with conflicting object types (same path as both 120000 symlink and 040000 directory) to create a symlink that redirects subsequent file writes outside the intended worktree.

RemediationAI

Vendor-released patch: gix-fs version 0.21.1 fixes the symlink prefix reuse vulnerability. Upgrade immediately by updating Cargo.toml dependencies to gix-fs = "0.21.1" or later, then run cargo update and cargo build. For applications using higher-level gitoxide crates (gix, gix-worktree), verify transitive dependency resolution brings in the patched gix-fs version. Advisory and patch details at https://github.com/GitoxideLabs/gitoxide/security/advisories/GHSA-f89h-2fjh-2r9q. If immediate upgrade is blocked, implement compensating controls: (1) Restrict repository cloning to explicitly trusted sources only-disable or audit any automated clone operations against public repositories, accepting reduced collaboration velocity; (2) Run gitoxide operations in sandboxed environments (containers, VMs) with restricted filesystem write permissions outside the worktree, though this may break legitimate workflows requiring access to .git metadata; (3) Use canonical Git (C implementation) for untrusted repository operations until upgrade completes, accepting toolchain heterogeneity overhead. No workaround fully mitigates the risk-upgrading to 0.21.1 is the only complete fix.

Share

CVE-2026-44471 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy