Server data from the Official MCP Registry
Audit MCP servers for tool poisoning, rug pulls and supply-chain risk (OWASP MCP Top 10).
About
Audit MCP servers for tool poisoning, rug pulls and supply-chain risk (OWASP MCP Top 10).
Security Report
Valid MCP server (2 strong, 1 medium validity signals). No known CVEs in dependencies. Package registry verified. Imported from the Official MCP Registry.
5 files analyzed · 1 issue found
Security scores are indicators to help you make informed decisions, not guarantees. Always review permissions before connecting any MCP server.
Permissions Required
This plugin requests these system permissions. Most are normal for its category.
How to Install
Add this to your MCP configuration file:
{
"mcpServers": {
"io-github-petrovicistefan-mcp-security-guard": {
"args": [
"-y",
"mcp-security-guard"
],
"command": "npx"
}
}
}Documentation
View on GitHubFrom the project's GitHub README.
mcp-security-guard
A Claude Code plugin that audits the MCP servers you have installed. Your code is covered by other tools. This one checks the servers that inject text into Claude's context.
| Check | What it catches |
|---|---|
| Tool poisoning | Instruction overrides, "don't tell the user", <IMPORTANT> tags, directives to read secrets (~/.ssh, .env), conversation harvesting, exfiltration via URLs, parameters and Markdown images, HTML comments, encoded payloads |
| Full-schema poisoning | The same checks on parameter names, descriptions, defaults, enums, required, plus non-schema text in type |
| Hidden text | Zero-width, bidi-control and Unicode-tag characters, ANSI terminal escapes, homoglyph tool names |
| Tool shadowing | A server whose descriptions reference another server's tools, and tool-name collisions between servers |
| Rug pulls | Tool definitions or launch commands that changed after you pinned them (SHA-256 per tool), and skills, commands, subagents, CLAUDE.md and hooks of a plugin or repository that changed after you pinned them (a plugin that changes files under the same version is flagged high). Re-checked automatically at every session start |
| Capabilities & score | Per-tool classification (execute, delete, write, egress), unauthenticated remote write access, 0–100 score and A–F grade per server, recommended permission rules |
| Supply chain | OSV vulnerabilities and malicious versions, typosquats, missing or brand-new packages, install scripts, publisher changes (opt-in network check) |
| Runtime | Hooks on every MCP call: ask before credentials are sent, warn on injected instructions or credentials in outputs, content-free audit log |
| Policy | .mcp-security.json approved/blocked servers and hosts, enforced in audits, CI and at session start |
| Toxic flows | Servers that hold all three legs of the "lethal trifecta" (untrusted input, private data, a way to send data out), on their own or together, with the tools to put behind approval. A posture note (low or info), not a defect |
| Agent context | The text Claude reads besides MCP tools: skills and their scripts, slash commands, subagents, rules, CLAUDE.md and plugin hooks. Instruction overrides, "don't tell the user", invisible text, HTML comments addressed to the model, directives to read credential files, commands that upload credentials, download-and-run, encoded execution, infostealer scripts, pre-approved unrestricted Bash |
| Configuration | Plaintext secrets in env/headers/args/URLs, plain-HTTP remotes, unpinned npx/uvx packages, privileged or unpinned Docker images, pipe-to-shell launches, duplicate names across scopes |
It discovers servers from every place Claude Code and Claude Desktop load them: user, local and project scope, servers shipped inside installed plugins and plugins synced from your claude.ai account (named <plugin>:<server>), claude_desktop_config.json and Claude Desktop extensions, the organisation-managed managed-mcp.json, other clients on the machine (Cursor, VS Code, Windsurf, user and project configs), and the claude.ai connectors you have used (names only: their configuration lives in your account).
It scans everything a server puts into Claude's context, not only tools: server instructions, prompts, resources and resource templates go through the same poisoning checks and are pinned for rug-pull detection.
Everything runs locally. Nothing is sent anywhere.
OWASP MCP Top 10 coverage
Every finding is tagged with its OWASP MCP Top 10 id, in reports and in SARIF.
| ID | Risk | Covered by |
|---|---|---|
| MCP01 | Token Mismanagement & Secret Exposure | ✅ Plaintext secrets in env, headers, args and URLs. At runtime, asks before a credential is sent to an MCP server and warns when one comes back. |
| MCP02 | Privilege Escalation via Scope Creep | ✅ Capability inventory (execute, delete, write, egress), ready-to-paste permissions.ask rules, privileged or broadly mounted containers |
| MCP03 | Tool Poisoning | ✅ 26/27 published techniques detected, including full-schema poisoning, shadowing and name collisions, plus rug-pull pinning |
| MCP04 | Supply Chain Attacks | ✅ Unpinned packages, images and git sources; OSV vulnerabilities and malicious versions; typosquats; new packages; install scripts; publisher changes |
| MCP05 | Command Injection & Execution | ✅ Flags tools that can execute commands; adversarial_test finds injectable parameters in servers you own |
| MCP06 | Prompt Injection via Contextual Payloads | ✅ In tool metadata and, at runtime, in tool outputs (English patterns) |
| MCP07 | Insufficient AuthN/AuthZ | ✅ Plain-HTTP remotes; remote servers exposing write or exec tools without authentication; OAuth detection |
| MCP08 | Lack of Audit and Telemetry | ✅ Local, content-free audit log of every MCP call, with query_audit_log |
| MCP09 | Shadow MCP Servers | ✅ Discovery across user, project, local, plugin and Claude Desktop configs; approved-server policy enforced in audits, CI and at session start |
| MCP10 | Context Injection & Over-Sharing | ✅ Conversation and system-prompt harvesting, Markdown-image exfiltration, credentials in outputs, network-egress inventory |
What a local tool cannot do (planned for a hosted Team plan): org-wide discovery and audit aggregation, and OAuth scope review.
Measured: detects 26/27 attacks from a corpus of publicly documented techniques, with 0 false positives on 13 hard benign samples and on 17 real servers (83 tools). See bench/RESULTS.md.
Install
/plugin marketplace add petrovicistefan/mcp-security-guard
/plugin install mcp-security-guard@mcp-security-guard
Then run /mcp-audit, or ask Claude "are my MCP servers safe?".
Other MCP clients (Cursor, VS Code, Windsurf, Claude Desktop, Cline, ...)
The same server is published on npm and runs with no install step:
{ "mcpServers": { "mcp-security-guard": { "command": "npx", "args": ["-y", "mcp-security-guard"] } } }
The command line tool is the same package: npx mcp-security-guard audit --project-only. It is also listed in the official MCP Registry as io.github.petrovicistefan/mcp-security-guard.
Team plan (paid, opt-in)
Team keys are issued by hand for now: write to me. With a team API key (MCP_SECURITY_API_KEY, or the key setting of the plugin) the plugin can also work with your organisation. Everything below is off without a key, and the free plugin stays fully functional.
- Central policy. An admin pushes one policy (allowed and blocked servers, remote hosts, plugins, pinned versions). Every member's plugin fetches it at session start (at most hourly, cached, enforced even when offline) and enforces it next to their own and the project's policy: a repository's
.mcp-security.jsoncannot loosen it. - Approved plugins.
allowedPluginsandblockedPluginsin a policy are enforced in audits, CI and at session start; a blocked plugin iscritical, an unlisted onehigh. - Fleet inventory, only with consent.
team reportsends which servers and plugins you run: names, scopes, transport, package names and versions or remote hostnames, pinned or not. Never paths, arguments, environment, headers, query strings or secrets. Reports are refused until an admin turns fleet visibility on,team report --dry-runshows exactly what would be sent, and sending at session start needsMCP_SECURITY_TEAM_REPORT=on. - Approval flow.
team request server project:linearasks the admin;team approveadds it to the policy's allow list for everyone. Alerts (new request, new violation, policy change) go to a Slack-compatible webhook. - Keys and seats. An admin creates a key per developer (
team keys create ana, shown once; only its hash is stored) and revokes it (team keys revoke); a purchase sets the seat limit. The same admin actions are in the web dashboard (/v1/team/dashboardon the service: fleet, approvals, policy, keys, settings; the key is typed in, kept in the browser tab only, and every value from the service is written as text). - Alerts by email (
team settings --email you@example.com) next to the Slack-compatible webhook; at most 20 a hour per organisation. - Admin actions are CLI only (
team approve,reject,policy-push,settings,inventory), not MCP tools, so injected text cannot trigger them. The MCP toolsteam_status,request_approvalandteam_reportask for confirmation and cannot approve anything.
mcp-security-guard team status
mcp-security-guard team report --dry-run
mcp-security-guard team request plugin some-plugin --note "for the docs site"
mcp-security-guard team approvals --status pending # admin
mcp-security-guard team approve apr_… --note ok # admin
mcp-security-guard team policy-push policy.json # admin
mcp-security-guard team keys create ana # admin: a key for a developer, shown once
mcp-security-guard team settings --fleet on --webhook https://hooks.slack.com/… --email alerts@acme.example # admin
Tools
| Tool | Launches servers? |
|---|---|
list_mcp_servers | No |
audit_mcp_config | No |
audit_server_tools | Yes, after explicit confirm_launch: true. Sends only initialize and list requests (tools, prompts, resources); never calls a tool, renders a prompt or reads a resource |
pin_tools | Yes (same as above). Writes ~/.claude/mcp-security/pins.json |
audit_agent_context | No. Reads skills, commands, subagents, rules, CLAUDE.md and plugin hooks (user, project and installed plugins); project_only limits it to the repository |
team_status, request_approval, team_report | Network, after confirmation. Team plan: sync the organisation's policy, ask the admin to approve a server or plugin, preview and send a fleet report (see above) |
pin_context | No. Writes ~/.claude/mcp-security/context-pins.json (SHA-256 per skill, command, subagent, rule, CLAUDE.md, hook config and script, per origin). Skips origins with critical or high findings unless force |
analyze_tool_definitions | No. Offline analysis of a tools/list payload, for MCP server authors |
check_supply_chain | No. Sends package names and versions to npm, PyPI and OSV after confirm_network: true |
apply_fixes | Only for the permissions fix. Dry run by default; with write: true it edits the project's .mcp.json / .claude/settings.json after a backup to ~/.claude/mcp-security/backups/ |
security_dashboard | Only with scan: "full" and confirm_launch: true. Interactive dashboard (MCP App) |
generate_policy | No. Returns a .mcp-security.json approving the current servers |
query_audit_log | No. Summarises the runtime audit log |
adversarial_test | Yes, and calls tools with injection payloads. Only for servers you own; needs i_own_this_server and confirm_launch; skips destructive tools |
Session-start check
A SessionStart hook re-verifies only the servers you have pinned (pinning is your consent to launch them) and stays silent unless something changed. Control it with MCP_SECURITY_SESSION_CHECK:
full(default): compare launch configs and re-list toolsconfig: compare launch configs only, launch nothingoff: disable the check
CI / GitHub Action
Fail pull requests that add risky MCP servers to .mcp.json, and show the findings in GitHub code scanning:
name: MCP security
on: [pull_request]
permissions:
contents: read
security-events: write
jobs:
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: petrovicistefan/mcp-security-guard@main
id: mcp
with:
fail-on: high # critical | high | medium | low | info | none
- uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: ${{ steps.mcp.outputs.sarif-file }}
To also fail pull requests that add a poisoned skill, command or CLAUDE.md to the repository, set context: true on the action (second SARIF file in context-sarif-file). The same checks run locally without Claude:
node plugin/dist/cli.mjs audit --project-only --format sarif --output mcp.sarif
node plugin/dist/cli.mjs analyze-tools tools.json --name my-server # for MCP server authors: a saved tools/list result
Scan the skills, commands, subagents and CLAUDE.md files next to your servers (add --project-only for a repository you are about to trust):
node plugin/dist/cli.mjs audit-context --project-only --fail-on high
Pin what you have reviewed with node plugin/dist/cli.mjs pin-context (or ask Claude to run pin_context); from then on audit-context and the session-start check report any pinned plugin, skill, command or CLAUDE.md that changed.
Quoted attack phrases inside examples or fenced code are reported as medium (documentation), install snippets such as curl … | sh as low; the same patterns in scripts, hooks and inline ! commands are high.
Check a server before installing it (launches it, sends only initialize and tools/list):
node plugin/dist/cli.mjs scan some-server.mcp.json --confirm-launch
Test your own server for command injection and path traversal (it calls the tools; run a test instance, ideally in a container):
node plugin/dist/cli.mjs adversarial my-server.mcp.json --server my-server --i-own-this-server --confirm-launch
Fix what the audit found (dry run first, then --write):
node plugin/dist/cli.mjs fix --pin-versions # npx pkg → pkg@x.y.z, uvx pkg → pkg==x.y.z (looks up npm/PyPI)
node plugin/dist/cli.mjs fix --env-refs --write # literal secrets in .mcp.json → ${VAR} references
node plugin/dist/cli.mjs fix --permissions --confirm-launch --write # permissions.ask rules for risky tools
Start a team policy from the servers configured today:
node plugin/dist/cli.mjs policy-init && git add .mcp-security.json
Any command takes --format markdown|json|sarif|html. The HTML report is a single self-contained file you can open in a browser or attach to a ticket.
Exit codes: 0 clean, 1 findings at or above --fail-on, 2 usage error.
Limitations
Remote servers that require OAuth (most hosted MCP servers) cannot be scanned at the tool level: the scanner cannot reuse Claude Code's tokens. Their configuration is still audited.
Interactive dashboard (MCP App)
security_dashboard is an MCP App: hosts that support MCP Apps (Claude Desktop, claude.ai, VS Code Copilot…) render it inline. It shows every server with its score and grade, findings filterable by severity and server, the OWASP MCP Top 10 breakdown, recommended permission rules, and Full scan and Pin buttons. Selecting a server tells Claude what you are looking at, so follow-up questions have context. Claude Code in a terminal gets the text summary instead.
To use it in Claude Desktop, add the server to claude_desktop_config.json and ask Claude to "open the MCP security dashboard":
{ "mcpServers": { "mcp-security-guard": { "command": "node", "args": ["/path/to/mcp-security-guard/plugin/dist/index.mjs"] } } }
The UI is a single self-contained HTML file. Server-supplied text reaches the page only as text (never as HTML), and the host's sandbox applies. Develop it with a local host that drives the real server: npm run dashboard:dev -- /path/to/project.
Runtime hooks
| Hook | What it does | Setting |
|---|---|---|
PreToolUse on mcp__* | Asks for confirmation when a call's arguments contain a credential | MCP_SECURITY_SECRET_GUARD=ask (default), deny or off |
PostToolUse on mcp__* | Warns Claude and you when an output contains injected instructions, hidden characters, exfiltration markup or a credential | always on |
| Audit log | ~/.claude/mcp-security/audit.jsonl: server, tool, time, input hash and sizes. Never arguments or outputs. Rotates at 10 MB. | MCP_SECURITY_AUDIT_LOG=off |
The hooks add about 40 ms per MCP call.
Trust model
- Read-only, apart from the pin file, the audit log, and
policy-init(which writes a file you asked for). - Network only when you opt in:
check_supply_chain/--supply-chainsend package names and versions to npm, PyPI and OSV. Theadversarial_testtool is the only one that calls tools. - Evidence from scanned servers is sanitised (invisible characters revealed, length capped) and labelled as untrusted data.
- Secrets are masked in all output.
- Static checks reduce risk. They do not prove a server safe: malicious behaviour in tool responses or server code is out of scope.
Development
npm install
npm run build # bundles to plugin/dist/ (committed, so the plugin runs without npm install)
npm test
npm run bench # false-positive gate on real servers (network; Docker images optional, see bench/RESULTS.md)
test/fixtures/poisoned-server.mjs is a deliberately malicious server used by the end-to-end test.
Pro & Team (early access)
Everything above is free and stays free: it runs locally and needs no account. Paid plans add what needs a server: a daily threat feed of known malicious MCP servers, packages and skills, alerts when a server you use ships changed tool descriptions, history, and team policies, approvals and a dashboard. They are opt-in through MCP_SECURITY_API_KEY; see PRIVACY.md for exactly what is sent.
Paid plans are not on sale yet, and there is no checkout. If you or your team would like one, write to hello@petrovicistefan.ro or join the early access list: I issue keys by hand for now, and early users get launch pricing, including a limited lifetime license.
Security, privacy, license
- Found a vulnerability? See SECURITY.md.
- What is read, written and sent: PRIVACY.md.
- Changes: CHANGELOG.md.
- MIT, see LICENSE.
About the author
I'm Stefan Petrovici: passionate about IT, a husband and a father. I built mcp-security-guard on my own. I'm looking for a job.
I build web applications end to end, frontend, backend, APIs and deployment, and I'm happy to work on anything else that needs building. This repository shows how I work: tests, CI, careful documentation and attention to security.
I also build WordPress and WooCommerce plugins, available at pluginsforstores.com.
If your team is hiring, write to me at hello@petrovicistefan.ro.
Reviews
No reviews yet
Be the first to review this server!
More Security MCP Servers
Toleno
Freeby Toleno · Developer Tools
Toleno Network MCP Server — Manage your Toleno mining account with Claude AI using natural language.
mcp-creator-python
Freeby mcp-marketplace · Developer Tools
Create, build, and publish Python MCP servers to PyPI — conversationally.
MCP Marketplace
Freeby mcp-marketplace · Developer Tools
Search and install MCP servers from inside your AI client.
FinAgent
Freeby mcp-marketplace · Finance
Free stock data and market news for any MCP-compatible AI assistant.
by Lharries · Communication
Read, search, and send WhatsApp messages through your AI assistant
Google Workspace MCP
Freeby Taylorwilsdon · Productivity
Control Gmail, Calendar, Docs, Sheets, Drive, and more from your AI
