TL;DR: Skill security has at least four layers: who may activate the Skill, which tools are available, which calls can skip an approval prompt, and what resources a command can actually reach.
allowed-toolsis temporary pre-approval, not a tool allowlist.disallowed-toolsremoves tools for the active turn, not an OS sandbox. Invocation controls do not replace service-side authorization. High-risk Skills need instructions, permissions, hooks, sandboxing, and human confirmation working together.
Part 6: From Inline to Forked Subagents determined whether a Skill runs in the current conversation or in an independent worker. Either way, its instructions may lead Claude to use Bash, Edit, MCP tools, or other capabilities.
That invites a dangerous shortcut:
The user invoked /deploy → therefore the user approved deployment → the Skill lists allowed-tools → therefore every subsequent action is safe None of those arrows follows automatically. Invocation intent, tool availability, approval policy, and actual isolation are separate security layers.
Four gates, not one
Gate 1 · Skill invocation Who can start this workflow? ↓ Gate 2 · Tool availability Which tools can the running agent see? ↓ Gate 3 · Permission decision Is this specific tool call allowed, denied, or sent for approval? ↓ Gate 4 · Execution boundary What do the process, filesystem, network, and external service permit? Different controls answer different questions:
| Security question | Relevant control |
|---|---|
| May Claude proactively invoke this Skill? | disable-model-invocation, Skill permission rules |
Does the user see /skill-name? | user-invocable, visibility settings |
| Which tool calls skip a prompt during activation? | allowed-tools |
| Which tools are temporarily unavailable? | disallowed-tools |
| Must a deterministic check run before a call? | Hooks, permission rules |
| Which files or network endpoints can Bash reach? | Sandbox, OS permissions, container |
| What can an MCP tool or API do? | External identity, scopes, server-side authorization |
No single row carries the entire security chain.
Gate 1: control the Skill entry point
Part 4 introduced two frontmatter controls:
disable-model-invocation: true user-invocable: false The first prevents normal proactive model invocation, so the user controls when a side-effectful workflow begins. The second hides a direct user command for reference-like knowledge that Claude should load when relevant.
Claude Code permission rules can also govern the Skill tool or individual Skills, for example Skill, Skill(release-check), or Skill(deploy *). That allows policies that deny model access to all Skills, permit only named Skills, or treat a particular Skill and its arguments differently.
Crucially, user-invocable: false is about the user's direct entry point; it does not by itself block Claude from using the Skill tool. To stop Claude from invoking the Skill, use disable-model-invocation or appropriate permission rules. Hiding a button is not disabling a capability.
Gate 2 and 3: allowed-tools grants temporary pre-approval
A commit Skill might say:
--- name: commit description: Inspect and commit the current changes disable-model-invocation: true allowed-tools: - Bash(git status *) - Bash(git diff *) - Bash(git commit *) --- During the turn that invokes this Skill, matching tool calls can proceed without asking the user again. This is not a rule that only those tools exist. Nor is it a permanent session allow rule, an OS permission upgrade, or a guarantee that later turns remain pre-approved.
Skill instructions can remain in conversation context ≠ allowed-tools grant remains in permission state The current Claude Code documentation says the grant clears when the user sends the next message. Invoking the Skill again reapplies it for that turn; session-wide pre-approval belongs in permission settings.
allowed-tools is not an allowlist
allowed-tools: Read Grep means Read and Grep gain pre-approval for the turn. It does not mean Edit and Bash disappear. Other tools remain callable under the baseline permission policy.
If the goal is a read-only Skill, pre-approving Read and Grep is insufficient. The agent may still request Edit or Bash. To narrow availability or effects, use disallowed-tools, a subagent tools allowlist, deny rules, a read-only agent, or a sandbox. “No prompt required” and “cannot be called” are different properties.
disallowed-tools temporarily removes a capability
Claude Code Skills can declare:
disallowed-tools: - Edit - Write That removes those tools from the available pool while the Skill is active, and the restriction clears with the next user message. It can express a workflow's negative capabilities: an audit should not edit files; a background loop should not ask the user; a research workflow should not send messages.
But this remains a runtime tool restriction, not an OS read-only filesystem. If Bash is still available, a shell command could write files indirectly. It does not replace external service permissions either. Audit the effect a tool can produce, not merely its name.
Govern the Skill and its actions separately
A high-risk workflow usually needs two layers of permission rules:
Skill(deploy-production *) → may this deployment workflow start? Bash(kubectl apply *) or an MCP deploy tool → may the actual deployment action run? The first blocks an inappropriate workflow. The second can still intercept a concrete action after the Skill loads. Only governing the Skill is insufficient: Claude might request the same deployment tool without using that Skill. Only governing the tool is also incomplete: sensitive or expensive instructions might be loaded when they should not be. The two layers address different risks.
Repository Skills are executable configuration
A project Skill can arrive with an unfamiliar Git repository. It is more than harmless Markdown:
-
allowed-toolsmay request broad pre-approval. - Dynamic context may execute shell commands during rendering.
- Bundled scripts may access files, the network, or credentials.
- References may contain prompt injection.
- Hooks may run at tool lifecycle events.
Treat .claude/skills/ more like executable development configuration than a folder of quotes. Do not assume workspace trust protects the allowed-tools field. Current Claude Code documentation explicitly says workspace trust does not gate that field: a project Skill can grant pre-approval even in a non-interactive run from a folder not previously trusted. This corrects a common but dangerous assumption.
Before running a third-party Skill, inspect its instructions, injected shell commands, tool grants and exclusions, scripts and their credential access, reference sources, hooks, and plugin update path. Treat installing a Skill more like installing software than saving a prompt snippet.
Dynamic shell executes before Claude reads
Part 5 covered the !commandform, such as `!`git diff --stat. For eligible local Skills, it executes before rendered instructions reach Claude. Even as “context preprocessing,” it is real shell execution.
The disableSkillShellExecution setting lets an organization permit prompt-based workflows while preventing dynamic shell expansion for user, project, plugin, and additional-directory Skills. Authors can move the command into an explicit tool step, returning it to the ordinary approval and audit path. One extra agent-loop step buys clearer control.
Hooks turn guidance into a checkpoint
An instruction can say, “Before every Bash call, check whether the command touches production.” That guides Claude, but it might misinterpret or omit the check. A Skill-scoped Hook can run at a fixed tool event:
Skill active ↓ Claude requests Bash ↓ PreToolUse Hook ├─ allow ├─ require approval └─ block Hooks suit dangerous-command interception, argument validation, post-edit formatting, end-of-workflow verification, or audit logging. Their timing is deterministic; their implementation is still code that needs validation and maintenance. Moving risk from a prompt to an unaudited shell Hook is not automatically safer.
A Skill tells Claude how to work; a Hook makes a lifecycle check happen at a defined point.
A sandbox constrains execution beyond tool policy
Permission policy decides whether a particular operation may be initiated. A sandbox decides what that operation can actually touch after it is allowed:
Permission layer → may run the command Sandbox layer → limits writable paths and network access OS/container → limits identity and system resources For highly automated Skills, a sandbox can be more reliable than repeated approval prompts: define a safe work area and permit work within it. But a sandbox does not decide business authorization. Network access does not imply permission to call a production API; a local kubeconfig does not imply a Skill should deploy to production.
The external service has the final authority
A Skill may call an MCP tool, cloud CLI, or API:
Local Skill/tool policy → may Claude request the deploy tool? Client credential → which identity makes the request? Service-side authorization → which environments may that identity deploy to? Local allow rules affect Claude Code's handling of the call. Data scope, write privileges, and audit logs ultimately belong to the external service. Sensitive Skills should use least-privilege credentials: separate staging and production, use read-only tokens for reads, require server-side approval for destructive actions, and treat external tool results as untrusted data. Instructions can orchestrate authorization; they cannot replace it.
Managed instructions are not absolute enforcement
An organization can distribute managed Skills for compliance checks, security reviews, shared references, and centrally updated workflows. That standardizes behavior. Yet “never upload sensitive data” written only in a managed Skill remains a prompt instruction. Enforce the restriction with deny rules, network policy, sandboxing, DLP, and service-side authorization when needed.
Managed instructions provide durable guidance; deterministic controls carry the hard boundary. The same distinction will matter in the later Memory series discussion of managed CLAUDE.md.
A compact security matrix
| Mechanism | Controls | Lifetime | Does not guarantee |
|---|---|---|---|
disable-model-invocation | Claude's proactive Skill invocation | Skill definition | Users cannot invoke it; file is unreadable |
user-invocable | Direct user entry | Skill definition | Claude cannot invoke it |
Skill(name) rule | Named Skill call | Permission policy | Its tool calls are safe |
allowed-tools | Temporary no-prompt access | Invoking turn | Only those tools exist; permanent grant |
disallowed-tools | Temporary tool removal | Invoking turn | OS isolation; no indirect side effects |
| Hook | Check at a defined event | Skill/session lifecycle | Hook code is correct |
| Sandbox | Filesystem/network reach | Process/session | Business authorization is correct |
| External auth | Server-side resource access | Credential/policy | Prompt injection cannot occur |
Review each row rather than declaring a Skill safe because one field looks reassuring.
Defense in depth for a production-deploy Skill
Entry point disable-model-invocation: true; user invokes explicitly Instructions validate environment, version, and approval state do not deploy before confirmation Tool permissions pre-approve read-only checks only require approval for the actual deploy Hooks PreToolUse validates the target environment Sandbox and credentials staging access by default separate, short-lived production authority External service RBAC, audit log, and rollback If one layer fails, another can still block the action. This is more credible than a stern paragraph in a prompt.
Skill security is a chain from intent to execution: invocation controls who can start; tool policy controls how actions are requested; Hooks ensure checks happen; sandboxes and external authorization determine what actions can actually reach.
Up next
After a Skill is discovered, invoked, and executed, do its instructions remain on the next turn? Does editing the file affect an already-loaded copy? How much survives compaction? Part 8 separates the source file, invocation record, conversation content, and post-compaction recovery.
References
- Claude Code documentation: Skill tool approval, invocation, and execution controls
- Claude Code documentation: Permissions and sandboxing
- Claude Code documentation: Hooks
- Previous article: From Inline to Forked Subagents
- Related Agent Loop article: From Tool Declarations to Pre-Execution Approval
- Related Agent Loop article: Hooks as Programmable Intervention Points