How to tell if a Claude Code plugin is safe? We test ModVet, the scanner that reviews it before installation

To know if a Claude Code plugin is safe, check what it’s going to run before you install it: its hooks, its mods, its MCP servers, and its bin/ folder, because all of that runs on your machine with your user permissions. ModVet, an open source security scanner published on PyPI this week, automates the first pass of that review: it works offline, without an LLM, and reports each suspicious line with its OWASP MCP Top 10 code. We tested it alongside the validator that Claude Code already includes, on official Anthropic plugins and mods. It detects classic attack primitives well, makes noise with legitimate code, and can’t tell you what intention a code snippet has.

:white_check_mark: yoDEV Tested · October 20, 2026 We ran ModVet 0.2.2 and claude plugin validate (Claude Code 2.1.304) on Linux with Python 3.13 on 13 official Anthropic plugins and 4 mods, ModVet’s own test fixtures, and the dsh-our-free-model repository. The results we report as ours come from that test.

How we tested it. We scanned the clean and malicious test fixtures that come in ModVet’s repository; the 13 plugins from plugins/ and the four built-in mods from mods/ in the anthropics/claude-code repository, at commit a6e289a (October 19, 2026); and the dsh-our-free-model repository at commit 49171b9, which we had already reviewed by hand. Neither tool executes what it analyzes, and neither did we: we didn’t install anything we scanned or write malicious code for the test. The malicious fixture is from the author and is inert: its download URL uses the reserved domain evil.example and its base64 payload decodes to echo "bad".

Why do you need to review a Claude Code plugin before installing it?

Because Anthropic’s own documentation says that a plugin you install can run arbitrary code on your machine with your user privileges. A plugin can bring:

  • Hooks: shell commands that run at different points in Claude Code’s lifecycle, for example before or after a tool call.
  • Monitors: background shell commands that Claude Code starts on its own.
  • Mods: JavaScript code that runs inside Claude Code with your permissions.
  • MCP and LSP servers: a stdio MCP server runs as a process that Claude Code starts on your machine.
  • A bin/ folder: gets added to the PATH of the Bash tool’s shell.
  • Skills, commands, and agents: enter Claude’s context as instructions.

The most important thing is what’s not covered. Claude Code’s permission rules and sandbox apply to tool calls that Claude makes, not to code that the plugin runs on its own: hooks, monitors, MCP and LSP servers, and processes started by a mod run outside the sandbox. And if automatic updates are turned on for the marketplace, the files you reviewed can change on disk after installation.

https://code.claude.com/docs/plugins/security

What is a Claude Code mod?

A mod is a plugin that changes Claude Code’s appearance and behavior through event handlers written in JavaScript or TypeScript. Claude Code calls them when an event occurs, like a tool call, a submitted prompt, or a part of the interface being drawn, and the handler can observe the event, modify it, or respond to it on its own. Mods require Claude Code v2.1.287 or later and come enabled by default; some of Claude Code’s own features, like /diff, are mods.

That’s why it’s the component worth reviewing most. According to the documentation, once a mod is loaded it can read and write files where your user can, read your environment variables and API keys, see every prompt and every tool call, rewrite them, approve a tool call before you’re asked, and call a model with your plan. It doesn’t run in a sandbox.

That’s exactly ModVet’s territory, whose README introduces itself as the way to review your Claude Code mods before installing them. Several of its detectors target what only a mod can do, like rewriting the prompt before sending it or the arguments to a tool call.

How do you review a Claude Code plugin without installing it?

Claude Code already includes a manual review path, and it’s worth taking before turning to any third-party tool:

  1. Run claude plugin marketplace list in your shell to see where each marketplace comes from.
  2. In a session, run /plugin and select the plugin. The details pane shows, under Will install, its commands, agents, skills, hooks, and MCP and LSP servers.
  3. The pane indicates that a hook exists, but not what it runs. For that, read hooks/hooks.json, .mcp.json, and each file in bin/.
  4. With the repository cloned, claude --plugin-dir <plugin directory> plugin details <plugin name> prints a Component inventory without starting a session.
  5. If the plugin brings a mod, claude plugin validate <plugin directory> lists, without running it, what events it handles and what it asks Claude Code to do.

Step 5 is the most revealing. In the built-in diff mod, the output includes these lines (trimmed):

> ./register.ts hooks: session.start, ui.render{component=PromptHint}, ui.render{component=Pane}, command.run{command=diff}, ... tool.call{tool=?|?}, prompt.submit
> ./register.ts calls: $.clock.after, ... $.env.get, $.fs.list, $.fs.read, $.fs.stat, $.process.run, $.session.id, $.session.messages, ...
> ./register.ts env writes: nothing
> ./register.ts env reads: CLAUDE_CODE_DISABLE_FILE_CHECKPOINTING

A mod can only read files, start processes, or make network requests through the mods API, and that’s why Claude Code can list those calls before you install it. If a mod that says it’s drawing a panel shows up calling $.process.run and reading environment variables, you already know what to ask.

