Modern developer workflows increasingly rely on AI agent configurations and Model Context Protocol (MCP) servers. Tools like Claude Desktop, Cursor, and Windsurf execute local commands, connect to remote services, and read workspace instructions from files like .cursorrules or claude_desktop_config.json.
However, these configuration files can introduce serious security vulnerabilities into your environment:
- Plaintext API keys and tokens committed to configuration files or exposed in local environments.
- Unpinned runtime commands (such as executing
npxoruvxpackages without fixed versions), allowing upstream package updates to execute unreviewed code on your machine. - Overly broad filesystem access, such as giving an MCP server read and write permissions to root (
/), home directories (~), or entire user profiles. - Unauthenticated remote endpoints that expose local agent tooling to network manipulation.
- Instruction injection and hidden Unicode characters (such as zero-width spaces or bidirectional overrides) embedded within repository agent instruction files.
agentconfig_audit_mcp_and_rules_scanner.py is an audit script designed to inspect MCP configuration files and agent instruction rulebooks to flag these specific security issues.
Install & Usage
The tool is self-contained and relies entirely on Python's standard library (argparse, json, pathlib, re, unicodedata, dataclasses, and shlex). You do not need to run pip install for any third-party dependencies.
Installation
Download the script file and save it to your workspace as agentconfig_audit_mcp_and_rules_scanner.py. Ensure you have Python 3.8 or later installed.
Basic Usage
You can display the built-in command options by invoking Python directly:
python agentconfig_audit_mcp_and_rules_scanner.py --help
To audit an entire workspace for both MCP configurations and rule files (such as .cursorrules, agents.md, and markdown prompts), pass the directory path to the script:
python agentconfig_audit_mcp_and_rules_scanner.py .
You can also target specific standard system locations where tools like Claude Desktop or Cursor store their MCP definitions:
# Auditing a specific configuration file
python agentconfig_audit_mcp_and_rules_scanner.py ~/.cursor/mcp.json
How It Works
The audit tool inspects two main surfaces: structured JSON MCP server configurations and plaintext rule/instruction documents.
1. Detecting Broad Filesystem Access and Unpinned Packages
When parsing mcpServers configurations, the scanner evaluates command arguments against dangerous system roots and verifies if package runners include immutable version specifications:
# Check Overly Permissive Filesystem Paths
if isinstance(args, list):
for arg in args:
if not isinstance(arg, str):
continue
expanded = os.path.expanduser(arg)
for pat in BROAD_PATH_PATTERNS:
if re.match(pat, arg.strip()) or re.match(pat, expanded.strip()):
findings.append(
Finding(
rule_id="MCP-BROAD-FILESYSTEM-ROOT",
title=f"Overly Broad Filesystem Access in '{server_name}'",
severity="CRITICAL",
file_path=str(file_path),
line_number=None,
description=(
f"Server '{server_name}' is assigned an expansive filesystem path '{arg}'. "
"Agents interacting with this server obtain arbitrary read/write access to user "
"home directories or root."
),
evidence=f"arg: {arg}",
remediation="Scope the server access specifically to a dedicated subproject folder.",
)
)
The script monitors paths matching expressions like ^/$, ^/home/?$, ^/Users/?$, ^~$, or root drives on Windows (^[A-Za-z]:\\?$). If an MCP server is configured to mount those locations, it raises a CRITICAL finding.
Similarly, the scanner evaluates whether npx or uvx executions pin their targets. If an argument lacks @<version> or ==<version>, the tool flags MCP-UNPINNED-SERVER to prevent automatic downstream execution of unpinned packages.
2. Identifying Hardcoded Secrets in Environment Blocks
The tool loops through every env key-value pair in each configured server. If a value contains known credential structures (such as GitHub personal access tokens, AWS keys, Slack tokens, or private key headers), or if keys containing TOKEN, KEY, or SECRET hold hardcoded strings longer than 11 characters, it generates an alert:
# Check Plaintext Credentials in 'env'
if isinstance(env, dict):
for env_key, env_val in env.items():
if not isinstance(env_val, str):
continue
# Skip template variables like ${VAR} or $VAR
if (env_val.startswith("${") and env_val.endswith("}")) or env_val.startswith("$"):
continue
for regex, label in SECRET_REGEXES:
if re.search(regex, env_val) or (
any(s in env_key.upper() for s in ("TOKEN", "KEY", "SECRET", "PASSWORD", "AUTH"))
and len(env_val) >= 12
):
findings.append(
Finding(
rule_id="MCP-PLAINTEXT-SECRET",
title=f"Exposed Secret in Server '{server_name}' Env",
severity="CRITICAL",
file_path=str(file_path),
line_number=None,
description=(
f"Environment variable '{env_key}' contains a hardcoded plaintext secret ({label})."
),
evidence=f"{env_key} = {env_val[:4]}...{env_val[-4:] if len(env_val) > 8 else ''}",
remediation="Extract credentials to the system shell environment or a secure local keyring and reference via variable expansion.",
)
)
break
If the value uses variable expansion syntax such as ${MY_SECRET} or $MY_SECRET, the scanner treats it as externalized and skips it.
3. Scanning Agent Rules for Hidden Unicode and Injection Directives
Files like .cursorrules, agents.md, and prompt.txt can contain hidden characters that alter model behavior without being visible in standard text editors. The scanner checks each line for:
- Zero-width spaces (
\u200B), non-joiners (\u200C), joiners (\u200D), and byte order marks (\uFEFF). - Bidirectional overrides (such as
\u202E), which can visually invert displayed text while preserving a different underlying instruction. - Explicit instruction-override heuristics, such as phrases like
ignore all previous instructions,do not follow safety guidelines, or injected XML tags like<system-instruction>.
Limitations
While this tool highlights high-risk patterns, it has specific design limitations based directly on its codebase:
-
Static Regex Heuristics: Secret detection and injection detection rely strictly on static regular expressions. A credential format not listed in
SECRET_REGEXESor an obfuscated prompt injection string that avoids common phrasing will not be caught. -
No Dynamic Variable Resolution: The scanner checks if an environment variable starts with
$or${...}to avoid false positives. It does not inspect whether the parent shell environment securely populates those variables. -
Hardcoded File Target Names: During workspace discovery,
discover_agent_files()only checks for a predefined set of filenames (such as.cursorrules,agents.md,claude.md, and.rulesextensions). Rules stored under custom or unexpected file extensions will be skipped unless explicitly passed as target paths. - JSON-Only MCP Config Support: The MCP configuration scanner assumes valid JSON formatting. It does not parse YAML, TOML, or alternative configuration formats used by non-standard orchestrators.
FAQ
Does the scanner transmit any found tokens or file contents to an external server?
No. The script runs entirely on your local machine using standard Python modules. It performs no network calls, uploads no telemetry, and outputs findings strictly to your local standard output stream.
Why does the script flag my npx or uvx command as high severity?
Commands like npx @modelcontextprotocol/server-filesystem download and run the latest published version by default. If that package is modified or compromised upstream, your agent environment executes that code automatically. The scanner requires pinning a specific version tag (e.g., npx @modelcontextprotocol/server-filesystem@0.1.0) to pass without a finding.
Can the scanner automatically redact secrets or remove invisible characters from my files?
No. The scanner is an auditing tool, not an in-place mutation tool. It reports the rule ID, offending file path, line evidence, and suggested remediation, leaving actual file modifications to the developer.
Full version and the rest of the toolkit: AgentConfig Audit MCP and rules scanner on PyForge. Product page: https://py-forge.com/products/agentconfig-audit-mcp-and-rules-scanner
Top comments (2)
The 'npx @modelcontextprotocol/server-filesystem' example is the most important warning here. Running unpinned packages is a supply chain risk that most developers don't think about, especially in agent configs where it's easy to copy-paste an example without pinning.
Thanks, agreed. That's the one that worries me most too, because agent configs get copy-pasted straight from READMEs and npx quietly fetches whatever the latest version is at launch time. Pinning an exact version (
@modelcontextprotocol/server-filesystem@x.y.z) and reviewing bumps like any other dependency goes a long way. A release-age delay before adopting new versions helps too, so a freshly compromised publish doesn't land on your machine the same day.