Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
🦀
🦀 crates.io📦 npm
Not in CISA KEV
CRITICAL severity

GHSA-7j5w-7r7x-9v27 — deepseek-tui

CRITICALFix: Hmbown/CodeWhale@9a34b50

GHSA-7j5w-7r7x-9v27 is a critical-severity (CVSS 9.3) CWE-73 vulnerability in deepseek-tui. A fix is available for deepseek-tui — see the affected versions and patch details below.

CodeWhale: Argument Injection in `git_show` Tool Allows Arbitrary File Write Without Approval

Also known asCVE-2026-75913
Published
Sep 4, 2026
Updated
Sep 4, 2026
Affected
4 pkgs
Patched
3 / 4
Exploits
None indexed
Exploitation data as of Sep 23, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

Exploitation Status

Proof-of-concept exploit code exists

  • CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.
  • A successful exploit gives an attacker total control of the affected component, not partial access.

Exploitation and automatability from CISA’s SSVC triage for GHSA-7j5w-7r7x-9v27.

EPSS Exploitation Probability

via FIRST.org ↗
0.3%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs26th percentile — riskier than 26% of all scored CVEsHighest risk

EPSS (Exploit Prediction Scoring System) is a daily probability model maintained by FIRST.org. It estimates the likelihood a CVE will be exploited in production environments within the next 30 days, derived from real-world threat intelligence signals.

How urgent is this, really

GHSA-7j5w-7r7x-9v27 plotted by exploitation likelihood (EPSS) against impact (CVSS). The shaded corner — EPSS 50%+ and CVSS 7.0+ — is where this CVE doesn't sit, though severity or exploitability alone can still warrant action.

Where this sits among everything scored

Of 378,567 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Real counts from FIRST.org, not a sample — log-scaled since the landscape is heavily right-skewed.

Real-World Exposure

4 pkgs affected

How broadly this vulnerability is actually deployed: weekly install volume shows current usage, a proxy for how much of the ecosystem is exposed.

deepseek-tuicrates.io
476downloads / week

Description

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_show Tool Allows Arbitrary File Write Without Approval

Overview

The git_show tool in DeepSeek-TUI executes git show with the model-supplied rev parameter passed unvalidated into the argv. git show honours the --output=<path> option, so a rev value beginning with --output= is interpreted as a flag rather than a revision. The tool is registered with ApprovalRequirement::Auto and declares ToolCapability::ReadOnly, so the write happens without a user prompt and contradicts the capability the catalog advertises to the model and the user.

This is the same vulnerability class as GHSA-72w5-pf8h-xfp4 (CVE-2026-45374): an auto-approved tool produces an effect outside the boundary the user consented to.

Impact

A malicious repository combined with prompt injection, the threat model already documented in CVE-2026-45311 (auto-loaded AGENTS.md is treated as instructions by the model) yields an unprompted arbitrary file write at the privilege of the user running DeepSeek-TUI.

