← Alla inlägg
Svenska

How to share API keys and secrets without putting them in Slack

A teammate needs the staging DATABASE_URL. It’s 4 PM on a Friday. The default options are: DM it in Slack, email it, or paste it into a Notion page. Each one leaves the credential in a system with effectively infinite retention and an unclear set of people who can read it next year.

A better handoff is a link that points at encrypted bytes, where the server holding them can’t read the plaintext, and the file is deleted after one download. The workflow is short enough to fit in the same five minutes you’d have spent setting up a shared password manager vault.

Why Slack, email, and Notion are wrong for secrets

A secret pasted into Slack:

  • Sits in both message histories until somebody manually deletes them.
  • Is searchable by anyone in the channel, including people added later.
  • Shows up in the workspace data export when somebody offboards.
  • Is one misclicked channel away from being visible to the whole company.

Email is worse. A credential sent over SMTP is stored on the sending server, the recipient’s inbox, whatever archive policy the IT team configured, and any downstream backup. Rotating the key every 90 days doesn’t fix this; it means the exposure window is 90 days long, not that it stops.

Notion, Linear, and Google Docs are built around persistence. That is exactly the wrong property for a secret.

Why a secret manager isn’t always the right tool

1Password, Doppler, Vault, Infisical all solve the “many secrets, many consumers” case well. They add real overhead for the “one credential, once” case. Setting up a shared vault for a one-off transfer is rarely worth it, and most teams just skip it and fall back to Slack.

The rough split: if a credential will be read repeatedly by multiple people, put it in a manager. If it will be read once and then rotated, a one-time link is a better fit.

What “one confirmed download” actually means

The credential is encrypted in the browser before it leaves the sender’s device. The encryption key is derived from a password that the server never sees. The server stores ciphertext, a download token hash, an upload log, and nothing that can be turned into plaintext.

The server’s copy is deleted only after an authenticated download completes end-to-end. Loading the landing page doesn’t count. A download that fails mid-transfer rolls the burn counter back. If nobody ever finishes a download, a short TTL deletes the file on the clock.

The server still keeps an audit log (URL token, timestamps, hashed and encrypted IPs, user agent, TCP source port, byte size). That’s intentional — it’s used for abuse investigation. It doesn’t let the operator read your file.

30-second workflow

  1. Open ttl.space.
  2. Paste the secret into a small text file or a .env stub and drop it into the upload area.
  3. Turn on burn-after-read.
  4. Copy the link and the generated password from the success page. They are two separate values.
  5. Send the link and the password over two different channels: link in Slack, password in SMS or Signal (or the reverse). A single compromised channel should not yield both.
  6. The recipient opens the link, enters the password, downloads the file. The server deletes its copy. The link starts returning 404.

At no point does the secret sit in a message history, cloud storage, or an email archive.

Why split across two channels. The link by itself is ciphertext plus a token; without the password it decrypts to nothing. Sending both in the same Slack thread defeats half the point, because compromising that thread yields both. Splitting them means an attacker has to compromise two systems within the window before the download happens.

Burn-after-read vs. TTL

Burn-after-read fits a handoff that will happen in the next few minutes. The first successful authenticated download deletes the file; every request after that gets a 404.

TTL fits the case where the recipient will open the file at some uncertain time later — a contractor who will read the credentials on Monday, for example. A 24-hour TTL gives them a window and bounds the exposure.

Limits

If the credential is already leaking — sitting in shell history, a CI log, or a screenshot that got auto-uploaded somewhere — rotate it first. A short-lived link stops future copies, not copies that already exist.

This is not a substitute for a secret manager at any real scale. It’s the tool for “one secret, one person, right now.” For a team sharing dozens of credentials a week, use a manager for the repeat case and use one-time links for the handoffs that don’t belong in one.

Burn-after-read can also be defeated by a recipient screenshotting the decrypted contents, or pasting them into a persistent tool anyway. If the credential is that sensitive, the real answer is a short-lived OAuth token, a hardware key, or a temporary role assumption — not a link at all. For everything else — a DB password, a staging key, a one-off webhook secret — a one-time link is a reasonable default.

Publicerad .