[READ-ONLY] Mirror of https://github.com/thoda-dev/shhh. Self-hostable zero-knowledge pastebin for secrets that expire on their own
docker end-to-end-encryption nuxt nuxtjs pastebin secrets selft-hosted zero-knowledge
shhh apps docs content 3.using-shhh 1.creating-a-paste.md
3.9 kB
Markdown


title: Creating a paste description: Text, files, passwords, expiry and read limits. navigation: icon: i-lucide-file-lock #

Paste your text, choose how long it should live, and get a link. That is the whole flow — no account needed unless the instance says otherwise.

Options #

Expires in — days before the paste disappears. Leave it empty to use the instance default. The instance caps how far ahead you can set it, and pastes always expire; there is no permanent option.

Max reads — how many times the paste may be decrypted before it is destroyed. Leave it empty for the instance default, or switch to unlimited. The counter is decremented atomically, so a one-read link cannot be read twice even under concurrent requests.

Password protection — adds a second key layer derived from your password with Argon2id. The recipient needs both the link and the password.

::note Getting the password wrong costs nothing: the browser proves it derived the right key before the server spends a read, so the recipient can try again. The server still never sees the password. ::

Formatting with Markdown #

Off by default: a paste is stored and shown exactly as you typed it, character for character.

Turn Format with Markdown on and the field becomes a rich text editor — headings, bold, lists, quotes, code blocks, tables. The recipient sees the formatted document, with View the source and Copy the Markdown source alongside it.

::warning Leave it off for a secret. A rich text editor stores Markdown, not what you typed: the password Tr0ub4dor&3_*hunter2* is saved as Tr0ub4dor&3\_*hunter2*, because _ and & mean something in Markdown and get escaped. It displays correctly, but the copy button hands over the source — and whoever pastes that into a login form is pasting the wrong password. The option is for notes, procedures and handover documents, not for a value someone will copy character for character. ::

Two things do not survive the trip, by design:

Images are never displayed. The instance hosts none, and its CSP loads images from its own origin only. Writing one gets you a warning rather than a refusal — the Markdown stays in the content, so it still works wherever you paste it next.

Links are not clickable. A paste is written by anyone and read by whoever was sent the link, on the page that holds the decryption key; a clickable link there is a phishing surface the plain text view never had. [docs](https://example.com) is shown as docs (https://example.com), so you can see where it points and copy it yourself.

Files #

File uploads require an account. The file and its name are both encrypted in the browser; only the MIME type is stored in clear, so the browser knows what to do with it on the way out.

The size cap is set by the instance — 2 MB by default.

The link contains the decryption key after the #. Copy it whole. Truncating it at the # gives a link that finds the paste but cannot decrypt it.

Treat the link as the secret itself: anyone holding it can read the paste.

::note Two share buttons appear once your paste is created.

Share by email opens your own mail client with the link pre-filled and no recipient — nothing goes through the server. Available to everyone.

Also send the link by email, offered at creation for signed-in users, has the server send one message with all recipients in blind copy. It is the only moment the key reaches the server; see the security model. ::

Reading a paste #

Opening a link shows the paste's metadata first — whether it exists, whether a password is needed, how many reads are left. Nothing is decrypted and no read is consumed until you click Reveal.

That two-step flow is what stops chat unfurlers and antivirus scanners from burning a one-read link before its recipient ever clicks.