Skip to main content

Free 30-min security demo  — We'll scan your real code and show live findings, no commitment Book Now

Offensive360
ZeroDays CVE-2026-63735
High CVE-2026-63735 CVSS 8.1 SurrealDB Rust

SurrealDB Tenant Scope Bypass in API Routes

CVE-2026-63735: SurrealDB before 3.2.0 fails to validate namespace/database scope in custom API routes, enabling cross-tenant data access and unauthorized operations.

Offensive360 Research Team
Affects: < 3.2.0
Source Code

Overview

CVE-2026-63735 is a broken access control vulnerability in SurrealDB, the open-source multi-model database that ships a built-in HTTP API layer alongside its query engine. The flaw exists in how SurrealDB resolves the namespace and database scope for custom API routes — endpoints that application developers define directly within the database using SurrealDB’s DEFINE API statement. When an authenticated request arrives, the server correctly validates the caller’s credentials against their own namespace and database, but then fails to re-validate that the resolved scope of the target endpoint matches the scope the caller is authorized to access. The result is that any authenticated user — regardless of which namespace or database issued their token — can craft a URL that invokes a custom API endpoint belonging to a completely different tenant.

The vulnerability was identified and responsibly disclosed by security researchers, with SurrealDB publishing a coordinated advisory through GitHub Security Advisories. The affected surface is SurrealDB’s custom HTTP API routing layer introduced in recent major versions, making this a relatively new attack surface that many operators may not yet have modeled in their threat assessments.

Organizations running SurrealDB as a multi-tenant backend — a common pattern given the database’s built-in auth primitives — are most directly at risk. A single compromised or malicious user account in any tenant can be leveraged to read data, trigger mutations, or invoke side-effectful operations defined in any other tenant’s custom API routes, with no additional privilege escalation required.

Technical Analysis

SurrealDB’s DEFINE API statement allows developers to register HTTP handlers directly in the database, binding a URL path to a SurrealQL handler function and scoping it to a namespace and database pair. The routing layer is responsible for two distinct jobs: resolving which handler to invoke based on the URL path, and enforcing that the authenticated session is authorized to invoke that handler.

The root cause of this vulnerability is that the route resolution step uses the namespace and database values extracted from the request URL path without verifying that these values match the authenticated session’s own namespace and database. The authentication middleware validates the bearer token and populates a session context with the caller’s ns and db, but the subsequent route dispatch replaces those values with whatever the URL specifies before the authorization check completes.

A simplified representation of the vulnerable dispatch pattern in Rust pseudocode:

// VULNERABLE — namespace/database resolved from URL before authorization check
async fn handle_custom_api(
    State(ds): State<Arc<Datastore>>,
    session: Session,          // session.ns and session.db are from the auth token
    Path((ns, db, path)): Path<(String, String, String)>,
    req: Request,
) -> impl IntoResponse {
    // BUG: ns and db are taken from the URL path, not the authenticated session.
    // No check that session.ns == ns && session.db == db before route lookup.
    let route = ds.resolve_api_route(&ns, &db, &path).await?;

    // Handler is now executing in the context of a *different* tenant's namespace/database
    let ctx = ExecutionContext {
        ns: ns.clone(),   // attacker-controlled
        db: db.clone(),   // attacker-controlled
        session,
    };

    route.handler.execute(ctx, req).await
}

An attacker holding a valid token for ns=tenant_a, db=app can craft a request such as:

GET /api/v1/tenant_b/production/admin/users HTTP/1.1
Host: surrealdb.example.com
Authorization: Bearer <token_for_tenant_a>

Because the bearer token is structurally valid, authentication passes. The route resolver then looks up the custom API handler registered under tenant_b / production / admin/users and executes it — returning data or performing operations entirely outside the attacker’s authorized scope.

The CVSS 8.1 HIGH score reflects the vector AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N — network-reachable, low complexity, requiring only low-privilege credentials, with high impact on both confidentiality and integrity. The absence of an availability component is the primary reason the score does not reach Critical.

Impact

In a multi-tenant SurrealDB deployment, this vulnerability effectively collapses tenant isolation at the custom API layer. An attacker with any valid credential set can:

  • Read cross-tenant data by invoking GET-style custom API endpoints in other namespaces, potentially exfiltrating PII, financial records, or application secrets embedded in handler responses.
  • Trigger unintended write operations by calling POST, PUT, or DELETE handlers in other tenants, including operations that modify or delete records, send notifications, initiate webhooks, or interact with downstream systems.
  • Enumerate tenant topology by probing known or guessed namespace and database names, using HTTP response codes and timing differences as an oracle.
  • Bypass application-layer business logic controls that are enforced only at the custom API layer rather than in underlying table permissions.

