The Code Comment Named the Gap, and the Gap Shipped — CVE-2026-102437 Turns a Git Diff Into Agent RCE
There is a particular kind of vulnerability that is worse than an oversight, because nobody overlooked anything. CVE-2026-102437, disclosed by GitLab's Threat Research Group on 29 September 2026, is one: the vulnerable code hardens its git invocations against exactly this attack class, closes four separate execution primitives on every call, and carries a comment naming the fifth one it had not closed. That fifth primitive is the bug.
The product is DeepSeek-Reasonix (Reasonix Studio), a desktop git client built for AI-assisted development, maintained by esengine. Its internal/gitcmd package wraps every git call with -c core.fsmonitor=false, -c maintenance.auto=false, and adds --no-ext-diff --no-textconv to diffs. Four sinks, deliberately shut. What it never touches is filter.<driver>.clean.
Why a deny-list could not close it
The other four primitives are fixed configuration keys. You can name them and override them. A filter driver is not: .gitattributes assigns a driver to a file per path, under a name the repository author invents, and .git/config defines what that named driver runs. There is no fixed key to override, because the key is filter.<whatever-the-attacker-called-it>.clean. That is precisely why the existing hardening pattern — enumerate the dangerous keys, neutralise each one — could not reach it.
The trigger is ordinary use. GitLab's write-up traces the chain through desktop/workspace_changes.go, which issues a fully hardened command for a changed file. Git still invokes the clean filter to build the comparison blob the diff needs, and that step none of those flags touch. GitLab reports that replaying the hardened command ran the payload twice — diff builds a clean-filtered blob for each side of the comparison, so the filter fires once per side. Notably, git status does not trigger it: status only checks which files changed and never builds the blob, which isolates the bug to diff rendering and matches the actual code path.
So the victim action is: open a project folder, look at a file's diff. That is the default UI feature the product exists to provide.
The delivery problem, and the agentic shortcut around it
The attack needs two files, and they do not travel equally. The .gitattributes entry assigning the filter driver is tracked content and survives a normal clone. The .git/config defining that driver's command does not — which is why GitLab notes that repositories hosted on GitLab are not affected by this vulnerability, since cloning over HTTPS or SSH does not transfer local configuration files. Delivery therefore requires an archive or tarball, a synced or shared folder, a CI cache, or a devcontainer image built with COPY . ..
That constraint sounds like it caps the blast radius, and for a human developer it largely does. For agentic tooling it mostly evaporates. GitLab makes the point directly: a rogue, compromised, or prompt-injected coding agent already running on the developer's machine has the developer's own filesystem access, and can write the poisoned .git/config straight into a repository that was cloned entirely normally. No archive, no synced folder, no CI cache needed. The agent supplies the half of the exploit that the clone refuses to carry.
This is the structural reason the bug class matters more now than when plain git clients first carried advisories for it. Coding agents run git against whatever directory a developer opens, and they inherit .git/config and .gitattributes from whoever wrote the repository — not from the developer who opened it. The files sit next to the code and look like they belong to the tool. They belong to the repository author.
Severity, versions, and a disagreement worth noting
The two records do not agree on how bad this is. The vendor advisory, GHSA-grg2-7gc6-36m6, rates it critical and assigns CWE-78 (OS command injection), with no CVSS vector attached. The NVD record for CVE-2026-102437, sourced from cve@gitlab.com, scores it CVSS 7.8 HIGH with vector AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H — local attack vector, user interaction required. Both are defensible readings of the same facts; the gap between them is the delivery constraint above, and a defender weighing it should price in the agent-writes-the-config path that collapses that constraint.
Affected and fixed versions are unambiguous: npm package reasonix < 1.39.3, fixed in 1.39.3; Reasonix Studio, confirmed at main-branch commit ea28602 and tagged pre-release studio-v2.9.0, fixed in 2.21.0. The disclosure timeline runs: advisory opened with esengine 27 August 2026, maintainer acceptance via a temporary private fork 29 September, fix shipped and advisory published 30 September (GitLab's post records the GHSA publication on the 30th; the GitHub advisory metadata shows 29 September), CVE assigned 30 September.
It is not one bug, it is the batch
CVE-2026-102437 arrived with four sibling advisories against the same project, all published 29 September 2026, and together they describe a product whose trust boundary ran in the wrong place throughout:
- GHSA-wqg8-98mr-4jcj (critical) — repository-supplied project-level MCP plugin configuration auto-started without trust confirmation. The repository author controls
commandandargs; the stdio MCP transport executes them. Fixed in reasonix 1.39.3. - GHSA-4p5q-jhpc-rf9q (high, CVSS 8.6) — a workspace's
reasonix.tomland.reasonix/settings.jsonwere merged over the user's own configuration as trusted input, able to relax the bash sandbox, its write and read roots, network access, permission mode and approval mode. Fixed in reasonix 1.39.5 and Studio 2.22.0, where workspace files may now only narrow the user's settings and declared programs require explicit per-folder approval viareasonix trust. - GHSA-83jp-h8cg-2gcr (high, CVSS 8.6, CWE-807) —
reasonix serveran an unauthenticated HTTP control plane on127.0.0.1:8787guarded only by a Host check and a content-type check. Because the sandbox defaults tonetwork = true, the sandboxed agent could read a pending approval ID fromGET /pending-promptsand resolve it viaPOST /approve— answering its own human-reserved write-access prompt and escaping the write boundary. The advisory names this as the same class as CVE-2026-82533 in DeepSeek Harness. Fixed in 1.39.3 / Studio 2.21.0. - GHSA-8789-pp7w-w83p (high) — startup RCE in the Reasonix CLI via
core.fsmonitor: the very primitivegitcmdneutralises in Studio, left live in the CLI.
That last pairing is the batch in miniature. One component closed core.fsmonitor and missed filter.clean; another left core.fsmonitor open entirely. Each surface was hardened against whatever incident last touched it.
The pattern GitLab says is still under embargo
GitLab states it found the same trust failure earlier this year in Serena, a different AI coding tool, which ran attacker code from a project's own .serena/project.yml when a developer opened the repository — different file, identical mistake. It further says the same pattern is present in several other widely used agent tools currently under coordinated disclosure, with details to follow as fixes ship. Treat CVE-2026-102437 as the first published case of a wave, not an isolated defect.
It also fits a line this site has been tracking all year: untrusted workspace state reaching an agent's execution path, from Kiro's repeat workspace-config write to the sandbox escapes catalogued across Cursor, Codex, Gemini and Antigravity. The repository is an input. Most tooling still treats it as configuration.
What to do
- Update Reasonix now, and note the two fix levels. Studio 2.21.0 / npm 1.39.3 close the filter.clean RCE, the MCP auto-start and the serve-API self-approval. The workspace-configuration trust fix landed later — 1.39.5 / Studio 2.22.0. Patching only to 1.39.3 leaves the config-widening issue open.
- On older versions, do not diff a repository you did not clone yourself. That is GitLab's own interim guidance, and it is precise: the clone path is what strips the attacker's
.git/config. - If you build anything that shells out to git, override every relevant key on every call. GitLab's list:
core.fsmonitor,core.pager,core.editor,core.hooksPath,diff.external,core.sshCommand, andfilter.<driver>.clean/smudgefor every driver name found across.gitattributes,.git/info/attributes, and global or system files. One flag does not cover another —--no-ext-diffaddressesdiff.externaland does nothing forcore.sshCommand. - Better: stop invoking the filter machinery at all. For byte-level content, read blobs with
git cat-fileorgit showand diff in-process. A sink you never call cannot be poisoned, and that is the only mitigation here that does not require maintaining a deny-list against an attacker-named key. - Assume the poisoned config can arrive after the clone. Another agent, extension, or process running with the developer's permissions can write it into an already-clean repository. Threat models that gate only on repository provenance miss this entirely.
- Ask vendors the right question. Not "how do you handle untrusted remotes" but "how do you neutralise repository-local configuration on every git invocation, and which keys does that cover." A tool that shells out to git on a developer's machine runs with that developer's full access.
Our verification was documentary and primary-source-led. We read GitLab's Threat Research Group write-up in full for the call chain, the workspace_changes.go invocation, the double-execution behaviour, the git-status contrast, the delivery vectors, the Serena precedent and the disclosure timeline. We then independently pulled all five DeepSeek-Reasonix advisories from the esengine repository via the GitHub Security Advisories API to confirm severities, CVSS vectors, CWE assignments, affected and patched version ranges, and the sibling advisories' technical content — and retrieved the CVE-2026-102437 record from NVD, where we found and have reported the CVSS 7.8 HIGH score that differs from the vendor's critical rating. Release tags were confirmed against the repository's release list. We did not run Reasonix, build a poisoned repository, or send traffic to any third-party system.
Sources:
- GitLab Threat Research Group — "DeepSeek-Reasonix: How a poisoned config can hijack an AI coding agent" (call chain, double filter execution, git status contrast, delivery vectors, agent-writes-config path, Serena precedent, remediation key list, disclosure timeline, GitLab-hosted repos unaffected)
- GHSA-grg2-7gc6-36m6 — critical, CWE-78; reasonix < 1.39.3 / Studio commit ea28602 and studio-v2.9.0; fixed 1.39.3 / 2.21.0
- NVD — CVE-2026-102437 (published 29 September 2026; CVSS 3.1 7.8 HIGH, AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H; source cve@gitlab.com)
- GHSA-83jp-h8cg-2gcr — unauthenticated serve API self-approval sandbox escape (CVSS 8.6, CWE-807; cites CVE-2026-82533 as the same class)
- GHSA-4p5q-jhpc-rf9q — workspace configuration could widen sandbox, permission and approval settings (CVSS 8.6; fixed 1.39.5 / Studio 2.22.0)
- GHSA-wqg8-98mr-4jcj — repository-supplied project-level MCP plugin config auto-started without trust confirmation (critical; fixed 1.39.3)
- GHSA-8789-pp7w-w83p — startup RCE in Reasonix CLI via core.fsmonitor (high)