Repository navigation
Description
I was doing a security audit of the official MCP servers and stumbled into something that gave me pause.
The get-env tool in server-everything returns the entire process.env object -- unfiltered, unsanitized, with no parameter required. Call it with empty args and you get ~6KB of every environment variable on the host machine.
What I saw
The tool's handler is literally:
server.registerTool(name, config, async (args): Promise<CallToolResult> => {
return {
content: [{ type: "text", text: JSON.stringify(process.env, null, 2) }],
};
});inputSchema is {}, so zero arguments triggers it. No annotations, no filtering, no opt-in.
What this leaks
On a typical Windows dev box this dumps:
USERNAME,USERDOMAIN,COMPUTERNAME-- host and user identityPATH,APPDATA,LOCALAPPDATA-- full directory structureHOMEPATH,USERPROFILE-- home directory path- Any API keys the user happens to have in env:
OPENAI_API_KEY,ANTHROPIC_API_KEY,GITHUB_TOKEN, etc.
The "etc" is the problem. You can't know what's in someone's env.
Why this matters for an official example
server-everything is the demo server. People copy it to learn the protocol. If get-env stays as-is, that pattern propagates. I've already seen community servers that copied the "return raw env" pattern because "the official one does it."
Also: the tool has no annotations object, so an MCP client has zero signal that this is a high-sensitivity read operation.
Suggested fixes
Option 1 (safest): Require a specific key parameter.
inputSchema: {
type: 'object',
properties: {
key: { type: 'string', description: 'Specific environment variable name' }
},
required: ['key']
}Option 2 (if you want to keep the bulk dump): Filter known-sensitive patterns.
const SENSITIVE = /TOKEN|KEY|SECRET|PASSWORD|CREDENTIAL|AUTH/i;
const filtered = Object.fromEntries(
Object.entries(process.env).filter(([k]) => !SENSITIVE.test(k))
);Option 3 (annotation-only, weakest but still useful): Add readOnlyHint: true and a big warning in the description that this returns the full environment.
My vote is Option 1. "Get one env var by name" is still a useful demo of a tool that reads from the host, without being a foot-gun.
Happy to open a PR if the maintainers agree on a direction.
Activity
cliffhall commentedon Oct 19, 2026
Triage: Priority Medium (total 7)
This is a security report, so it is handled by the maintainers and the details aren't discussed here. If you have more to add, please use the advisory form rather than this thread.
Board: Servers V2 (#43), Status
Incoming, awaiting maintainer review (no milestone yet). Part of the backlog triage in #4875.cliffhall commentedon Oct 20, 2026
Prior work, from the PR backlog triage (#4877). These outside pull requests addressed this issue against the pre-refactor code:
They are being closed as part of the backlog triage in #4875, since the repository now takes issues rather than outside PRs and their diffs predate the v2 refactor. They stay readable and serve as prototypes for the fix here. Thank you to their authors.
cliffhall commentedon Oct 27, 2026
Fixed by #5293, merged into
v2/main:get-envnow masks the values of credential-like names unlessGET_ENV_INCLUDE_SECRETSis set. Ships in v2.2.0 (tracker #5266).fix(everything): get-env masks credential-like values by default