{"slug": "auditing-mcp-configurations-and-ai-agent-rules-for-security-risks", "title": "Auditing MCP Configurations and AI Agent Rules for Security Risks", "summary": "A developer released agentconfig_audit_mcp_and_rules_scanner.py, a self-contained Python standard-library script that audits Model Context Protocol server configurations and AI agent rule files for security risks. The tool flags overly broad filesystem access (such as root, home directories, or Windows drive roots) as CRITICAL findings, detects unpinned npx/uvx package executions that could run unreviewed upstream code, and scans environment variables for embedded credentials like GitHub, AWS, and Slack tokens. It targets configs used by tools including Claude Desktop, Cursor, and Windsurf, and requires Python 3.8 or later with no third-party dependencies.", "body_md": "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`. \n\nHowever, these configuration files can introduce serious security vulnerabilities into your environment:\n\n`npx` or `uvx` packages without fixed versions), allowing upstream package updates to execute unreviewed code on your machine.`/`), home directories (`~`), or entire user profiles.\n`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.\n\nThe 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.\n\nDownload 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.\n\nYou can display the built-in command options by invoking Python directly:\n\n```\npython agentconfig_audit_mcp_and_rules_scanner.py --help\n```\n\nTo 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:\n\n```\npython agentconfig_audit_mcp_and_rules_scanner.py .\n```\n\nYou can also target specific standard system locations where tools like Claude Desktop or Cursor store their MCP definitions:\n\n```\n# Auditing a specific configuration file\npython agentconfig_audit_mcp_and_rules_scanner.py ~/.cursor/mcp.json\n```\n\nThe audit tool inspects two main surfaces: structured JSON MCP server configurations and plaintext rule/instruction documents.\n\nWhen parsing `mcpServers` configurations, the scanner evaluates command arguments against dangerous system roots and verifies if package runners include immutable version specifications:\n\n```\n# Check Overly Permissive Filesystem Paths\nif isinstance(args, list):\n    for arg in args:\n        if not isinstance(arg, str):\n            continue\n        expanded = os.path.expanduser(arg)\n        for pat in BROAD_PATH_PATTERNS:\n            if re.match(pat, arg.strip()) or re.match(pat, expanded.strip()):\n                findings.append(\n                    Finding(\n                        rule_id=\"MCP-BROAD-FILESYSTEM-ROOT\",\n                        title=f\"Overly Broad Filesystem Access in '{server_name}'\",\n                        severity=\"CRITICAL\",\n                        file_path=str(file_path),\n                        line_number=None,\n                        description=(\n                            f\"Server '{server_name}' is assigned an expansive filesystem path '{arg}'. \"\n                            \"Agents interacting with this server obtain arbitrary read/write access to user \"\n                            \"home directories or root.\"\n                        ),\n                        evidence=f\"arg: {arg}\",\n                        remediation=\"Scope the server access specifically to a dedicated subproject folder.\",\n                    )\n                )\n```\n\nThe 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.\n\nSimilarly, 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.\n\nThe 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:\n\n```\n# Check Plaintext Credentials in 'env'\nif isinstance(env, dict):\n    for env_key, env_val in env.items():\n        if not isinstance(env_val, str):\n            continue\n        # Skip template variables like ${VAR} or $VAR\n        if (env_val.startswith(\"${\") and env_val.endswith(\"}\")) or env_val.startswith(\"$\"):\n            continue\n\n        for regex, label in SECRET_REGEXES:\n            if re.search(regex, env_val) or (\n                any(s in env_key.upper() for s in (\"TOKEN\", \"KEY\", \"SECRET\", \"PASSWORD\", \"AUTH\"))\n                and len(env_val) >= 12\n            ):\n                findings.append(\n                    Finding(\n                        rule_id=\"MCP-PLAINTEXT-SECRET\",\n                        title=f\"Exposed Secret in Server '{server_name}' Env\",\n                        severity=\"CRITICAL\",\n                        file_path=str(file_path),\n                        line_number=None,\n                        description=(\n                            f\"Environment variable '{env_key}' contains a hardcoded plaintext secret ({label}).\"\n                        ),\n                        evidence=f\"{env_key} = {env_val[:4]}...{env_val[-4:] if len(env_val) > 8 else ''}\",\n                        remediation=\"Extract credentials to the system shell environment or a secure local keyring and reference via variable expansion.\",\n                    )\n                )\n                break\n```\n\nIf the value uses variable expansion syntax such as `${MY_SECRET}` or `$MY_SECRET`, the scanner treats it as externalized and skips it.\n\nFiles 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:\n\n`\\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>`.\nWhile this tool highlights high-risk patterns, it has specific design limitations based directly on its codebase:\n\n`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.\n**Does the scanner transmit any found tokens or file contents to an external server?**\n\nNo. 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.\n\n**Why does the script flag my `npx` or `uvx` command as high severity?**\n\nCommands 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.\n\n**Can the scanner automatically redact secrets or remove invisible characters from my files?**\n\nNo. 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.\n\nFull version and the rest of the toolkit: [AgentConfig Audit MCP and rules scanner on PyForge](https://py-forge.com/products/agentconfig-audit-mcp-and-rules-scanner?utm_source=devto&utm_medium=article&utm_campaign=agentconfig-audit-mcp-and-rules-scanner). Product page: [https://py-forge.com/products/agentconfig-audit-mcp-and-rules-scanner](https://py-forge.com/products/agentconfig-audit-mcp-and-rules-scanner)", "url": "https://wpnews.pro/news/auditing-mcp-configurations-and-ai-agent-rules-for-security-risks", "canonical_source": "https://dev.to/alessio99xx/auditing-mcp-configurations-and-ai-agent-rules-for-security-risks-nc5", "published_at": "2026-11-01 21:39:14+00:00", "updated_at": "2026-11-01 21:52:23.513462+00:00", "lang": "en", "topics": ["ai-agents", "agent-protocols", "ai-safety", "developer-tools", "ai-tools"], "entities": ["Model Context Protocol", "Claude Desktop", "Cursor", "Windsurf", "GitHub", "AWS", "Slack"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/auditing-mcp-configurations-and-ai-agent-rules-for-security-risks", "markdown": "https://wpnews.pro/news/auditing-mcp-configurations-and-ai-agent-rules-for-security-risks.md", "text": "https://wpnews.pro/news/auditing-mcp-configurations-and-ai-agent-rules-for-security-risks.txt", "jsonld": "https://wpnews.pro/news/auditing-mcp-configurations-and-ai-agent-rules-for-security-risks.jsonld"}}