Keel
Security

What's actually in the code.

Not a compliance checklist for software that doesn't exist yet. Every item below is a real check you can go read in the repo.

Sessions via Better Auth

Email/password, magic links, and OAuth all issue the same signed, httpOnly session cookie. No custom auth logic to audit, no home-grown JWT handling.

API keys are hashed, not stored

Generated keys are shown once at creation. Only the hash is persisted, so a database leak doesn't hand out working credentials.

Webhook signatures are verified

Stripe, LemonSqueezy, and Polar webhooks are checked against the provider's signing secret before anything in the payload is trusted, and each event ID is recorded once to guard against a re-delivered event being processed twice.

Every team-scoped route checks permission first

authorizeTeamAccess(teamId, permission) runs before a handler touches the database. Role and rank checks live in one file, not scattered across routes.

Audit log

Team-level actions are written to an append-only audit log, kept separate from the records being changed, so history survives even if the underlying row is later deleted.

Typed queries, no raw SQL

All database access goes through Drizzle's query builder. There's no string-concatenated SQL in the codebase for user input to escape into.

Found something?Report it to security@keel.dev and we'll get back to you within a business day.