CodeWhale before 0.8.64 Argument Injection via git_blame
Collected exploitation and prediction evidence
Risk source coverageCISA KEV is observed exploitation evidence. FIRST EPSS is a dated prediction of exploitation in the next 30 days. Missing scores are unknown. This collector requests predictions only for explicit CVE aliases in the public NuGet archive; Microsoft release views retain their existing prediction scope.
No collected risk observation for these identifiers. This does not establish absence of exploitation or a zero probability.
cve-program · CVE-2026-75912
PublishedCodeWhale versions before 0.8.64 contain an argument injection vulnerability in the git_blame tool that allows attackers to read arbitrary files by injecting git options into the unvalidated rev parameter. Attackers can supply rev values like --contents=/path/to/file to exfiltrate sensitive files such as SSH keys and credentials through the tool output returned to the model.
- Source published
- 18 Aug 2026 15:22:00 UTC
- Source modified
- 19 Aug 2026 14:38:38 UTC
- Observed here
- 23 Oct 2026 15:48:27 UTC
- Source terms
- CVE Program Terms of Use
Original source record · Cite this exact observation · Complete original publisher JSON
This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: cve-program · CVE Program Terms of Use. Source text is retained; field grouping and change labels are provided by ChangeIntel.
CVSS 4.0 · 8.3 CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:H/VI:N/VA:N/SC:H/SI:N/SA:N
CVSS 3.1 · 7.4 CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:N/A:N
euvd · EUVD-2026-60970
PublishedCodeWhale versions before 0.8.64 contain an argument injection vulnerability in the git_blame tool that allows attackers to read arbitrary files by injecting git options into the unvalidated rev parameter. Attackers can supply rev values like --contents=/path/to/file to exfiltrate sensitive files such as SSH keys and credentials through the tool output returned to the model.
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.
Original publisher date fields
datePublished: Aug 18, 2026, 3:22:00 PM
dateUpdated: Aug 19, 2026, 2:38:38 PM
- Source published
- Aug 18, 2026, 3:22:00 PM (timezone not stated)
- Source modified
- Aug 19, 2026, 2:38:38 PM (timezone not stated)
- Observed here
- 7 Nov 2026 14:28:14 UTC
- Source terms
- ENISA EUVD · source terms and attribution apply
Original source record · Cite this exact observation · Complete original publisher JSON
This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: euvd · ENISA EUVD · source terms and attribution apply. Source text is retained; field grouping and change labels are provided by ChangeIntel.
EUVD CVSS 4.0 · 8.3 CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:H/VI:N/VA:N/SC:H/SI:N/SA:N
nvd · CVE-2026-75912
PublishedCodeWhale versions before 0.8.64 contain an argument injection vulnerability in the git_blame tool that allows attackers to read arbitrary files by injecting git options into the unvalidated rev parameter. Attackers can supply rev values like --contents=/path/to/file to exfiltrate sensitive files such as SSH keys and credentials through the tool output returned to the model.
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.
Source analysis status: Deferred
Weakness classifications: CWE-88
Original publisher date fields
published: 2026-08-18T16:18:23.220
lastModified: 2026-10-22T22:10:00.250
- Source published
- 18 Aug 2026 16:18:23 UTC
- Source modified
- 22 Oct 2026 22:10:00 UTC
- Observed here
- 25 Oct 2026 15:19:09 UTC
- Source terms
- NIST NVD usage terms; underlying source attribution retained
Original source record · Cite this exact observation · Complete original publisher JSON
This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: nvd · NIST NVD usage terms; underlying source attribution retained. Source text is retained; field grouping and change labels are provided by ChangeIntel.
CVSS 4.0 · [email protected] · Secondary · 8.3 CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:H/VI:N/VA:N/SC:H/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
CVSS 3.1 · [email protected] · Secondary · 7.4 CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:N/A:N
osv · GHSA-c6mw-8xh8-gpq6
Published### Maintainer resolution The CodeWhale maintainers validated this report. The affected package ranges are recorded in the advisory metadata. Version 0.8.64 contains the fix in commit 9a34b5034d29f05d1f28fa61b04719ca6a741020. Users should upgrade to 0.8.64 or later. The original reporter analysis is preserved below. # Argument Injection in `git_blame` Tool Allows Arbitrary File Read Without Approval ## Overview The `git_blame` tool in DeepSeek-TUI passes the model-supplied `rev` parameter unvalidated into the argv of `git blame`. `git blame` accepts `--contents=<file>`, which causes it to use the file's contents in place of the working tree and echo each line verbatim in the blame output. A `rev` value of `--contents=/path/to/secret` therefore exfiltrates the targeted file's contents into the tool result, which is returned to the model and displayed in the chat transcript. The tool is registered with `ApprovalRequirement::Auto` and declares `ToolCapability::ReadOnly`. The read is in-scope for the capability label, but the *target* of the read is not the user expects `git_blame` to read files inside the workspace, not arbitrary paths on the host. This is a sibling of the `git_show` argument-injection vulnerability filed separately, sharing the same root cause (missing `--end-of-options` sentinel and unvalidated `rev`). ## Impact Arbitrary file read at the privilege of the user running DeepSeek-TUI, via malicious repository content combined with prompt injection (the threat model already documented in CVE-2026-45311). Reachable as the invoking user: - `~/.ssh/id_rsa`, `~/.ssh/id_ed25519`, and other private keys - `~/.aws/credentials`, `~/.config/gh/hosts.yml`, `~/.netrc` - `.env` files anywhere in the filesystem - Any project file outside the workspace the tool would normally restrict to The leaked contents land in the model's context. The same model that obeyed the prompt-injection in step one can be instructed to forward the leak via `fetch_url` (network-policy permitting), summarize it in chat, or write it into a tool output the attacker can later retrieve. ## Technical Details ### Root Cause `crates/tui/src/tools/git_history.rs`: ```rust // L314-316 fn approval_requirement(&self) -> ApprovalRequirement { ApprovalRequirement::Auto } // L322-358 (excerpt) async fn execute(&self, input: Value, context: &ToolContext) -> Result<ToolResult, ToolError> { let path_str = required_str(&input, "path")?; let resolved_path = context.resolve_path(path_str)?; // path is bounded to workspace ... let rev = optional_str(&input, "rev").unwrap_or("HEAD"); // rev is NOT bounded ... let mut args = vec![ "blame".to_string(), "--date=iso".to_string(), format!("-L{start_line},{end_line}"), ]; if porcelain { args.push("--line-porcelain".to_string()); } args.push(rev.to_string()); // unvalidated, no sentinel args.push("--".to_string()); args.push(pathspec.display().to_string()); ... } ``` `path` correctly flows through `context.resolve_path`, which enforces workspace containment (`spec.rs:342`). `rev` does not and the `--` separator after `rev` only ends pathspec parsing, it does not stop option parsing of `rev` itself. The JSON schema for `rev` (L283-285) is `{"type": "string"}` with no constraints. ### Why `--contents` Works `git blame --contents=<file> -- <pathspec>` blames the working tree path *as if its contents were the supplied file*. Each line of the supplied file appears verbatim in the porcelain or human-readable output, prefixed with the attribution marker `00000000 (External file (--contents) <date> N)`. The full line content is preserved. Two secondary primitives in the same parser also leak data, with smaller yield: - `--ignore-revs-file=<file>` : surfaces parse errors that disclose partial content when the file is not a valid revs list. - `-S <file>`, `--reverse <rev1>..<rev2>` : not directly exploitable for read but expand the option surface that argv injection can reach. ## Proof of Concept Argv assembled by the tool with input `{"path": "a.txt", "rev": "--contents=/home/a/.ssh/id_rsa"}`: ``` git blame --date=iso -L1,200 --contents=/home/a/.ssh/id_rsa -- a.txt ``` Reproduced against system `git` as a non-root user: ``` $ id uid=1001(a) gid=1001(a) groups=1001(a) $ echo "PRIVATEKEYDATA" > /home/a/.ssh/id_rsa $ chmod 600 /home/a/.ssh/id_rsa $ git blame --date=iso -L1,5 "--contents=/home/a/.ssh/id_rsa" -- a.txt 00000000 (External file (--contents) 2026-05-19 07:05:51 -0400 1) PRIVATEKEYDATA ``` A non-readable target (`/etc/shadow`, owned by root with mode 0640) returns `Permission denied`, confirming the read is bounded by uid as expected; this is not a privilege boundary bypass, it is the desktop user's own filesystem view being exposed past the workspace boundary the tool's `path` argument otherwise enforces. End-to-end exploitation is identical to the `git_show` companion: malicious repo → `AGENTS.md` injection → model calls `git_blame` with the crafted `rev` → auto-approval → leaked content returned in tool output and consumed by the model. ## Remediation Same shape as the `git_show` fix: ```rust args.push("--end-of-options".to_string()); args.push(rev.to_string()); args.push("--".to_string()); args.push(pathspec.display().to_string()); ``` Plus a leading-hyphen rejection on `rev`. A regression test should pin both `rev = "--contents=/etc/passwd"` and `rev = "--ignore-revs-file=/etc/passwd"` as rejected inputs.
- Source published
- 4 Sep 2026 18:11:45 UTC
- Source modified
- 4 Sep 2026 19:00:05 UTC
- Observed here
- 24 Oct 2026 13:17:17 UTC
- Source terms
- GitHub Advisory Database · CC-BY-4.0
Original source record · Cite this exact observation · Complete original publisher JSON
This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: osv · GitHub Advisory Database · CC-BY-4.0. Source text is retained; field grouping and change labels are provided by ChangeIntel.
CVSS_V3 · CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:N/A:N
CVSS_V4 · CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:H/VI:N/VA:N/SC:H/SI:N/SA:N
Publisher rating · HIGH