AGENT PERMISSION CONFIG CHECK · RUNS IN YOUR BROWSER

Is your AI coding agent's permission config over-broad?

Paste your Claude Code .claude/settings.json, or an .mcp.json / .cursor/mcp.json / .vscode/mcp.json MCP-server config, and see every blanket Bash allow-all rule, unscoped destructive-command allow with no matching deny rule, MCP server reached over plain http://, and hardcoded-looking secret sitting in a server's env or headers instead of an environment-variable reference.

Nothing is uploaded. The JSON you paste is parsed entirely in this browser and never sent anywhere. This tool never launches a server's command and never contacts a server's URL — it only reads the text you give it.

1. Paste your config

Prefer a CLI, or want this as a CI gate?

Same logic, zero dependencies, one file — and it also flags whether a config carrying a hardcoded-looking secret is tracked by git:

node cli.mjs check                          # auto-discovers config files under .
node cli.mjs check --root               # auto-discovers under 
node cli.mjs check --file  [--file ...] # check specific file(s)
node cli.mjs check --json

Get cli.mjs — Node 18+, nothing to install. It reads only the config file(s) it finds or is told about, plus a best-effort local git ls-files check on the same file — no network call, ever. Exits 1 if any high/medium finding is present, so it works as a CI gate on the same pull request that adds or edits the config.

What's checked

CheckHow
Blanket Bash allow-allA permissions.allow entry of bare "Bash" or "Bash(*)" — every shell command runs with no prompt
Unscoped destructive commandAn unscoped allow entry for a command family whose blast radius is large (sudo, rm, curl, wget, chmod, eval, dd, mkfs, shutdown, reboot), with no matching deny rule for the same command
Plain-http MCP serverAn mcpServers entry whose url starts with http:// instead of https://
Hardcoded-looking secretAn mcpServers entry's env or headers value that is a literal matching a known API-token format (high confidence) or a long, space-free, unrecognised literal (medium confidence), instead of an ${VAR}-style reference
No deny rules at allInformational only: allow is non-empty and deny is completely empty, so nothing blocks a future edit from widening allow

This is a static shape-matcher, not a runtime guard and not a secret-verification service — it never launches a server's command, never contacts a server's url, and never checks whether a flagged value is a real, live credential. A clean result is not a certification that your config is safe; a flagged one is not proof a value is a secret. See why these configs are worth linting, and where this checker's own edges are, or this checker vs. reading the JSON by eye.

Common questions

Why does a Bash allow-all rule matter?

Claude Code's permission rules scope a tool by an optional pattern, e.g. Bash(git diff:*). A bare "Bash", or a pattern whose scope is itself a wildcard, grants every shell command with no prompt at all — functionally the same as disabling permission prompts for the one tool an agent can use to do almost anything else on the machine, including reading other credentials, modifying git history, or making arbitrary network requests via curl.

Why flag a plain http:// MCP server URL?

An MCP server reached over http:// sends every request, including any bearer token or API key in its headers, unencrypted on the wire. Anyone on the same network path can read or tamper with it. This is worth catching mechanically because a config that started as a local http://localhost dev server during setup is easy to copy into a shared or committed file without ever switching to https://.

Does this tool run, connect to, or attack anything the config describes?

No. It only reads the JSON text you give it (pasted, or a local file when using the CLI) and looks for known-risky shapes in it — it never launches an MCP server's command, never makes a network request to a server's url, and never sends a value anywhere to test whether it is a real, live credential.

How confident is the hardcoded-secret check?

A value matching a known token format (an Anthropic, OpenAI, GitHub, Slack, AWS, Google, GitLab, or npm token prefix) is reported at high confidence. A long, space-free, unrecognised literal is reported at medium confidence — flagged because it looks more like a token than a normal setting, not because it is proven to be a secret. Either way, verify by reading the value yourself before rotating anything.