{"id":"GHSA-pg4w-g64p-qwhj","revision":null,"records":[{"revision":"ba0a7c29cb074ee4b4e9e941bed1c854","observedAt":"2026-10-23T15:48:27.903+00:00","statement":{"source":"cve-program","id":"CVE-2026-82252","aliases":[],"title":"gitoxide before 0.52.1 Repository Boundary Violation via symlinked .gitmodules","description":"gitoxide before 0.52.1 follows symlinks when reading the worktree .gitmodules file, allowing attackers to inject out-of-repository bytes into submodule metadata. Attackers can create a malicious repository with a symlinked .gitmodules pointing outside the repository tree, causing gitoxide to parse arbitrary external files as submodule configuration and expose attacker-controlled name, path, and url values.","state":0,"publishedAt":"2026-08-28T10:49:36.897+00:00","modifiedAt":"2026-08-29T13:38:27.91+00:00","affected":[{"ecosystem":"Vendor product","name":"gitoxide","ranges":[],"versions":[],"rawVersionEvidence":"{\n                    \"vendor\": \"GitoxideLabs\",\n                    \"product\": \"gitoxide\",\n                    \"defaultStatus\": \"unaffected\",\n                    \"packageURL\": \"pkg:cargo/gitoxide\",\n                    \"versions\": [\n                        {\n                            \"version\": \"0\",\n                            \"status\": \"affected\",\n                            \"versionType\": \"semver\",\n                            \"lessThan\": \"0.52.1\"\n                        },\n                        {\n                            \"version\": \"0.52.1\",\n                            \"status\": \"unaffected\",\n                            \"versionType\": \"semver\"\n                        }\n                    ]\n                }"},{"ecosystem":"Vendor product","name":"gitoxide","ranges":[],"versions":[],"rawVersionEvidence":"{\n                    \"vendor\": \"GitoxideLabs\",\n                    \"product\": \"gitoxide\",\n                    \"defaultStatus\": \"unaffected\",\n                    \"packageURL\": \"pkg:cargo/gix\",\n                    \"versions\": [\n                        {\n                            \"version\": \"0\",\n                            \"status\": \"affected\",\n                            \"versionType\": \"semver\",\n                            \"lessThan\": \"0.82.0\"\n                        },\n                        {\n                            \"version\": \"0.82.0\",\n                            \"status\": \"unaffected\",\n                            \"versionType\": \"semver\"\n                        }\n                    ]\n                }"}],"metrics":[{"system":"CVSS 4.0","vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N","score":8.7,"severity":"HIGH"},{"system":"CVSS 3.1","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N","score":7.5,"severity":"HIGH"}],"references":["https://github.com/GitoxideLabs/gitoxide/security/advisories/GHSA-pg4w-g64p-qwhj","https://www.vulncheck.com/advisories/gitoxide-before-0.52.1-repository-boundary-violation-via-symlinked-gitmodules"],"sourceUrl":"https://www.cve.org/CVERecord?id=CVE-2026-82252","license":"CVE Program Terms of Use","key":"cve-program:CVE-2026-82252","identifiers":["CVE-2026-82252"]},"retained":false,"historicalAffected":[]},{"revision":"3279988f94f04905baa859c10d34704a","observedAt":"2026-11-13T17:09:18.964+00:00","statement":{"source":"euvd","id":"EUVD-2026-67704","aliases":["CVE-2026-82252","GHSA-wj8r-8wwg-mq4f"],"title":"gitoxide before 0.52.1 follows symlinks when reading the worktree .gitmodules file, allowing attackers to inject out-of-repository bytes into submodule metadata. Attackers can create a malicious repository with a symlinked .gitmodules point…","description":"gitoxide before 0.52.1 follows symlinks when reading the worktree .gitmodules file, allowing attackers to inject out-of-repository bytes into submodule metadata. Attackers can create a malicious repository with a symlinked .gitmodules pointing outside the repository tree, causing gitoxide to parse arbitrary external files as submodule configuration and expose attacker-controlled name, path, and url values.","state":0,"publishedAt":null,"modifiedAt":null,"affected":[],"metrics":[{"system":"EUVD CVSS 4.0","vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N","score":8.7,"severity":null}],"references":["https://github.com/GitoxideLabs/gitoxide/security/advisories/GHSA-pg4w-g64p-qwhj","https://www.vulncheck.com/advisories/gitoxide-before-0.52.1-repository-boundary-violation-via-symlinked-gitmodules"],"sourceUrl":"https://euvd.enisa.europa.eu/vulnerability/EUVD-2026-67704","license":"ENISA EUVD · source terms and attribution apply","enrichment":{"sourceStatus":null,"weaknesses":[],"productCriteria":[],"sourceDates":{"datePublished":"Aug 28, 2026, 10:49:36 AM","dateUpdated":"Aug 29, 2026, 1:38:27 PM"},"relatedAdvisories":[{"id":"msrc_CVE-2026-82252","title":"gitoxide before 0.52.1 Repository Boundary Violation via symlinked .gitmodules","vulnerabilityIds":["CVE-2026-82252"]}],"note":"EUVD source date text has no stated timezone and is retained without inventing a UTC instant. Related bulletin membership is not an alias, common cause or applicability claim. A missing vector with a zero score is treated as unrated. Complete vendor/product and underlying source evidence remains in the original JSON."},"key":"euvd:EUVD-2026-67704","identifiers":["EUVD-2026-67704","CVE-2026-82252","GHSA-wj8r-8wwg-mq4f"]},"retained":false,"historicalAffected":[]},{"revision":"45d3d23ca02840a285ea4d78da606a7c","observedAt":"2026-10-25T16:19:10.271+00:00","statement":{"source":"nvd","id":"CVE-2026-82252","aliases":[],"title":"gitoxide before 0.52.1 follows symlinks when reading the worktree .gitmodules file, allowing attackers to inject out-of-repository bytes into submodule metadata. Attackers can create a malicious repository with a symlinked .gitmodules point…","description":"gitoxide before 0.52.1 follows symlinks when reading the worktree .gitmodules file, allowing attackers to inject out-of-repository bytes into submodule metadata. Attackers can create a malicious repository with a symlinked .gitmodules pointing outside the repository tree, causing gitoxide to parse arbitrary external files as submodule configuration and expose attacker-controlled name, path, and url values.","state":0,"publishedAt":"2026-08-28T12:16:37.887+00:00","modifiedAt":"2026-08-29T14:16:37.8+00:00","affected":[],"metrics":[{"system":"CVSS 4.0 · disclosure@vulncheck.com · Secondary","vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","score":8.7,"severity":"HIGH"},{"system":"CVSS 3.1 · disclosure@vulncheck.com · Secondary","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N","score":7.5,"severity":"HIGH"}],"references":["https://github.com/GitoxideLabs/gitoxide/security/advisories/GHSA-pg4w-g64p-qwhj","https://www.vulncheck.com/advisories/gitoxide-before-0.52.1-repository-boundary-violation-via-symlinked-gitmodules"],"sourceUrl":"https://nvd.nist.gov/vuln/detail/CVE-2026-82252","license":"NIST NVD usage terms; underlying source attribution retained","enrichment":{"sourceStatus":"Deferred","weaknesses":["CWE-59"],"productCriteria":[],"sourceDates":{"published":"2026-08-28T12:16:37.887","lastModified":"2026-08-29T14:16:37.800"},"relatedAdvisories":[],"note":"NVD analysis and CPE criteria are source context, not proof that a package or your environment is affected. Complete affected data, logical configurations and SSVC are retained in the original JSON."},"key":"nvd:CVE-2026-82252","identifiers":["CVE-2026-82252"]},"retained":false,"historicalAffected":[]},{"revision":"f5f01df5b73140288d687a8fa30b4dd9","observedAt":"2026-10-24T13:19:54.901+00:00","statement":{"source":"osv","id":"GHSA-pg4w-g64p-qwhj","aliases":["CVE-2026-82252"],"title":"gix and gitoxide's symlinked .gitmodules are followed and parsed from outside of the repository","description":"## 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.","state":0,"publishedAt":"2026-05-05T19:26:09+00:00","modifiedAt":"2026-09-10T03:51:06.5467366+00:00","affected":[{"ecosystem":"crates.io","name":"gitoxide","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"0"},{"kind":"fixed","version":"0.52.1"}]}],"versions":[],"rawVersionEvidence":null},{"ecosystem":"crates.io","name":"gix","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"0"},{"kind":"fixed","version":"0.83.0"}]}],"versions":[],"rawVersionEvidence":null}],"metrics":[{"system":"CVSS_V4","vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N/E:P","score":null,"severity":null},{"system":"Publisher rating","vector":null,"score":null,"severity":"HIGH"}],"references":["https://github.com/GitoxideLabs/gitoxide/security/advisories/GHSA-pg4w-g64p-qwhj","https://github.com/GitoxideLabs/gitoxide"],"sourceUrl":"https://github.com/advisories/GHSA-pg4w-g64p-qwhj","license":"GitHub Advisory Database · CC-BY-4.0","key":"osv:GHSA-pg4w-g64p-qwhj","identifiers":["GHSA-pg4w-g64p-qwhj","CVE-2026-82252"]},"retained":false,"historicalAffected":[]}],"coverage":[{"source":"cisa-kev:global","scope":"Complete CISA KEV catalog; all vendors. Missing entries do not establish absence of exploitation.","generation":"2026-11-15T06:30:52.8313382+00:00","complete":true,"records":1781,"lastAttemptAt":"2026-11-15T06:30:52.8313382+00:00","lastSuccessAt":"2026-11-15T06:30:52.9739799+00:00","error":null,"lastVerifiedAt":"2026-11-15T06:30:52.9739809+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"cve-program","scope":"Official CVE Program baseline and cumulative hourly delta; all vendors, published and rejected records","generation":"cve-7de4d7559a5263003f03d9f70577ab06f92ba4178309f26fce53e22a4a959294-5e215490d55c14930215665213ddac0f30153138ec392bed5f309d985bc5e0a1","complete":true,"records":425770,"lastAttemptAt":"2026-11-15T06:30:52.1466825+00:00","lastSuccessAt":"2026-11-15T06:30:52.1389052+00:00","error":null,"lastVerifiedAt":"2026-11-15T06:30:52.1466825+00:00","snapshotPublishedAt":"2026-11-15T06:27:22+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"euvd","scope":"Rolling EUVD lookups of CVE aliases in current public OSV archives; 500 identifiers per refresh, rechecked after 48 hours. Not a global EUVD catalog. Successful not-found lookups count as checked; they do not imply withdrawal or safety. No reader inventory is sent.","generation":"enrichment-5a4abd14253544b78d8c3044915082da","complete":false,"records":13821,"lastAttemptAt":"2026-11-15T06:39:25.4859854+00:00","lastSuccessAt":"2026-11-15T06:39:24.47+00:00","error":"64 identifier lookups failed; latest failures include AccessDenied (HTTP 403). Other identifiers were checked independently.","lastVerifiedAt":"2026-11-15T06:39:24.47+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":13810,"expectedIdentifiers":13874,"failedIdentifiers":64},{"source":"first-epss:nuget","scope":"FIRST EPSS for explicit CVE aliases in the collected public NuGet archive. Not a global EPSS backfill.","generation":"2026-11-15T06:30:52.8313382+00:00","complete":true,"records":1125,"lastAttemptAt":"2026-11-15T06:30:52.8313382+00:00","lastSuccessAt":"2026-11-15T06:30:52.9749685+00:00","error":null,"lastVerifiedAt":"2026-11-15T06:30:52.9749715+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"nvd","scope":"Rolling NVD lookups of CVE aliases in current public OSV archives; 500 identifiers per refresh, rechecked after 48 hours. Not a global NVD catalog. Successful not-found lookups count as checked; they do not imply withdrawal or safety. No reader inventory is sent.","generation":"enrichment-35abf047bdfe46089a52c4c139c37942","complete":false,"records":13833,"lastAttemptAt":"2026-11-15T06:30:58.1452571+00:00","lastSuccessAt":"2026-11-15T05:33:23.837+00:00","error":"12 identifier lookups failed; latest failures include HttpError (HTTP 503). Other identifiers were checked independently.","lastVerifiedAt":"2026-11-15T05:33:23.837+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":13862,"expectedIdentifiers":13874,"failedIdentifiers":12},{"source":"osv:Go","scope":"Complete OSV Go ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"go-64eea06dbd27de8464d5dbce1b78cc794cc59e2d901516ae0d3ea76e624cdae0","complete":true,"records":9955,"lastAttemptAt":"2026-11-15T06:30:52.7627278+00:00","lastSuccessAt":"2026-11-14T13:57:23.1208135+00:00","error":null,"lastVerifiedAt":"2026-11-15T06:30:52.7627278+00:00","snapshotPublishedAt":"2026-11-14T13:17:57+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"osv:NuGet","scope":"Complete OSV NuGet ecosystem archive, including GitHub Advisory Database records; NuGet version matching only","generation":"nuget-f4424d7d4861b1af1404bd15abcb83f295dcd003412a9340ca99dc8200aa148a","complete":true,"records":2014,"lastAttemptAt":"2026-11-15T06:30:52.191726+00:00","lastSuccessAt":"2026-11-13T19:57:08.2864435+00:00","error":null,"lastVerifiedAt":"2026-11-15T06:30:52.191726+00:00","snapshotPublishedAt":"2026-11-13T19:33:10+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"osv:crates.io","scope":"Complete OSV crates.io ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"crates.io-012aff9b2fb349d53e2c4bace6ca57956b6f5f9d82c1dc9fdc1c9b3c738f8977","complete":true,"records":3148,"lastAttemptAt":"2026-11-15T06:30:52.7798435+00:00","lastSuccessAt":"2026-11-14T04:57:03.8279646+00:00","error":null,"lastVerifiedAt":"2026-11-15T06:30:52.7798435+00:00","snapshotPublishedAt":"2026-11-14T03:02:50+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"osv:npm","scope":"Complete OSV npm ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"npm-878f718ccd076f540460423958c8e379b139b997b45858275573ecc4d702fe9a","complete":true,"records":232474,"lastAttemptAt":"2026-11-15T06:30:52.6600161+00:00","lastSuccessAt":"2026-11-15T05:33:06.8241102+00:00","error":null,"lastVerifiedAt":"2026-11-15T06:30:52.6600161+00:00","snapshotPublishedAt":"2026-11-15T04:33:08+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null}]}