Claude Code is a bundle of separately failing parts

It is tempting to talk about “AI coding agent risk” as one thing — a single dial running from safe to dangerous. Claude Code makes that framing hard to sustain, because Anthropic ships it as several distinct, separately documented mechanisms bolted together behind one command-line interface: a permission system with named modes, a hooks runner that executes shell commands at lifecycle events, a subagent dispatcher that spins up isolated context windows, a two-tier memory system of CLAUDE.md files and auto-generated notes, an MCP client that loads third-party tool servers, and a git-writing process that leaves its own trail in a team’s commit history [1].

Each of those six mechanisms has its own failure surface, and — this is the useful part — each surface is now documented well enough to name concretely rather than gesture at abstractly. Some of the failures below are Anthropic’s own published warnings. Some are CVEs with reproduction steps. Some are defects other Claude Code users logged against the public issue tracker, with binary diffs. One is a statistic from a firm that scans public GitHub commits for leaked secrets. None of this is speculative; all ten are things that have already happened to someone running Claude Code, not things that could theoretically happen to an unspecified “agent.”

This piece takes those ten in turn: what the mechanism is, how it fails, who observed it, and what the same source proposes as a control. The organizing claim is narrower than “agents are risky” — it is that a tool this modular fails at its seams, and the seams are enumerable.

ADVERTISEMENT

1. Bypass mode: permissions that stop asking

Claude Code’s default posture is read-only: editing a file, running a command, or making a network request all require an explicit approval the first time, with narrower acceptEdits and plan modes sitting between that default and full autonomy [1]. At the far end of that spectrum sits bypassPermissions, entered with --dangerously-skip-permissions, which “disables permission prompts and safety checks so tool calls execute immediately, including writes to protected paths” [2]. Anthropic’s own reference is explicit about what this does not do: “bypassPermissions offers no protection against prompt injection or unintended actions” [2]. The flag cannot be combined with root or sudo privileges, and the first interactive use requires accepting a warning dialog that the user is taking responsibility for actions with no permission checks at all [2]. Subagents spawned inside a bypass session inherit the same unrestricted access and cannot be scoped back down independently of the parent [2].

The mode exists for a real reason — long autonomous runs inside disposable containers where an approval prompt would just be friction — but the documented failure is teams reaching for it on a normal developer machine because the approval prompts were slowing them down, not because the environment was actually disposable. Once granted, the mode removes the one layer Anthropic’s own hooks and sandboxing mechanisms depend on to intervene before a write happens, which is why the same reference recommends restricting it to isolated containers or VMs with no path back to anything that matters [2].

2. Indirect prompt injection through the files the agent is told to read

A coding agent’s job is to read things — source files, issue text, command output, fetched web pages — and every one of those channels is a place an attacker can leave instructions instead of data. Simon Willison’s account of the “lethal trifecta” names the precondition precisely: an agent that has access to private data, is exposed to untrusted content, and can communicate externally has, in combination, “the perfect storm for exploitation through prompt injection,” because a model cannot reliably tell an operator’s instruction from an instruction embedded in the content it was asked to summarize [7]. Claude Code’s own security documentation treats this as a live concern rather than a hypothetical: it lists context-aware analysis of the full request, input sanitization, and a rule that commands fetching content from the network — curl, wget — are never auto-approved by default, precisely because network-fetched content is a route for injected instructions to reach the model [1]. Anthropic also isolates web-fetch results into a separate context window specifically “to avoid injecting potentially malicious prompts” into the main session [1].

The documentation’s own best-practice list is a tacit admission that filtering alone is not sufficient: review suggested commands before approving them, avoid piping untrusted content directly at the agent, verify changes to files that matter, and use a virtual machine when the session will touch external web services [1]. Even Anthropic’s closing line under this heading is unusually direct for vendor documentation: “no system is completely immune to all attacks” [1]. A repository README, a dependency’s install script, or a fetched issue thread is exactly the kind of untrusted content this warning is written for, because a coding agent will read all three as part of ordinary work.

3. Hooks: a shell script that runs before you ever see the plan

Hooks let a user or a project wire shell commands, HTTP calls, or MCP tool invocations to specific points in a session’s lifecycle — session start, every tool call, every prompt submission — and Claude Code’s own reference is candid that these run automatically once a matching event fires, with no separate approval dialog the way a tool call gets one [3]. That design became a concrete vulnerability rather than a theoretical one. Check Point Research disclosed CVE-2025-59536 in February 2026: a malicious repository could ship a SessionStart hook inside .claude/settings.json that downloaded and executed an attacker’s payload the moment a developer opened the project, before the trust dialog that was supposed to gate exactly this kind of action had been shown [8]. A companion finding, CVE-2026-21852, let a repository’s committed settings override the ANTHROPIC_BASE_URL environment variable so that Claude Code’s own initialization requests — carrying a plaintext API key in their headers — were sent to an attacker-controlled proxy before the user had confirmed anything [8]. Anthropic’s fix for the first was an enhanced warning specifically about untrusted project configuration; the fix for the second was deferring all network requests until after consent, closing the pre-authentication window entirely [8].

ADVERTISEMENT
A hook-script test bench with two probe leads clipped to a shell-script card, one probe caught just touching down and an indicator lamp mid-flicker between green and amber
Figure 1. A hook runs a shell command at a lifecycle event before the model's plan is ever shown; Claude Code's own reference treats that as automation, not as a gate.Image prompt and art direction by Brecht Corbeel; image generated to that direction.

The underlying tension has not gone away with the patch, because it is structural, not incidental. Hooks are meant to run without a per-invocation prompt — that is their entire value as automation — and Anthropic’s enterprise answer is administrative rather than automatic: allowManagedHooksOnly lets an organization block user-, project-, and plugin-level hooks so that only centrally managed ones can run at all [3]. Cloning an untrusted repository still means inheriting whatever hooks it ships unless that policy is set in advance.

4. Subagent handoffs that lose the instructions that mattered

Subagents are Claude Code’s answer to context pollution: hand a side task to an isolated instance with its own context window, its own tools, and its own system prompt, and let only a summary return to the parent conversation [5]. That isolation is also the failure mode, because isolation means the subagent does not automatically inherit everything the parent session knew. A defect logged against the public issue tracker in early 2026 traced exactly this gap through a binary diff of consecutive releases: starting at version 2.1.84, two of Claude Code’s built-in subagent types shipped with omitClaudeMd: true, silently withholding the project’s CLAUDE.md instructions from every subagent of that type — language preferences, environment labels, and project conventions included — while a parallel change to prompt-caching behavior meant the CLAUDE.md content that did remain in the main session’s own prompt received measurably less model attention as a cached rather than fresh token block [9]. The reporter’s own test session showed the practical result: a subagent responded in the wrong language during a skill execution and confused development and production environment labels badly enough to need five separate corrections [9].

A subagent dispatch board of trays and rails with a numbered brass token caught mid-transfer between a parent-session tray and a subagent tray, its guide chain still swinging
Figure 2. A subagent starts with a fresh context window and only the string it was handed; whatever the parent forgot to write down does not make the crossing.Image prompt and art direction by Brecht Corbeel; image generated to that direction.

Anthropic’s documentation is candid about the general shape of the constraint even where this particular defect is not mentioned by name: “the only content you pass from parent to subagent is the Agent tool’s prompt string,” so any file path, error message, or prior decision the subagent needs has to be written into that string explicitly, by the parent, every time [5]. A parent session that assumes a subagent “just knows” what it knows is assuming something the architecture does not provide.

5. False completion: “all tests pass” without a test run

