Skip to content
Domain 7
8.1%

Quick Reference: Domain 7 — Security and Safety

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 software update will remove it.

Direct injection and jailbreaksIndirect injection
AdversaryThe user of your applicationWhoever shaped content Claude reads
Arrives viaThe input the user typesEmails, fetched pages, OCR text, tool results
Controls sit onThe 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_idThe tool surface and the outbound path

Indirect is the class that matters in agentic applications: the attacker never uses your interface. On the exam: questions 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) lets your executor decide what Claude sees of a page. Treat everything a page supplies as untrusted. Build page reads from what the page renders, the accessibility tree or visible text, and never from raw DOM source. This way, hidden text never reaches Claude.

Delivering Untrusted Content (7.1)

Current docs go further than wrapping everything in XML tags. Five rules, in the order the page gives them:

  1. Deliver third-party content inside tool_result blocks, never in system prompts or plain user text blocks. Claude is trained to treat instructions inside tool results with scepticism.
  2. Say what the content is and where it came from, in the tool description or in the structure of the result.
  3. 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.
  4. 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 make the text after it read as instructions.
  5. The rule that developers break by doing the opposite: 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 help the model tell where content came from. None is enforcement, which is why the next two methods exist.

Screening, and Least Privilege Over the Tool Surface (7.1)

Screening runs in both directions. Inbound, a harmlessness screen checks the user's content using a lightweight model (the docs name Claude Haiku 5.5). Structured outputs constrain its verdict to a parseable boolean rather than prose. A stop_reason: "refusal" on the screening call is treated as a harmful verdict. Outbound, the same pattern checks a tool's raw output before it is returned as a tool_result. It is a check with an enforcement point, a place where the check can stop the content, 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 works together with deterministic controls instead of replacing them.

Least privilege has three distinct methods, and they are not interchangeable:

MoveMechanismStrength
Remove the tooldisallowed_tools=["Bash"]; a bare name strips the definition from the requestStrongest: Claude never sees the tool
Scope the tooldisallowed_tools=["Bash(rm *)"]; denied in every permission mode, bypassPermissions includedAn enforceable boundary, not a preference
Narrow the credentialRead-only where reading suffices; the end user's entitlements rather than a service account'sBounds the blast radius

The published evaluation order: hooks → deny rules → ask rules → permission mode → allow rules → the canUseTool callback. It contains two traps that work in opposite directions. 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. Leak-resistant prompt engineering comes last because it adds complexity to the model's main task and may degrade performance elsewhere. Rank the fixes: the most reliable one is not putting the value in the context at all; the practical one is an output check; the least reliable 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 the route by which leaked data leaves, so constrain which tools can send, fetch or write, and to where. In a browser use executor (September 2026) that means two things. Refuse any navigate scheme other than http or https, and check it with a URL parser rather than a string prefix. Confine file_upload to a dedicated, allowlisted directory, never the browser's download folder.

PII (personally identifiable information) is a data-flow decision at four points. The first is what enters the context: minimise, redact, tokenise. The second is what the provider retains. The third is what your own systems keep. The fourth is 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. ZDR (Zero Data Retention) is arranged per organisation. It never extends 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 the data before it is written to the log.

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 control its actions can use that wider authority. Keep the three checks distinct. First, authentication establishes who the caller is. Second, authorisation establishes what that caller may do, and it is checked per action. Third, 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. Retrieving data first and filtering it afterwards 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, a control that influences the model's behaviour, not a guardrail. Most lists of guardrails become shorter the first time you apply that test to them.

LayerCatchesLimit
Input checksClassification, pattern filtering, redaction, shape validationProbabilistic, and blind to anything arriving on a channel they do not sit on
System prompt and trainingGenuinely shapes behaviour; stating an untrusted-content policy is recommendedEnforces nothing. The single most important sentence in the sub-skill
Tool-level controlsWhich tools exist, credential scope, approvals, deterministic pre-execution checksWhere enforcement actually lives; removal beats denial
Output checksShape validation, policy classification, redaction, and blocking the resulting actionSkipping the action half is the common defect

Use several layers because each layer fails in a different way, not because extra protection feels safer. 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 (unmatched commands require approval). Its own documentation adds a caveat: no system is completely immune.

The Usage Policy as a Specification (7.2)

The governing document is the Usage Policy. "Acceptable Use Policy" remains 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 apply: 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.

