# How SkillSpector Detects MCP Tool Poisoning: A Deep Dive into TP1-TP4 Analysis

> SkillSpector detects MCP tool poisoning through TP1-TP4 analysis using regex, Unicode scanning, parameter injection, and LLM behavioral verification. Learn how SkillSpector secures your NVIDIA Skill Manifests.

- Repository: [NVIDIA Corporation/SkillSpector](https://github.com/NVIDIA/SkillSpector)
- Tags: deep-dive
- Published: 2026-06-21

---

**SkillSpector detects MCP tool poisoning by statically analyzing NVIDIA Skill Manifests for four distinct threat patterns—TP1 through TP4—using specialized regex-based detection, Unicode deception scanning, parameter injection analysis, and LLM-powered behavioral verification.**

SkillSpector, NVIDIA's open-source static analysis framework for AI skill manifests, implements a comprehensive **MCP tool poisoning detection** system that identifies malicious capabilities hidden in tool definitions. The analyzer examines every textual field within a skill manifest to uncover steganographic attacks, visual spoofing, and semantic mismatches that could compromise AI agents.

## Understanding MCP Tool Poisoning Threats

MCP (Malicious Capability Poisoning) represents a class of attacks where adversaries embed hidden instructions or deceptive behaviors within tool manifests that AI agents consume. SkillSpector's dedicated analyzer node specifically targets these threats by implementing four distinct detection layers (TP1-TP4) that range from static pattern matching to semantic analysis using large language models.

## The Four Threat Patterns (TP1-TP4)

The analyzer in [`src/skillspector/nodes/analyzers/mcp_tool_poisoning.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/nodes/analyzers/mcp_tool_poisoning.py) implements specific detection logic for each threat pattern, orchestrated through the main `node()` function.

### TP1 – Hidden Instructions

The first threat pattern targets **steganographic content** embedded in manifest text fields. The `_check_tp1()` function (lines 27-44) scans for HTML comments (`<!--...-->`), Markdown comments (`[//]: #(...)`), zero-width Unicode characters, Base64-encoded blobs, and Data URI payloads. It uses the regex patterns `_HTML_COMMENT_RE`, `_MARKDOWN_COMMENT_RE`, `_ZERO_WIDTH_RE`, `_BASE64_RE`, and `_DATA_URI_RE` to identify potential hidden instructions. Each match generates a `Finding` object indicating the presence of concealed content.

### TP2 – Unicode Deception

**Visual spoofing attacks** leverage confusable Unicode characters to trick developers and AI systems. The `_check_tp2()` implementation (lines 39-78) detects Cyrillic/Greek homoglyphs, right-to-left (RTL) directional override characters, and invisible formatting markers by scanning against the `_CONFUSABLES`, `_RTL_CHARS`, and `_INVISIBLE_CHARS` character sets. The function also employs `_get_script_prefix()` to identify mixed-script identifiers that could indicate homograph attacks designed to visually mimic legitimate tool names.

### TP3 – Parameter Description Injection

This pattern focuses on **malicious parameter definitions** within the manifest's parameters list. The `_check_tp3()` function (lines 84-130) walks through the `parameters` array and applies targeted regexes including `_TP3_INSTRUCTION_OVERRIDE_RE`, `_TP3_SYSTEM_TOKEN_RE`, `_TP3_EXFILTRATION_RE`, `_TP3_MALICIOUS_URL_RE`, and `_TP3_SHELL_CMD_RE`. These patterns detect instruction overrides, system prompt tokens, data exfiltration cues, and executable payloads disguised as default values or description text.

### TP4 – LLM-Based Behavior Mismatch

Unlike the static regex-based approaches of TP1-TP3, **TP4 employs semantic analysis** to detect discrepancies between a tool's declared description and its actual implementation. The `_check_tp4()` function (lines 75-115) extracts code snippets from the state's `file_cache`, constructs a specialized prompt comparing the manifest's description, triggers, and permissions against the executable code, and invokes `chat_completion()` from [`src/skillspector/llm_utils.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/llm_utils.py). When the LLM reports a mismatch with sufficient confidence, the analyzer emits a `Finding` indicating potential behavioral deception.

## Implementation Deep Dive

### The Core Analyzer Architecture

The complete implementation resides in [`src/skillspector/nodes/analyzers/mcp_tool_poisoning.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/nodes/analyzers/mcp_tool_poisoning.py), where the `node(state: SkillspectorState)` function orchestrates the analysis pipeline:

```python
def node(state: SkillspectorState) -> AnalyzerNodeResponse:
    manifest = state.get("manifest") or {}
    if not manifest:
        return {"findings": []}
    # extract all textual fields

    metadata_texts = _extract_metadata_texts(manifest)
    # TP1-TP2 over every field

    for text, field, is_id in metadata_texts:
        findings.extend(_check_tp1(text, field))
        findings.extend(_check_tp2(text, field, is_id))
    # TP3 over parameters only

    findings.extend(_check_tp3(manifest.get("parameters") or []))
    # optional TP4 LLM check

    if state.get("use_llm", True):
        findings.extend(_check_tp4(state))
    return {"findings": findings}

```

### Key Source Files

The detection system spans several critical files:

- [`src/skillspector/nodes/analyzers/mcp_tool_poisoning.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/nodes/analyzers/mcp_tool_poisoning.py) – Core analyzer implementing TP1-TP4 checks
- [`src/skillspector/models.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/models.py) – Definition of the `Finding` data class used for reporting
- [`src/skillspector/llm_utils.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/llm_utils.py) – Helper `chat_completion` function used by TP4
- [`src/skillspector/nodes/__init__.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/nodes/__init__.py) – Registers the `mcp_tool_poisoning_node` in the node registry
- [`tests/test_mcp_tool_poisoning.py`](https://github.com/NVIDIA/SkillSpector/blob/main/tests/test_mcp_tool_poisoning.py) – Test suite verifying each TP detection path

## Running the Analyzer

### Command-Line Interface

Execute the analyzer directly from the terminal using the SkillSpector CLI:

```bash
skillSpector analyze --analyzer mcp_tool_poisoning path/to/skill/

```

### Programmatic Integration

Integrate the detection logic into custom Python workflows by importing the node directly:

```python
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

```

Inspecting individual findings reveals specific threat details:

```python
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

- SkillSpector implements **four distinct detection layers** (TP1-TP4) to identify MCP tool poisoning in NVIDIA Skill Manifests.
- **TP1 and TP2** use static regex patterns to detect hidden instructions and Unicode deception in [`src/skillspector/nodes/analyzers/mcp_tool_poisoning.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/nodes/analyzers/mcp_tool_poisoning.py).
- **TP3** specifically targets parameter-level injection attacks through specialized regex matching against system tokens and malicious URLs.
- **TP4** leverages LLM semantic analysis via `chat_completion()` to identify behavioral mismatches between declared tool descriptions and actual code implementation.
- The analyzer can run via **CLI** or **programmatically**, returning structured `Finding` objects defined in [`src/skillspector/models.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/models.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 malicious parameters within AI tool manifests. These poisoned tools can manipulate AI agent behavior, exfiltrate data, or execute unauthorized commands when invoked by the system.

### How does TP4 differ from TP1-TP3 detection methods?

While TP1 through TP3 rely on static regex patterns to detect syntactic anomalies like hidden comments or homoglyphs, **TP4 uses semantic analysis** via large language models. It compares the human-readable description in the manifest against the actual executable code to detect behavioral discrepancies that pattern matching cannot identify.

### Can I run TP1-TP3 checks without LLM access?

Yes. The analyzer supports offline operation by checking `state.get("use_llm", True)` before executing TP4. When the LLM flag is disabled or unavailable, the node still performs complete TP1-TP3 analysis using only local regex-based detection, making it suitable for air-gapped environments.

### Where are the detection results stored?

Each threat detection generates a `Finding` object defined in [`src/skillspector/models.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/models.py), containing fields for `rule_id`, `message`, `severity`, and `matched_text`. These findings are returned as a list in the `AnalyzerNodeResponse` dictionary under the `findings` key, allowing for programmatic processing or CLI reporting.