The Two Threat Models (7.1)
Claude receives one context: system prompt, conversation turns, tool definitions, tool results. All of it is text, and nothing structural marks your sentences as commands and a supplied document's sentences as data. Injection is a property of how these systems work, not a defect awaiting a patch. No release note will retire it.
| Direct injection and jailbreaks | Indirect injection | |
|---|---|---|
| Adversary | The user of your application | Whoever shaped content Claude reads |
| Arrives via | The input the user types | Emails, fetched pages, OCR text, tool results |
| Controls sit on | The input path: harmlessness screen, input validation, a system prompt stating boundaries and how to refuse, a policy for repeat offenders backed by an opaque, hashed metadata.user_id | The tool surface and the outbound path |
Indirect is the class that matters in agentic applications: the attacker never touches your interface. On the exam: items describe which situation you are in, and the wrong answer is usually the right control for the other one. The guide's own published rationale kills three postures outright: temperature is irrelevant to injection, a polite request is not an enforceable control, and a more instruction-following model can be more susceptible, because injected text is instructions too.
The browser use tool (as of September 2026) puts what Claude sees of a page in your executor's hands. Treat everything a page supplies as untrusted, and build page reads from what the page renders, the accessibility tree or visible text, never raw DOM source, so hidden text never reaches Claude.
Delivering Untrusted Content (7.1)
Current docs have moved past wrapping everything in XML tags. Five rules, in the order the page gives them:
- Deliver third-party content inside
tool_resultblocks, never insystemprompts or plain usertextblocks. Claude is trained to treat instructions inside tool results with scepticism. - Say what the content is and where it came from, in the tool
descriptionor in the structure of the result. - State the policy in your system prompt: content from tools, documents and searches is untrusted data, and instructions inside it are information to report rather than commands to follow.
- JSON-encode the untrusted string where possible, rather than concatenating it. Escaping gives unambiguous delimiters, so an attacker cannot close a quote or a tag to break out into an instruction context.
- The one developers get backwards: do not put your own instructions inside a tool result. Claude treats that content as untrusted data and may ignore it or flag it as an injection attempt. Yours go in the user turn that follows or, on models that support one, a mid-conversation system message.
All five make the model a better reader of provenance. None is enforcement, which is why the next two moves exist.
Screening, and Least Privilege Over the Tool Surface (7.1)
Screening runs in both directions: inbound, a harmlessness screen on the user's content using a lightweight model (the docs name Claude Haiku 5.5), with the verdict constrained by structured outputs to a parseable boolean rather than prose, and a stop_reason: "refusal" on the screening call treated as a harmful verdict; outbound, the same pattern on a tool's raw output before it is returned as a tool_result. It is a check with an enforcement point, because the application decides whether the content reaches the model. But it is also a model, so it is probabilistic and it misses. That is exactly why it composes with deterministic controls instead of replacing them.
Least privilege has three distinct moves, and they are not interchangeable:
| Move | Mechanism | Strength |
|---|---|---|
| Remove the tool | disallowed_tools=["Bash"]; a bare name strips the definition from the request | Strongest: Claude never sees the tool |
| Scope the tool | disallowed_tools=["Bash(rm *)"]; denied in every permission mode, bypassPermissions included | An enforceable boundary, not a preference |
| Narrow the credential | Read-only where reading suffices; the end user's entitlements rather than a service account's | Bounds the blast radius |
The published evaluation order: hooks → deny rules → ask rules → permission mode → allow rules → the canUseTool callback. Two reciprocal traps live in it. A call approved at any earlier step skips canUseTool entirely, so a security check written there is silently bypassed for that tool. And allowed_tools does not constrain bypassPermissions, so listing three read-only tools alongside that mode still approves everything you left off the list.
Leak, PII, and Whose Authority the Call Carries (7.1)
Prompt leak. No method is foolproof. The documented ordering is monitoring first, then output screening and post-processing, and only then leak-resistant prompt engineering, which comes last because it adds complexity to the model's main task and may degrade performance elsewhere. Rank the fixes: the durable one is not putting the value in the context at all; the practical one is an output check; the fragile one is instructing the model to keep a secret. Prefilling the assistant turn is not supported on Claude 4.6 and later, so it is not available as a leak control.
The outbound path is where a leak travels, so constrain which tools can send, fetch or write, and to where. In a browser use executor (September 2026) that means refusing any navigate scheme other than http or https, checked with a URL parser rather than a string prefix, and confining file_upload to a dedicated, allowlisted directory, never the browser's download folder.
PII is a data-flow decision at four points: what enters the context (minimise, redact, tokenise), what the provider retains, what your own systems keep, and what your users are told (every consumer-facing chatbot must disclose that it is AI). Retention detail as verified 2026-08-21: retained data is never used for training without express permission, and ZDR is arranged per organisation, never extending automatically to a sibling organisation on the same account. ZDR also excludes Console usage, Managed Agents sessions, consumer plans and features such as code execution, and it does not override retention of a flagged session for up to two years. Covered Models require 30-day retention and are not ZDR-eligible. Your own request-and-response log is a complete second copy of everything the model saw, so redact at the write.
The confused deputy. An agent acts on somebody's behalf. If its credential is broader than the person it acts for, any text that can steer it has borrowed the wider authority. Keep the three checks distinct: authentication establishes who the caller is, authorisation establishes what that caller may do and is checked per action, integrity covers whether the data and the action are what they claim to be (approval gates, audit records). Multi-tenant isolation follows from authorisation, never from a system-prompt sentence. Retrieve-then-filter is a defect, not a control.
The Four Guardrail Layers (7.2)
Ask three questions of any proposed control: what does it inspect, where does the code run, and what happens when it fires? If the answer to the third is that the model reads something and decides, it is a behaviour shaper, not a guardrail. Most guardrail tables shrink the first time you run that test over them.
| Layer | Catches | Limit |
|---|---|---|
| Input checks | Classification, pattern filtering, redaction, shape validation | Probabilistic, and blind to anything arriving on a channel they do not sit on |
| System prompt and training | Genuinely shapes behaviour; stating an untrusted-content policy is recommended | Enforces nothing. The single most important sentence in the sub-skill |
| Tool-level controls | Which tools exist, credential scope, approvals, deterministic pre-execution checks | Where enforcement actually lives; removal beats denial |
| Output checks | Shape validation, policy classification, redaction, and blocking the resulting action | Skipping the action half is the common defect |
Layer because each layer fails differently, not from belt-and-braces sentiment. Layers are not interchangeable: a stricter output check cannot see what an input screen would have caught before the draft was written. Claude Code ships a worked example: a permission system, context-aware analysis, input sanitisation, network commands such as curl and wget left out of the auto-approved set, an isolated context window for web fetch, trust verification for first-time codebases and new MCP servers, command injection detection, and fail-closed matching. Its own caveat closes the point: no system is completely immune.
The Usage Policy as a Specification (7.2)
The governing document is the Usage Policy. "Acceptable Use Policy" survives only as the URL slug and an alias. Three parts:
- Universal Usage Standards: prohibitions applying to everyone.
- High-risk Use Case Requirements: these apply to a High-risk AI Recommendation, a recommendation in one of eleven High-risk Areas: legal, medical, finance, credit, insurance, housing, employment, education and credentials, healthcare access, public benefits and services, and legal status and adjudication. Two controls attach: a qualified person with the authority to change or modify it must meaningfully review it before it is delivered as advice or used to implement a decision, and the person affected must be clearly told that AI was used to produce it.
- Additional Use Case Guidelines: consumer-facing chatbots and agents, products serving minors, agentic use cases, and software listed in Anthropic's directories. Every consumer-facing chatbot or AI agent that communicates directly with external users must disclose that users are interacting with AI rather than a human, at a minimum at the beginning of each chat session or in the product interface, whether or not a High-risk AI Recommendation is involved. If you ship an agent that acts on somebody's behalf, this part describes your product: you are responsible for making sure that what it does, including through tools, browsers and connected systems, complies with the policy.
Read the high-risk controls as build work: a human gate with a named owner who can change the output, a disclosure the affected person sees, a refusal path, an escalation route, and a log entry proving the gate ran. The exam distractor is always a technically sound control that does not discharge the obligation, such as a better classifier where the policy asks for a qualified person's review. The exam tests whether you notice that a scenario has landed inside a High-risk Area at all.
Fail Closed, and Deployment Discipline (7.2)
Availability engineering says degrade gracefully and keep serving. On the security path the instinct is inverted: when the classifier times out, validation is inconclusive, or the approval service does not answer, refuse or hold the consequential action. Proceeding converts the check into a suggestion that any dependency failure removes, and whoever can cause the failure gets the unguarded path for free.
Two properties make a hold shippable: separate the consequential action from the whole feature (holding one publication is not an outage), and give the held work somewhere to go and someone to tell: a queue, a notification, and a resume trigger. Retrying is fine; ending the retry chain at the model is not, because that swaps the enforcement point for the layer that enforces nothing.
Named instances. Claude Code's fail-closed matching: in Manual mode (config value default), unmatched commands require approval by default. As of September 2026 interactive sessions start in auto mode from v2.1.283, while claude -p and the Agent SDK start in default. The Agent SDK's dontAsk mode denies any call that would otherwise prompt, which is what a headless agent with nobody to prompt should do. Calls your allow rules pre-approve, and calls that need no approval in default mode, still run.
Rollout and observation are part of the guardrail, not operations beside it. Stage the exposure, monitor security-relevant events rather than only the error rate, red-team your own agent before deploying with documents and tool outputs that deliberately carry injection attempts, give reports an owner, and keep a rollback nobody has to argue for. The docs treat analysis of outputs as an input to the guardrails: findings refine prompts, validation and filtering. A well-built deployment with no observation is a wrong answer, not merely an under-instrumented one.
Hooks: the Deterministic Control (7.3)
One idea, quoted verbatim: hooks give "deterministic control: certain actions always happen rather than relying on the LLM to choose to run them." When a team has told the model three times not to do something, the fix is not a fourth telling; it is a check the model does not participate in.
PreToolUse mechanics, all keyed facts:
| Signal | Effect |
|---|---|
| Exit 2 | Blocks; the reason on stderr reaches Claude |
| Exit 0 | No objection, which is not approval; the normal permission flow still applies |
| Any other non-zero, without valid JSON on stdout | Non-blocking error, and the action proceeds, unless the hook sets onFailure: "block" (October 2026). A script that exits 1 has quietly disabled itself |
JSON hookSpecificOutput | permissionDecision of allow, deny, ask or defer, with permissionDecisionReason. defer is honoured only in a -p run, which exits with the call preserved for a later resume. Precedence across hooks: deny > defer > ask > allow |
On blocking-capable events, exit 2 wins regardless, and even a printed allow cannot override it. Hooks run first in the evaluation order, so a hook deny binds even in bypassPermissions. The reciprocal stops over-claiming: a hook returning allow does not clear a matching deny or ask rule. Hooks tighten; they do not loosen.
Matchers (as of September 2026): a matcher of only letters, digits, _, -, spaces, commas and | is an exact name or list. Any other character makes it an unanchored regular expression, so Edit.* also matches NotebookEdit. mcp__archive matches no tool, while mcp__archive__.* matches the whole server. Other safety events: UserPromptSubmit can block a prompt before Claude processes it. PostToolUse cannot undo a call, but updatedToolOutput replaces what Claude sees, while decision: "block" only adds a reason beside the original output.
Limits worth stating out loud. Five types exist and only some are deterministic: command, http and mcp_tool run code you control, while prompt is a single-turn model evaluation and agent is multi-turn verification with tool access, both documented as being for decisions requiring judgement rather than deterministic rules, and agent hooks are still experimental. A rule about intent is not hook-shaped. A hook is a synchronous check, so it costs wall-clock time on the path it guards (our observation, not a documented limit, though the per-type timeout defaults exist because of it). Both ways of removing that latency open the gate: an async hook cannot block, and a command hook that times out on PreToolUse does not block either, so the call proceeds through the permission flow. disableAllHooks is an off switch, and only managed settings keep managed hooks running when a lower-scope file turns them off. Path-based deny rules do not reach a subprocess that opens files itself, so OS-level enforcement across every process means the sandbox, not a rule.
Keys: Where They Live, and What to Do When One Leaks (7.4)
Anything shipped to a client is public. A JavaScript bundle, a mobile binary, a desktop application: the running code reads the credential, so anyone who can run the code can read it. Minification and encoding are transformations the code reverses on every start. Obfuscation is not secrecy. The fix is a boundary rather than a hiding place: the client talks to your backend, and the backend holds the credential and calls Claude. It buys three things, where distractors usually fix only the first. It removes the credential from the client. It gives you a place to authenticate the user and authorise the request. And it gives you the enforcement point for per-user rate limiting and quota. One dated exception, verified 2026-08-21: App Attest lets an attested iOS or macOS installation call the API with no back end, on workspace-scoped tokens that expire after an hour and authorise only Messages API calls. It is not a licence for a browser bundle.
| Fact | Detail |
|---|---|
| Static key | sk-ant-api... sent as Authorization: Bearer; the x-api-key header is legacy but still supported (September 2026). SDKs read ANTHROPIC_API_KEY. Disable a leaked key (reversible) or delete it (permanent) |
| Key types | Personal (acts as you; archived when you are removed), service account (the identity for shared or automated workloads), workspace (legacy; acts as no one and keeps working whoever created it) |
| Expiration | Chosen at creation from 3 hours, 1 day, 7 days, 30 days, a custom duration or Never. Cannot be changed afterwards. Expired keys return 401 authentication_error and cannot be reactivated |
| Its place | Limits the lifetime of a leaked credential, and the docs call it no substitute for secret hygiene |
| Workload Identity Federation | Exchange an IdP identity token at POST /v1/oauth/token for a short-lived token; the SDK refreshes it. No sk-ant-api... string to mint, distribute or rotate. Caveat: only as strong as the IdP configuration. A federation rule's match conditions (subject_prefix, claims such as ref, audience, a CEL condition) decide who may mint, and its oauth_scope is a ceiling, so a Claude-only workload gets workspace:inference |
| Creation | Console only. The Admin API reads, renames and changes status (inactive disables reversibly, archived deletes) and audits; it does not provision |
| Managed Agents vaults | Beta. Credentials registered once and referenced by ID per session; an environment_variable secret is swapped in at egress, so the agent never sees it. Outbound only: a token fetched with it arrives unredacted |
The exposure playbook is a sequence, and the sequence is the examinable part. 1. Kill the credential, because until the exposed key is dead everything else is decoration. 2. Remove it from wherever it leaked, knowing git history, build caches, CDN copies and screenshots keep their own copies. 3. Fix the design that put it there, usually the client-side architecture. 4. Review the access logs, and only then decide whether the incident is closed. Every wrong answer here is a real step performed in the wrong order.
Verification at the Point of Use, and Attribution (7.4)
Authenticate the caller at the edge, then verify the level at the point of use, per action, so an elevated operation re-checks entitlement rather than inheriting the answer a session got when it opened. Where an agent acts on somebody's behalf, its tool calls carry that person's authority, not a service account's. Approval flows belong here too: who may authorise an elevated action, and how the decision is recorded so it can be produced later.
A key with no attribution cannot be investigated. If three services share one credential, an anomalous spike names none of them, and the first fix is a distinct key per service so the alert has something to point at, not a better alert. Usage and cost attribution runs per key and per workspace, so keys scoped by project or environment give every line of spend a caller. The Admin API lists keys with status, workspace and expires_at, so rotation is auditable rather than remembered. Usage and Cost API and Rate Limits API for the numbers, the Compliance API Activity Feed for the audit record, and for Claude Code, OpenTelemetry events through the OTLP logs exporter as the audit source. Tool arguments such as the Bash command need OTEL_LOG_TOOL_DETAILS=1, and an API-key session carries no account, so attach identity with OTEL_RESOURCE_ATTRIBUTES.
Two documented details that make good items. Organisation roles are user, claude_code_user, developer, billing and admin, with workspace roles separate. And on offboarding, it depends on the key type: personal keys are archived when their owner is removed, service account keys keep working unless the service account is archived, and legacy workspace keys keep working regardless. A production service belongs on a service account key, never on a person's.