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.
PHP security releases, October 2026.
Three advisories affect the PHP runtime Whity ships on. Two are fixed by updating; the third has no patch yet and needs a configuration change on every version. If you self-host Whity, all three apply to you.
v0.2.16 or later, which builds on PHP 8.4.27 and sets both ini values below. If you cannot update today, setsession.upload_progress.enabled = 0 in your PHP configuration and restart your workers — that closes two of the three on its own.| Advisory | Severity | Fixed in | Status in Whity |
|---|---|---|---|
CVE-2026-109618 | 9.2 — unauthenticated RCE | PHP 8.4.27 | Fixed in v0.2.16 |
CVE-2026-109619 | 9.2 — unauthenticated RCE | PHP 8.4.27 | Fixed in v0.2.16 |
CVE-2026-115560 | RCE, narrow preconditions | No patch published | Mitigated in v0.2.16 |
You do not need PHP 8.5.
The fixes for the first two were backported across every supported branch — 8.5.12, 8.4.27, 8.3.36 and 8.2.35 all carry the same patch. Moving a minor version buys no security here. CVE-2026-115560 affects 8.5.12 as well, so it would not have helped there either.
Whity v0.2.16 pins dunglas/frankenphp:1-php8.4.27 exactly, rather than a floating php8.4 tag.
Why it must be ini, not middleware.
PHP runs the upload-progress handler from the SAPI while parsing a multipart body, and starts a session itself to do it. That path is reached before any application code, by an unauthenticated POST, on routes unrelated to uploads — and regardless of whether your application uses PHP sessions at all.
Whity sets session.upload_progress.enabled = 0 andexpose_php = Off in a conf.d file baked into the image. Nothing in the platform reads upload progress.
Two critical Next.js advisories, for anyone who builds the web workspace.
v0.2.16 moves Next.js to 16.4.2, closing an unauthenticated remote code execution in the image optimization API when SVG files are served, and a second inuse cache functions returning typed arrays. Whity sets neitherimages.dangerouslyAllowSVG nor any use cache directive, so neither path is reachable in a default build — but if you have turned either on in your own, it was. Storybook moves to 10.6.3 for a preview origin-validation flaw; it is development tooling and ships in nothing.
Whity publishes no frontend artifact, so this reaches you only if you build theweb workspace yourself. npm audit against the release reports nothing at any severity.
Background on how this was found, and why the fix we care about is a test rather than a version bump: The dependency watcher that could not see.
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.