EvoPlatform handles authentication, session issuance, tenant isolation, and password storage. A flaw in any of those affects every application built on it, so security reports are welcome and taken seriously.
Please do not open a public issue for a security problem.
Report it privately through GitHub's private vulnerability reporting (Security → Report a vulnerability). That creates a private advisory only you and the maintainer can see.
Useful things to include, as far as you have them:
- What the issue lets an attacker do, and what access they'd need first
- Steps to reproduce, or a proof of concept
- Affected version or commit
- Any suggested fix
This is a small project maintained by one person, so this is a statement of intent rather than a service-level guarantee:
- Acknowledgement as soon as the report is seen.
- An assessment — whether it reproduces, and how it's rated — once investigated.
- Credit in the advisory and release notes, unless you'd rather not be named.
Please give a reasonable window to ship a fix before disclosing publicly.
EvoPlatform is pre-1.0. Only the current main branch is supported —
fixes land there, and there are no backports to earlier tags.
In scope — anything in this repository: the platform service, the Node
SDK, the evo CLI, and the starter templates. Particularly:
- Authentication and token handling (JWT/JWKS signing, verification, refresh, passkeys)
- Cross-tenant data access, or any bypass of per-app access enablement
- Privilege escalation between roles (member → tenant admin → platform admin)
- Password storage and reset/invite/verification token flows
- Injection, SSRF, or anything exposing the admin console to unauthenticated callers
Out of scope — deployments (the operator's own servers, DNS, or TLS configuration), third-party dependency vulnerabilities with no exploitable path through this code, and findings from automated scanners with no demonstrated impact.
Every registered app holds a client id and secret; together they are the app's identity to the platform. Treat a leaked pair as a leaked password for that app and rotate it from the console. Holding them lets a caller act for that app, and only that app:
- Read the entitlement of any workspace the app is enabled for, and start a
checkout or billing-portal session for those workspaces (
/billing/*). - Send mail through the platform: from the platform's default relay when no
workspace is named, or from a workspace's own relay when the app is enabled
for it, within a per-app quota (
/email/send). - Push audit events for workspaces the app is enabled for. They are stored
under the app's own name (
my-app.thing.created), so an app event can never read as one of the platform's own (/events). - Read the app's own brand record (
/brand).
Client credentials do not reach another app's workspaces, cannot mint a user
session, and read nothing under /admin/*. A report that an app can do one of
those is in scope. A report that it can do the things listed above is a
description of the design.
Two operator responsibilities the code cannot enforce, both covered in docs/INSTALL.md and docs/DEPLOY.md:
- Change the bootstrap admin credentials. The first-boot admin is created from environment variables. Leaving the example values in place leaves a known account on a public host.
- Keep signing keys outside the deploy tree, and back them up separately. Losing them invalidates every issued token; leaking them lets anyone mint valid ones.