Only marketplaces from github.com/anthropics/ can use official or community names, so a third-party catalog can’t pretend to be an Anthropic one. But a marketplace name tells you who publishes the catalog, not what each plugin does.

What is ModVet?

ModVet is a deterministic security scanner to review Claude Code mods and plugins before installing them. It’s written in Python by Jörg Michno, licensed Apache-2.0, has no dependencies, and its engine comes from an earlier project by the same author, ClawGuard. It walks through a plugin’s directory and looks for three types of problem:

  • Prompt injection and instructions trying to override the agent’s: about 400 patterns in English and German, with normalization of homoglyphs, leetspeak, base64, zero-width characters, and reversed text.
  • Dangerous capabilities in combination: a fetch or a read of process.env on their own are normal plugin work, so it only reports combinations in the same expression, like reading environment variables and also sending a POST. It also marks attack primitives directly: chained downloads to a shell, base64 decoded to a shell, reverse shells, hooks that elevate permissions, configuration rewriting, .env files included in the repository, and npm lifecycle scripts.
  • Hardcoded secrets: API key and token patterns.

Each finding includes a reference to the OWASP MCP Top 10 (from MCP01 to MCP10) in the owasp_mcp field of the report JSON. Output can be human-readable, JSON, or SARIF 2.1.0 for GitHub Code Scanning, and exit codes let you use it in CI.

No account, no network, and no LLM. It’s the design choice that makes sense here: what you’re scanning isn’t trusted, and asking a model to judge it gives the plugin a chance to talk to the judge.

How do you install and use ModVet?

It installs from PyPI (requires Python 3.9 or later):

pip install modvet

To scan a plugin’s directory:

modvet scan ./my-plugin                    # readable report
modvet scan ./my-plugin --json             # machine report
modvet scan ./my-plugin --format sarif     # for GitHub Code Scanning
modvet scan ./my-plugin --fail-on CRITICAL # fail only on CRITICAL findings

Exit codes: 0 clean, 1 findings equal to or greater than --fail-on (default HIGH), 2 usage error.

To scan a plugin you’ve already installed, point it to the installed copy, which Claude Code keeps in ~/.claude/plugins/cache/<marketplace>/<plugin>/<version>/.

For updates, ModVet has two more commands: modvet snapshot ./my-plugin records a baseline after a clean install, and modvet diff ./my-plugin --against .modvet-snapshot.json audits only what changed. Since automatic updates can change files after you review them, that’s the tool’s most useful idea. The author sums it up in one sentence: “the update is the attack”.

What does ModVet detect? Prompt injection, secrets, and dangerous commands

In the author’s malicious fixture, everything we expected. The clean fixture returns 0 findings and exit code 0. The malicious one returns 9 findings, a risk score of 10/10, and exit code 1:

Finding Severity OWASP MCP
Ignore previous instructions in a system prompt CRITICAL MCP01
Hardcoded key sk-… CRITICAL MCP03
Reading environment variables + HTTP POST (exfiltration path) HIGH MCP03
curl … | sh CRITICAL MCP05
base64 -d | sh CRITICAL MCP03
mcpServers declared in .mcp.json MEDIUM MCP08

For each one, the report shows the detected text, the line, and a recommended action. In a plugin built to trigger the rules, it triggers them all.

One nuance: that fixture is synthetic and doesn’t follow the documented format of a Claude Code mod. claude plugin validate rejects it because it has no .claude-plugin/plugin.json. That doesn’t reduce the value of the detectors, which search for patterns in any file, but it means the author’s demo doesn’t say anything about how ModVet behaves with real mods. We did the following test for that.

Does ModVet flag Claude Code’s official plugins and mods as dangerous?

Yes, some of them. Of the 13 official plugins, nine came out clean, including code-review, feature-dev, and pr-review-toolkit. Of the four built-in mods, two came out clean: agents-md and telemetry. These fail with the default threshold:

Plugin or mod Findings Max severity
hookify (plugin) 5 HIGH
ralph-wiggum (plugin) 4 HIGH
plugin-dev (plugin) 11 CRITICAL
security-guidance (plugin) 83 CRITICAL
diff (built-in mod) 4 HIGH
sec-default (built-in mod) 5 CRITICAL

The HIGH and CRITICAL findings we reviewed were false positives:

  • In plugin-dev and ralph-wiggum, shell lines like echo "$SYSTEM_PROMPT" are interpreted as “instruction replay”, and a Markdown heading **Critical rules:** triggers an “instruction header injection” rule.
  • In the diff and sec-default mods, all alerts come from code comments and test files: a phrase about a git rule, the description of a tool mentioned in a comment, a test fixture.
  • security-guidance is the extreme case: it documents dangerous patterns (eval(), verify=False, !!python/object) to warn about them, and the scanner doesn’t distinguish between documenting a risk and the risk itself.

