Security¶
Reporting a vulnerability¶
Use GitHub's private vulnerability reporting on the rosschiu/kiban repository ("Security"
tab, "Report a vulnerability"). Do not post details in a public issue. If the button is not
available, open an issue that says only that you need a private channel; a maintainer will
arrange one.
Include the affected version or commit (kiban_build_info{version,commit} on every service), a
reproduction, and the impact you believe it has.
What the platform guarantees¶
Authorization¶
Authorization fails closed: any error while evaluating a decision is a refusal. Every object check is bound to the request's company: companies and company modules by id, positions and groups through their company, module objects through the anchor tuple their module writes at creation. An object from another company is denied.
A grant names the company and may only write tuples on object types the caller owns: an
app's backend, identified by the verified azp of its service-client token matching the app's
registered service client id, on the app's own types in any company where the app is enabled;
a superadmin, or a member who passes the module's company-scope decision, on a built-in module's
types; module-tier tuples additionally need the company-module administrator relation. Every
object must carry its company anchor. Base-model tuples cannot be written through the grants
route at all. A registered app's checks are limited to the feature keys its manifest declares.
The superadmin role is a single authorization tuple. Grant and revoke are immediate and audited, and the last superadmin cannot be revoked.
The authorization engine is compared against OpenFGA in make test (65 vectors, two mutation
proofs, a cycle proof, 5000 generated checks). The limitations page says what that does not
cover.
Identity and audit¶
The actor of every request is the verified bearer token; client-supplied identity headers are rejected.
Every mutation is audited in the same transaction, with the actor taken from the verified token
(never from the request body) and the request's correlation id. A definite denial on an
administrative route is audited with its reason. Foundation audit tables refuse updates, deletes
and TRUNCATE at the database level, and the service roles have no privilege to bypass that.
Authenticator-app or passkey MFA policy is set globally or per user; a per-user override can only raise the requirement. Passkey enrolment works; the login challenge for a passkey policy does not yet (see limitations).
Bootstrap enforces brute-force protection (temporary lockout after ten failures) and the
password policy length(12) and notUsername and notEmail. The realm binds one browser flow
(kiban browser): password form, conditional one-time code, then Kiban's MFA-setup
authenticator as a required step, so every interactive login passes through it. There is no
direct-grant or client-credentials client that issues a Kiban token (see limitations).
Deployment¶
Every service connects to the database with its own role, limited to its own schema. kiban is
the non-superuser owner of the application database and runs migrations and bootstrap;
keycloak owns Keycloak's database; the superuser (POSTGRES_USER, default postgres) is used
only at initialisation.
The superadmin's initial password, the identity client secret and the Keycloak admin password
reach Kiban's services as mounted files (_FILE variables), never as process environment. See
the limitations page for Keycloak's own container.
Gateway responses carry X-Content-Type-Options, X-Frame-Options, Referrer-Policy and (over
TLS) Strict-Transport-Security; the shell is served with an enforced Content-Security-Policy.
Over-limit bodies are refused. The Keycloak admin console and the master realm are not reachable
through the gateway.
Application containers run as uid 65532 with a read-only root filesystem, all capabilities dropped and no privilege escalation, in Compose and in the Kubernetes template.
There is no runtime dependency on any third-party service. TLS is either operator certificates on the gateway or your own TLS-terminating reverse proxy in front of it; the gateway never contacts a certificate authority.
Secret scanning, dependency licence scanning and vulnerability checks run in make check.
Known gaps¶
See known limitations. Items there that touch security are listed first.