Useful targets reachable as the invoking user:

  • ~/.ssh/authorized_keys
  • ~/.bashrc, ~/.zshrc, ~/.profile
  • ~/.gitconfig (chainable into RCE via core.editor)
  • ~/.config/**, ~/.aws/credentials, project source files

The written content is the git show rendering of HEAD commit hash, author/date header, indented commit message, and (when patch=true) diff hunks. The commit subject, body, author identity, and diff text are entirely attacker-controlled because the attacker owns the repository HEAD. The leading commit <hash> line prevents clean overwrite of formats that reject unknown tokens, but is silently ignorable in files parsed as comments-or-text (crontab, dotfiles consumed by tolerant readers) and is irrelevant for the destructive/DoS sub-case (clobbering ~/.ssh/authorized_keys locks the user out; clobbering a project file corrupts source).

Technical Details

Root Cause

crates/tui/src/tools/git_history.rs:

// L196-198
fn approval_requirement(&self) -> ApprovalRequirement {
    ApprovalRequirement::Auto
}

// L204-228 (excerpt)
async fn execute(&self, input: Value, context: &ToolContext) -> Result<ToolResult, ToolError> {
    let rev = required_str(&input, "rev")?;
    ...
    let mut args = vec![
        "show".to_string(),
        "--no-color".to_string(),
        "--no-ext-diff".to_string(),
    ];
    if patch { args.push(format!("--unified={unified}")); }
    else     { args.push("--no-patch".to_string()); }
    if stat  { args.push("--stat".to_string()); }
    args.push(rev.to_string());        // unvalidated, no `--end-of-options` sentinel
    ...
}

The JSON schema for rev is {"type": "string"} (L161-164) with no pattern, no enum, and no length cap. required_str performs no semantic validation. The argv has no --end-of-options separator between the trailing options and rev, so git's option parser keeps consuming flags from rev.

The same pattern in git_blame (L322-388) is tracked in a separate advisory.

Why --output Works

git show shares its option parser with git log / git diff, which expose --output=<file>. The implementation opens the path with O_WRONLY | O_CREAT | O_TRUNC and writes the formatted output there. No permission check beyond the filesystem's own running as the user is sufficient to clobber anything the user owns.

Proof of Concept

The vulnerable argv assembled by the tool when invoked with {"rev": "--output=/home/victim/.bashrc"} is equivalent to:

git show --no-color --no-ext-diff --no-patch --stat --output=/home/victim/.bashrc

Reproduced against system git as a non-root user:

$ id
uid=1001(lowtest) gid=1001(lowtest) groups=1001(lowtest)

$ cd /tmp/lp && git init -q
$ echo a > a.txt && git add a.txt
$ git -c user.email=a@b -c user.name=a commit -q -m "lol"

$ git show --no-color --no-patch "--output=/home/lowtest/.bashrc_clobbered" HEAD
$ ls -la /home/lowtest/.bashrc_clobbered
-rw-rw-r-- 1 lowtest lowtest 128 May 19 07:05 /home/lowtest/.bashrc_clobbered

End-to-end exploitation path:

  • Attacker publishes a repository whose AGENTS.md instructs the model to call git_show with rev set to a crafted --output= string targeting a file in the victim's home directory. The same auto-load pathway documented in CVE-2026-45311 applies.
  • Victim opens the repository in DeepSeek-TUI and issues any prompt that exercises the agent loop.
  • The model issues the tool call. Because approval_requirement() returns Auto, no approval UI is shown.
  • git show --output=<path> overwrites the target file with attacker-controlled commit metadata and diff text.

Remediation

Two changes in crates/tui/src/tools/git_history.rs:

Insert an end-of-options sentinel before rev so git stops parsing flags:

args.push("--end-of-options".to_string());
args.push(rev.to_string());

Reject rev values that begin with - (or restrict to a revision-shape regex ^[A-Za-z0-9._/^~@:{}-]+$ after the leading character check):

if rev.starts_with('-') {
    return Err(ToolError::invalid_input("rev must not start with '-'"));
}

A regression test mirroring run_tests_requires_user_approval (test_runner.rs:197) should assert that rev = "--output=/tmp/x" is rejected.

Affected Packages

4 total 3 fixed
EcosystemPackageVulnerable rangeFix
🦀crates.iodeepseek-tui≥ 0.3.27No fix
🦀crates.iocodewhale-tui≥ 0.8.41&&< 0.8.640.8.64cargo update -p codewhale-tui --precise 0.8.64
📦npmdeepseek-tui≥ 0.3.27&&< 0.8.410.8.41npm install deepseek-tui@0.8.41
📦npmcodewhale≥ 0.8.41&&< 0.8.640.8.64npm install codewhale@0.8.64

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for deepseek-tui, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.

  2. Fix

    No patched version of deepseek-tui has shipped for GHSA-7j5w-7r7x-9v27 yet. Where your build allows, override or pin the dependency away from the vulnerable range, and apply any maintainer-recommended mitigation.

  3. Workarounds

    If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.

  4. How O3 protects you

    O3 Security's impact-aware SCA analyses which vulnerable code paths your application actually calls, so a match like GHSA-7j5w-7r7x-9v27 can be triaged on real exposure rather than presence alone.

Tailored to GHSA-7j5w-7r7x-9v27. Runtime protection reduces exposure until a permanent patch is applied and verified — it complements patching, it doesn't replace it.

Frequently Asked Questions

### 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_show` Tool Allows Arbitrary File Write Without Approval ## Overview The `git_show` tool in DeepSeek-TUI executes `git show` with the model-supplied `rev` parameter passed unvalidated into the argv. `git show` honours the `--output=<path>` option, so
O3 Security · Impact-Aware SCA

Is GHSA-7j5w-7r7x-9v27 in your dependencies?

O3 Security finds GHSA-7j5w-7r7x-9v27 across crates.io, npm dependencies, including transitive ones, and its impact-aware SCA ranks findings by whether your code actually calls the vulnerable path.

GHSA-7j5w-7r7x-9v27: RCE (Critical 9.3) | O3 Security