SKILL 30 / SAFETY · DEEP DIVE

How Risky Is Installing Another Person's Skill

Two paths: it executes code as you, or it rewrites your instructions as a document — and neither one goes through the sandbox

2026-10-01 · BigCat

The official page gives away the answer in its first sentence: "A Claude Code plugin you install can execute arbitrary code on your machine with your user privileges." This issue gives you three commands you can run today, the official four-step review, what each trust tier actually guarantees, and the least intuitive part — you don't have to install anything at all. A git clone and one claude -p is enough.

Same series → Skill 12, the security boundary when you wire up MCP · Skill 29, safety & governance roundup

// WHY THIS MATTERS

Skills and plugins are already a link in your software supply chain; nobody manages them like a dependency. NVIDIA's own scanner puts an uncomfortable number in its README: in the analyzed subset of their research dataset, 26.1% of skills contain vulnerabilities and 5.2% show likely malicious intent (per the NVIDIA/SkillSpector GitHub repository page, 2026-10). This issue doesn't stop at the scare: the runnable intake pipeline comes first, the criteria come later, and the criteria exist to choose among the tools named here.

// 01

What it kills for you: turning "invisible before install" into "itemized before install"

The claim: reviewing a third-party skill doesn't require you to read vulnerabilities. It requires listing what the thing wants to put on your machine. Four commands already do that.
# 1. Inventory what is ALREADY on this machine (covers a dozen-plus clients)
uvx snyk-agent-scan@latest

# 2. For the next candidate: static scan (--no-llm = no model calls, static only)
uv tool install git+https://github.com/NVIDIA/skillspector.git
skillspector scan ./candidate-skill/ --no-llm

# 3. Official: no session, just list what it would add
claude --plugin-dir ./that-plugin plugin details <plugin-name>

# 4. Structural check — note it validates structure, not safety
claude plugin validate ./that-plugin

What each one kills, and when not to use it

The pane says "there is a hook." It does not say what the hook runs. That's why the official review steps name three files to read by hand: hooks/hooks.json (the command each hook actually executes), .mcp.json (each server's command or URL), and bin/ (every file in the directory). Until you've read those three, the commands above are just a warm-up.
// 02

Mechanism: why permission rules and the sandbox don't catch this

The claim: the danger isn't that a plugin can call tools. It's that half of what a plugin carries never travels as a tool call at all — and the sandbox and permission rules can't see that half.

The code-execution path (four entry points)

The official boundary is blunt: permission rules and the sandbox cover the tool calls Claude makes, not the code a plugin runs by itself — Claude Code runs hooks and MCP servers outside the sandbox, with your full user permissions. Only when Claude uses Bash to run an executable from bin/ is that a tool call, and only then do your permission rules apply.

The instruction-injection path (harder to defend)

Skills, slash commands and agents don't execute code. They enter Claude's context as instructions and change what the model does with the tools it already has. And a skill's allowed-tools can grant itself access: the docs say plainly that workspace trust doesn't gate that field — "A skill can grant itself broad tool access, so review the allowed-tools of skills checked into a repository before you run Claude Code there." The ! command lines in a skill body are the same story: they run on your machine before the content reaches the model.

