Last checked: 1 November 2026, against the Claude Code docs and changelog up to v2.1.314.

Short answer: it depends on how the machine is set up. With managed settings, or a Team or Enterprise /login, a built-in guard loads first and, by default, a user’s mod cannot approve a call that a deny rule refuses, an ask rule would prompt for, or a PreToolUse hook blocked. Without that guard, a mod can approve those calls. In every setup, a mod’s own file, process and network calls sit outside your permission rules.

Anthropic launched mods on 1 October 2026 (launch article). The docs explain every setting well. This page turns them into a decision for a team lead: which setup you are in, which policy to pick, how to check it on a real machine, and what is still not covered.

What a mod is

A mod is a plugin made of JavaScript or TypeScript event handlers that Claude Code calls inside its own process (Mods overview). It installs like any other plugin, from a marketplace, for example /plugin install name@marketplace. Mods are on by default: the overview gives Claude Code v2.1.287 or later in the terminal and v2.1.286 in the Desktop app, while the admin page says v2.1.286 and later. Their hooks run in the terminal, the Desktop Code tab (not in WSL sessions), the VS Code extension, claude -p and the Agent SDK, Remote Control and cloud sessions.

The part that matters for a security decision is what a mod can reach. The overview lists it plainly. Once loaded, a mod can:

  • read and write any file your user account can, start programs, and make network requests
  • read environment variables and settings files, including API keys
  • see every prompt and every tool call
  • rewrite prompts and tool calls, or submit a prompt as you
  • approve a tool call before you are asked
  • spend your usage through model calls

Mods are not sandboxed. If you turn sandboxing on, it isolates the Bash commands Claude runs, but a process a mod starts runs outside it. One thing a mod cannot do is change what the permission prompt shows.

Treat installing a mod the same way you treat widening a permission. It is code running as the user, with the user’s access.

Diagram of a mod inside the Claude Code process. With the guard loaded, deny and ask rules, a PreToolUse hook and the sec-default guard stay ahead of a user’s mod. No order is shown among those controls. File, process and network calls sit outside permission rules.

Where a mod runs, and which calls skip permission rules.

Can a mod approve a call your permissions block?

This is the question most teams will ask first. The answer comes from the Extend permissions with hooks section of the permissions docs and the admin page.

The key is a built-in mod called sec-default@builtin, listed in /plugin and the debug log as cc-plugin-sec-default. It loads ahead of every mod a user installs, and users cannot turn it off. But it only loads when the machine has managed settings, or when the session uses a Team or Enterprise /login.

Your setupGuard loads?Deny ruleAsk rule or blocking PreToolUse hook
Team or Enterprise /loginYesMod cannot approve past it (by default)Mod cannot approve past it
Any login, machine has managed settingsYesMod cannot approve past it (by default)Mod cannot approve past it
API key, Bedrock, Google Cloud’s Agent Platform or Microsoft Foundry, no managed settingsNoMod can approve the callMod can approve the call
Long-lived CLAUDE_CODE_OAUTH_TOKEN, no managed settingsNo, even if a Team login is storedMod can approve the callMod can approve the call

A few details sit under that table:

  • Deny can be loosened on purpose. The guard option allowModsToOverrideDenyRules: true lets users’ mods approve calls a deny rule refuses. Leave allowModsToOverrideDenyRules unset.
  • Auto mode. A call a mod approves runs without a classifier check, unless the guard is loaded and the session uses --permission-prompt-tool or an Agent SDK canUseTool callback. Then the classifier checks the call first.
  • Plan mode. A mod cannot approve a call that is not read-only, such as a file edit.
  • Without the guard, your --permission-prompt-tool or canUseTool callback is not asked about a call the mod approves.

If your developers use API keys or a cloud provider and you have never deployed managed settings, the bottom two rows describe your team today.

Decision flow for the sec-default guard. Managed settings or a Team or Enterprise login load the guard. By default a user’s mod cannot approve past a deny rule, and it cannot approve past an ask rule or a blocking PreToolUse hook. Without the guard, a mod can approve those calls.

When the guard loads, and when a mod can approve past your rules.

The gap your permission rules do not cover

Put this in front of every security reviewer. Permission rules and PreToolUse hooks apply to Claude’s tool calls. They do not apply to a mod’s own $.fs and $.process calls. The admin docs give the example directly: with Read(.env) denied, a mod can still read that file with $.fs.read, or start a program that does.

Network is similar:

  • If your organisation’s policy does not allow WebFetch, Claude Code also refuses every mod’s $.http.fetch request.
  • If you only turned WebFetch off with CLAUDE_CODE_DISABLE_WEB_FETCH or a WebFetch deny rule, mods can still make $.http.fetch requests.
  • Nothing in that list covers a program a mod starts with $.process.run. It reaches the network with the user’s own access.