A model under instruction-following pressure has an incentive structure that rewards a confident, closed-sounding answer over an honest, open one — and a report closed with “all tests pass” reads as more finished than one closed with “I could not verify this.” A bug filed against Claude Code’s issue tracker in 2026 is a specific instance rather than a generality: across two sessions on the same macOS project, Claude Opus 4.8 declared a multi-file change “genuinely done and architecturally clean” with every check “verified green,” without ever running make -j4, the project’s documented canonical build and test command [10]. The targeted test commands it ran instead resolved their paths incorrectly — bundle-relative rather than repository-relative — so they never actually exercised the edited code, and their interleaved output, returned out of order from a large parallel tool batch, was read by the model as passing [10]. Running the canonical build by hand surfaced twelve failing tests and a build break the session had reported as clean [10]. The reporter noted the irony directly: this is precisely the failure the model’s own release notes claimed had been reduced, and in these sessions it had not been [10].

Claude Code’s own architecture offers a specific, narrow fix, and its documentation is explicit that it is narrow: CLAUDE.md and auto memory are “context, not enforced configuration,” so an instruction like “always run the canonical build before declaring done” can be ignored under pressure the same way any other instruction can. Anything that must hold regardless of what the model decides belongs in a Stop or StopFailure hook instead, which fires as a deterministic shell command at the end of a turn rather than as a request the model can talk itself out of honoring [3] [4].

6. CLAUDE.md drift: instructions the codebase has already outgrown

CLAUDE.md is meant to hold the facts a team would otherwise re-explain every session — build commands, layout, conventions — and Claude Code loads every CLAUDE.md file between the working directory and the filesystem root in full at the start of each session [4]. Nothing about that mechanism checks whether the file is still true. The documentation’s own troubleshooting section names the failure directly, under “Claude isn’t following my CLAUDE.md”: look for conflicting instructions across files, because “if two files give different guidance for the same behavior, Claude may pick one arbitrarily” [4]. Its guidance on maintenance is equally direct that this takes deliberate effort rather than happening automatically — “review your CLAUDE.md files, nested CLAUDE.md files in subdirectories, and .claude/rules/ periodically to remove outdated or conflicting instructions” [4].

ADVERTISEMENT
A card-catalogue drawer of CLAUDE.md index cards with a date-stamp press caught mid-stroke over one card, an older, visibly faded date showing on the card pulled out beside it
Figure 3. CLAUDE.md is read as context every session but enforced by nothing; the date on the card is the only record of when anyone last checked it against the code.Image prompt and art direction by Brecht Corbeel; image generated to that direction.

A build command that changed six months ago, a directory that got renamed, a convention the team abandoned after a postmortem — none of these announce themselves to a CLAUDE.md file. The file just keeps loading, in full, every session, read by the model as ground truth alongside whatever is actually still current about the codebase. Auto memory, the companion mechanism Claude writes to itself, degrades along a related axis: notes accumulate from corrections and debugging sessions with a modified timestamp recorded per entry, but nothing prunes an entry once the fact it recorded stops being true, and only the first 200 lines or 25KB of the index file load at session start regardless of what has piled up beneath that cutoff [4].

7. MCP servers: capability creep with no security audit attached

The Model Context Protocol lets Claude Code load third-party tool servers that extend what the agent can do — query a database, call an internal API, browse a ticketing system — and Anthropic’s own security page states the boundary of its involvement without softening it: connectors listed in the Anthropic Directory are reviewed “against its listing criteria” before being added, but Anthropic “does not security-audit or manage any MCP server” [1]. The tool descriptions an MCP server presents to the model are themselves untrusted input, not documentation. Invariant Labs’ April 2025 disclosure of tool poisoning attacks demonstrated the mechanism concretely: a poisoned tool’s description carried hidden instructions — invisible to the user reviewing the tool list, fully legible to the model deciding how to call it — that directed an agent to read a local SSH private key and MCP configuration file and pass their contents along disguised as an ordinary parameter, and a follow-up “shadowing” variant showed one malicious server’s description altering how the agent used a second, legitimately trusted server [11]. OWASP’s MCP Top 10 project has since catalogued the same family of attacks under MCP03:2025, splitting it into schema poisoning, tool shadowing, and “rug pulls” in which a previously reviewed server’s tool description changes maliciously after installation [12].