Treat the high-risk controls as things to build: 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 tempting wrong answer on the exam is always a technically sound control that does not meet 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 is 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 rule is the opposite: when the classifier times out, validation is inconclusive, or the approval service does not answer, refuse or hold the consequential action. If the action proceeds, any dependency failure removes the check, so the check is only a suggestion. Anyone who can cause the failure can then take the action with no check.

Two properties make a hold shippable. First, separate the consequential action from the whole feature: holding one publication is not an outage. Second, give the held work somewhere to go and someone to tell: a queue, a notification, and a resume trigger. Retrying is fine; letting the model decide after the retries fail 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 (one with no person present to answer a 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. Release the agent in stages. Monitor security-relevant events rather than only the error rate. Before deploying, red-team your own agent with documents and tool outputs that deliberately carry injection attempts. Give reports an owner. Keep a rollback that 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 one with too little monitoring.

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 to tell it a fourth time. The fix is a check that the model does not take part in.

PreToolUse mechanics, all facts the exam tests:

SignalEffect
Exit 2Blocks; the reason on stderr reaches Claude
Exit 0No objection, which is not approval; the normal permission flow still applies
Any other non-zero, without valid JSON on stdoutNon-blocking error, and the action proceeds, unless the hook sets onFailure: "block" (October 2026). A script that exits 1 has quietly disabled itself
JSON hookSpecificOutputpermissionDecision of allow, deny, ask or defer, with permissionDecisionReason. defer is honoured only in a -p run, which ends the turn with the call kept for a later resume. Precedence across hooks: deny > defer > ask > allow

On blocking-capable events, exit 2 takes precedence regardless, and even a printed allow cannot override it. Hooks run first in the evaluation order, so a hook deny applies even in bypassPermissions. The opposite rule limits what a hook can do: a hook returning allow does not clear a matching deny or ask rule. Hooks can make permissions stricter, but they cannot make them less strict.

Matchers (the patterns that choose which tools a hook runs for, 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. In contrast, decision: "block" only adds a reason beside the original output.

Limits to state clearly. Five types exist and only some are deterministic. command, http and mcp_tool run code you control. prompt is a single-turn model evaluation, and agent is multi-turn verification with tool access. Both are documented as being for decisions requiring judgement rather than deterministic rules. Agent hooks are still experimental. A rule about intent is not one a hook can check. A hook is a synchronous check, so it costs wall-clock time on the path it guards. This is our observation, not a documented limit, though the per-type timeout defaults exist because of it. Both ways of removing that latency let the call through: 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 apply to a subprocess that opens files itself, so OS-level enforcement across every process requires 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 to separate the client from the credential, not to hide the credential: the client talks to your backend, and the backend holds the credential and calls Claude. It gives three benefits, and the wrong options usually give 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. It uses workspace-scoped tokens that expire after an hour and authorise only Messages API calls. It does not permit the same approach in a browser bundle.

FactDetail
Static keysk-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 typesPersonal (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)
ExpirationChosen 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 placeLimits the lifetime of a leaked credential, and the docs call it no substitute for secret hygiene
Workload Identity FederationExchange 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
CreationConsole only. The Admin API reads, renames and changes status (inactive disables reversibly, archived deletes) and audits; it does not provision
Managed Agents vaultsBeta. 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 response to an exposed key is a sequence, and the sequence is the examinable part. 1. Disable, delete or rotate the credential, because until the exposed key stops working, every other step has no real effect. 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. This way, an elevated operation re-checks entitlement rather than reusing 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 does not show which service caused it. The first fix is a distinct key per service, not a better alert, so the alert can identify a service. Usage and cost attribution runs per key and per workspace, so keys scoped by project or environment link every line of spend to a caller. The Admin API lists keys with status, workspace and expires_at, so rotation is auditable rather than dependent on someone's memory. Use the Usage and Cost API and Rate Limits API for the numbers. Use the Compliance API Activity Feed for the audit record. For Claude Code, use OpenTelemetry events through the OTLP logs exporter as the audit source. Tool arguments such as the Bash command need OTEL_LOG_TOOL_DETAILS=1. An API-key session carries no account, so attach identity with OTEL_RESOURCE_ATTRIBUTES.

Two documented details that make good exam questions. Organisation roles are user, claude_code_user, developer, billing and admin, with workspace roles separate. And on offboarding (when a person is removed from the organisation), 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.