Sylvode (formerly OpenPR) holds project data, business records, bot credentials and plugin code for every workspace on an instance. We take reports about it seriously and handle them privately until a fix is available.
Security fixes land on main and ship in the next release. Only the latest release is
supported; older releases do not receive backports, so upgrade to the latest release to get a
fix.
| Version | Supported |
|---|---|
| Latest release | Yes |
| Any earlier release | No, upgrade to the latest release |
The legacy names that the compatibility matrix keeps (the mcp-server CLI subcommands,
config/openpr.toml, OPENPR_* compose variables, openpr:// resource URIs and
openpr-<target> release archives) are part of the same build and receive the same fixes. See
the compatibility matrix.
Please do not open a public issue, pull request or discussion for a security problem.
Report it privately through GitHub's private vulnerability reporting: open the repository's Security tab and choose Report a vulnerability (https://github.com/openprx/sylvode/security/advisories/new). Private reporting is enabled on the repository when this release is published. If you do not see the Report a vulnerability button, it is not enabled for you yet; use e-mail instead.
By e-mail, write to security@openprx.dev, the OpenPRX organisation's published security
contact. Do not put exploit details in any public channel while you wait for an answer.
A useful report contains:
- the affected version (a release tag, or the
versioninCargo.tomland the commit SHA of a source build) and how it is deployed (compose, prebuilt binaries, behind which proxy); - the relevant configuration sections with every secret removed;
- a minimal proof of concept: the HTTP requests, MCP JSON-RPC messages, CLI invocation or plugin module that triggers the problem;
- what an attacker gains, and which role or credential they need to start with.
Reports in English or Chinese are both fine.
We will acknowledge the report, confirm or dispute the finding, and keep you informed
while we work on a fix. When a fix is released we publish a GitHub security advisory and
list the fix under ### Security in CHANGELOG.md. Reporters are credited
in the advisory unless they ask not to be.
Please give us a reasonable chance to release a fix before disclosing publicly, and coordinate the disclosure date with us in the advisory thread. Test only against deployments you own or are explicitly allowed to test, and do not access or modify data that belongs to anyone else.
These areas carry the highest impact, and reports about them are especially welcome.
- Tenant isolation. Workspaces are the isolation boundary. Any way for a user, bot token or plugin in one workspace to read or change another workspace's projects, records, Flow objects, attachments, events or audit entries is in scope, including through search, MCP resources, export packages and signed download URLs.
- WASM plugin sandbox. Any workspace member, and a bot token with write permission, can install a project plugin, so the sandbox is a security boundary. Plugins run in wasmtime with no imports at all (a module that imports anything fails to instantiate), a module size limit of 4 MiB, a fuel budget, a memory limit, one instance, memory and table (of at most 65,536 elements), and a wall-clock deadline that covers compilation and interrupts the guest. The manifest can raise these limits only up to fixed maxima (30 s, 1,000,000,000 fuel, 128 MiB). Escaping the sandbox, reaching host I/O, exceeding these limits, or crashing or stalling the API from a plugin is in scope.
- MCP server and bot tokens. Bot tokens (
opr_prefix) are scoped to one workspace and carryread,writeoradminpermissions that the API enforces. Over thehttpandssetransports each request is made with the caller's own bearer token, which the MCP server forwards to the API; only/healthis reachable without one. Acting without a valid token, acting beyond a token's permissions or workspace, the MCP project policy gate admitting a call it should refuse, or forging theX-Sylvode-MCP-*/X-OpenPR-MCP-*attribution recorded in the audit trail is in scope. - Webhooks and outbound requests. Outbound webhook deliveries are signed with
HMAC-SHA256 over the raw body in
X-Webhook-Signature: sha256=<hex>. Delivery targets that resolve to loopback, private, link-local or other internal addresses are refused unless listed in[outbound] allowed_hosts, and redirects are not followed. A forged or unverifiable signature, a way past the outbound address filter (SSRF), or a secret leaking into logs or stored delivery records is in scope. The inbound side lives in the separate Sylvode Webhook repository and has its own policy. - Collaboration sessions. Live editing uses short-lived tickets bound to an origin in
[flow] collab_allowed_origins. Joining, reading or writing a document without the corresponding Flow permission, or keeping access after it is revoked, is in scope.
Generally out of scope: findings that require an already compromised host or database,
volumetric denial of service, documented insecure settings intended for local
development (such as outbound.allow_private = true or auth.allow_insecure_cookies
on a loopback listener) and vulnerabilities in dependencies with no reachable path in
Sylvode. For a dependency advisory, a normal public issue is fine; cargo audit and
cargo deny run in CI.