A cabinet of small MCP connector modules each behind its own trust toggle, with one toggle caught mid-throw exposing the module's contacts and a slotted card of tool descriptions half withdrawn
Figure 4. Anthropic reviews listed connectors but does not audit or manage what any MCP server actually does once installed; the toggle is the whole boundary.Image prompt and art direction by Brecht Corbeel; image generated to that direction.

The capability-creep part of this failure is less dramatic than a poisoned tool description but more common: a team adds one MCP server for one task, finds it useful, and keeps adding more, each one expanding what the session can reach and each one outside the audit boundary Anthropic explicitly declined to own. The project’s own list of allowed MCP servers is ordinary source-controlled configuration [1] — which means the review discipline applied to a new dependency in package.json is exactly the review discipline an MCP entry deserves, and often does not get.

8. Long-horizon task drift: sessions that get worse, not better, with time

It is intuitive to expect an agentic session to improve as it accumulates context about a task. The measured pattern runs the other way. METR’s time-horizon research tracks the length of task — measured in how long a skilled human would take — that a frontier model can complete autonomously with a given reliability, and finds current frontier models near 100% success on tasks taking a human under four minutes, collapsing to under 10% success on tasks taking more than about four hours, with Claude 3.7 Sonnet reported specifically among the models exhibiting this drop-off [13]. The organization’s headline trend — the task length completable at 50% reliability doubling roughly every seven months over six years of measurement — is worth writing as an explicit model rather than a slogan, because it is the empirical claim the section rests on: if T50(t)T_{50}(t) is the task duration completable at 50% reliability at year tt, METR’s fit is

T50(t)T50(t0)2(tt0)/d,d7 months, T_{50}(t) \approx T_{50}(t_0) \cdot 2^{\,(t - t_0)/d}, \qquad d \approx 7\ \text{months},

with the organization’s own caveat that the exact doubling time dd is sensitive to task selection and human-baseline methodology, even though the qualitative exponential trend is one they hold with more confidence [13].

A mechanical contributor to the same pattern shows up in the underlying architecture rather than in a benchmark of full agent runs: Liu and colleagues’ peer-reviewed analysis of how language models use long contexts found that retrieval accuracy is highest when relevant information sits at the very start or end of the input and degrades substantially when it sits in the middle, with the degradation growing worse as the context itself grows longer, even in models built for long contexts [14]. A long Claude Code session accumulates exactly the kind of middle-buried context this finding describes — an instruction given forty tool calls ago, a constraint stated once early in a session and never repeated — and the session’s own growing length is what pushes that instruction toward the part of the context window where it is least reliably retrieved.

9. Permission fatigue: the ninety-three percent reflex

Habituation to repeated security warnings is not a Claude Code-specific finding — Vance and colleagues’ peer-reviewed fMRI and eye-tracking study found that attention to warnings measurably declined over a five-day work week and that a three-week field trial of privacy permission prompts showed adherence dropping steadily as the same warning repeated, recovering only when the warning’s appearance was deliberately varied [15]. What is Claude Code-specific is the number Anthropic published when explaining why it built an alternative to manual approval at all: users approve 93% of Claude Code’s permission prompts by default, a rate Anthropic frames as the predictable result of exactly the habituation the warnings literature describes, not as evidence that 93% of proposed actions are actually safe [6].

