Security

You are being asked to put a kink, a device, a partner, and sometimes your face into someone else’s database. That deserves specifics rather than a badge that says “bank-level encryption.” This page names the actual algorithms and the actual failure modes, and it ends with what we have not done — because a security page without that section is marketing.

Your password

Passwords are hashed with Argon2id, the current recommendation for password storage. We never store the password itself, and there is no mechanism — support, admin, or otherwise — that can reveal it.

New passwords are checked against the Have I Been Pwned breach corpus using k-anonymity: your password is hashed locally and only the first five characters of that hash ever leave the server. HIBP cannot tell which password was checked, and neither can anyone watching the connection.

Login also runs a hash comparison against a dummy value when the account does not exist, so the response time cannot be used to discover which email addresses are registered.

Staying signed in

Your session lives in an httpOnly cookie, which JavaScript on the page cannot read. This is the difference that matters: if someone ever manages to run a script on the site, they still cannot steal your session token, because the browser will not hand it to them.

Two-factor authentication is available and uses standard TOTP — any authenticator app. The secret behind it is encrypted at rest, not stored in the clear.

Lock combinations

The combination to your lock is the most sensitive thing we hold, so it is not stored as text. It is encrypted with AES-256-GCM, with a fresh random nonce for every single record and an authentication tag that makes silent tampering detectable rather than merely unlikely.

Each encrypted value is stamped with the identifier of the key that sealed it, so the master key can be rotated later without stranding existing locks. That is a small detail, and it is the kind of thing that is impossible to retrofit if you did not think about it on day one.

Images you upload

Uploads go to a bucket with public access blocked. The API checks that on every boot and refuses to start in production if it is not true, because every other protection here assumes it.

What happens then depends on what the image is, and the distinction is worth stating precisely. Anything private — your combination photo, verification photos, task submissions, direct-message attachments, identity documents — is never given a permanent address. It is served through a signed link that expires in about fifteen minutes, so a URL that leaks or gets screenshotted stops working rather than lasting forever.

A verification photo is seen by your keyholder or a moderator. If you choose to share a verification link, the people you send it to can also see that photo once they sign in, and only until the check is settled. Anyone else holding the link sees your username and the vote count, never the photo. You can turn a link off at any time.

Public display media is different: your avatar and anything you post publicly keep a stable, cacheable URL, and anyone holding that link can load it. That is what a public profile picture is, and it would be dishonest to describe it as private.

Upload screening is built, and it is switched off right now. Keyhold is in closed testing with people we know, and during that period the scan step is bypassed, so uploads are not being screened today. It will be switched on before signups open to the public. We would rather tell you that than let the description below read as a promise it is not yet.

With screening on, an upload is not visible to anyone until it has been through the pipeline:

  1. Confirm the file actually landed in storage
  2. Screen it against PhotoDNA for known child sexual abuse material
  3. Run general content moderation
  4. Only then release it

The important part is step 2 and what happens when it fails. If the CSAM scan cannot complete — the provider is down, the credentials are wrong, anything — the media is held, not released, and a moderation review is opened. It fails closed. A platform that lets unscannable uploads through when its scanner breaks does not really have a scanner — which is exactly why the bypass we are using for testing has to go before the public arrives.

Keyhold’s content policy is narrow on purpose. Verification and task photos must show the device, not sexually explicit conduct or exposed genitals. We are not trying to be a place where explicit material is posted, which keeps the entire category of problem smaller.

Deleting your account

When you ask to delete your account, it is scheduled for 30 days later, and you can cancel any time before then. The account keeps working during those 30 days, but other people can no longer find your profile.

When the 30 days are up, here is precisely what happens: your username and email are replaced with placeholders, your password and two-factor secret are wiped, you are signed out everywhere, your API keys and app authorisations are revoked, your locks and posts are removed, your uploaded media is flagged for erasure from storage, and the body of every direct message you sent is destroyed.

Two honest caveats. Message threads survive, because the other person’s side of a conversation is their history and not ours to delete — but your text and attachments in them are gone. And the underlying files are erased by a background worker rather than in the same instant the account is erased, so there is a short window where the rows are marked dead before the bytes are actually removed.

One exception, stated plainly: media that has been flagged as CSAM is retained under legal hold and is not erased by account deletion. That is a legal obligation, it applies to every platform in this space, and the ones that do not mention it have not thought about it.

What we have not done

Keyhold is built by one developer. That has real advantages — a bug you report can be fixed the same week — and real limits, and pretending otherwise would undercut everything above.

  • Upload screening for CSAM is switched off during closed testing. It is switched on before public signups.
  • No third-party penetration test has been performed.
  • There is no formal bug bounty programme.
  • There is no SOC 2, ISO 27001, or comparable audit.
  • There is no 24/7 on-call rotation. There is one person, who sleeps.

None of those are secrets you would have discovered later. They are the normal state of a small independent platform, and you should weigh them against the fact that the person who wrote the authentication code is a security engineer who will answer your email personally.

Reporting a vulnerability

If you find a security problem, email [email protected]. Tell us what you found and how to reproduce it.

We will not threaten you, and we will not involve lawyers over a report made in good faith. Please give us a reasonable window to fix the issue before publishing it, and please do not access, alter, or exfiltrate any account that is not your own while testing — the accounts here belong to real people with a great deal to lose.

The same honesty applies to how we measure people. The reliability score is calculated in public, limits included.