Report suspected vulnerabilities through Prisma's private security/escalation channel; do not put tenant data, credentials, exploit details, or bucket coordinates in a public issue.
The multi-tenant model described in docs/MULTITENANCY.md is implemented and enforced — it is not roadmap:
- Customer credentials are short-lived JWTs, JWKS-verified against
the Control-Plane publisher (
STREAMS_AUTH_MODE=enforce), carrying scoped grants intersected with the credential's feed-published grant at the samegrant_version— neither a stale cache nor a widened token can grant beyond the other. - Policies, grants, and signing keys arrive as versioned feeds with
monotonic-publication rules: high-water marks survive snapshot
omissions, so a stale replay cannot restore a previous owner,
reactivate a revoked credential, resurrect removed scopes, or
reintroduce a retired signing key; a workspace change is structurally
bound to an
ownership_versionincrement. - Long-lived subscriptions re-prove authorization for their whole life: every SSE connection carries a lease checked at the response- body boundary on generation change and deadline, terminates at token or credential expiry, and can never start on authorization that was already invalidated. Fleet-internal (workload-JWT) subscriptions are bounded by their token's expiry too.
- Fleet identity is short-lived workload JWTs under the release posture; the static bridge token is a named legacy posture that boot validation refuses there.
Every release runs cargo deny check against the locked dependency graph
(scripts/release-gate.sh). Unknown registries and Git sources, wildcard
requirements, OpenSSL/native-TLS dependencies, unapproved licenses, known
vulnerabilities, and yanked crates fail the gate. Duplicate major versions
are reported for review.
2026-07-21 first run: upgraded object_store 0.14.0→0.14.1 /
quick-xml 0.40.1→0.41.0 (two remotely reachable XML CPU/memory DoS
advisories, RUSTSEC-2026-0194/0195) and spin 0.10.0→0.10.1 (yanked).
The exact exceptions live in deny.toml; each must be reviewed on every
SlateDB/foyer dependency update.
| advisory | dependency path | why it is not currently exploitable | removal condition |
|---|---|---|---|
| RUSTSEC-2025-0141 | SlateDB 0.14.1 → foyer → bincode 1.3.3 | unmaintained status, not a reported vulnerability | upgrade SlateDB/foyer when it removes bincode 1.x |
| RUSTSEC-2024-0436 | SlateDB 0.14.1 → foyer → paste | unmaintained build-time macro crate | same |
| RUSTSEC-2024-0449 | SlateDB 0717cc1 → figment → serde_yaml → unsafe-libyaml | unmaintained; Streams never calls SlateDB's YAML/file/env settings loaders (only Settings::default()) |
SlateDB drops or feature-gates figment's yaml provider |
GitHub advisories that the RustSec database (and so cargo deny) does
not carry, raised by Dependabot. Each row is a triage, not a deny.toml
exception.
| advisory | dependency path | why it is not currently exploitable | removal condition |
|---|---|---|---|
| GHSA-h395-gr6q-cpjc (CVE-2026-25537), Dependabot alert 1, triaged 2026-09-27, re-checked 2026-10-17, fixed by upgrade 2026-10-18 | streams-slate → jsonwebtoken 11.1.0 (direct, crypto backend aws_lc_rs, which rustls and object_store already link; cargo tree -i jsonwebtoken: no other dependent, in no other lockfile) |
fixed upstream in 10.3.0 ("type confusion with exp/nbf when not required"); before the upgrade it was not exploitable here either: a time claim of the wrong JSON type ("nbf": "…") parsed as absent, so jsonwebtoken's own exp/nbf checks skipped it, but src/auth.rs uses jsonwebtoken only to verify the signature (validate_exp, validate_nbf and validate_aud off, required_spec_claims empty; unchanged by the upgrade), the claims deserialize into RawClaims / RawInternalClaims, whose exp: i64 and nbf: Option<i64> refuse a string (the token is refused as AuthError::BadSignature), and check_times checks them against the injected clock |
none: closed by the upgrade (Dependabot closes alert 1 when slate's lockfile carries the fixed version) |
Two independent factors: authentication gates each surface, and the per-stream encryption key gates the data — a leaked token cannot decrypt. Keys never persist server-side; storage and backups are ciphertext.
/v1/streams/*(product API): customer credentials only./v1/stream/*(pinned Durable Streams surface) and/v1/internal/*: INTERNAL-ONLY under shared-cell enforcement — fleet identity per exact operation, never customer tokens./operatorand/v1/debug/*: bearer-gated in every non-off mode (SR-5); the operator dashboard serves operational metadata only — never stream names, tenant identifiers, tokens, keys, or signed URLs.
Never commit tokens, keys, or presigned URLs — deploy tooling keeps them in a local scratch directory outside the repo.