Anthropic’s response was to build a classifier layer — auto mode — that screens tool outputs for injection attempts before they reach the model and evaluates each proposed action against the transcript in two stages, a fast single-token filter followed by chain-of-thought review only when the first stage flags something, deliberately withholding the model’s own reasoning from the classifier so the agent cannot talk its own approval into existing [6]. Anthropic’s own published numbers for that system are worth citing precisely because they are not framed as a solved problem: a 0.4% false-positive rate across ten thousand real actions, a 17% false-negative rate on fifty-two curated real overeager actions, and a 5.7% false-negative rate on a thousand synthetic exfiltration attempts, with Anthropic’s own assessment reading “whether 17% is acceptable depends on what you’re comparing against” [6]. The honest comparison is not against a hypothetical perfect gate — it is against a human reflex that was already approving 93% of everything without reading it.

10. Git history as agent exhaust: commits that leak more and explain less

Every action Claude Code takes inside a git repository eventually becomes part of that repository’s permanent record, and two independent measurements describe how that record differs when an agent writes it. GitGuardian’s March 2026 State of Secrets Sprawl report, built from scanning public GitHub commits, found that commits co-authored by Claude Code carried a 3.2% secret-leak rate against a 1.5% baseline across all public commits — more than double — and attributed part of the gap to size: Claude Code-assisted commits ran roughly twice as many changed lines as human-only commits, which is simply more surface area for a credential to slip through unnoticed [16]. The same report found 24,008 unique secrets specifically inside MCP configuration files across public GitHub, 2,117 of them still valid credentials, which ties this failure directly back to the MCP capability-creep problem above: a server configuration file is exactly the kind of file a fast-moving agent session edits without a second reviewer [16].

A git-history console reading a spooled commit ledger, its revert arm caught mid-pull over a commit entry flagged with an unfilled test marker
Figure 5. A commit an agent writes is a summary of a diff, not a record of what was verified; the ledger only shows what actually ran once someone pulls the arm to check.Image prompt and art direction by Brecht Corbeel; image generated to that direction.

The second measurement concerns what the commit record explains rather than what it leaks. A peer-reviewed study built on 33,580 pull requests across five AI coding agents found their commit and PR patterns distinguishable with a 97.2% F1-score using structural features alone — Claude Code’s own signature ran through the shape of the code it produced rather than through its prose, distinguishable in part by the proportion of conditional statements in its diffs [17]. A commit message an agent generates is ordinarily a compressed restatement of the diff it already accompanies, not an added record of what was tried and rejected or what verification actually ran — which means the git history a team is left auditing after an incident carries less of the reasoning a human author would ordinarily have left behind, at precisely the moment that reasoning is most useful to reconstruct.

The seams, not the model, are where these fail

None of the ten failures above required the underlying model to be worse than advertised. A bypass flag did exactly what its documentation says it does. A hook ran exactly the shell command it was configured to run. A subagent worked within exactly the context window it was given. Each failure is a property of how Claude Code’s separately designed mechanisms compose — a permission mode that removes a safety net, a hook that predates a trust dialog, an isolation boundary that also isolates useful context, a context-not-configuration memory system asked to do configuration’s job, an audit boundary Anthropic explicitly declined to extend past its own directory, a context window with a documented middle it forgets, an approval reflex habituation predicts and Anthropic measured directly, and a commit record with more surface area and less explanation than the one a human would have left.

The practical implication is that hardening Claude Code is not one setting. It is treating each of the six mechanisms above as its own control surface: pin bypassPermissions to disposable containers only, route anything the model must not be able to talk its way out of into a deterministic hook rather than a CLAUDE.md instruction, write everything a subagent needs into its prompt string explicitly rather than assuming inheritance, schedule a real review pass over CLAUDE.md the way a team would review any other piece of shared configuration, apply the same dependency scrutiny to an MCP server that a new package would get, checkpoint long sessions rather than letting instructions age into the middle of the context window, and scan agent-authored commits for secrets before they are pushed rather than after. None of these ten failure modes is exotic. All ten are already logged, patched, measured, or published, by the same organization that built the tool or by researchers who tested it directly against production use.