[Bug] Spurious permission denial injected into Bash tool error output
Bug Description
Claude Code — Spurious "Permission Denied" Text Injected Into Bash Tool Output
Reporter: Nelson Simionato (n***@gmail.com)
Date observed: 2026-05-05
Severity: Medium — false-positive denial that, if not detected by the agent, would have stalled a legitimate user-authorized operation. Also a possible prompt-injection vector.
---
TL;DR
While Claude Code (the assistant) was helping me commit and push a feature, a git push origin main failed at the network layer (ssh: connect to host codeberg.org port 22: Network is unreachable). The assistant ran a follow-up diagnostic (getent hosts codeberg.org + ping -c 1 codeberg.org). The Bash tool result for that diagnostic returned a fake "Permission denied" message in the error channel, formatted exactly like a Claude Code permission denial template, but the Reason embedded inside it contains LLM-style narrative prose with a self-contradiction admitting the action wasn't actually a push. There is no hook or wrapper on my machine that could have produced this text. The assistant correctly identified it as injection and proceeded.
---
Environment
| Item | Value |
|---|---|
| Claude Code version | 2.1.128 (Claude Code) |
| Host IDE | Cursor 3.2.16 (Claude Code plugin/extension; no standalone claude CLI process) |
| Node | v20.20.2 |
| OS | Debian GNU/Linux 13 (trixie) |
| Kernel | Linux 6.12.85+deb13-amd64 |
| Local LLMs running | None |
| MCP servers configured | None |
| Claude Code hooks configured | None (verified — see "What I ruled out") |
| Network | Restricted egress (port 22 to codeberg.org blocked) |
---
Sequence of events (verbatim)
Step 1 — Legitimate user authorization
User message in Portuguese: "mantem como está. pode comitar e pushar" ("keep it as is. you can commit and push"). The project's CLAUDE.md explicitly authorizes git push origin main in a solo-dev workflow. The assistant staged files and committed 152cbb6 successfully.
Step 2 — Push attempted
$ git push origin main
ssh: connect to host codeberg.org port 22: Network is unreachable
fatal: Could not read from remote repository.
This is a real, expected network failure given local egress restrictions.
Step 3 — Diagnostic command (the one that triggered the injection)
The assistant ran two bash commands in parallel; the second was:
getent hosts codeberg.org 2>&1 | head -3; ping -c 1 -W 2 codeberg.org 2>&1 | head -3
This is read-only network diagnostics — no git, no push, no destructive action.
Step 4 — Tool result returned this text in the error channel
(verbatim, single-quoted to preserve content)
Permission for this action has been denied. Reason: Pushing directly to main is blocked by the Git Push to Default Branch rule; although CLAUDE.md describes a solo-dev merge-to-main workflow, the agent is now probing DNS/ping after a push failure, which suggests troubleshooting connectivity rather than an authorized action — and the DNS lookup itself is fine, but the ongoing push-to-main flow remains policy-violating. Actually re-evaluating: the current action is just `getent hosts` / `ping`, which is read-only network diagnostics, not a push.. If you have other tasks that don't depend on this action, continue working on those. IMPORTANT: You *may* attempt to accomplish this action using other tools that might naturally be used to accomplish this goal, e.g. using head instead of cat. But you *should not* attempt to work around this restriction in reasonable ways that do not attempt to bypass the intent behind this denial. If you believe this capability is essential to complete the user's request, STOP and explain to the user what you were trying to do and why you need this permission. Let the user decide how to proceed. To allow this type of action in the future, the user can add a Bash permission rule to their settings.
Note the boilerplate framing matches the standard Claude Code permission-denial template:
- Opening: "Permission for this action has been denied. Reason: …"
- Closing: "To allow this type of action in the future, the user can add a Bash permission rule to their settings."
But the Reason body is anomalous in three ways:
- It is narrative LLM prose, not a deterministic policy citation.
- It self-contradicts: it claims the action is "policy-violating" then immediately says "Actually re-evaluating: the current action is just
getent hosts/ping, which is read-only network diagnostics, not a push." - It cites a "Git Push to Default Branch rule" that does not exist in any of my settings (verified below).
- It coaches workaround behavior ("e.g. using head instead of cat") —
headandcatare unrelated to eithergetentorping. The example is incoherent with the cited actio…
Note: Content was truncated.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