How SkillSpector Detects MCP Tool Poisoning: Four Static Analysis Methods Explained
SkillSpector employs four specialized detection patterns—covert instruction extraction (TP1), Unicode deception analysis (TP2), parameter injection scanning (TP3), and LLM-powered semantic verification (TP4)—to identify malicious capabilities embedded in NVIDIA Skill Manifests.
NVIDIA SkillSpector is a static analysis framework designed to validate skill manifests against security threats before deployment. The tool implements comprehensive MCP tool poisoning detection through a dedicated analyzer node that processes textual fields, Unicode properties, parameter definitions, and code semantics to surface hidden attack vectors.
The MCP Tool Poisoning Analyzer Architecture
The analyzer implementation lives in src/skillspector/nodes/analyzers/mcp_tool_poisoning.py. This node extracts all textual content from a manifest—including names, descriptions, triggers, and parameter fields—then routes them through four specialized threat detection routines. Each detection pattern targets a specific attack vector used to inject malicious instructions into tool definitions.
The main node(state) function orchestrates the analysis by first calling _extract_metadata_texts() to gather metadata, then executing TP1 and TP2 checks across every text field, TP3 specifically against the parameters list, and optionally TP4 when LLM validation is enabled.
TP1 – Hidden Instruction Detection
The _check_tp1() function scans for covert payloads embedded in manifest text using specialized regex patterns. This detection layer identifies:
- HTML comments (e.g.,
<!-- hidden instruction -->) - Markdown comments using the
[//]: #(...)syntax - Zero-width Unicode characters that render invisibly
- Base64 encoded blobs that may hide executable content
- Data-URI payloads embedded in text fields
The implementation uses the regex constants _HTML_COMMENT_RE, _MARKDOWN_COMMENT_RE, _ZERO_WIDTH_RE, _BASE64_RE, and _DATA_URI_RE to build a Finding object for each match discovered in the manifest.
TP2 – Unicode Deception Analysis
The _check_tp2() function identifies visual spoofing attacks that use Unicode properties to disguise malicious tool names or descriptions. This check processes each text field with the following logic:
First, it scans for characters defined in the _CONFUSABLES, _RTL_CHARS, and _INVISIBLE_CHARS sets to detect Cyrillic/Greek homoglyphs, right-to-left override characters, and invisible formatting characters. Second, it uses the _get_script_prefix() helper to identify mixed-script identifiers that combine visually similar characters from different alphabets to deceive users.
TP3 – Parameter Description Injection
The _check_tp3() function specifically examines the parameters list in the manifest for injection attacks targeting the tool's input layer. This method applies regex patterns to detect:
- Instruction-override phrases that attempt to redirect tool behavior
- System-prompt tokens embedded in parameter descriptions
- Exfiltration cues suggesting data theft mechanisms
- Overly long descriptions that may contain hidden payloads
- Malicious defaults including URLs or shell commands
The detection uses _TP3_INSTRUCTION_OVERRIDE_RE, _TP3_SYSTEM_TOKEN_RE, _TP3_EXFILTRATION_RE, _TP3_MALICIOUS_URL_RE, and _TP3_SHELL_CMD_RE to flag suspicious parameter definitions that could compromise the execution environment.
TP4 – LLM-Based Semantic Verification
The _check_tp4() function performs deep semantic analysis to detect description-to-behavior mismatches. Unlike the pattern-based TP1-TP3 checks, this method uses an LLM to validate whether the tool's declared functionality matches its actual implementation.
The function collects code snippets from the state's file_cache, constructs a detailed comparison prompt, and calls chat_completion() from src/skillspector/llm_utils.py. It parses the JSON response to emit a Finding when the LLM reports a significant mismatch between the manifest description and the executable code with sufficient confidence.
Running the Analyzer
You can execute the MCP tool poisoning analyzer from the command line:
skillSpector analyze --analyzer mcp_tool_poisoning path/to/skill/
For programmatic use within a Python environment:
from skillspector.graph import build_graph
from skillspector.nodes.analyzers.mcp_tool_poisoning import node as mcp_node
# Load a skill directory into a SkillspectorState
graph = build_graph("path/to/skill")
state = graph.state
# Run only the MCP-tool-poisoning analyzer
result = mcp_node(state)
print(result["findings"]) # list of Finding objects
To inspect individual findings returned by the analyzer:
finding = result["findings"][0]
print(f"Rule: {finding.rule_id}")
print(f"Message: {finding.message}")
print(f"Severity: {finding.severity}")
print(f"Location: {finding.matched_text}")
Summary
- TP1 detects hidden instructions using regex patterns for HTML comments, Markdown comments, zero-width characters, Base64 blobs, and Data-URIs in
src/skillspector/nodes/analyzers/mcp_tool_poisoning.py. - TP2 identifies Unicode deception through homoglyph detection (
_CONFUSABLES), RTL character analysis (_RTL_CHARS), and mixed-script identification via_get_script_prefix(). - TP3 scans parameter descriptions for injection attacks, system token overrides, and malicious defaults using specialized TP3 regex constants.
- TP4 leverages
chat_completion()to perform semantic validation between manifest descriptions and actual code stored in thefile_cache. - All findings are emitted as
Findingobjects defined insrc/skillspector/models.pyand registered in the node system viasrc/skillspector/nodes/__init__.py.
Frequently Asked Questions
What is MCP tool poisoning?
MCP (Malicious Capability Poisoning) refers to attacks where adversaries embed hidden instructions, deceptive Unicode characters, or semantic misrepresentations in tool manifests to manipulate AI system behavior or exfiltrate data. SkillSpector detects these attempts through static analysis before the tools are deployed.
How does SkillSpector detect hidden text in manifests?
The _check_tp1() function in mcp_tool_poisoning.py applies regex patterns including _HTML_COMMENT_RE, _MARKDOWN_COMMENT_RE, and _ZERO_WIDTH_RE to detect HTML comments, Markdown metadata comments, and zero-width Unicode characters that could hide malicious payloads from casual review.
Can SkillSpector detect visually similar but malicious tool names?
Yes, through TP2 Unicode deception analysis. The _check_tp2() function checks for confusable Cyrillic/Greek homoglyphs, RTL directional-override characters, and mixed-script identifiers using character sets defined in _CONFUSABLES, _RTL_CHARS, and _INVISIBLE_CHARS to catch visual spoofing attacks.
What role does the LLM play in TP4 detection?
TP4 uses the chat_completion() utility to compare the skill's declared description and triggers against the actual executable code retrieved from the state's file_cache. This semantic validation identifies behavioral mismatches that pattern-based detection might miss, such as a tool claiming to "read files" while actually executing shell commands.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →