Built to contain failure.
Whity holds many organisations in one database, so isolation is the property that cannot quietly break. Here is what the platform enforces, what it deliberately doesn't, and how to tell us when something is wrong.
Reporting a vulnerability
Don't open a public issue. Public tickets put exploit details in front of every reader before a fix exists. Email it instead, and you'll get a reply.
Include what you found, which versions it affects, how to reproduce it, and what you think the impact is. If you'd rather stay anonymous in the credits, say so — that's respected.
Acknowledged within 48 hours
You get a human reply confirming we received it and are reproducing it.
Patch target: 7 days
We ask for a reasonable window before public disclosure — 7 days is the target, longer only by mutual agreement.
Credited on release
Once the fix ships you're credited in the release notes and
CHANGELOG.md, unless you'd rather not be. There's no bug-bounty programme today; this runs on goodwill.
What the platform enforces.
These aren't conventions a reviewer has to remember. Each one has a test that fails the build.
Tenant isolation, three times
Middleware rejection, an explicit tenant_id predicate in every query, and a request-scoped context that resets between requests on persistent workers.
RBAC on every route
Routes declare the resource:action permission they require; the host enforces it and returns a structured 403. A plugin route whose permission the plugin never declared fails closed and isn't registered.
No state across requests
On a persistent worker pool, a static cache is a cross-request leak waiting to happen. Request-scoped state is a hard rule, with dedicated worker-leakage and request-isolation tests.
An audit trail that records provenance
Permission denials and data modifications are logged with actor, tenant, IP and timestamp. CLI-originated writes record the command word — never its arguments, because command lines carry secrets.
Encryption
TLS 1.3+ in transit. AES-256 for sensitive stored fields such as TOTP secrets. Passwords and 2FA recovery codes hashed with bcrypt via password_hash(); a move to Argon2id is tracked as future hardening.
Proven in CI, not asserted
Integration tests must prove RBAC route protection and cross-tenant rejection for behaviour changes. PHPStan at level 8, mutation testing, and a suite that fails on warnings and risky tests.
Plugins are not sandboxed.
Whity loads plugins in-process. A plugin runs with the same privileges as the core: it can reach the database, the filesystem and the network. There is no runtime sandbox, and the hot-load error boundary contains crashes, not intent — it stops a broken plugin taking the host down; it does not stop a malicious one.
So treat installing a plugin exactly like adding a dependency to your own application: a code-trust decision. Read it, or trust whoever wrote it. This is the same bargain every in-process plugin system makes, and we would rather say it plainly here than let you discover it later.
One supported line.
| Version | Security fixes |
|---|---|
main (HEAD) | Supported |
| Latest tag | Supported |
| Older tags | Not supported |
Whity is pre-1.0 and carries no legacy-compatibility stance. Fixes land onmain and ship in the next tag; there is no backporting to older tags yet. An internal adversarial audit has been run against the codebase and its findings fixed — it is not a substitute for independent professional testing, which has not yet happened.
Security FAQ.
How do I report a security vulnerability in Whity?
Email amroksaleh@gmail.com with a description, affected versions, reproduction steps and potential impact. Do not open a public GitHub issue — that keeps exploit details out of the public tracker until a fix ships. You will get an acknowledgement within 48 hours, and the target for a patch is 7 days.
Does Whity have a bug bounty?
No. There is no paid bounty programme today. Reports are handled on a best-effort, goodwill basis, and reporters are credited in the release notes and CHANGELOG unless they prefer to stay anonymous.
Which versions of Whity get security fixes?
Whity is pre-1.0, so there is one supported line: the latest tagged release plus main. Fixes land on main and ship in the next tag. There is no backport policy for older tags while the project is pre-1.0.
Are Whity plugins sandboxed?
No. Plugins are loaded in-process and run with the same privileges as the core. Installing a plugin is a code-trust decision, equivalent to adding a dependency to your own application — install plugins you trust and review, the same way you would any package.
How does Whity keep one tenant's data away from another's?
Isolation is enforced three separate times: the EnforceTenantIsolation middleware rejects cross-tenant requests before a handler runs, every handler and repository query binds an explicit tenant_id predicate from TenantContext, and TenantContext itself is reset between requests on persistent workers. A cross-tenant rejection suite asserts this per tenant-owned table, and CI fails if a table is not covered.
Found something?
Email it privately. You'll hear back within 48 hours.