GATE020: Environment passthrough exposes multiple credentials to one server
A single MCP server is handed three or more credentials, or an entire environment file.
- Name
Severity- Type
- High
- Description
Default severity. An individual finding may be reported higher or lower when the surrounding configuration justifies it.
- Name
Capabilities- Type
- secrets
- Description
Capability classes this rule reasons about.
- Name
Explain locally- Type
- gate explain GATE020
- Description
The same text, in your terminal, with no network access.
What Gate detected
Gate found an MCP server whose configuration supplies three or more distinct credentials, or which is pointed at an environment file such as .env.
Why this matters
Each credential handed to a server is a credential that server can lose. Bundling several into one process means a single compromised or malicious MCP server, or a single prompt injection that reaches a tool on it: yields all of them at once. This is the difference between an incident scoped to one integration and an incident scoped to your whole stack. An .env file is worse still: it is every secret the application has, handed over as a unit, including the ones the server has no use for.
Example
This is the shape of configuration that triggers the rule.
{
"mcpServers": {
"kitchen-sink": {
"command": "node",
"args": ["./tools/server.js", "--env-file", ".env"],
"env": {
"GITHUB_TOKEN": "${env:GITHUB_TOKEN}",
"AWS_SECRET_ACCESS_KEY": "${env:AWS_SECRET_ACCESS_KEY}",
"STRIPE_SECRET_KEY": "${env:STRIPE_SECRET_KEY}",
"OPENAI_API_KEY": "${env:OPENAI_API_KEY}"
}
}
}
}
Remediation
Split the server, or narrow what it receives. Give each MCP server exactly the credentials its own tools need and nothing else. Never pass a shared .env file to a server: enumerate the variables explicitly so that the list is reviewable.
Suppressing this rule
If this finding is acceptable in your repository, record why alongside the suppression:
gate.config.ts
export default defineConfig({
ignore: [
{
rule: 'GATE020',
reason: 'Why this is acceptable here',
},
],
})
Gate refuses to apply an ignore entry with no reason. The reason is the only thing that will tell the next person whether the suppression is still true.