All posts
SecurityMCPOperations··7 min read

Tokens, headers, and the quiet leaks AI apps keep shipping

Bearer tokens in URLs, chat IDs in console logs, Authorization headers visible to every extension on the page. A pragmatic checklist for AI app security.

G

Gautam Manak

Founder, doc2mcp

Glass cards labelled Bearer Token, RLS Policies, Signed Webhooks, Audit Logs and Zero Trust orbiting a glowing shield with a padlock on a dark navy background.

The fastest way to leak an MCP token in 2026 is not a fancy attack. It’s a screenshot. A streamer Cmd-Shift-4s their editor’s settings panel, your bearer token sits there in plain text, and 90 seconds later someone is running your API on a free tier. This isn’t theoretical — we’ve watched it happen.

When you’re shipping AI tooling, the threat model is wider than a normal web app. The model sees secrets. The IDE renders them. The browser extension on top of your app reads the DOM. Logs land in three different places. Here’s the checklist we apply to every doc2mcp release.

1. Never put secrets in the URL

Query strings get logged everywhere — browser history, server access logs, error reporters, screen recorders. A token in a path becomes a token in 14 places you didn’t plan for. Use Authorization: Bearer … headers, always.

2. Strip the console

In dev, console.log(session) is convenient. In prod, it’s a beacon. We run a build-time check that fails the deploy if console.log ships in client bundles. The exceptions are structured logs that have been explicitly scrubbed.

  • Never log tokens, refresh tokens, or signed cookies.
  • Never log full request bodies on payment / auth routes — only the fields you need.
  • Chat IDs are PII-adjacent. Log a hashed prefix if you must, never the full ID alongside an email.

3. Security headers, properly set

We set the boring ones because they keep working when fancier defences fail:

http

Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()

X-Frame-Options: DENY alone kills an entire class of clickjacking attacks on auth modals. Costs you nothing if you don’t embed your app in iframes.

4. RLS or it didn’t happen

Supabase / Postgres Row-Level Security is the cheapest insurance policy in the industry. If your table is reachable from the public schema and RLS is off, you’re one missing WHERE from a full table dump. Turn it on, write the policy, write the negative test.

Every public table without RLS is a Tuesday-morning incident waiting for a slow Monday.

5. Sign your webhooks both ways

Razorpay, Stripe, and friends sign their outgoing webhooks. Verify them with constant-time comparison (timingSafeEqual), not string equality, or you’re vulnerable to timing oracles. When you send a webhook out, sign it the same way and document the algorithm clearly.

6. Rotation is a UX feature

If rotating an MCP token takes three pages, users will reuse the same token forever. We made it a one-click action with a “revoke previous in 60 seconds” warning. Now rotation actually happens.

Boring is the goal

Nothing in this list is novel. That’s the point. AI security incidents are rarely zero-days — they’re forgotten basics, applied a little too late. Build the checklist into your release template and revisit it quarterly.

Try it

Paste a docs URL. Get an MCP server in 90 seconds.

Free tier included. Works with Cursor, Claude, Windsurf, VS Code, Codex, and Zed.

Generate your MCP

Keep reading