How the MCP Least Privilege Analyzer Verifies Capability Declarations in SkillSpector
The MCP least privilege analyzer verifies capability declarations by comparing the permissions listed in a skill's SKILL.md manifest against the actual capabilities detected in the source code through regex pattern matching.
The NVIDIA SkillSpector repository includes a static analysis tool that ensures skill manifests accurately reflect security-relevant code behavior. The analyzer enforces four specific LP (Least Privilege) rules by cross-referencing declared permissions against detected capabilities, generating structured findings when mismatches occur.
Processing Skill Manifests and Source Code
The analyzer begins by ingesting the skill's state, which contains both the declared permissions and the actual source code files.
Loading the Manifest and File Cache
In src/skillspector/nodes/analyzers/mcp_least_privilege.py, the node function receives a SkillspectorState object containing the skill manifest and a cache of executable files. Lines 66-70 extract these components:
manifest = state.get("manifest") or {}
file_cache = state.get("file_cache") or {}
The file_cache maps file paths to their source content, enabling the analyzer to inspect every executable file without redundant disk I/O.
Detecting Capabilities with Regex Patterns
For each file in the cache, the analyzer calls _detect_capabilities (lines 27-35) to scan the source text against a table of regex patterns defined in _CAPABILITY_PATTERNS:
caps = _detect_capabilities(content)
These patterns identify usage across six categories: shell, network, file_read, file_write, env, and mcp. The function returns a mapping of file_capabilities holding detected categories per file, while all_caps aggregates unique categories across the entire skill.
Mapping Declared Permissions to Categories
The analyzer normalizes manifest permissions using _map_permissions_to_categories (line 64), which converts raw permission strings like "bash" or "network" into standardized capability categories via the _PERM_TO_CAPABILITY lookup table.
The Four LP Rules for Capability Verification
The core verification logic implements four distinct rules (LP1-LP4) that generate findings based on the comparison between declared and detected capabilities.
LP2: Flagging Wildcard Permissions (lines 92-132)
If any permission value matches wildcards such as "*", "all", "full", or "any" (defined in _WILDCARD_PERMS), the analyzer immediately emits a high-severity finding. This prevents overly broad permission declarations that violate the principle of least privilege.
LP3: Identifying Missing Permission Declarations (lines 135-159)
When the permissions key is missing or empty in the manifest, yet the capability detection found security-relevant code patterns, the analyzer generates an LP3 finding. This catches skills that use capabilities like subprocess.Popen without explicitly declaring them in SKILL.md.
LP1: Detecting Under-Declared Capabilities (lines 162-204)
For each capability detected in the code that is not covered by the declared categories, the analyzer produces an LP1 finding with high severity. The confidence score varies based on context: capabilities found in test files receive a confidence of 0.55, while production code receives 0.75. All confidence values are clamped to the [0, 1] range using the _clamp helper.
LP4: Reporting Over-Declared Permissions (lines 207-254)
When the manifest declares permissions that map to capability categories not detected in the code, the analyzer generates a low-severity LP4 finding. This identifies stale or unnecessary permissions that should be removed from the manifest to maintain accuracy.
Practical Examples of Capability Verification
The following scenarios demonstrate how the analyzer processes real-world skill configurations.
Example 1: Missing Permissions Declaration
Consider a SKILL.md that omits the permissions field entirely:
# SKILL.md
name: greet
description: Says hello
If the skill contains subprocess.Popen in its source, running the MCP scan produces an LP3 finding:
from skillspector.mcp_server import run_scan
result = await run_scan(
target="/path/to/greet_skill",
use_llm=False,
output_format="json",
)
print(result["findings"])
# → [{'rule_id': 'LP3', 'message': 'Skill has no declared permissions ...'}]
Example 2: Over-Declared Network Permission
When a skill declares network access but only performs file operations:
# SKILL.md
permissions:
- network # declared, but code only reads files
The analyzer emits an LP4 finding since no network capability patterns were detected:
{
"rule_id": "LP4",
"message": "Permission 'network' is declared but no corresponding code capability (network) was detected."
}
Example 3: Under-Declared Shell Capability
If a skill declares only file read permissions but executes shell commands:
permissions:
- file_read
The presence of subprocess.Popen triggers an LP1 finding for the missing shell capability:
{
"rule_id": "LP1",
"message": "Code capability 'shell' detected in greet.py but not covered by declared permissions."
}
Summary
- The MCP least privilege analyzer in
src/skillspector/nodes/analyzers/mcp_least_privilege.pyvalidates thatSKILL.mdmanifests accurately reflect code capabilities. - It uses regex patterns in
_CAPABILITY_PATTERNSto detect six categories of security-relevant operations across thefile_cache. - LP2 blocks wildcard permissions like
"*"or"all"that grant excessive access. - LP3 catches skills using capabilities without any declared permissions list.
- LP1 identifies under-declared capabilities with higher confidence for production code (0.75) versus test files (0.55).
- LP4 flags over-declared permissions that have no corresponding code usage.
- Each finding follows the
Findingmodel defined insrc/skillspector/models.py, containing rule IDs, severity levels, and remediation advice.
Frequently Asked Questions
What is the MCP least privilege analyzer?
The MCP least privilege analyzer is a static analysis component in the NVIDIA SkillSpector repository that verifies whether a skill's declared permissions in its SKILL.md manifest match the actual security capabilities used in its source code. It implements four specific rules (LP1-LP4) to enforce the principle of least privilege for MCP (Model Context Protocol) skills.
How does the analyzer detect capabilities in code?
The analyzer detects capabilities using the _detect_capabilities function (lines 27-35 of mcp_least_privilege.py), which scans source code against predefined regex patterns in _CAPABILITY_PATTERNS. These patterns identify specific imports, function calls, or APIs related to shell execution, network operations, file system access, environment variables, and MCP interactions.
What is the difference between LP1 and LP4 findings?
LP1 findings indicate under-declared capabilities, meaning the code uses a security-sensitive operation (like shell execution) that is not covered by the manifest's permissions. LP4 findings indicate over-declared permissions, meaning the manifest lists a capability (like network access) that the code does not actually use. LP1 carries higher severity since it represents a potential security risk, while LP4 represents manifest hygiene issues.
How does the analyzer handle test files?
The analyzer applies different confidence scores based on file context. When capabilities are detected in test files, the confidence score is reduced to 0.55 compared to 0.75 for production code. This differentiation helps prioritize remediation efforts toward production security risks while still acknowledging test-time capability usage.
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 →