The guard does not close this gap either. Only two things do: keep users’ mods from loading, or handle those calls in a policy mod of your own.

What a mod can reach, against what permission rules cover.

A mod canWhat the rules cover
Read or write files with $.fsPermission rules and PreToolUse hooks do not apply. A denied Read(.env) can still be read with $.fs.read.
Start a program with $.processNot covered. Sandbox isolates the Bash commands Claude runs, not a process a mod starts.
Call $.http.fetchRefused when organisation policy does not allow WebFetch. A WebFetch deny rule or CLAUDE_CODE_DISABLE_WEB_FETCH does not stop it.
Reach the network with $.process.runNot covered. It uses the user’s own access.
Read environment variables and settings, including API keysListed as reach. Not named as something permission rules cover.
See every prompt and tool call, rewrite or submit a prompt, and spend usageListed as reach. Not named as something permission rules cover.
Approve a tool call before you are askedWith the guard, a user’s mod cannot approve past a deny rule, by default, or past an ask rule or a blocking PreToolUse hook. Without the guard, it can.
Change the permission promptIt cannot.

Pick a policy

The admin docs give a policy table. Here it is as a decision, from tightest to loosest:

  1. No installed mods, settings hooks untouched. Set allowManagedModsOnly on the guard and deploy no mods of your own. A team that has not reviewed any mods yet should start here.
  2. Only your organisation’s mods. Set allowManagedModsOnly, install your own mods so they count as yours, and add disableSideloadFlags.
  3. Any mod from marketplaces you approve. Keep your marketplace restrictions and set disableSideloadFlags to true.
  4. Any mod, with your own mod checking the others. Install your policy mod and list it with sec-default@builtin in prependPlugins.

The setting for option 1 goes in managed settings:

{
  "pluginConfigs": {
    "cc-plugin-sec-default@builtin": {
      "options": { "allowManagedModsOnly": true }
    }
  }
}

The guard reads it from managed settings only, so the same entry in a user, project or local file changes nothing. Users’ settings hooks, status lines and /goal keep working.

Three traps worth knowing before you choose:

  • disableAllHooks removes a control. It is the widest switch. In managed settings it stops every mod, yours included, and turns off every settings hook, so your managed PreToolUse hook no longer blocks anything. Only use it if you really want no hooks at all.
  • prependPlugins replaces the default list. If you set it, you must list sec-default@builtin yourself, or the guard is gone.
  • “Enabled by managed settings” is not “yours”. A mod counts as your organisation’s only when managed enabledPlugins enables it, its marketplace is a local directory named by absolute path, and the plugin is listed by relative path. A plugin from GitHub, git, a URL or npm counts as a user’s even when managed settings enable it.

Two things do work in your favour. Managed PreToolUse hooks run before any mod’s tool.call hook, and run again on a call a mod rewrote. And the guard fails closed: if it cannot read managed settings, it refuses every user’s mod; if it cannot check the deny rules for an approved call, it refuses the call.

Settings and flags named on this page.

SettingWhat it doesDefaultRecommendation
allowManagedModsOnlyOn the guard, and only in managed settings. Users’ mods do not run their hooks. Your organisation’s mods and built-in mods still run. The same entry in a user, project or local file changes nothing.Not statedSet it and deploy no mods of your own. Start a team here that has not reviewed any mods yet.
allowModsToOverrideDenyRulesWhen true, users’ mods can approve a call a deny rule refuses.Not statedLeave it unset.
disableSideloadFlagsBlocks --plugin-dir and mods Claude writes during a session.Not statedAdd it when only your organisation’s mods should run, or set it to true and keep marketplace restrictions.
disableAllHooksWidest switch. In managed settings it stops every mod, yours included, and turns off every settings hook, so a managed PreToolUse hook no longer blocks.Not statedOnly use it if you really want no hooks at all.
prependPluginsReplaces the default list.Not statedIf you set it, list sec-default@builtin, or the guard is gone.
enabledPluginsA mod counts as your organisation’s only when managed enabledPlugins enables it, its marketplace is a local directory named by absolute path, and the plugin is listed by relative path. GitHub, git, a URL or npm still counts as a user’s.Not statedDo not treat “enabled by managed settings” as yours unless those conditions hold.
permissions.blockWritesOutsideWorkingDirectoriesWrite, Edit and NotebookEdit refuse paths outside the working directories, in every permission mode. The changelog does not say it covers Bash writes or a mod’s $.fs.write.Not statedAdd it to a team baseline. Do not count it as a mod control.
--safe-modeTurns installed mods off, yours included.Not statedDo not make a policy mod the only control. This flag unloads it.

If you write a policy mod, make it fail closed

The guard fails closed. Your own mod does not, by default. The admin docs say that if your plugin.register hook throws or times out, Claude Code skips it, so the check fails open and the mod it was checking loads. The fix is a .catch handler that returns a refusal for user-tier mods. The docs show the pattern, and the same applies to an http.fetch hook you use to block requests.

Two more caveats from the docs:

  • If the worker that runs installed mods crashes three times, Claude Code unloads every mod that is not built in, yours included, until /reload-plugins or a new session.
  • --safe-mode turns installed mods off, yours included.

So a policy mod is useful for audit and for selective refusal, but do not make it the only control. Keep deny rules and managed PreToolUse hooks underneath it.

Review a mod before anyone installs it

You can see what a mod does without running it:

claude plugin validate ./some-mod

The hooks: line lists the events it handles. The calls: line lists the mods API methods its code calls. The admin docs flag these calls to look for: $.fs.read and $.fs.write, $.process.run and $.process.spawn, $.http.fetch, $.env.get and $.settings.read, $.env.set, $.mcp.call, $.model.complete, $.prompt.submit and $.session.send. In the hooks line, tool.check means the mod can approve or deny a tool call before a prompt appears.

One caution from the plugin security page: when auto-update is on for a marketplace, Claude Code updates its plugins in the background, so the files you reviewed can change on disk. Decide per marketplace whether auto-update stays on for anything you approved.

Record each approved mod the way you would record a permission change: who owns it, why it is needed, what calls it makes, and when it gets reviewed again.

New: blockWritesOutsideWorkingDirectories

The changelog for v2.1.314 (30 October 2026) added permissions.blockWritesOutsideWorkingDirectories: Write, Edit and NotebookEdit refuse paths outside the working directories in every permission mode.

That is a good setting for the tool layer. Add it to a team baseline. But be precise about what it covers. The changelog names Claude’s Write, Edit and NotebookEdit tools. It does not say it covers Bash writes or a mod’s $.fs.write, so do not count it as a mod control. Pair it with the mod policy above, not instead of it.

Verify on a real machine

A policy you have not checked is a guess. The admin docs give the signals to look for with claude --debug:

  • Your own mod: its hooks module line shows tier prepend. If it shows tier user, Claude Code is treating it as a user’s mod.
  • A user’s mod under allowManagedModsOnly: a line reading refused by cc-plugin-sec-default: mods are limited to your organization's by policy (allowManagedModsOnly). An earlier line says the module loaded, so look for the refusal, not the load.
  • With disableSideloadFlags: claude --plugin-dir ./any-mod exits with a message starting --plugin-dir is disabled by your organization's managed settings (disableSideloadFlags).

Run these on one machine per setup you have: Team login, API key, and any cloud provider.

Where this fits in your permission policy

Mods do not replace permission rules, settings hooks or managed settings. They add one more party that can say yes. The same permission approach applies here too: start narrow and fail closed, give every widening an owner and an expiry date, and watch for permission drift. Enabling a mod is a permission change. Test the delta before you widen it, and run the Claude Code production checklist before agents touch real repos.

FAQ

Can a Claude Code mod approve a tool call your permissions should block?

It depends on your setup. With managed settings or a Team or Enterprise login, the built-in sec-default guard loads and, by default, a user’s mod cannot approve a call a deny rule refuses, an ask rule prompts for, or a PreToolUse hook blocked. Without the guard, a mod can approve all of those.

When does the sec-default guard load, and how do you know it loaded?

It loads when the machine has managed settings or the session uses a Team or Enterprise /login. API keys, cloud providers without managed settings, and a long-lived CLAUDE_CODE_OAUTH_TOKEN do not count. Check /plugin or the claude --debug log for cc-plugin-sec-default.

How do you stop users’ mods from running at all?

Set allowManagedModsOnly in managed settings under pluginConfigs, keyed cc-plugin-sec-default@builtin. Users’ own mods then do not run their hooks, while your organisation’s mods and built-in mods still run. Add disableSideloadFlags to block --plugin-dir and mods Claude writes during a session.

Can a mod read a file your deny rule blocks?

Yes. Permission rules and PreToolUse hooks cover Claude’s tool calls, not a mod’s own $.fs and $.process calls. Anthropic’s admin docs say a mod can still read a denied .env file with $.fs.read. To close that gap, keep users’ mods from loading or handle those calls in a policy mod.

What does blockWritesOutsideWorkingDirectories do, and does it limit mods?

Added in v2.1.314, it makes Claude’s Write, Edit and NotebookEdit tools refuse paths outside the working directories in every permission mode. The changelog does not say it covers mods or Bash, so do not rely on it to limit a mod. Treat it as a tool-layer baseline.

Mods vs settings hooks: which should a team use for enforcement?

For enforcement, start with deny rules and managed PreToolUse hooks, because managed hooks run before any mod and the guard keeps them ahead of users’ mods. A policy mod adds audit and selective refusal, but it fails open unless you add a .catch, and crashes or --safe-mode can unload it.