Sep 5, 2026·6 min read·2 visits
An authenticated SurrealDB user with minimal privileges can access and execute custom APIs defined by other tenants in multi-tenant environments, leading to unauthorized read/write access to arbitrary database resources.
SurrealDB prior to version 3.2.0 is vulnerable to an authorization bypass where authenticated users can invoke custom API endpoints belonging to other tenants. This cross-tenant data access occurs because the system fails to validate authorization scope boundaries against request-supplied namespace and database identifiers before executing scripts with elevated definer's rights.
SurrealDB provides an architecture that allows developers to define custom HTTP API endpoints. These endpoints map direct external web requests to internal SurrealQL execution scripts. This mapping is defined via DEFINE API statements, which designate a custom route and associated queries.
By design, these custom API handlers execute with definer's rights, meaning traditional table-level and record-level permissions are bypassed during their execution to allow the engine to process specialized transactions. Because the script runs with permissions disabled, verifying the authentication and authorization scope of the caller before dispatching to the script is critical.
The attack surface exists at the routing boundary where HTTP requests targeting /api/{namespace}/{database}/{endpoint} are parsed. In multi-tenant environments, a failure to restrict users to their assigned namespace and database scopes allows low-privileged actors from one tenant context to manipulate other tenants' data stores via custom API execution.
The core flaw is a failure in authorization boundary enforcement combined with request-driven session pollution. When an HTTP request is made to a custom API route, the routing framework extracts the target namespace (ns) and database (db) parameters directly from the URL path.
Prior to the patch, the HTTP server overrode the active session state's namespace and database parameters with the user-supplied values from the request URL. While the server verified that the user's cryptographic token (such as a JWT) was valid, it omitted the step of verifying whether the authenticated security principal had authorization to operate within the targeted namespace and database.
This gap allowed an authenticated session associated with tenant_a to target the endpoint namespace and database belonging to tenant_b. Once the session context was overwritten, the engine proceeded to look up and execute the custom API endpoint configured under tenant_b. Because the custom API executed with definer's rights, the engine completed the database queries on behalf of the attacker, completely bypassing the isolation boundary.
The vulnerability was mitigated through patches implemented in commits 0938f88d196dc4eb11a82af343df3fffe9c195e2 and 75b7154f84904d047619b5a47b08d256254dceca. The solution introduces a structured authorization check, can_access_ns_db, which validates the authenticated level against the target resource parameters.
// surrealdb/core/src/iam/auth.rs
impl Auth {
/// Check whether the authenticated level is permitted to operate within the
/// given namespace and database.
pub fn can_access_ns_db(&self, ns: &str, db: &str) -> bool {
match self.level() {
Level::Root => true,
Level::Namespace(n) => n.eq(ns),
Level::Database(n, d) => n.eq(ns) && d.eq(db),
Level::Record(n, d, _) => n.eq(ns) && d.eq(db),
Level::No => true,
}
}
}This helper is placed at the critical chokepoint in the API request processor to intercept calls before execution occurs:
// surrealdb/core/src/api/invocation.rs
pub async fn process_api_request_with_stack(
api: &ApiDefinition,
req: ApiRequest,
) -> Result<ApiResponse> {
// Tenant-boundary enforcement (GHSA-848m-r628-vrxw)
let (ns_name, db_name) = opt.ns_db()?;
if !opt.auth.can_access_ns_db(ns_name, db_name) {
trace!(
request_id = %req.request_id,
"API request denied: selected namespace/database is outside the authenticated session scope"
);
return Ok(ApiResponse::from_error(ApiError::PermissionDenied, req.request_id.clone()));
}
// ... execution continues only if authorized
}A matching block was added to the datastore routing level in surrealdb/core/src/kvs/ds.rs to secure direct database routing over HTTP. These boundary checks ensure that even if route parsing overwrites session variables, the security context level acts as the authoritative boundary constraint.
An attacker can exploit this vulnerability through two separate vectors: direct HTTP custom API calls and the SQL api::invoke routine. The execution mechanics depend on the attacker having a valid authenticated session on any namespace in the system.
In a direct HTTP attack, the attacker generates a JWT for their legitimate low-privileged account within namespace_attacker. The attacker then crafts an HTTP request targeting the custom endpoint configured in namespace_victim:
GET /api/namespace_victim/database_victim/secret_endpoint HTTP/1.1
Host: target-surrealdb-instance:8000
Authorization: Bearer <attacker_jwt_token_for_namespace_attacker>The server receives the request, parses the URL, and updates the connection session namespace to namespace_victim and database to database_victim. The security layer validates that the token is authentic. In unpatched versions, the request is passed directly to the executor, which processes the custom API and returns the victim's data to the attacker.
In the SQL attack path, the attacker establishes an active database session under their own scope and calls the api::invoke function while attempting to target the victim's namespace context:
USE NS namespace_victim DB database_victim;
RETURN api::invoke("/secret_endpoint");Because the database session environment is mutated prior to the api::invoke validation, the engine processes the API call using the victim's scope parameters, allowing the attacker to retrieve data.
The impact of this vulnerability is critical in multi-tenant installations of SurrealDB. It completely breaks tenant isolation, which is a foundational requirement for Cloud and Software-as-a-Service (SaaS) environments where database instances are shared among multiple clients.
Because custom APIs run with definer's rights, an attacker does not need read or write permissions to the underlying tables of the victim database. Instead, they gain access to whatever capabilities the custom API endpoint itself exposes. If a victim has defined endpoints to create, modify, or delete records, the attacker can leverage these capabilities to perform unauthorized actions.
The CVSS v4.0 rating is 8.6 (High), with high confidentiality and high integrity impact scores. There is no direct availability impact on the database daemon, and the scope remains unchanged as the target is confined to the database instance itself.
The primary remediation strategy is upgrading the SurrealDB engine to version 3.2.0 or newer. This version implements robust validation of session levels against requested resources.
If upgrading is not immediately possible, organizations should apply the following defensive workarounds:
PERMISSIONS FULL unless manual identity checks are integrated into the custom SQL script.$auth within the endpoint scripts to verify that the calling identity is authorized to access the requested tenant resources.CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
SurrealDB SurrealDB | < 3.2.0 | 3.2.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-639: Authorization Bypass Through User-Controlled Key |
| Attack Vector | Network |
| CVSS v4.0 Score | 8.6 (High) |
| EPSS Score | 0.00367 (Percentile: 29.78%) |
| Exploit Status | PoC (Proof of Concept documented in integration tests) |
| CISA KEV Status | Not Listed |
| Vulnerability Class | Improper Authorization |
The system fails to check if an authenticated user possesses the authority to perform operations on a targeted database resource identified by a user-supplied key in the request URL.
An argument injection vulnerability in CodeWhale (CVE-2026-75912 / GHSA-c6mw-8xh8-gpq6) allows unauthenticated remote attackers to execute arbitrary option commands on the git binary. By passing malicious command-line flags inside git_blame and git_show tool helper functions, an attacker can bypass typical access controls to read arbitrary local system files via the underlying git process.
An incorrect authorization vulnerability (CWE-863) in SurrealDB allows authenticated, low-privileged users to execute unauthorized state-modifying queries. This occurs because the database disabled permissions during evaluation of custom PERMISSIONS WHERE predicates to prevent infinite recursion.
SiYuan before v3.7.4 fails to enforce publish-access filters on five filetree path-resolution endpoints, allowing unauthenticated attackers to reconstruct private directory layouts and map document structures.
Prior to version v3.7.4, the SiYuan personal knowledge management system contained a critical logical authorization vulnerability within its database view rendering component. The flaws allowed unauthenticated remote attackers to bypass publish-access filters on databases, exposing sensitive Relation and Rollup cell contents belonging to private or password-protected repositories.
An information disclosure vulnerability exists in SiYuan prior to v3.7.4 due to missing authorization checks on the getEncryptedNotebookStatus API endpoint, allowing unprivileged or anonymous users to enumerate protected notebooks.
An information disclosure vulnerability in the SiYuan application exposes the global session cookie signing key via the `/api/system/getConf` endpoint. This allows unauthenticated remote attackers or low-privileged users to forge administrative session cookies and gain unauthorized access to the application kernel.