Incident · malicious MCP server

The postmark-mcp backdoor: what a malicious MCP server looks like on a Mac, and why Kilobat wouldn’t have seen it

In September 2025, an unofficial npm package that let AI assistants send email through Postmark added one line to its code: from version 1.0.16, every email it sent carried a hidden blind copy to an address on the publisher’s own domain. It is a useful case precisely because the Mac never contacted anything unusual.

When: September 2025Sources checked: 1 November 2026

In short

  • Protection: Wouldn’t help

    The Mac only ever talked to Postmark’s API. The copies were delivered by Postmark’s mail servers, as ordinary email.

  • Agent guard: Wouldn’t help

    No paste site, tunnel, raw address or large upload to a new host. Sending email through an email API is what the tool was for.

  • Agent network log: Limited

    It would have listed the MCP server under the agent that started it, talking to api.postmarkapp.com, which is expected. The extra recipient lives inside the encrypted request.

What happened

The researchers at Koi Security who found it describe an npm package called postmark-mcp, built from the code of a repository of the same name maintained by Postmark’s owner, ActiveCampaign, and published by someone else. It was an MCP server: a small program an AI assistant such as Claude Desktop, Cursor or Claude Code starts, so the assistant can call its tools, here sendEmail and sendEmailWithTemplate.

The first fifteen versions worked as advertised. Version 1.0.16 added a Bcc field with a fixed address on the giftshop[.]club domain to every message the tool sent, so password resets, invoices or anything else the assistant emailed was copied. Koi put downloads at about 1,500 a week and estimated that thousands of emails a day were copied. When Koi contacted the publisher, the package was deleted from npm, which does nothing for copies already installed.

Postmark said the package was not theirs, that they hadn’t published an MCP server on npm, and that their API and services were unaffected. Snyk published the package’s code and the one-line difference between the clean 1.0.15 and the later versions.

Timeline

  1. 15 Sep 2025

    postmark-mcp 1.0.0 is published on npm (Snyk’s timeline).

  2. 15–17 Sep 2025

    A run of releases follows; 1.0.16 adds the hidden BCC, and 1.0.18 is the last noted release.

  3. Late September 2025

    Koi’s risk engine flags the change in behaviour; Koi publishes its findings and the package disappears from npm.

  4. 25 Sep 2025

    Postmark says the package isn’t theirs and advises rotating credentials sent by email; Snyk publishes its analysis and indicators.

What it looked like on the network

On the Mac, the MCP server is a node process started by the assistant, often through npx. To send an email it called Postmark’s API at api.postmarkapp.com over HTTPS, through Postmark’s own Node library, exactly as the clean versions did. The blind-copy address was one more field inside that encrypted request, and the message size barely changed.

The copy then travelled the way all email does: Postmark’s servers delivered it to the mail server for giftshop[.]club. No connection from the Mac went anywhere new, and no traffic pattern changed between 1.0.15 and 1.0.16.

Indicators

As the sources document them. Domains are text, never links, and are defanged ([.]) where the source defangs them. Most of this infrastructure is long gone: indicators help you check old logs, files and accounts, not block today’s campaigns.

IndicatorTypeWhere it showsNote
postmark-mcp 1.0.16 and laternpm packageMCP client configs, npm cacheNot Postmark’s own. Removed from npm in September 2025, but installed copies keep working.
phan@giftshop[.]clubEmail addressPostmark message activityThe fixed Bcc recipient. It never shows in the Mac’s network traffic.
giftshop[.]clubDomainMail logsSnyk suggests blocking it at egress while you check; it receives mail, not connections from your Mac.
api.postmarkapp.comHost (legitimate)Your MacThe only host the MCP server contacted, as the clean versions did.

What Kilobat would have shown or blocked

  • Agent network log. MCP servers an agent starts are part of its process tree, so the session would list node, the MCP server, connecting to api.postmarkapp.com, with bytes sent. That is what an email tool should do. It would be flagged first time only the first day any agent on the Mac used Postmark, and never for the hidden recipient.
  • Protection. Nothing to block, and nothing that should be. Postmark is a legitimate service, and when we checked on 1 November 2026 giftshop[.]club wasn’t on Kilobat’s threat lists, which wouldn’t matter here: the Mac never connects to it.
  • Agent guard. None of its rules apply. The upload cut is for more than 10 MB to a host no agent used before, and email requests are small.

Where Kilobat wouldn’t have helped

  • The theft happened inside an allowed request to an allowed service. No tool that watches connections, on the Mac or on the network, can see a field inside encrypted HTTPS.
  • The copies were delivered by Postmark’s mail servers, from Postmark’s network, not from the Mac.
  • The MCP server did exactly what the assistant asked, plus one thing. The assistant had no way to see the extra recipient either.
  • Kilobat never reads what apps send, by design, so it can’t tell a normal email from a copied one.

Check your Mac now

  1. List the MCP servers Claude Code is set up to start.

    claude mcp list
  2. Search the other assistants’ MCP settings for the package.

    grep -n "postmark-mcp" ~/Library/Application\ Support/Claude/claude_desktop_config.json ~/.cursor/mcp.json ~/.codeium/windsurf/mcp_config.json 2>/dev/null
  3. Look for copies npm installed globally or cached for npx.

    npm ls -g postmark-mcp; find ~/.npm/_npx -maxdepth 3 -type d -name "postmark-mcp"
  4. If you used it, remove it from every config, rotate the Postmark server token it had, and in Postmark’s activity for that server look for messages with a Bcc to giftshop[.]club.

  5. Treat anything sent through it as read by someone else: change passwords and revoke links or tokens that went out by email. Use the MCP servers a service links from its own documentation.

  6. With Kilobat, see which hosts each MCP server reaches. A server contacting hosts unrelated to its job is worth a look, even though this one didn’t.

    kilobat agent-log --all

Questions

Could Kilobat have caught this?

No. Every connection was one the tool was supposed to make. This is the kind of attack only code review, package reputation checks or the email service’s own logs can find.

Are MCP servers riskier than other npm packages?

They run with whatever access you give the assistant, and the assistant calls them many times without a person looking at each call. Koi’s point was that one changed line was enough.

Sources

Checked on 1 November 2026.

See what your agents and apps connect to

Kilobat is a Mac menu-bar app that names the app, process and agent behind every connection, keeps them away from known-bad hosts, and logs what each agent session reached.

Download for Mac ↓
brew install seifip/kilobat/kilobat