{"id":"CVE-2026-63475","aliases":["EUVD-2026-116273","GHSA-96wc-2m84-2cj7"],"status":"published","title":"isomorphic-git: Circular symbolic references cause non-terminating resolution (DoS)","description":"isomorphic-git is a pure JavaScript implementation of Git for Node.js and browsers. Prior to 1.38.6, isomorphic-git persists server-supplied circular symref= capabilities through updateRemoteRefs, and GitRefManager.resolve() follows the resulting loose symbolic references without a default depth limit or cycle detection. After a clone from a malicious or man-in-the-middle-controlled remote, operations such as log, status, checkout, and branch that resolve refs/remotes/origin/a or refs/remotes/origin/b do not terminate. The circular references remain on disk, leaving the repository unusable for the application and causing a persistent denial of service. This issue is fixed in version 1.38.6.","severity":{"version":"3.1","score":4.3,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:L","level":"medium","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-12","score":0.00398,"percentile":0.3454,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-674","CWE-835"],"published":"2026-11-03T19:45:24.488Z","modified":"2026-11-09T20:15:03Z","fixes":[{"ecosystem":"npm","package":"isomorphic-git","fixed_in":["1.38.6"],"sources":["ghsa","osv"]}],"affected":[{"source":"ghsa","ecosystem":"npm","package":"isomorphic-git","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"last_affected":"1.38.5"},{"fixed":"1.38.6"}]}]},{"source":"osv","ecosystem":"npm","package":"isomorphic-git","ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"1.38.6"}]}]}],"products":[{"vendor":"isomorphic-git","product":"isomorphic-git"}],"references":[{"url":"https://github.com/isomorphic-git/isomorphic-git/security/advisories/GHSA-96wc-2m84-2cj7","tags":["x_refsource_CONFIRM","exploit","advisory","web"]},{"url":"https://github.com/isomorphic-git/isomorphic-git/pull/2370","tags":["x_refsource_MISC","fix","web"]},{"url":"https://github.com/isomorphic-git/isomorphic-git/commit/823843d1cd19182df79bc907c767f5bcecb39a0b","tags":["x_refsource_MISC","fix","web"]},{"url":"https://github.com/isomorphic-git/isomorphic-git/releases/tag/v1.38.6","tags":["x_refsource_MISC","web"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-63475","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-96wc-2m84-2cj7"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/63xxx/CVE-2026-63475.json","tags":["advisory"]},{"url":"https://github.com/isomorphic-git/isomorphic-git","tags":["package"]}],"sources":{"cve":[{"id":"CVE-2026-63475","title":"isomorphic-git: Circular symbolic references cause non-terminating resolution (DoS)","description":"isomorphic-git is a pure JavaScript implementation of Git for Node.js and browsers. Prior to 1.38.6, isomorphic-git persists server-supplied circular symref= capabilities through updateRemoteRefs, and GitRefManager.resolve() follows the resulting loose symbolic references without a default depth limit or cycle detection. After a clone from a malicious or man-in-the-middle-controlled remote, operations such as log, status, checkout, and branch that resolve refs/remotes/origin/a or refs/remotes/origin/b do not terminate. The circular references remain on disk, leaving the repository unusable for the application and causing a persistent denial of service. This issue is fixed in version 1.38.6.","status":"published","published":"2026-11-03T19:45:24.488Z","modified":"2026-11-03T21:31:07.998Z","cvss":[{"version":"3.1","score":4.3,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:L","level":"medium","assessor":"cna"}],"cwes":["CWE-674","CWE-835"],"updated_at":"2026-11-03T22:58:38.387176Z"}],"euvd":[{"id":"EUVD-2026-116273","description":"isomorphic-git: Circular symbolic references cause non-terminating resolution (DoS)","status":"published","published":"2026-11-09T19:58:32Z","modified":"2026-11-09T19:58:32Z","cvss":[{"version":"3.1","score":4.3,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:L","level":"medium"}],"updated_at":"2026-11-09T21:18:10.039091Z"}],"ghsa":[{"id":"GHSA-96wc-2m84-2cj7","title":"isomorphic-git: Circular symbolic references cause non-terminating resolution (DoS)","description":"### Summary\nA malicious server can advertise circular `symref=` capabilities (e.g. `a → b` and `b → a`). isomorphic-git writes them to disk as loose symrefs, and `GitRefManager.resolve()` follows them with no depth limit and no cycle detection, so any later operation that resolves one of them (`log`, `status`, `checkout`, `branch`, …) **loops forever** — a persistent denial of service from a single clone.\n\n### Details\n`src/managers/GitRefManager.js` — `resolve()` only enforces a depth limit when a `depth` argument is passed (`depth = undefined` by default), and has no visited-set:\n\n```js\nstatic async resolve({ fs, gitdir, ref, depth = undefined }) {\n  if (depth !== undefined) { depth--; if (depth === -1) return ref }\n  …\n}\n```\n\n`updateRemoteRefs` persists all server-supplied symrefs unconditionally. After clone the client has `refs/remotes/origin/a → ref: refs/remotes/origin/b` and `b → a` on disk; resolving either never terminates. Because the bad refs live on disk, the repo is effectively bricked for the application.\n\n#### Canonical git behavior (divergence)\ngit caps symref resolution at `SYMREF_MAXDEPTH = 5` (refs.c): `git rev-parse a` returns immediately with `warning: ignoring dangling symref` — no recursion, no hang.\n\n### PoC\n`https://github.com/spiceoverflow/av5-circular-symref` — open in a Codespace; clone writes the circular symrefs, then `git.log` on one never returns (the runner stops it after a 20s hang):\n\n```\n[AV-5] refs/remotes/origin/a contains: ref: refs/remotes/origin/b\n[AV-5] refs/remotes/origin/b contains: ref: refs/remotes/origin/a\n[run] *** DoS CONFIRMED: resolving a circular symref never terminates ***\n```\n\n### Impact\nA persistent denial of service via non-terminating symbolic-ref resolution (CWE-674 / CWE-835). After a single clone from a malicious (or MitM'd) server the circular refs are written to disk, so every later operation that resolves them (`log`, `status`, `checkout`, `branch`, …) hangs forever — the repository becomes effectively unusable for the application.\n\nImpacted: any application that clones from untrusted/compromised remotes with isomorphic-git.\n\n### Suggested fix\nAdd visited-set cycle detection (and/or a default maximum depth, as git does) in `GitRefManager.resolve()`; optionally validate server-supplied symref targets before persisting.","status":"published","published":"2026-11-09T19:58:32Z","modified":"2026-11-09T19:58:33Z","cvss":[{"version":"3.1","score":4.3,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:L","level":"medium"}],"cwes":["CWE-674","CWE-835"],"updated_at":"2026-11-09T20:19:39.584745Z"}],"nvd":[{"id":"CVE-2026-63475","description":"isomorphic-git is a pure JavaScript implementation of Git for Node.js and browsers. Prior to 1.38.6, isomorphic-git persists server-supplied circular symref= capabilities through updateRemoteRefs, and GitRefManager.resolve() follows the resulting loose symbolic references without a default depth limit or cycle detection. After a clone from a malicious or man-in-the-middle-controlled remote, operations such as log, status, checkout, and branch that resolve refs/remotes/origin/a or refs/remotes/origin/b do not terminate. The circular references remain on disk, leaving the repository unusable for the application and causing a persistent denial of service. This issue is fixed in version 1.38.6.","status":"published","published":"2026-11-03T20:18:15.903Z","modified":"2026-11-03T22:19:47.803Z","cvss":[{"version":"3.1","score":4.3,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:L","level":"medium","assessor":"secondary"}],"cwes":["CWE-674","CWE-835"],"updated_at":"2026-11-04T00:48:10.032782Z"}],"osv":[{"id":"CVE-2026-63475","title":"isomorphic-git: Circular symbolic references cause non-terminating resolution (DoS)","description":"isomorphic-git is a pure JavaScript implementation of Git for Node.js and browsers. Prior to 1.38.6, isomorphic-git persists server-supplied circular symref= capabilities through updateRemoteRefs, and GitRefManager.resolve() follows the resulting loose symbolic references without a default depth limit or cycle detection. After a clone from a malicious or man-in-the-middle-controlled remote, operations such as log, status, checkout, and branch that resolve refs/remotes/origin/a or refs/remotes/origin/b do not terminate. The circular references remain on disk, leaving the repository unusable for the application and causing a persistent denial of service. This issue is fixed in version 1.38.6.","status":"published","published":"2026-11-03T19:45:24.488Z","modified":"2026-11-05T03:30:19.670102188Z","cvss":[{"version":"3.1","score":4.3,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:L","level":"medium"}],"cwes":["CWE-674","CWE-835"],"updated_at":"2026-11-05T07:12:46.161235Z"},{"id":"GHSA-96wc-2m84-2cj7","title":"isomorphic-git: Circular symbolic references cause non-terminating resolution (DoS)","description":"### Summary\nA malicious server can advertise circular `symref=` capabilities (e.g. `a → b` and `b → a`). isomorphic-git writes them to disk as loose symrefs, and `GitRefManager.resolve()` follows them with no depth limit and no cycle detection, so any later operation that resolves one of them (`log`, `status`, `checkout`, `branch`, …) **loops forever** — a persistent denial of service from a single clone.\n\n### Details\n`src/managers/GitRefManager.js` — `resolve()` only enforces a depth limit when a `depth` argument is passed (`depth = undefined` by default), and has no visited-set:\n\n```js\nstatic async resolve({ fs, gitdir, ref, depth = undefined }) {\n  if (depth !== undefined) { depth--; if (depth === -1) return ref }\n  …\n}\n```\n\n`updateRemoteRefs` persists all server-supplied symrefs unconditionally. After clone the client has `refs/remotes/origin/a → ref: refs/remotes/origin/b` and `b → a` on disk; resolving either never terminates. Because the bad refs live on disk, the repo is effectively bricked for the application.\n\n#### Canonical git behavior (divergence)\ngit caps symref resolution at `SYMREF_MAXDEPTH = 5` (refs.c): `git rev-parse a` returns immediately with `warning: ignoring dangling symref` — no recursion, no hang.\n\n### PoC\n`https://github.com/spiceoverflow/av5-circular-symref` — open in a Codespace; clone writes the circular symrefs, then `git.log` on one never returns (the runner stops it after a 20s hang):\n\n```\n[AV-5] refs/remotes/origin/a contains: ref: refs/remotes/origin/b\n[AV-5] refs/remotes/origin/b contains: ref: refs/remotes/origin/a\n[run] *** DoS CONFIRMED: resolving a circular symref never terminates ***\n```\n\n### Impact\nA persistent denial of service via non-terminating symbolic-ref resolution (CWE-674 / CWE-835). After a single clone from a malicious (or MitM'd) server the circular refs are written to disk, so every later operation that resolves them (`log`, `status`, `checkout`, `branch`, …) hangs forever — the repository becomes effectively unusable for the application.\n\nImpacted: any application that clones from untrusted/compromised remotes with isomorphic-git.\n\n### Suggested fix\nAdd visited-set cycle detection (and/or a default maximum depth, as git does) in `GitRefManager.resolve()`; optionally validate server-supplied symref targets before persisting.","status":"published","published":"2026-11-09T19:58:32Z","modified":"2026-11-09T20:15:03.974348308Z","cvss":[{"version":"3.1","score":4.3,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:L","level":"medium"}],"cwes":["CWE-674","CWE-835"],"updated_at":"2026-11-09T20:39:59.362871Z"}]}}
