Skip to content

Security

kitset.io holds the record of who was told what, who approved what, and who had access to which system. That is worth protecting, and it is worth being specific about how.

Tenant isolation

Every record in the system carries the workspace that owns it, and every query filters on it. A request for a record belonging to another workspace does not return "forbidden" — it returns "not found", because from inside your workspace the record genuinely does not exist. That behaviour is asserted by automated tests that run on every change, against both SQLite and PostgreSQL.

The one deliberate exception is the email suppression list. When an address hard-bounces or files a spam complaint, delivery to it stops platform-wide, because sending reputation is shared. Which workspace triggered it is never disclosed to any other workspace.

Accounts and sessions

Passwords

Hashed with a salted, iterated key-derivation function. Never stored or logged in the clear, and never returned by any endpoint.

Two-factor authentication

TOTP, compatible with any authenticator app, with single-use recovery codes. The requirement is enforced on the session, not on the sign-in form, so password reset and invitation acceptance cannot walk past it.

Second-factor secrets

Encrypted at rest with a key held separately from the session-signing key, so rotating one does not destroy the other.

Sessions

Server-side and revocable. You can list your active sessions and end them, and changing your password ends all the others.

Brute force

Sign-in, password reset, invitation acceptance and second-factor entry are rate-limited per account and per source address.

Cookies and CSRF

Session cookies are HTTP-only and, in production, secure-only. Every state-changing request carries a double-submitted token bound to the session.

Authorization

A request is allowed only after tenant membership, account state, session validity, licence type, role, permission mode, scoped grants, module installation, record relationship and location scope have all been evaluated on the server. The browser interface is not treated as a security boundary: hiding a button does not protect the endpoint behind it, so the endpoint is protected too. An automated check walks every route that writes and fails the build if one of them does not make an authorization decision.

Data handling

In transit

HTTPS only, with HSTS in production. Strict content security, frame-denial, referrer and permissions policies on every response.

Files

Uploaded to private object storage directly from the browser using short-lived signed URLs. A file whose uploaded size or type does not match what was declared is quarantined rather than served.

Secrets

Systems & Access records who owns and who can reach a business system. It is deliberately not a password manager, and storing credentials in it is prohibited by the acceptable use policy.

Logs

Structured JSON with credential redaction at the handler, so a token cannot reach a log file by being interpolated into a message. Query strings are omitted from access logs because they carry single-use account tokens.

Audit trail

Every meaningful change writes an audit row naming the actor, the entity, the summary and the time. Administrators can read and export it.

Where it runs

Application and database in Singapore, object storage in ap-southeast-1, email via us-east-1. The full list is on the subprocessors page.

What we do not claim

The useful half of a security page.

Reporting a vulnerability

Email [email protected] with enough detail to reproduce the issue. We will acknowledge within three business days. Please do not test against another customer's workspace, run denial-of-service traffic, or access data that is not yours; a trial workspace of your own is free and is the right place to look.