Skip to main content
← All rules

mcp-scan rule

Data exfiltration vector

exfiltration-vectorhigh

What mcp-scan saw

Three separate triggers in the AST scanner share this id. Per argument, a dotted-quad IP or a domain-shaped token that is not path-like, not a known file extension, and not in allowedDomains pushes MEDIUM. Then HIGH fires when a ${VAR} reference and a network endpoint both appear in the arguments, and again when the arguments carry filesystem access (/, ~, a /Users or /home prefix, or a .ssh or .env substring) alongside any http(s):// in the command.

Why it fires

The first trigger just inventories outbound endpoints. The two HIGH triggers are about pairing: a variable next to a destination means a value you consider secret enough to hold in env is being handed to a host, and filesystem reach next to a network reach means one process can do both halves of a transfer without anything in between to stop it.

When this is a false positive

  • The domain shape is scheme-optional, so any dotted token with a 2-plus character last segment counts. A version pinned as pkg@1.2.30 matches, since 30 is two characters and is not in the file-extension allowlist.
  • The filesystem-plus-network trigger fires on the standard filesystem server config: a /Users path argument plus any https:// anywhere in the command line is enough, and that is what the reference server-filesystem setup looks like.
  • A file path with an uncommon extension, for example config.internal or data.parquet, is read as a domain because the extension allowlist is a fixed set of about 50 entries.
  • The ${VAR}-plus-endpoint trigger does not check what the variable holds. A ${PORT} or ${REGION} next to an API base URL is the same signal as a token next to an attacker host.

How to fix it

  1. Populate allowedDomains in .mcp-scan.json with the hosts this server is meant to reach. The scanner matches on domain suffix, so listing example.com covers api.example.com but not evil-example.com.
  2. Re-scan. Allowed hosts stop counting as external endpoints and both the MEDIUM inventory finding and the network half of the HIGH triggers drop out.
  3. For the filesystem-plus-network case, narrow the path argument to the project directory. A path deeper than the /Users or /home root no longer matches the filesystem test.
  4. If a version pin or a file path is being read as a domain, move it out of args into an env var, or pin with a separate --version argument.
  5. If the pairing is real, split the server so the tool that reads the disk is not the tool that reaches the network.