It’s the cost of pattern-based deterministic detection, and it’s worth knowing before putting ModVet in CI: with the default --fail-on HIGH, it would have blocked four Anthropic plugins and two mods. The author reports that false positives in 12 repositories dropped from 1,815 to under 300 between engine v0.1 and the current one. That’s his own benchmark, on repositories he chose, and it’s consistent with what we saw: it makes noise, but it’s no longer unusable.

ModVet or claude plugin validate?

Both, because they answer different questions. claude plugin validate is an inventory of capabilities: it tells you what events a mod handles and what it will ask Claude Code to do, like read files, start processes, or read environment variables, and it doesn’t give you an opinion on whether that’s malicious. ModVet is a pattern detector: it searches the text for known attack forms, like curl | sh or an instruction to ignore the system prompt, but it doesn’t inventory calls to the mods API.

In our test they complemented each other well. The validator showed that the diff mod calls $.process.run and reads environment variables, something that makes sense for a panel showing git changes and that ModVet didn’t mention. ModVet, for its part, judges what the validator doesn’t claim to judge: whether there are hardcoded secrets, dangerous shell commands, or prompt injection text in any file in the plugin.

What can’t a security scanner like ModVet see?

Intention. Earlier this week we read the code of dsh-our-free-model, a plugin for DeepSeek Harness, by hand, and found that its index.js imports a “channel pack” bundled on every startup, with no setting to disable it. That import was the central finding of our review.

ModVet doesn’t flag it. In that same index.js it reports three findings, two of them CRITICAL of type “Secret Assignment” on text templates in code examples (api_key="${shownKey}"), which are false positives. The important import is a completely normal line of JavaScript. A fair clarification: that plugin isn’t for Claude Code, so it’s outside ModVet’s declared scope. But the limitation is general. A pattern-based scanner recognizes known attack forms; it can’t tell you that a legitimate-looking import loads 2.9 MB of code that operates account pools against other providers.

Two practical limits also showed up:

  • Speed depends on size. The README’s “in milliseconds” didn’t hold up on our machine. code-review took about 0.6 seconds including Python startup, the built-in mods between 3 and 26 seconds, and security-guidance about 11 seconds. A single 500 KB JavaScript file took 15 seconds, and the complete dsh-our-free-model repository, 25 MB, hadn’t finished after 10 minutes, so we stopped it.
  • Part of the output is in German. The “Context” and “Action” lines for many findings, and half the README, are in German. The severity, the pattern name, and the OWASP code are understandable in any language, but you might need a translator for the explanation.

ModVet or Snyk?

According to ModVet’s own README comparison table, the difference is model: Snyk scans MCP servers and skills within a broader DevSecOps platform, with a cloud account and SaaS pricing, while ModVet runs local and offline, no account, and each rule is visible in open source. ModVet adds snapshot and diff to audit only changes from each update. We didn’t test Snyk for this note, so take that as the author’s comparison, not ours.

Does ModVet scan skills and MCP servers?

Not yet in a dedicated way, as of October 20, 2026. ModVet 0.2.2 scans mod and plugin directories; its prompt injection patterns read any text file, but the README presents dedicated scanning of SKILL.md and MCP servers as the next step, and mentions a possible Pro or audit offering “after traction”, with no further details. The project is days old: it uploaded three versions to PyPI on October 19, has no releases on GitHub, and has no documentation beyond the README and the specs/ folder. If what you need to review are skills, NVIDIA’s SkillSpector tackles that problem: SkillSpector: NVIDIA Wants to Scan Your Skills Before You Install Them.

So, how do you decide if a Claude Code plugin is safe?

Use ModVet as a first filter, not as a verdict:

  1. Review where it comes from with claude plugin marketplace list and the /plugin details pane.
  2. If it brings a mod, run claude plugin validate and compare the calls it lists with what the plugin says it does.
  3. Run modvet scan on the cloned plugin. A clean result means it found no known attack primitives. A CRITICAL for curl | sh, base64 -d | sh, or environment read plus POST deserves careful review.
  4. Read each finding in context. Many will be comments, documentation, examples, or test files.
  5. Read the hooks, .mcp.json, bin/, and the mod code yourself anyway. That’s where neither tool can judge intention.
  6. Take a snapshot after installing with modvet snapshot and run modvet diff after each update, or turn off automatic updates for that marketplace.

In CI, consider using --fail-on CRITICAL instead of the default, so a plugin that documents risks doesn’t block your pipeline.


What about you? What’s the first thing you check before installing a Claude Code plugin?

Before installing a third-party plugin or mod, I usually…
  • Install it if the marketplace looks trustworthy
  • Read the hooks, scripts, and mod code
  • Run it through a validator or scanner
  • Do something else (tell us what)
0 votantes

Comment below or, if this article reached you by email, reply directly to the email: your answer is posted here.

Related: Is dsh-our-free-model safe? What we found reading the code of the “free” plugin for DeepSeek Harness

1 Like