
Company News
AWS Security Hub Adds Socket for Supply Chain Security
Socket is now in the AWS Security Hub Extended plan. Adopt it through AWS, apply committed spend, and block malicious open source packages.
Zero-knowledge secure email CLI + MCP server — encrypt messages and attachments on your own machine, gate delivery with an SMS code or passphrase
Zero-knowledge secure messaging for small regulated firms. Send a confidential message + files to anyone (no account for the recipient) with true end-to-end encryption — the server only ever holds ciphertext and keys it cannot unwrap.
Installing from npm? This package is the client — a zero-dependency CLI and MCP server for the hosted service at salamailer.fi. Encryption happens on your machine; you need an account to send.
npm install -g salamailer
salamailer init --origin https://salamailer.fi --email you@firm.fi
claude mcp add salamailer -- salamailer mcp # 12 tools for agents
Jump to CLI & MCP for the full tool surface
and the agent guardrails. The rest of this file documents the server, which is
proprietary and not part of the npm package (see LICENSE).
Zero npm dependencies. All integrations (Stripe, Twilio, Brevo/Postmark,
S3-compatible storage) are implemented with fetch + node:crypto — there is no
supply chain to audit beyond Node itself. See DECISIONS.md for how the build
maps to PLAN.md, and DEPLOY.md for production setup.
Requires Node ≥ 22.5 (built-in node:sqlite).
npm start # → http://localhost:3000
npm test # 146-check e2e suite: crypto, replies, gates, billing, SSO, hardening, CLI/MCP
npm run hashes # SHA-256 of every served asset (publish for auditors)
With no configuration, email/SMS print to the console + data/outbox.log,
billing is off (everyone's on trial), and blobs live on local disk. Copy
.env.example → fill in keys → each integration goes live independently.
Your browser generates a fresh AES-256-GCM content key per message and encrypts
everything (filenames included) before upload. The key travels only in the URL
fragment of the recipient's link — browsers never send fragments to servers. A
separate, rate-limited second channel (SMS code or passphrase) gates the
ciphertext download; it is not part of the key, so short codes can't be
brute-forced offline. The sender's copy of each key is wrapped under a vault key
wrapped under their password — so senders can re-send links, but a full server
breach yields nothing readable. Full threat model (including its honest limits):
/security in the running app.
/register) — password is stretched locally; it never leaves the browser./compose) — pick Passphrase for a fully-offline demo. Send.data/outbox.log in an incognito window,
enter the passphrase → decrypts in the browser./app./app): resend link/code, revoke (real delete), export receipt,
inbox of encrypted replies./account): plan, quotas, Stripe upgrade (when configured);
team owners also get the admin console — per-member usage, an org
recipient-domain policy enforced server-side on every channel, and SSO
(OIDC) setup. SSO authenticates the session only; the vault still unlocks
with the user's password, client-side (/unlock) — IdPs never see keys.Verify the zero-knowledge claim yourself: DevTools → Network during a send — all
request bodies are ciphertext and the #key fragment appears in no request. Then
inspect data/salamailer.db and data/blobs/.
cli/salamailer.mjs is a zero-dependency CLI that reuses the same crypto module
the web app serves, so plaintext and keys exist only on the sending machine:
salamailer init --origin https://app… --email you@firm.fi # password prompted, never stored
salamailer send --to client@x.fi --message "…" --file contract.pdf --burn [--self-relay] [--lang fi|en|sv]
salamailer list · replies · reply <id> [--save-dir d] · status · contacts · receipt <id> · resend <id> · resend-code <id> · revoke <id>
--self-relay finalizes without handing the link to the server, so the content
key never reaches it even transiently — you deliver the printed link yourself
(parity with the web compose checkbox).
Saved recipients give a regular correspondent one standing gate passphrase
instead of a fresh one per message: salamailer contacts add --to partner@co.fi --passphrase "…", and every later send to them reuses it automatically (they
learn it once). The passphrase is stored encrypted under your vault key, synced
across web/CLI/MCP; the server never reads it. Manage the same list on /account.
salamailer mcp runs it as an MCP server (stdio), exposing twelve tools —
send_secure_message (with self_relay / save_passphrase),
list_sent_messages, get_delivery_receipt, get_account_status,
resend_notification, resend_sms_code, revoke_message, save_contact,
list_contacts, delete_contact, plus list_replies / read_reply (inbound
secure replies, decrypted locally) — full parity with the web dashboard's
sender surface, so any MCP-capable agent can run a complete round trip
(send → client replies → agent reads the reply) in zero-knowledge mail:
claude mcp add salamailer -- salamailer mcp
Transport auth is an API key (created on the /account page or by init;
stored SHA-256-hashed server-side; can't manage other keys). Agent sends are
metered against the same plan quotas — agents are senders, senders are who pays.
The credentials file (~/.config/salamailer/config.json, 0600) holds the API key
and the raw Vault Key: treat it like an SSH private key.
Agent guardrails (config file / init flags) make the MCP a policy
enforcement point for a prompt-injected agent:
"hideRecipients": true (--hide-recipients) — privacy mode, strictest:
the model never sees recipient emails or phone numbers at all. Sends are
addressed by saved-contact label (contact arg; resolved locally inside
the CLI process), tool outputs mask every address, the standing passphrase is
not echoed, and contact management stays human-only. Implies contactsOnly.
For teams where even the recipient list is confidential to the AI vendor."contactsOnly": true (--contacts-only) — the agent may only
send to recipients a human has saved as contacts; new recipients are
refused with instructions for out-of-band approval, and the agent channel
cannot add or remove contacts itself (no self-approval)."allowedRecipientDomains": […] (--allow-domain) — looser: restrict to
recipient domains."attachmentRoot": "/path" — attachments may only come from inside this
directory (default: the cwd where salamailer mcp starts).Every send is gated (SMS code / passphrase) and audit-logged server-side, so the operator's answer to a mis-send attempt is: "the guardrails blocked it — here is the log."
src/
server.js routing, strict CSP, CSRF origin checks, static serving
handlers.js API endpoints (auth, messages, gate, billing, webhook)
config.js all env-driven configuration (see .env.example)
billing.js entitlements, Stripe REST + webhook signature verification
storage.js ciphertext blobs: S3 SigV4 adapter or local fs
notify.js email/SMS providers (console | brevo | postmark | twilio)
db.js node:sqlite schema (PLAN.md §7.2 + billing)
security.js scrypt hashing, tokens, HMAC (gates only — never key material)
ratelimit.js per-IP/user sliding windows
retention.js expiry sweep + real hard-delete
audit.js metadata-only audit log
public/
js/crypto.js the crypto heart — Web Crypto only, runs on the sender/recipient device
js/*.js page logic (register, login, compose, app, account, read)
cli/
salamailer.mjs CLI + MCP server (stdio JSON-RPC), reuses public/js/crypto.js
scripts/
hashes.mjs published build hashes ("verify us, not trust us")
test/
e2e.mjs boots the server, drives the real client crypto end-to-end
FAQs
Zero-knowledge secure email CLI + MCP server — encrypt messages and attachments on your own machine, gate delivery with an SMS code or passphrase
The npm package salamailer receives a total of 47 weekly downloads. As such, salamailer popularity was classified as not popular.
We found that salamailer demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Company News
Socket is now in the AWS Security Hub Extended plan. Adopt it through AWS, apply committed spend, and block malicious open source packages.

Research
/Security News
Popular npm packages keyv and cacheable compromised.

Security News
A misconfiguration gave three Anthropic models internet access, and one, believing it was in a simulation, shipped a credential-stealing package to PyPI.