Environments where SurrealDB is exposed as a backend-for-frontend, where each customer has their own namespace, face the highest risk. Single-tenant deployments with a single namespace/database pair are not practically affected, but operators should assume multi-tenant exposure whenever SurrealDB is used as a managed service layer.

How to Fix It

Upgrade to SurrealDB 3.2.0 or later. This is the only fully supported remediation. The 3.2.0 release introduces a strict scope enforcement check that verifies the URL-derived namespace and database match the authenticated session’s claims before route resolution proceeds.

# Using the SurrealDB install script
curl -sSf https://install.surrealdb.com | sh -s -- --version v3.2.0

# Verify the installed version
surreal version

For containerized deployments:

docker pull surrealdb/surrealdb:v3.2.0

The corrected dispatch logic performs the scope check before any route resolution occurs:

// FIXED — enforce scope match before route lookup
async fn handle_custom_api(
    State(ds): State<Arc<Datastore>>,
    session: Session,
    Path((ns, db, path)): Path<(String, String, String)>,
    req: Request,
) -> impl IntoResponse {
    // Enforce that the URL-specified scope matches the authenticated session scope.
    if session.ns.as_deref() != Some(&ns) || session.db.as_deref() != Some(&db) {
        return Err(StatusCode::FORBIDDEN);
    }

    // Route resolution now happens only within the caller's authorized scope.
    let route = ds.resolve_api_route(&ns, &db, &path).await?;

    let ctx = ExecutionContext {
        ns: session.ns.clone().unwrap(),
        db: session.db.clone().unwrap(),
        session,
    };

    route.handler.execute(ctx, req).await
}

If an immediate upgrade is not feasible, operators should consider placing a reverse proxy (e.g., Nginx or Caddy) in front of SurrealDB that strips or enforces the namespace and database URL segments based on the authenticated identity, preventing requests from specifying arbitrary scopes. This is a defense-in-depth measure, not a substitute for patching.

Our Take

This vulnerability is a textbook example of a confused deputy problem at the API routing layer — a class of authorization flaw that re-emerges repeatedly in systems that conflate route-level addressing with session-level authorization. The pattern is especially common in databases and platforms that expose programmable HTTP layers, because developers naturally focus security review on the query execution engine while underweighting the routing and dispatch infrastructure that sits in front of it.

For enterprise teams, this is a reminder that custom API capabilities in databases — increasingly common in modern multi-model systems — expand the authorization attack surface significantly beyond traditional database permission models. Table-level and record-level access controls provide no protection when the routing layer allows scope substitution before those controls are evaluated.

From an architectural standpoint, scope context should always be derived exclusively from the authenticated session — never from attacker-controlled URL parameters — and this derivation should happen as early as possible in the request lifecycle, before any tenant-specific resources are resolved.

Detection with SAST

This vulnerability class maps to CWE-863: Incorrect Authorization and CWE-639: Authorization Bypass Through User-Controlled Key. SAST detection targets the pattern where route-handling code resolves a resource scope (namespace, tenant ID, organization ID, database name) from request input and then uses that resolved scope in a downstream operation without first asserting that the authenticated session’s claims bound that scope.

Offensive360’s analysis engine flags the following code patterns in Rust and similar systems:

  • Extraction of scope identifiers from Path, Query, or Header extractors followed by their direct use in datastore or service calls, without an intervening equality assertion against a session or JWT claim.
  • Functions that accept both a session or claims parameter and a separately extracted ns/db/tenant parameter, where no branch explicitly validates the relationship between the two before performing privileged operations.
  • Middleware chains where authentication and authorization are handled in separate layers with no shared context binding, creating windows for scope substitution between layers.

SAST rules in this category are classified under the Broken Access Control rule set, and taint-tracking analysis traces attacker-controlled URL path segments to sensitive datastore resolution calls to surface these flows automatically during CI pipeline analysis.

References

#authorization #multi-tenancy #scope-bypass #api-security

Detect this vulnerability class in your codebase

Offensive360 SAST scans your source code for CVE-2026-63735-class vulnerabilities and thousands of other patterns — across 60+ languages.