OFFLINE
Awaiting data
Security intelligence
MajorCritical vulnerability

CVE-2026-63395: isomorphic-git: Arbitrary file write outside of working tree via directory symlink during checkout (potential RCE)

GitHub Advisories · officialPublished Nov 9, 2026Risk 37/100

### Summary `git.checkout` writes working-tree files through a directory **symlink** without checking the leading path, so a malicious repository can write **outside the intended working directory**. The defect is in isomorphic-git's checkout logic itself and is therefore **independent of the `fs` provider**. The *impact* depends on the configured filesystem; worst case is arbitrary file write on the host, e.g. injecting an attacker key into `~/.ssh/authorized_keys` → remote login / code execution. ### Details A single git tree can't hold a name as both a symlink and a directory, so the attack uses two states: ``` Commit N: config (mode 120000, symlink → ../.ssh) Commit N+1: config/ (mode 040000, tree) authorized_keys (mode 100644, attacker public key) ``` Checking out commit N writes `config` as a directory symlink. Checking out commit N+1 sees `config/authorized_keys` as a new path: isomorphic-git `mkdir`s the parent (`config`, already a symlink → `EEXIST`, ignored) then `writeFile`s the file, which the OS resolves through the symlink to outside the working directory. A *file*-level symlink swap is caught (the `120000`→`100644` mode change triggers an `rm`), but the **directory**-level variant is not — the payload is always a new child path, a plain `create`, so the parent symlink is never removed. The symlink target is attacker-chosen. Besides `~/.ssh`, pointing it at the repo's own control directory — `hooks → .git/hooks` then `hooks/pre-commit`, or `x → .git` then overwriting `.git/config` (`core.hooksPath` / alias / `core.fsmonitor`) — yields RCE on the next native `git` command **without** depending on `~/.ssh` existing, since `.git/` is always present in a fresh clone. #### Canonical git behavior (divergence) git refuses to do this: `has_symlink_leading_path()` (symlinks.c) checks each leading path component during checkout and will not follow a symlink — the hardening behind CVE-2021-21300 and CVE-2024-32002. isomorphic-git has no equivalent check. ### PoC `https://github.com/spiceoverflow/av1-symlink-hook-rce` — open in a Codespace; it builds the malicious repo, serves it locally, and runs a victim. Output on Linux: ``` [AV-1] Directory symlink on disk: …/config → ../.ssh (→ /home/node/.ssh) [AV-1] *** SSH KEY INJECTION CONFIRMED *** ``` **Trigger:** minimal realistic path is `clone` (commit N) + a later `pull` (commit N+1) — ordinary sync of an already-trusted repo. It also collapses to a single `clone` when the consuming app reads or writes into the cloned tree, or when a symlink already exists on disk. ### Impact isomorphic-git is filesystem-agnostic, so exploitability and blast radius depend on the active `fs` provider — specifically whether it creates a symlink and follows it on a later write: - **Node `fs` on Linux/macOS** (servers, CI, CLIs, Electron/desktop tooling — the common server-side use): real OS symlinks → the write lands anywhere the process can reach → **arbitrary file write on the host → RCE** (the PoC above). Highest impact. - **Node `fs` on Windows:** `fs.symlink` typically requires privilege and throws `EPERM`, so the symlink-plant step usually fails — not exploitable by default. (A property of the OS/provider, not of isomorphic-git.) - **In-memory / browser providers** (memfs, ZenFS, lightning-fs, custom `fs`): there is no host filesystem to escape to, so the worst case is writing **outside the intended clone directory but within that virtual filesystem** — i.e. corrupting other repos/app data the same provider holds. Bounded by the sandbox, and only if the provider implements symlink creation + following. The CVSS above reflects the worst-case (Node `fs` on a POSIX host). Browser/in-memory-only deployments are lower severity (sandboxed integrity impact). ### Suggested fix Before each working-tree write, `lstat` every leading path component and refuse to traverse a symlink (mirrors git's `has_symlink_leading_path()`); optionally honor `core.symlinks=false`.

Upgrade affected packages to a patched version: isomorphic-git 1.38.6.

Vendor
Not specified
Product
isomorphic-git
Exploitation
none known
Evidence
official
CVSS
8.8

This record is attributed to GitHub Advisories. Exploitation status and remediation guidance are kept separate from the vulnerability's technical severity.

Open primary source