{"id":"CVE-2026-82252","aliases":["GHSA-pg4w-g64p-qwhj"],"url":"https://o3.security/vulnerability/CVE-2026-82252","summary":"gitoxide before 0.52.1 Repository Boundary Violation via symlinked .gitmodules","details":"## Summary\nattachments:\n[pocs.zip](https://github.com/user-attachments/files/26431422/pocs.zip)\n\n\nWhen `Repository::submodules()` loads submodule metadata, it prefers the worktree `.gitmodules` file if that path exists. In the current implementation, the path is read with `std::fs::read()`, which follows symlinks. As a result, a repository can present a symlinked `.gitmodules` that points outside the repository, and gitoxide will parse the out-of-repository bytes as submodule configuration.\n\nThis is a repository-boundary violation. A caller using the high-level submodule API can believe it is reading repository-local submodule metadata, while the bytes are actually coming from an arbitrary file outside the repository tree.\n\n## Root cause analysis\n\nThe relevant flow is:\n\n1. [`gix/src/repository/location.rs`](https://github.com/GitoxideLabs/gitoxide/blob/v0.52.0/gix/src/repository/location.rs) derives the worktree `.gitmodules` path as `workdir/.gitmodules`.\n2. [`gix/src/repository/submodule.rs`](https://github.com/GitoxideLabs/gitoxide/blob/v0.52.0/gix/src/repository/submodule.rs) reads that path with `std::fs::read(&path)` and immediately parses the bytes as a submodule configuration file.\n3. `Repository::submodules()` exposes the parsed entries through the high-level API.\n\nThe issue is not in the parser. The issue is that the worktree path is treated as an ordinary file without checking whether it is a symlink, and without checking whether the canonicalized target remains inside the repository worktree.\n\nBecause `std::fs::read()` follows symlinks, a malicious repository can cause gitoxide to ingest bytes from an attacker-chosen location outside the repository. The resulting `Submodule` objects then expose `name`, `path`, and `url` values derived from that external file.\n\n## Reproduction steps\n\nUse the attached PoC zip that contains the `pocs/` workspace.\n\n1. Unzip the PoC archive.\n2. Enter `pocs/F001`.\n3. Run:\n    \n    ```bash\n    cargo run --quiet\n    ```\n    \n4. Compare the output with `pocs/F001/result.txt`.\n\nImportant outputs include:\n\n- `gitmodules_symlink=.../victim-repo/.gitmodules`\n- `symlink_target=.../outside/modules.conf`\n- `parsed_name=symlinked`\n- `parsed_path=deps/symlinked`\n- `parsed_url=https://attacker.example/symlinked.git`\n\nThese outputs show that gitoxide parsed the submodule configuration from the symlink target outside the repository, not from repository-local bytes.\n\n## Impact\n\nConfirmed impact:\n\n- out-of-repository bytes can be injected into the result of `Repository::submodules()`;\n- callers can be misled about submodule metadata such as `name`, `path`, and `url`;\n- any downstream workflow that uses those values to decide clone, fetch, update, or policy behavior is operating on attacker-controlled data that did not actually originate from the repository tree.\n\nThis report does **not** claim direct command execution from this code path by itself. The demonstrated impact is metadata injection across the repository boundary.\n\n## Recommended fix\n\nA safe fix is to stop silently following symlinks for the worktree `.gitmodules` path in this loading path.\n\nReasonable options include:\n\n1. use `symlink_metadata()` / `lstat`style checks and reject symlinked `.gitmodules` when loading from the worktree;\n2. canonicalize the target and verify that it still resides under the repository worktree before reading it;\n3. for security-sensitive callers, prefer loading `.gitmodules` from the index or `HEAD` tree rather than following the worktree path.\n\nAt minimum, the worktree path should not silently follow symlinks to arbitrary external files.","published":"2026-08-28T10:49:36.897Z","modified":"2026-10-28T02:30:23.273556245Z","cvss":null,"epss":null,"cisaKev":null,"exploitsKnown":null,"affectedPackages":[{"ecosystem":"crates.io","name":"gitoxide","fixedVersion":"0.52.1"},{"ecosystem":"crates.io","name":"gix","fixedVersion":"0.83.0"}],"fix":null,"references":[{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/82xxx/CVE-2026-82252.json"},{"type":"ADVISORY","url":"https://github.com/GitoxideLabs/gitoxide/security/advisories/GHSA-pg4w-g64p-qwhj"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-82252"},{"type":"ADVISORY","url":"https://www.vulncheck.com/advisories/gitoxide-before-0.52.1-repository-boundary-violation-via-symlinked-gitmodules"},{"type":"PACKAGE","url":"https://github.com/GitoxideLabs/gitoxide"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-10-28T02:30:23.273556245Z"}}