security section as bullet list
This commit is contained in:
35
README.md
35
README.md
@@ -125,29 +125,18 @@ The tools people use to communicate should belong to the people using them. Not
|
||||
|
||||
Letting people participate anonymously doesn't mean letting them run wild. Echoboard takes security seriously at every layer - protecting the people who give feedback, the people who manage it, and the data in between.
|
||||
|
||||
**Spam protection without surveillance.** Instead of CAPTCHAs - which are inaccessible, annoying, and train someone else's machine learning models with your users' labor - Echoboard uses ALTCHA proof-of-work challenges. The user's browser solves a small computational puzzle before submitting. It's invisible to real people and expensive for bots. No third-party scripts, no tracking pixels, no "select all the traffic lights."
|
||||
|
||||
**Encrypted at rest.** Display names and other personal data aren't stored as plain text in the database. Each field is individually encrypted with AES-256-GCM - even if someone gets access to your database, they can't read user identities without the encryption key. Lookups happen through blind indexes (HMAC-SHA256), so searches work without ever exposing the plaintext.
|
||||
|
||||
**Passwords never touch the wire in the clear.** Admin passwords are hashed with bcrypt (cost factor 12) before storage. Timing-safe comparisons prevent attackers from figuring out whether an email exists based on how long a login attempt takes. Failed login attempts trigger exponential backoff, making brute force impractical.
|
||||
|
||||
**Passkeys are phishing-proof.** Unlike passwords, passkeys use public-key cryptography. The private key never leaves the user's device - not to your server, not to anyone. Even if someone intercepts the authentication exchange, they can't replay it. There's nothing to phish, nothing to leak, nothing to stuff into a credential database.
|
||||
|
||||
**Recovery codes are single-use and hashed.** When a user generates a recovery phrase, the plaintext is shown once and never stored. What goes into the database is a bcrypt hash and a blind index. Even someone with full database access can't reverse the phrase. Each code works exactly once and expires after 90 days.
|
||||
|
||||
**Token blocklisting.** When someone logs out, changes their identity, or has their account deleted, their session tokens are immediately blocked. The blocklist is persistent (stored in the database, not in memory), so a server restart doesn't magically revalidate revoked sessions.
|
||||
|
||||
**Role-based access for the team.** Not every team member needs the same level of access. Super admins, admins, and moderators have different permissions, enforced server-side on every single request. A moderator can't escalate to admin by calling API endpoints directly - the backend checks your role before doing anything, not just the frontend.
|
||||
|
||||
**Invite links are single-use and expiring.** Team invites are hashed before storage, expire after a configurable window, and can only be claimed once. The claim happens inside a serializable database transaction, so even two simultaneous requests can't both succeed.
|
||||
|
||||
**Webhooks can't reach your internal network.** Outbound webhook delivery validates the destination URL against a blocklist of private IP ranges, resolves DNS before connecting (preventing rebinding attacks), and connects directly to the resolved IP with TLS verification. Your internal services stay invisible.
|
||||
|
||||
**Content security headers everywhere.** HSTS with a two-year max-age, strict CSP, X-Content-Type-Options, X-Frame-Options, Referrer-Policy set to no-referrer. The embed widget runs in a sandboxed iframe. Custom CSS input is decoded and scanned before storage to prevent injection.
|
||||
|
||||
**File uploads are validated, not trusted.** Uploaded images are checked against magic byte signatures (not just file extensions or MIME types). Path traversal is prevented with realpath resolution. If a database insert fails after a file is written, the orphaned file is cleaned up automatically.
|
||||
|
||||
**Rate limiting on everything.** Every endpoint has a rate limit appropriate to its sensitivity - from 100/minute for general browsing down to 3/15 minutes for recovery code attempts. This isn't just a global throttle; each endpoint is tuned individually.
|
||||
- **Spam protection without surveillance** - instead of CAPTCHAs (which are inaccessible, annoying, and train someone else's models with your users' labor), Echoboard uses ALTCHA proof-of-work challenges. The browser solves a small puzzle before submitting. Invisible to people, expensive for bots. No third-party scripts, no tracking pixels, no "select all the traffic lights."
|
||||
- **Encrypted at rest** - display names and personal data are individually encrypted with AES-256-GCM. Even with database access, identities can't be read without the encryption key. Lookups work through blind indexes (HMAC-SHA256), so searches never expose plaintext.
|
||||
- **Admin passwords hashed and timing-safe** - bcrypt cost factor 12, timing-safe comparisons that don't leak whether an email exists, and exponential backoff on failed attempts making brute force impractical.
|
||||
- **Passkeys are phishing-proof** - public-key cryptography where the private key never leaves the user's device. Nothing to phish, nothing to leak, nothing to replay.
|
||||
- **Recovery codes are single-use and hashed** - the plaintext is shown once and never stored. The database holds a bcrypt hash and a blind index. Each code works exactly once and expires after 90 days.
|
||||
- **Persistent token blocklisting** - logging out, changing identity, or deleting an account immediately blocks session tokens in the database. A server restart doesn't revalidate revoked sessions.
|
||||
- **Role-based access enforced server-side** - super admins, admins, and moderators have different permissions checked on every request. A moderator can't escalate by calling API endpoints directly.
|
||||
- **Single-use expiring invite links** - team invites are hashed, expire after a configurable window, and claimed inside serializable transactions so two simultaneous requests can't both succeed.
|
||||
- **Webhooks can't reach internal networks** - destination URLs are checked against private IP blocklists, DNS is resolved before connecting to prevent rebinding, and connections go directly to the resolved IP with TLS verification.
|
||||
- **Security headers everywhere** - HSTS with two-year max-age, strict CSP, X-Content-Type-Options, X-Frame-Options, Referrer-Policy set to no-referrer. The embed widget runs in a sandboxed iframe. Custom CSS is decoded and scanned before storage.
|
||||
- **File uploads validated by content, not trust** - images are checked against magic byte signatures, not just extensions or MIME types. Path traversal is blocked with realpath resolution. Orphaned files are cleaned up if database inserts fail.
|
||||
- **Per-endpoint rate limiting** - every endpoint is individually tuned, from 100/minute for browsing down to 3/15 minutes for recovery code attempts. Not a blunt global throttle.
|
||||
|
||||
Security isn't a feature you bolt on at the end. It's a set of choices you make from the beginning about what data to collect (as little as possible), how to store it (encrypted), how to verify identity (without passwords when possible), and how to fail (safely, loudly, and without leaking information). Echoboard makes those choices so you don't have to think about them.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user