← Back to Blog
· 8 min read · API Stronghold Team

Your MCP Settings Tool Just Handed Your Secrets to the Model

Cover image for Your MCP Settings Tool Just Handed Your Secrets to the Model

On 5 September 2026, a vendor emailed customers with a precaution. Until that day, their MCP server returned every plugin’s settings to any connected AI agent. Password fields. Polling headers. The raw values, in plaintext.

There was no attacker. Nobody exploited a zero-day. An engineer connected Claude Code or Cursor the way the docs tell you to, the agent called a perfectly ordinary “show me the settings” tool, and the secret came back in the tool result. Workloft Labs wrote it up as a customer who got that email, rotated, and then pointed out the part that should bother you: almost every MCP server can do this, and most operators have never checked.

A few weeks earlier, ArcadeDB shipped the same class of bug under a CVE. CVE-2026-67357 is a settings tool that returned the high-availability cluster token in cleartext. That token is enough to impersonate root through a couple of headers. CVSS 7.7. Fixed in 26.7.3. It is not a database bug that MCP happened to expose. The tool was designed to return settings, and nobody filtered the output for secrets.

If you have been treating MCP security as prompt injection plus “don’t install random servers,” you are looking at the wrong half of the protocol.

The model only knows what the tool returns

MCP does not give a language model a dashboard. It gives it tools. list_resources. get_config. describe_cluster. The model cannot peek at your admin UI. It only sees the JSON (or text) that comes back from a tool call.

So the moment you ship a read tool that answers “what is the current configuration,” you have to decide, field by field, what the model is allowed to see. Miss one secret-typed field and it goes out like any other value. A key sitting inside a URL counts. An Authorization header stuffed into a polling config counts. A cluster token named clusterToken in a settings blob counts.

This is why the Workloft note called it a class, not a bug. A settings tool is the most natural thing in the world to build. Every integration has one. The default serialization path is “dump the object.” Password-typed fields in a UI are a display hint. They are not an access-control boundary.

Once that value is in a tool result, it is in the model context. From there it can land in:

  • the chat transcript the user never scrolls back to
  • the MCP client’s session log
  • the model provider’s request payload
  • any downstream tool the agent calls next, if it “helpfully” passes config along

Workloft’s honest answer to “was I affected” was not “check the logs.” It was “assume yes and rotate,” because the evidence that would say otherwise often does not exist. Tool-call logging is still optional in a lot of clients. MCP08 in the OWASP MCP Top 10 is literally “no logging of tool invocations, impossible incident response.”

August already told you this was coming

The ArcadeDB case is the named one. August also produced CVE-2026-73498 in Atlassian MCP: an authenticated client gets an arbitrary file read across everything the server process can reach, with credentials and environment variables called out in the advisory. Different mechanism, same ending. The MCP surface can read secrets the operator never intended to put in front of a model.

None of those CVEs required a jailbreak. They required a connected agent and a tool that returned too much.

That is a different threat from tool poisoning, where a hostile description hijacks what the agent does. Here the tool is doing exactly what you asked. The failure is a serialization default. Benign server, benign tool, benign read, secret still gone.

Check yours in five minutes

You do not need a red team for this. You need to treat every MCP server your agents touch as something that will hand the model whatever its tools return.

  1. List the MCP servers your agents actually connect to. IDE plugins, homegrown servers, the one someone added to .mcp.json last Tuesday.
  2. Find the read tools that return configuration, settings, or state. Call one. Read the output yourself.
  3. If any field contains a key, token, header, password, or a credential buried in a URL, rotate it. Assume it has been in a model context.
  4. If you build MCP servers, redact on the server. Never in the client. Never in a system prompt that says “please don’t echo secrets.”

A minimal redaction layer looks like this. It is boring on purpose.

const SECRET_KEYS = /^(password|secret|token|api[_-]?key|authorization|auth[_-]?header|cluster[_-]?token)$/i;

function redact(value, key = "") {
  if (value && typeof value === "object") {
    if (Array.isArray(value)) return value.map((item) => redact(item));
    const out = {};
    for (const [k, v] of Object.entries(value)) {
      out[k] = SECRET_KEYS.test(k) ? "[redacted]" : redact(v, k);
    }
    return out;
  }
  if (typeof value === "string" && /https?:\/\/[^/@:]+:[^/@]+@/i.test(value)) {
    return value.replace(/(\/\/[^/@:]+:)[^/@]+@/, "$1***@");
  }
  return value;
}

// Inside the tool handler, before you return
return { content: [{ type: "text", text: JSON.stringify(redact(settings)) }] };

That catches the ArcadeDB-shaped bug and the “password field in plugin settings” bug. It does not catch a tool that concatenates Bearer ${process.env.STRIPE_SECRET} into a debug string named status. For that you need a rule: secret values never appear in tool results, even under a friendly key. Return a reference (stripe_key_id: "k_9f3"), not the material.

