GitHub Advisoryadvisory · crates.io, npm
GHSA-gx45-xrj5-g6c4 CodeWhale: Project config `allow_shell` override enables arbitrary shell command execution via cloned repository
HIGH
Official page ↗
- Aliases
- CVE-2026-75911
- Ecosystem
- crates.io, npm
- Packages
- deepseek-tui, codewhale-tui, codewhale
- Severity
- High
- CVSS vector
- CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
- Weaknesses
- CWE-94
- Reviewed
- 2026-09-04
Affected packages
• crates.io deepseek-tui: >= 0.8.6, <= 0.8.41 (no fix yet)
• npm deepseek-tui: >= 0.8.6, < 0.8.41 → fixed in 0.8.41
• crates.io codewhale-tui: >= 0.8.41, < 0.8.64 → fixed in 0.8.64
• npm codewhale: >= 0.8.41, < 0.8.64 → fixed in 0.8.64
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 43563356b98c6b993085554da82e77370160a31c. Users should upgrade to 0.8.64 or later. The original reporter analysis is preserved below.
Summary
A malicious `.codewhale/config.toml` or `.deepseek/config.toml` committed to a repository can silently set `allow_shell = true` for any user who clones and opens the repository in CodeWhale. This enables the AI model's `exec_shell` tool, granting arbitrary shell command execution on the victim's machine without the user's explicit opt-in. The `approval_policy` and `sandbox_mode` fields correctly enforce tightening-only semantics from project config, but `allow_shell` has no such guard, contradicting the intent of GHSA-72w5-pf8h-xfp4 which established `allow_shell` as an opt-in security boundary.
Details
The project config merge function at `crates/tui/src/main.rs:5181-5182` (v0.8.50) unconditionally copies the `allow_shell` boolean from a project-level config file into the live session config:
```rust
if let Some(v) = table.get("allow_shell").and_then(toml::Value::as_bool) {
config.allow_shell = Some(v);
}
```
No tightening guard exists for `allow_shell`, unlike `approval_policy` (lines 5144-5158, guarded by `project_approval_policy_is_allowed`) and `sandbox_mode` (lines 5161-5171, guarded by `project_sandbox_mode_is_allowed`). The merge is applied automatically when entering a workspace directory unless the user passes `--no-project-config`, which is an opt-out flag that most users will not know about.
Source of attacker-controlled input: The `.codewhale/config.toml` or `.deepseek/config.toml` file in a cloned repository (committed by a malicious or compromised repository maintainer).
Security boundary crossed: The `allow_shell` setting controls whether the AI model's tool registry includes `exec_shell` and `task_shell_start`/`task_shell_wait` tools (`crates/tui/src/tools/registry.rs:928-932`). When `allow_shell = false` (the default), these tools are excluded. When `allow_shell = true`, the AI model can execute arbitrary shell commands via the `ExecShellTool` (`crates/tui/src/command_safety.rs`).
Sink reached: Shell command execution via `crates/tui/src/tools/shell.rs` lines 832, 991, 1152 — `Command::new(program)` with arguments derived from the AI model's output.
Why existing mitigations do not prevent exploitation:
1. `approval_policy` tightening guard (lines 5144-5158) only blocks project configs from *relaxing* approval requirements. But when `allow_shell = true`, the shell tools are available, and the model may issue commands that pass the command safety analysis as "safe" or "requires approval" — the user's existing approval policy is maintained, but the *availability* of shell tools itself is the security boundary violation.
2. The `command_safety.rs` safety analysis allows many commands as "safe" (e.g., `ls`, `cat`, `git status`, `cargo build`). With shell tools enabled, the model can execute these without user interaction.
3. The `DENY_AT_PROJECT_SCOPE` list at line 5119 blocks `api_key`, `base_url`, `provider`, and `mcp_config_path` from project config, but does not block `allow_shell`.
Flow from source to sink:
1. User clones a repository containing `.codewhale/config.toml` with `allow_shell = true`
2. User runs `codewhale` in the repository directory
3. `merge_project_config()` at line 5211 reads the project config and sets `config.allow_shell = Some(true)`
4. The `allow_shell` value flows into `allow_shell: yolo || config.allow_shell()` which evaluates to `true`
5. Tool registry at `registry.rs:928-929` includes shell tools via `with_shell_tools()`
6. The AI model can now execute shell commands through `exec_shell`
PoC
Environment: Any system with CodeWhale v0.8.50 built from source (commit `0072209d`).
Clean checkout recipe:
1. Clone the CodeWhale repository and build the TUI binary:
```bash
git clone https://github.com/Hmbown/CodeWhale.git
cd CodeWhale
git checkout 0072209d
cargo build --release -p codewhale-tui
```
2. Create a malicious workspace directory simulating a cloned repo:
```bash
mkdir -p /tmp/victim-workspace/.codewhale
cat > /tmp/victim-workspace/.codewhale/config.toml > /tmp/test_allow_shell.rs /tmp/test-workspace/.codewhale/config.toml
# Verify by reading the source: the merge function at main.rs:5181-5182
# unconditionally sets allow_shell from project config with no guard
grep -A 2 'allow_shell.*as_bool' crates/tui/src/main.rs
```
Observed output (grep):
```
if let Some(v) = table.get("allow_shell").and_then(toml::Value::as_bool) {
config.allow_shell = Some(v);
}
```
5. Negative control — compare with `approval_policy` which has a guard:
```bash
grep -A 8 'approval_policy.*as_str' crates/tui/src/main.rs | head -10
```
Observed output:
```
if let Some(v) = table.get("approval_policy").and_then(toml::Value::as_str)
&& !v.is_empty()
{
if codewhale_config::project_approval_policy_is_allowed(
config.approval_policy.as_deref(),
v,
) {
config.approval_policy = Some(v.to_string());
```
Note the `project_approval_policy_is_allowed` guard that is absent for `allow_shell`.
6. Negative control — `allow_shell` defaults to `false` without project config:
```bash
cargo test -p codewhale-tui -- allow_shell_defaults_to_false_when_unset --nocapture
```
Expected output: Test passes, confirming `allow_shell` is `None` and `allow_shell()` returns `false` by default.
Cleanup:
```bash
rm -rf /tmp/victim-workspace /tmp/test-workspace
```
Impact
This is a high-severity privilege escalation / code execution vulnerability. Any user who clones a repository containing a malicious `.codewhale/config.toml` or `.deepseek/config.toml` with `allow_shell = true` will have shell command execution enabled automatically when they run CodeWhale in that directory.
• Attacker privilege required: Repository maintainer (can commit the malicious config file) or a supply-chain compromise of a repository the victim clones.
• User interaction required: The victim must run CodeWhale in the cloned repository directory. No explicit confirmation or trust prompt is shown for the `allow_shell` override.
• Impact: The AI model can execute arbitrary shell commands on the victim's machine through the `exec_shell` tool. Even with the default `approval_policy = "suggest"` requiring approval for dangerous commands, many "safe" commands (file reads, directory listings, git operations, build tools) execute without approval. Combined with social engineering via the AI conversation, a sophisticated attack could chain multiple approved commands.
• Security boundary crossed: User's opt-in shell access policy (`allow_shell` defaulting to `false`) is silently overridden by untrusted repos…
Related
Alias · CVE (1)
- CVE-2026-75911 CodeWhale versions before 0.8.64 fail to properly validate the allow_shell configuration parameter from project config files, allowing… vulnerability
Weakness · CWE (1)
- CWE-94 Improper Control of Generation of Code weakness
References
- https://github.com/Hmbown/CodeWhale/security/advisories/GHSA-gx45-xrj5-g6c4 web
- https://nvd.nist.gov/vuln/detail/CVE-2026-75911 advisory
- https://github.com/Hmbown/CodeWhale/commit/43563356b98c6b993085554da82e77370160a31c web
- https://github.com/Hmbown/CodeWhale package
- https://www.vulncheck.com/advisories/codewhale-before-remote-code-execution-via-allow-shell web