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:
npx or uvx packages without fixed versions), allowing upstream package updates to execute unreviewed code on your machine./), home directories (~), or entire user profiles.
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.
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.
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.
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:
python agentconfig_audit_mcp_and_rules_scanner.py ~/.cursor/mcp.json
The audit tool inspects two main surfaces: structured JSON MCP server configurations and plaintext rule/instruction documents.
When parsing mcpServers configurations, the scanner evaluates command arguments against dangerous system roots and verifies if package runners include immutable version specifications:
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.
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:
if isinstance(env, dict):
for env_key, env_val in env.items():
if not isinstance(env_val, str):
continue
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.
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:
\u200B), non-joiners (\u200C), joiners (\u200D), and byte order marks (\uFEFF).\u202E), which can visually invert displayed text while preserving a different underlying instruction.ignore all previous instructions, do not follow safety guidelines, or injected XML tags like <system-instruction>.
While this tool highlights high-risk patterns, it has specific design limitations based directly on its codebase:
SECRET_REGEXES or an obfuscated prompt injection string that avoids common phrasing will not be caught.$ or ${...} to avoid false positives. It does not inspect whether the parent shell environment securely populates those variables.discover_agent_files() only checks for a predefined set of filenames (such as .cursorrules, agents.md, claude.md, and .rules extensions). Rules stored under custom or unexpected file extensions will be skipped unless explicitly passed as target paths.
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