Security

What it protects, and how

What it protects, from whom, and how. And, just as plainly, what it doesn't do yet.

Not yet independently audited. It has had repeated rounds of internal adversarial review (by AI reviewers, each given one area), and every finding is fixed. That helps, but it isn't an audit: please don't rely on it until it has had one.

What it promises

  1. Nobody signs in as someone else.
  2. Nobody learns a password, from it or from a copy of its database.
  3. A session works only in the browser it was given to, and ends when it should.
  4. Signing in doesn't reveal who has an account.
  5. It stays usable under ordinary attack.

Each is kept by the measures below, and each measure has a test that fails if it stops working.

How

AgainstWhat it does
Guessing passwordsscrypt at OWASP's cost; 15 characters or more; 5,500 common passwords refused; limits per account, per address, and per IPv6 block, counted before any password is checked
A copy of the databasePasswords only as salted scrypt hashes; sessions only as hashes of 256-bit tokens
Stealing a sessionA cookie scripts can't read, sent only to this exact site over HTTPS; a session ends after 7 days unused, and 30 at most
Other sites acting for someoneEvery change must come from the site's own pages, as JSON
Planting a sessionA fresh session at every sign-in; two session cookies in one request mean nobody
Racing a password changeA session starts only if the password just checked is still the account's
Finding who has an accountA wrong email and a wrong password get the same answer, after the same work
Swamping the serverTwo passwords checked at once, with a short queue; small bodies; malformed requests answered, never crashing
Lookalike or invisible charactersEmails normalised, and invisible characters refused

The threat model has every threat, its measure, and where in the code it lives.

What it doesn't do yet

  • Sign-up says when an email already has an account. Hiding it needs email confirmation, which is on the roadmap.
  • No password reset yet. That needs email too.
  • Someone with many addresses can pause sign-in to an account for up to an hour. Its owner, already signed in, can still change the password.
  • Letters from other alphabets that look alike (a Cyrillic "а") make a different account that looks the same.
  • One factor only: NIST's Authenticator Assurance Level 1. Two-step sign-in is on the roadmap.

How the project stays secure

  • No runtime dependencies, and CI fails if one is added, or if anything but Node's own modules is imported.
  • CI refuses invisible or direction-changing characters in code ("Trojan Source").
  • CI fails if the source goes over 1,000 lines.
  • CodeQL checks every change, OpenSSF Scorecard grades the project weekly, and GitHub Actions are pinned to exact commits.
  • Releases are to be published only by CI, from a tag on main, with provenance linking each to its source.

Reporting a vulnerability

Please don't describe it in public. Use the repository's Security tab, then Report a vulnerability, with what you found, how to make it happen, and what an attacker could do with it. You'll hear back within 5 working days.