The least intuitive part: you don't have to install anything. In the official table of what runs before you trust a folder — a project skill's hooks and allowed-tools: Used (used even in a claude -p run in a folder you've never trusted); servers in .mcp.json: under -p, connected without asking, approved or not; and permissions.allow: Not used until you accept the dialog. The dangerous half applies by default; the half that protects you does not.

So run an unfamiliar repository like this

# Cheapest one-shot: read no project-side customization at all
claude --bare -p "review the structure of this repo"
# Or turn things off piecemeal: user settings only / all hooks off / reject one server
claude --setting-sources user -p "…"
claude --settings '{"disableAllHooks": true}' -p "…"
# Two standing settings: kill shell execution in skill bodies; deny a skill by name
{ "disableSkillShellExecution": true,
  "permissions": { "deny": ["Skill(skill:deploy)"] } }

Putting disableAllHooks in your user settings isn't enough — project settings take precedence and can set it back to false, so pass it via --settings. In deny rules, a bare Skill removes the whole tool from the model's context; the Skill(skill:<name>) form matches that one skill under any of its names.

// 03

Use and limits: what each trust tier guarantees, and how to pin a version

The claim: a trust tier only decides how much reviewing you still owe. It never replaces per-plugin review — the docs say it themselves: a marketplace's name tells you who publishes the catalog, not what each plugin in it does.
Tier Marketplace name Reviewed by Auto-update What you still do ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Official claude-plugins-official + 13 Anthropic, or On (2 excl.) Read the Will install other reserved names (agent- its partners pane; note it self-updates skills / life-sciences / …) Community claude-community Submitted via Off Automated scan is not (repo anthropics/claude- claude.ai, auto- per-item human review; plugins-community) scanned, approved entries pin a commit SHA Third-party everything else (a coworker's, nobody Off The full four steps: pane → your own) source → hooks.json / .mcp.json / bin/ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Impersonation can't get in: Claude Code accepts the official and community names only for marketplaces sourced from github.com/anthropics/. Right name, wrong source → the whole marketplace stops loading, and so do the plugins you already installed from it.

The community catalog states its guarantee concretely in the README: every plugin listed there was submitted via claude.ai, "passed automated security scanning, and been approved for distribution." The repository itself is a read-only mirror, direct pull requests are closed automatically, and it syncs nightly from the internal pipeline. The hard constraint lives client-side: that catalog pins a commit SHA for nearly every entry, and Claude Code refuses to install a different commit. The third-party tier has none of this — in Anthropic's words, Anthropic doesn't review third-party marketplaces.

Reviewed-then-changed: pin the version

Uninstalling is not cleaning up

After claude plugin uninstall <plugin> --scope <the scope you installed at>, its files stay under ~/.claude/plugins/cache/ for fourteen days before a background sweep removes them; delete that directory yourself if you want them gone now. If it's the owner you distrust, remove the marketplace too — that uninstalls every plugin you got from it.

Team side: six named managed-settings keys

strictKnownMarketplaces (source allowlist, alias allowedMarketplaces; an empty [] blocks the official one too) · blockedMarketplaces (blocklist, checked before the allowlist) · disableSideloadFlags (rejects --plugin-dir, --plugin-url, --agents and CLAUDE_CODE_PLUGIN_DIRS) · strictPluginOnlyCustomization (allows skills / agents / hooks / mcp only from a plugin, managed settings or the built-ins) · allowManagedHooksOnly · pluginTrustMessage (appends your own text to the pre-install trust warning).

// 04

Cost and alternatives: a scanner gives you leads, not a verdict

The claim: the real cost of this class isn't false positives. It's that a risk score looks far too much like a green checkmark. And the cheapest alternative was always there: copy the body, don't install the thing.

Two costs to book

Not installing it: what else you can do (cheapest first)

  1. Copy, don't install. Read its SKILL.md and copy the twenty lines that actually help into your own .claude/skills/ — without its hooks, without bin/, without the MCP server it drags along. For methodology-style skills the value is almost entirely in the body, and the body is the one part you can read end to end.
  2. Try it once. claude --plugin-dir ./that-plugin loads it for one session only and never writes to enabledPlugins (note: this is rejected where a team sets disableSideloadFlags).
  3. Read the official ones first, to calibrate "normal." anthropics/skills (about 179k stars per its GitHub repository page, 2026-10; mostly Apache-2.0, with the docx/pdf/pptx/xlsx set source-available) and anthropics/claude-plugins-official. Only after reading a few normal ones can you see why the third-party one has an extra hook.
Locking down has a cost too. strictKnownMarketplaces: [] blocks the official marketplace along with everything else, and setting any allowlist without a {"source": "skills-dir"} entry stops your own plugins under ~/.claude/skills/ that carry a .claude-plugin/plugin.json from loading (a plain SKILL.md is unaffected). And once a machine has started under a policy that blocked the official marketplace, Claude Code records the blocked attempt and won't retry registration after you change the policy back.
Even Anthropic doesn't present its own skills as finished goods: the anthropics/skills README says these skills are "provided for demonstration and educational purposes only" and asks you to "always test skills thoroughly in your own environment before relying on them for critical tasks." A star count is not a security property.

// ONE-PAGE ACTION CARD

Do these three today: 1. uvx snyk-agent-scan@latest — inventory what's already on the machine; most people discover something here they forgot installing. 2. Run the next third-party candidate through the sequence: skillspector scan ./x --no-llm → claude --plugin-dir ./x plugin details <name> → read hooks/hooks.json, .mcp.json and bin/ by hand. 3. Write two standing settings: "disableSkillShellExecution": true, and leave auto-update off for third-party marketplaces (off is the default).

Add as needed: claude plugin validate (you publish a marketplace) · strictKnownMarketplaces + disableSideloadFlags (you set team policy) · a Skill(skill:<name>) deny rule (keep a skill but stop the model from firing it) · claude --bare -p (you run non-interactively in an unfamiliar repo) · trailofbits/mcp-context-protector (it ships an MCP server and you want pin-on-first-trust).

Explicitly don't: run a bare claude -p in an unfamiliar repo · treat "passed the scan" as "safe" · assume more stars means safer · turn auto-update on for a third-party marketplace · put --dangerously-run-mcp-servers in a script · uninstall the plugin but keep the marketplace · read the Will install pane and think you've read the hook · leave disableAllHooks only in your user settings.

// GLOSSARY

workspace trust
The trust dialog you get the first time you start an interactive session in a folder. It gates things that grant the repository more power, such as permissions.allow. It does not gate hooks or a skill's allowed-tools.
Component inventory
The listing claude plugin details prints: skills and commands, agents, hooks with each hook's event, and MCP and LSP servers. Available before install via --plugin-dir.
reserved marketplace names
The fourteen names that belong to Anthropic's marketplaces. A marketplace using one of them whose source isn't under github.com/anthropics/ is refused, so third parties can't impersonate one.
reviewed-then-changed (TOCTOU)
The content changes between the moment you review it and the moment it runs. In plugins this comes from auto-update; the answer is to turn it off and pin a #ref or a sha256.
allowed-tools
A skill frontmatter field that pre-approves a set of tools for the turn that invokes the skill, with no prompt. It only widens, never narrows — and workspace trust doesn't gate it.
skills-dir plugin
One kept under ~/.claude/skills/ or a project's .claude/skills/ with a .claude-plugin/plugin.json. Set a marketplace allowlist and you must add {"source": "skills-dir"} or these stop loading.

// THREE THINGS THAT DON'T ADD UP

If the community catalog already passed automated security scanning, why review it again?
Because "passed an automated scan" and "someone understood what it intends to do" are different claims, and the first one's limits are exactly the list SkillSpector publishes about itself: static, English, no runtime. More importantly, a scanner can't judge intent match — a plugin that claims to format code shipping a hook that makes outbound requests is entirely legal pattern-wise. So read the tiers as "how much review is still owed": the official tier owes you a glance at Will install, the community tier owes you "why does it need this hook," the third-party tier owes the full four steps. The community catalog's real hard guarantee is a different one — entries pin a commit SHA, so the version you reviewed is the version you install. That's worth more than the scan verdict.
A skill is just text. Why is it harder to defend against than an MCP server?
Because an MCP server is a process, and processes have boundaries you can argue about: put it in a container, restrict egress, run it read-only, use fully qualified names — the whole panel of knobs from Skill 12 still applies. A skill has no process. It becomes the model's instructions directly, and "should the model obey this paragraph" has no syscall-level enforcement point. Worse, it looks harmless: one Markdown file, a short diff, easy to skim past in review. That's the real asymmetry — MCP risk you can configure away; skill risk you can only read away. Which is why the only gate that works for this class is "I read the body," and why "copy, don't install" isn't settling — it's the sane default at this layer.
SkillSpector scored it 70. Should I install it?
That's the wrong question, and wrong in a very typical way: a risk score is lead density, not a conclusion. Use it to decide how long to look — low score, spot-check three files; high score, read line by line or walk away. The questions worth answering are concrete: which file do the hits land in (a hit in a hook or in bin/ is a different order of magnitude from wording in the body), does the feature it claims require that capability, and what do you lose by not installing it. The third one usually decides it. Most of the time the answer is "twenty lines of prompt," and then how to read a 70 never comes up.

// FURTHER READING