MCP security checklist: eight ways it goes wrong, and how to check yours
Short answer: an MCP server is code that your agent trusts and runs with your rights, configured by a plaintext file. Most incidents so far come from a handful of avoidable things: secrets in that file, unpinned or malicious servers, outdated clients and glue tools, and giving the agent more access than the task needs. Paste your config into the free checker to find the first four in seconds; the checklist below covers the rest.
Every item below is tied to something that happened or a published advisory (read 2026-11-01). The checker is static and runs in your browser; it cannot judge a server’s code, which is why the last section is about what to do beyond it.
Eight ways it goes wrong
| # | Failure | Real example | What to do |
|---|---|---|---|
| 1 | Secrets written into the config | GitGuardian found 24,008 unique secrets in MCP-related config files on public GitHub, 2,117 of them valid (report) | Reference secrets by file path or environment variable; never paste a token into JSON |
| 2 | A server that turns malicious | postmark-mcp on npm built trust over 15 versions, then version 1.0.16 silently BCC’d every email it sent to an attacker; about 1,500 downloads in a week per Koi Security (The Register) |
Pin exact versions, update on purpose, read the diff for tools that send data |
| 3 | Unpinned launch commands | npx -y some-server fetches the newest release at every start, so failure 2 reaches you on the next launch |
npx -y [email protected], uvx pkg==1.2.3, or a vendored binary |
| 4 | Vulnerable glue tools | mcp-remote before 0.1.16 allowed OS command injection when connecting to an untrusted MCP server, CVE-2025-6514, CVSS 9.6 (NVD, advisory) |
Keep clients and bridges current; run a dependency check on them like any other code |
| 5 | Config files that change under you | Cursor 1.2.4 and earlier let an attacker swap a trusted MCP entry for a malicious command in a shared repo (CVE-2025-54136); before 1.3.9 a prompt injection could create a new .cursor/mcp.json without approval (CVE-2025-54135) (NVD, NVD) |
Update the client; treat mcp.json in a cloned repo as untrusted code; review config diffs |
| 6 | The lethal trifecta in one server | The GitHub MCP server could read private repos and public issues; a malicious public issue tricked the agent into leaking private repo data (Willison, May 2025) | Don’t combine private data, untrusted input and an outbound channel in one agent session |
| 7 | Auto-approve and broad access | Tools on an always-allow list run without a human seeing the call; a filesystem server rooted at / exposes keys and history |
Auto-approve only reviewed read-only tools; scope filesystem roots to the project |
| 8 | Plain http and shell wrappers | A remote server over http:// leaks traffic; bash -c "curl … | sh" runs anything on every start |
https:// only; run binaries directly with list arguments |
The checklist
Config file
- No token, key or password is written in the file (the checker flags token-shaped values and secret-named variables, including in headers, arguments and URL query strings).
- Secrets are referenced: a
0600file path, or an environment variable the client expands. - The file is not in version control, or contains no secrets if it is.
Servers
- Every
npx/uvx/bunxserver is pinned to an exact version. - You can say, for each server, who maintains it and what it can reach. Remove the rest.
- Servers that send data out (email, chat, HTTP) are separate from servers that read private data.
- Remote servers use
https://and a credential scoped to what the task needs.
Client and bridges
- The client (Cursor, Claude Code, VS Code, etc.) is on a version past the fixes above.
-
mcp-remote, if you use it, is 0.1.16 or later. - You treat an MCP config that arrives with a cloned repository as untrusted until you read it.
Agent permissions
- Auto-approve lists contain only reviewed, read-only tools.
- The agent runs with read-only credentials unless it must write, and writes are limited to named resources.
- You can review what the agent did (an audit log you actually read).
The checker, and what it can’t do
Paste your config and it reports each finding with a fix. It runs entirely in your browser (no request is made with your config), shortens any secret it finds to a prefix, and supports the JSON shapes used by Claude Desktop, Cursor, Windsurf, VS Code (servers) and .claude.json. Codex’s TOML is not supported yet.
It cannot tell you:
- whether a server’s code is honest (failure 2 would pass a static check on any single version);
- whether its tool descriptions are trying to steer the agent;
- what a remote server does with your data;
- whether your client has an unpatched vulnerability.
For those, pinning, review, least privilege and a sandbox around the agent are the controls.
How Dynv’s own MCP server lines up
Dynv ships a local MCP server (dynv mcp) that was designed against this list. Documented and shipped: a read-only default and --read-only; masked values unless --allow-reveal; writes only for variables named in --allow-keys, with code-loading variables like NODE_OPTIONS always refused; dry_run on every write; the token read from a 0600 file via DYNV_MASTER_TOKEN_FILE, with a startup warning if it came from an inline environment variable; and dynv doctor mcp, which validates the client’s config shape and runs the server through initialize and tools/list. Its documented limits are in the MCP docs: a value an agent sets passes through the agent, and an agent that can read files as your user may read the token file. The checker’s “load Dynv’s recommended setup” button shows a config that passes with no findings, and our tests assert that every published snippet does.
For the bigger picture, see AI agent secrets management.
Facts last verified . Spotted an error? Tell us.