If you cannot redact, do not expose the tool. A settings dump that cannot be filtered should not be an MCP tool.

Redaction is necessary. It is not sufficient.

Here is the part teams skip after they patch the settings tool.

Even a perfect redaction layer only stops secrets from leaving through that tool. The MCP server process still has them. They are in the environment, in mcp.json, in a .env the process loaded at boot. GitGuardian’s 2026 Secrets Sprawl report found 24,008 unique secrets sitting in MCP configuration files on public GitHub. Trend Micro sampled MCP docs and found around 48% recommending insecure storage, mostly plaintext files.

So you get this stack:

  • the agent never needed the Stripe key to “check settings”
  • the settings tool used to return it anyway
  • after you redact, the key is still in the server’s environment
  • the next path traversal (see Atlassian) or SSRF (see Azure MCP CVE-2026-26118, facebook-ads-mcp-server CVE-2026-19956) reads the environment or the metadata service instead

BlueRock’s early-2026 scan of public MCP servers put SSRF potential at 36.7% and no authentication at 41% of the 518 they tested for auth. Of the ones that did require credentials, 53% used static API keys or personal access tokens. The settings-tool leak is one door. The process environment is the rest of the house.

We already argued that MCP servers should not hold long-lived API keys. This week’s disclosures are why. A tool result is just another way a long-lived secret leaves the box.

If a settings tool can return it, your agent can leak it

Keep real API keys in the vault. Give MCP servers session-scoped tokens that expire in minutes. A leaked tool result should be a placeholder, not a live key.

No credit card required

What the agent should hold instead

The pattern is the same one we use for phantom tokens. The agent (and the MCP server in front of it) never receives the upstream credential. It receives a short-lived, scoped handle. The real key stays at a proxy boundary. The proxy attaches it on the way out.

Concretely, for an MCP server that talks to Stripe and GitHub:

  1. Register the MCP server as an agent identity. Freeze its scopes at issuance: read:stripe:invoices, read:github:prs:status. No writes unless the task needs them.
  2. Issue a session token at connect time with a hard TTL. Fifteen minutes is a reasonable default. The server gets svt_..., not sk_live_....
  3. On each upstream call, the vault validates the session token, swaps in the real key server-side, and forwards. The MCP tool result contains Stripe JSON, never the key.
  4. If a settings tool, a path traversal, or a prompt-injected agent dumps process env, the attacker gets a phantom token that is already dying.
curl -X POST https://server.apistronghold.com/mcp/servers/$SERVER_ID/tokens \
  -H "Authorization: Bearer $AS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "ttl_seconds": 900,
    "scopes": ["read:stripe:invoices", "read:github:prs:status"]
  }'

What comes back is a session-scoped token with an expiry. Put that in the MCP runtime, not the Stripe secret. When the session ends, the token is dead. When you revoke the MCP server, every outstanding token dies with it.

That is the difference between “we redacted the settings tool” and “a settings tool cannot return a live key because the process does not have one.”

OWASP MCP01 is token mismanagement and secret exposure. MCP07 is missing authentication. MCP10 is context over-sharing. The September disclosures sit on all three. Redacting tool output covers MCP10. Short-lived scoped tokens cover MCP01. Neither replaces the other.

What to do on Monday

Call the settings tool. Read what comes back. Rotate anything you would not paste into a stranger’s chat window.

Then stop storing upstream API keys in the MCP server’s environment. If the server needs to call Stripe, it should present a session token to a broker and let the broker hold sk_live_. If you cannot do that this week, at least cap the key you do store: one provider, one verb, a TTL you will actually enforce.

The vendor in the 5 September email disclosed fast and told customers plainly. ArcadeDB shipped a fix. That is the easy part. The uncomfortable part is the servers that have not had their external researcher yet. Those are probably the ones your agents already talk to.

API Stronghold is a zero-knowledge credential vault for AI agents and MCP servers. Real keys stay in the vault. Agents get phantom tokens. A tool result cannot leak what the process never held.

Stop putting live API keys in MCP tool results

API Stronghold issues session-scoped tokens for MCP servers. Upstream keys never enter the agent, the tool output, or the model context.

No credit card required

Keep your API keys out of agent context

One vault for all your credentials. Scoped tokens, runtime injection, instant revocation. Free for 14 days, no credit card required.

Get posts like this in your inbox

AI agent security, secrets management, and credential leaks. One email per week, no fluff.

Your CI pipeline has permanent keys sitting in env vars right now. Scoped, expiring tokens fix that in an afternoon.

One vault for all your API keys

Zero-knowledge encryption. One-click sync to Vercel, GitHub, and AWS. Set up in 5 minutes — no credit card required.