
MCP Security Audit
OfficialFreeEnsure your MCP configurations are secure and compliant.
Free · Opens the source repo
What MCP Security Audit does
The MCP Security Audit skill is designed to help developers and security professionals assess the security of Model Context Protocol (MCP) server configurations. It systematically reviews .mcp.json files for vulnerabilities such as hardcoded secrets, shell injection risks, and unpinned dependencies. By parsing each server configuration, the skill identifies potential security issues that could lead to unauthorized access or execution of malicious commands.
This skill focuses on several critical checks. First, it scans for hardcoded secrets in server arguments and environment variables, which can expose sensitive information. Next, it looks for dangerous shell command patterns that could allow for command injection. Additionally, the skill verifies that all dependencies are pinned to specific versions, avoiding the use of @latest to prevent unexpected changes in behavior or security posture. Finally, it checks whether registered MCP servers align with an approved list, ensuring compliance with governance policies.
The MCP Security Audit skill is particularly useful in scenarios where security is paramount, such as onboarding new MCP servers, performing audits in a monorepo, or conducting pre-commit checks on configuration changes. By integrating this skill into your development workflow, you can proactively identify and mitigate security risks before they reach production, thereby enhancing the overall security posture of your applications.
This skill is intended for developers, DevOps engineers, and security professionals who work with MCP configurations and need to ensure that their setups are secure and compliant with best practices. It provides a comprehensive approach to auditing MCP configurations, making it an essential tool for maintaining security in environments that utilize the Model Context Protocol.
When to use it
Use this skill when reviewing `.mcp.json` files or onboarding new MCP servers to ensure security best practices are followed.
When not to use it
This skill may not be suitable for configurations that do not use MCP or for environments where security auditing is not a priority.
What you can build with it
Onboarding New MCP Servers
Use the skill to audit new MCP servers being added to a project, ensuring they meet security standards.
Pre-Commit Security Checks
Integrate the skill into your version control workflow to automatically check MCP configurations before changes are committed.
Auditing Monorepos
Run the skill across multiple MCP configurations in a monorepo to identify and address security vulnerabilities in one go.
How to install MCP Security Audit
View source1. Install with the skills CLI
npx skills add github/awesome-copilot/mcp-security-audit --agent claude-code2. Or install it manually
Download the skill folder and drop it into ~/.claude/skills/ for all projects, or .claude/skills/ to scope it to one repo. Restart Claude Code so it picks up the new skill.
Anthropic's agentic coding CLI, and the reference implementation of Agent Skills. Drop a skill folder into ~/.claude/skills and Claude Code loads it automatically whenever a task matches the skill's description. Claude Code docs
Inside SKILL.md
Written by githubMCP Security Audit
Audit MCP server configurations for security issues — secrets exposure, shell injection, unpinned dependencies, and unapproved servers.
Overview
MCP servers give agents direct tool access to external systems. A misconfigured .mcp.json can expose credentials, allow shell injection, or connect to untrusted servers. This skill catches those issues before they reach production.
.mcp.json → Parse Servers → Check Each Server:
1. Secrets in args/env?
2. Shell injection patterns?
3. Unpinned versions (@latest)?
4. Dangerous commands (eval, bash -c)?
5. Server on approved list?
→ Generate Report
When to Use
- Reviewing any
.mcp.jsonfile in a project - Onboarding a new MCP server to a project
- Auditing all MCP servers in a monorepo or plugin marketplace
- Pre-commit checks for MCP configuration changes
- Security review of agent tool configurations
Audit Check 1: Hardcoded Secrets
Scan MCP server args and env values for hardcoded credentials.
import json
import re
from pathlib import Path
SECRET_PATTERNS = [
(r'(?i)(api[_-]?key|token|secret|password|credential)\s*[:=]\s*["\'][^"\']{8,}', "Hardcoded secret"),
(r'(?i)Bearer\s+[A-Za-z0-9\-._~+/]+=*', "Hardcoded bearer token"),
(r'(?i)(ghp_|gho_|ghu_|ghs_|ghr_)[A-Za-z0-9]{30,}', "GitHub token"),
(r'sk-[A-Za-z0-9]{20,}', "OpenAI API key"),
(r'AKIA[0-9A-Z]{16}', "AWS access key"),
(r'-----BEGIN\s+(RSA\s+)?PRIVATE\s+KEY-----', "Private key"),
]
def check_secrets(mcp_config: dict) -> list[dict]:
"""Check for hardcoded secrets in MCP server configurations."""
findings = []
raw = json.dumps(mcp_config)
for pattern, description in SECRET_PATTERNS:
matches = re.findall(pattern, raw)
if matches:
findings.append({
"severity": "CRITICAL",
"check": "hardcoded-secret",
"message": f"{description} found in MCP configuration",
"evidence": f"Pattern matched: {pattern}",
"fix": "Use environment variable references: ${ENV_VAR_NAME}"
})
return findings
Good practice — use env var references:
{
"mcpServers": {
"my-server": {
"command": "node",
"args": ["server.js"],
"env": {
"API_KEY": "${MY_API_KEY}",
"DB_URL": "${DATABASE_URL}"
}
}
}
}
Bad — hardcoded credentials:
{
"mcpServers": {
"my-server": {
"command": "node",
"args": ["server.js", "--api-key", "sk-abc123realkey456"],
"env": {
"DB_URL": "postgresql://admin:password123@prod-db:5432/main"
}
}
}
}
Audit Check 2: Shell Injection Patterns
Detect dangerous command patterns in MCP server args.
import json
import re
DANGEROUS_PATTERNS = [
(r'\$\(', "Command substitution $(...)"),
(r'`[^`]+`', "Backtick command substitution"),
(r';\s*\w', "Command chaining with semicolon"),
(r'\|\s*\w', "Pipe to another command"),
(r'&&\s*\w', "Command chaining with &&"),
(r'\|\|\s*\w', "Command chaining with ||"),
(r'(?i)eval\s', "eval usage"),
(r'(?i)bash\s+-c\s', "bash -c execution"),
(r'(?i)sh\s+-c\s', "sh -c execution"),
(r'>\s*/dev/tcp/', "TCP redirect (reverse shell pattern)"),
(r'curl\s+.*\|\s*(ba)?sh', "curl pipe to shell"),
]
def check_shell_injection(server_config: dict) -> list[dict]:
"""Check MCP server args for shell injection risks."""
findings = []
args_text = json.dumps(server_config.get("args", []))
for pattern, description in DANGEROUS_PATTERNS:
if re.search(pattern, args_text):
findings.append({
"severity": "HIGH",
"check": "shell-injection",
"message": f"Dangerous pattern in MCP server args: {description}",
"fix": "Use direct command execution, not shell interpolation"
})
return findings
Audit Check 3: Unpinned Dependencies
Flag MCP servers using @latest in their package references.
def check_pinned_versions(server_config: dict) -> list[dict]:
"""Check that MCP server dependencies use pinned versions, not @latest."""
findings = []
args = server_config.get("args", [])
for arg in args:
if isinstance(arg, str):
if "@latest" in arg:
findings.append({
"severity": "MEDIUM",
"check": "unpinned-dependency",
"message": f"Unpinned dependency: {arg}",
"fix": f"Pin to specific version: {arg.replace('@latest', '@1.2.3')}"
})
# npx with unversioned package
if arg.startswith("-y") or (not "@" in arg and not arg.startswith("-")):
pass # npx flag or plain arg, ok
# Check if using npx without -y (interactive prompt in CI)
command = server_config.get("command", "")
if command == "npx" and "-y" not in args:
findings.append({
"severity": "LOW",
"check": "npx-interactive",
"message": "npx without -y flag may prompt interactively in CI",
"fix": "Add -y flag: npx -y package-name"
})
return findings
Good — pinned version:
{ "args": ["-y", "my-mcp-server@2.1.0"] }
Bad — unpinned:
{ "args": ["-y", "my-mcp-server@latest"] }
Audit Check 4: Full Audit Runner
Combine all checks into a single audit.
def audit_mcp_config(mcp_path: str) -> dict:
"""Run full security audit on an .mcp.json file."""
path = Path(mcp_path)
if not path.exists():
return {"error": f"{mcp_path} not found"}
config = json.loads(path.read_text(encoding="utf-8"))
servers = config.get("mcpServers", {})
results = {"file": str(path), "servers": {}, "summary": {}}
total_findings = []
# Run secrets check once on the whole config (not per-server)
config_level_findings = check_secrets(config)
total_findings.extend(config_level_findings)
for name, server_config in servers.items():
if not isinstance(server_config, dict):
continue
findings = []
findings.extend(check_shell_injection(server_config))
findings.extend(check_pinned_versions(server_config))
results["servers"][name] = {
"command": server_config.get("command", ""),
"findings": findings,
}
total_findings.extend(findings)
# Summary
by_severity = {}
for f in total_findings:
sev = f["severity"]
by_severity[sev] = by_severity.get(sev, 0) + 1
results["summary"] = {
"total_servers": len(servers),
"total_findings": len(total_findings),
"by_severity": by_severity,
"passed": len(total_findings) == 0,
}
return results
Usage:
results = audit_mcp_config(".mcp.json")
if not results["summary"]["passed"]:
for server, data in results["servers"].items():
for finding in data["findings"]:
print(f"[{finding['severity']}] {server}: {finding['message']}")
print(f" Fix: {finding['fix']}")
Output Format
MCP Security Audit — .mcp.json
═══════════════════════════════
Servers scanned: 5
Findings: 3 (1 CRITICAL, 1 HIGH, 1 MEDIUM)
[CRITICAL] my-api-server: Hardcoded secret found in MCP configuration
Fix: Use environment variable references: ${ENV_VAR_NAME}
[HIGH] data-processor: Dangerous pattern in MCP server args: bash -c execution
Fix: Use direct command execution, not shell interpolation
[MEDIUM] analytics: Unpinned dependency: analytics-mcp@latest
Fix: Pin to specific version: analytics-mcp@2.1.0
Related Resources
- MCP Specification
- Agent Governance Toolkit — Full governance framework with MCP trust proxy
- OWASP ASI-02: Insecure Tool Use
Frequently asked questions about MCP Security Audit
Similar skills
Secret Scanning
Protect your code by preventing secret leaks.
iMessage Access Management
Control access to your iMessage channel securely.
Implementing Secret Scanning with Gitleaks
Automate detection of hardcoded secrets in git repositories.
Secrets Vault Manager
Manage and secure your secret infrastructure efficiently.
AWS Secrets Manager
Safely manage secrets without exposing plaintext values.
Agent Hardening
Prepare your agent for secure, production-ready deployment.
