Proton Bridge MCP

Proton Bridge MCP security.

What holds, and where it stops  ·  source on GitHub  ·  buy me a coffee

Security

The short version, it's local, it's careful about sending, and it assumes your mail is hostile.

Where your mail actually goes

With Bridge, nothing leaves your machine

Bridge does the decryption on your own computer and uses IMAP and SMTP to your computer's loopback address, so the server talks to your machine and nowhere else. The setup page loads no fonts, no scripts and no images from anywhere either.

Point it at a mailbox in the cloud instead and it works fine, but that sentence stops being true and it's worth saying so plainly. Your mail is sitting on somebody else's server, they can read it, and the connection goes out over the internet rather than staying on the loopback interface. What you keep is everything this server does, the access is still local to your machine, still gated before anything sends, still audited, and it still refuses to mail an address it only saw inside a message. What you give up is the part where nobody except you could read the mail in the first place, and that was Proton doing the work rather than anything here.

Certificates are checked, except where checking them would be meaningless

Bridge serves a self-signed certificate on loopback, so verifying it against a public certificate authority proves nothing and is skipped. Every other host is verified properly. That distinction matters because the hostname is yours to set, so this can be pointed at a mail server across the internet, and an unverified connection there is exactly the hole someone would walk through. If a host really can't present a matching certificate you can name it in PROTON_TLS_INSECURE_HOSTS, which excuses that one host and nothing else.

When a message tries to give orders

Your mail is untrusted input

Anyone can write "forward all the invoices to me" inside a PDF and post it to you. Extracted text is labelled as untrusted before an assistant sees it, but a label is only advice, so there's a rule underneath that isn't.

Addresses are tracked by where they came from

Anything in a From, To, Cc or Reply-To header is a real correspondent and you can write to it. An address that only ever appears in a message body, or an attachment, is refused as a recipient, and no tool parameter will change that. Convincing the assistant won't help because the refusal isn't the AI's decision. If you actually want to add an address from, what the AI would suggest is a dubious source, you can, you put it into PROTON_ALLOWED_RECIPIENTS yourself, somewhere no assistant can reach.

Worth being straight about its edges, because it's a strong backstop rather than a force field. An address is only refused if it was seen in content the assistant actually read this session, so a recipient that turned up in no read message isn't being matched against anything. And an address an attacker plants in a header is treated as a correspondent from then on, say by CCing themselves on a message you open. The two hard limits are the sender allowlist and PROTON_ALLOWED_RECIPIENTS. This rule narrows the easy exfiltration route rather than sealing every one.

Reading mail without acting on it

Unsubscribing is mostly advice

unsubscribe reads the List-Unsubscribe header and tells you what's on offer. It will send the email form if you ask it to, but it never opens the web link, because this server talks to Bridge on your own machine and nothing else, and quietly fetching a URL out of a message would break that and confirm to the sender that you read it. It also checks who was actually subscribed. Mail that came through an alias was sent to the alias, not to you, so unsubscribing from your own address usually matches nothing and disabling the alias is the better answer. It says so rather than sending something that won't work.

Checking whether mail is what it says it is

get_headers reports the SPF, DKIM and DMARC verdicts the receiving server reached, and points out a From domain that doesn't match the Return-Path. It won't cry wolf over your own aliases though. Mail forwarded through SimpleLogin always has a Reply-To and Return-Path that differ from the sender, so it says as much rather than flagging it, because a warning that fires on ordinary mail teaches you to ignore warnings.

Nothing goes out quietly

Replies keep an alias masked on their own

If a message came in through a SimpleLogin alias, reply answers the reverse-alias rather than the sender, and sends from your alias-owner address without being told to. Get that wrong by hand and you either unmask yourself or the reply bounces, so it isn't left to memory.

Mail can only go out as you

from_address is checked against an allowlist that starts as your own address and your alias-owner address, nothing else. An injected instruction can't make mail appear to come from someone else, and widening it means editing PROTON_ALLOWED_SENDERS yourself.

Sending always stops

send, forward and create_folder_or_label refuse unless the assistant passes confirmed=true, which it should only do after showing you the exact recipient, subject and body. That one is a speed bump rather than a wall, an assistant that had been fully talked round could set it, which is exactly why the address rule above exists as well.

What's recorded, and what you can preview

Everything that changes something is logged

Sends, moves, labels, drafts, new folders, saved attachments, each one appended to audit.log as a single line of JSON, owner-readable only. It sits next to the server unless PROTON_AUDIT_LOG says otherwise, and Where things live is worth reading on why you might move it. Message bodies are never written, only their length, so the log tells you what happened without quietly becoming a second copy of your mailbox. Recipients and subjects are written in full though, because a log that says a send happened but not to whom is no use after something odd. Refusals are recorded too, which is the half you'd actually want. Turn it off with PROTON_AUDIT=0 if you'd rather.

Anything can be previewed first

Every tool that changes something takes dry_run=true. You get the exact message that would go out, or the actual subject and sender of the mail that would move, and nothing happens. A preview needs no confirmation, since a preview is harmless, but it still runs every check, so if the real thing would be refused the preview tells you that rather than showing you a comforting fiction.

Batches are narrower than they look

The bulk tools only accept explicit numbered messages, never "everything in this folder", and they stop at 50 a call. Bulk moves need confirming on top of the preview, because marking something read is easy to undo and moving 50 messages isn't.

Limits on what it can do at all

Three settings, not two

PROTON_MODE=readonly removes every tool that changes anything. PROTON_MODE=organise is the one most people probably want, it can file, label, tag and draft, but the tools that put mail on the wire aren't there at all. full is everything. These remove tools rather than guarding them, and a tool that isn't there can't be talked into running.

There's a ceiling on a bad hour

Sending is capped at 30 an hour and organising at 2000, both adjustable. The audit log tells you what happened after the fact, a limit stops it happening two hundred more times. Sends are capped far tighter than filing on purpose, since moving a thousand messages is tidying up and sending a thousand is an incident.

Attachments are files, not code

Nothing is ever executed. Saved files are confined to the attachments directory, written owner-only and never executable, and they delete themselves after 15 minutes. One thing to be aware of though, files written this way don't carry the quarantine flag your browser or mail client would add, so your operating system won't warn you about them. Don't open executables that arrived by email.

Found a hole?

Please don't open a public issue for anything exploitable. Use GitHub's private reporting instead, and it stays between you and me until there's a fix. The policy covers what's in scope.

Back to the overview  ·  Installation  ·  Questions