GHSA-6GQW-JQV7-V88M: Tenant Predicate Fix for Cross-Tenant Decay and Quarantine Access
Summary
The patch adds explicit tenant scoping to decay candidate selection, decay route/job propagation, quarantine list/read/moderation lookups, and CLI maintenance entry points, with regression tests demonstrating prior cross-tenant exposure. Based on the provided sources, the fix addresses the documented root cause for decay and quarantine by enforcing tenant_id predicates at the SQL selection layer and threading tenant context through callers. However, the advisory summary also mentions tombstone systems, which are not represented in the supplied patch snippets, so the review can only validate the covered surfaces.
Analysis
Vulnerability
GHSA-6GQW-JQV7-V88M describes a multi-tenant isolation bypass in stigmem-node caused by missing SQL tenant_id predicates. The supplied patch materials show two concrete manifestations of that flaw: decay candidate selection in node/src/stigmem_node/lifecycle/decay.py and quarantine list/moderation paths in node/src/stigmem_node/routes/quarantine.py. In the vulnerable decay flow, candidate queries were parameterized by TTL, confidence, and optional scope, but not by tenant, allowing one tenant to expire another tenant's facts or use dry_run as a cross-tenant count oracle. In the vulnerable quarantine flow, list and fact lookup behavior allowed broader visibility than tenant boundaries should permit, including fact lookup by id without a tenant predicate.
The patch summary is source-consistent with a classic multi-tenant authorization failure: authorization context existed at the request layer, but data access queries did not consistently enforce tenant isolation. That makes the database selection logic the effective trust boundary, and missing predicates there become read/write/delete cross-tenant primitives.
-- vulnerable pattern implied by the supplied snippets
SELECT ...
FROM facts f
WHERE ... -- TTL/confidence/quarantine conditions
-- missing: AND f.tenant_id = ?Relevant sources: patch PR / code digest, GitHub Security Advisory, CVE Reports summary.
Patch
The patch introduces tenant scoping at the query and call-chain levels for the covered surfaces.
For decay, the patch changes the candidate selectors in node/src/stigmem_node/lifecycle/decay.py to accept tenant_id: str and adds AND f.tenant_id = ? to the SQL. It also updates parameter ordering accordingly and threads tenant_id through run_decay_sweep callers. The route layer in node/src/stigmem_node/routes/decay.py now passes identity.tenant_id into the worker and direct sweep invocation. The CLI maintenance path adds a --tenant argument with default default, then forwards that tenant into maintenance execution.
conn: Any, effective_ttl: int, scope: str | None, now_dt: datetime, tenant_id: str
"AND f.tenant_id = ? "
params: list[Any] = [cutoff, tenant_id]
...
ttl_ids = _select_ttl_candidates(conn, effective_ttl, scope, now_dt, tenant_id)For quarantine, the patch updates list filtering so that tenant scope applies to all callers, including admins, by appending f.tenant_id = ? using identity.tenant_id. It also updates fact lookup/moderation helpers to require AND f.tenant_id = ? when resolving a fact by id, and passes tenant_id=identity.tenant_id into garden lookup. The revised comments explicitly redefine admin authority as tenant-local rather than node-global for quarantine moderation.
The tests added in node/tests/test_decay_tenant_scope.py and node/tests/test_quarantine_tenant_scope.py are meaningful regression coverage. The decay tests verify both write isolation and elimination of the dry_run count oracle. The quarantine tests exercise the real HTTP path with the multi-tenant plugin enabled, which is important because tenant resolution behavior depends on plugin activation.
Review
Pros
The strongest aspect of the patch is that it fixes the issue at the data-selection layer rather than relying only on route-level checks. Adding tenant_id directly to the SQL candidate selectors in decay addresses the actual enforcement point. This is the right place to prevent both unauthorized mutation and side-channel leakage via counts.
The patch also correctly propagates tenant context end-to-end. In decay, the route worker signature, direct invocation path, and CLI maintenance path all now carry tenant identity into the lifecycle logic. That reduces the chance of a secure query function being bypassed by an unscoped caller.
For quarantine, the patch removes the dangerous assumption that a node admin is inherently cross-tenant. The new comments and filters align authorization semantics with tenant isolation, and the fact-by-id lookup now enforces tenant ownership before moderation actions proceed.
The regression tests are well targeted and source-grounded. They validate both direct SQL effects and HTTP behavior, and they explicitly cover the previously exploitable count oracle and cross-tenant moderation path.
Cons
The supplied sources do not show any tombstone-related changes, even though the advisory summary mentions decay, quarantine, and tombstone systems. That means the review cannot confirm full remediation of every affected subsystem from the provided patch set alone. If tombstone paths exist elsewhere and remain unscoped, the overall vulnerability class may persist outside the reviewed files.
The CLI default of default is operationally sensible for backward compatibility, but it can be risky in multi-tenant deployments if operators assume a global sweep. The patch improves safety by requiring an explicit tenant parameter path, but it also creates a behavior contract that administrators must understand.
The fix appears localized to known query sites rather than introducing a centralized tenant-scoping abstraction. While the direct SQL predicates are correct, this class of bug can recur if future queries against facts or related tables are added without a shared enforcement helper or repository pattern.
Verdict
Root-cause.
For the decay and quarantine surfaces shown in the patch, the remediation addresses the root cause by enforcing tenant predicates in the SQL paths that actually select and act on data, and by ensuring tenant context is propagated from request/CLI entry points into those queries. The added tests substantiate that the prior cross-tenant write and read/count behaviors are blocked after the change.
That said, this verdict is bounded by the supplied evidence. Because the advisory summary references tombstone systems but the provided diffs do not include tombstone code, engineers should verify that all tombstone read/write/delete paths also enforce tenant_id predicates with equivalent regression coverage. If not, the product-level issue may be only partially remediated even though the reviewed patch is root-cause-correct for the covered components.
Recommended Labs
Try this vulnerability pattern yourself with hands-on labs.
- Middleware.js
Best match for this GHSA’s core issue: missing authorization enforcement leading to cross-tenant data access. The advisory describes authenticated users reaching data outside their tenant because server-side access checks are absent from data operations. This lab is tagged to OWASP A01:2021 and maps to CWE-639/CWE-863 style authorization failures, which aligns closely with tenant-isolation bypass caused by missing tenant predicates.
- Broken Auth.api
Useful as an API-focused defensive lab for strengthening authenticated request validation and authorization boundaries. While this is broader than the exact SQL tenant-filter bug, the GHSA is fundamentally an authenticated API/backend isolation failure. This lab helps practice fixing broken auth/authz controls in service endpoints where trust in caller context is insufficient.
- OAuth.py
A strong complementary lab for defensive thinking around authorization decisions in backend services. The vulnerability here is not OAuth-specific, but the advisory’s root cause is failure to bind authenticated identity to permitted tenant-scoped resources. This lab reinforces server-side authorization validation patterns that help prevent horizontal privilege escalation and cross-tenant access.