An anonymous caller could create new namespaces and databases on a running SurrealDB instance without holding DEFINE NAMESPACE or DEFINE DATABASE permission. USE NS <name> and USE DB <name> automatically create the target when it does not exist. The three places USE is handled — the RPC use method, Datastore::process_use, and the SurrealQL executor — did not check whether the caller was allowed to create the resource. Under default capabilities …
A vulnerability was discovered where the user-supplied WHERE clause in a SELECT statement is evaluated against the full record data before PERMISSIONS FOR SELECT WHERE determines whether the principal is authorised to access that record. A side-effecting expression in the WHERE clause can exfiltrate record contents before the permission check runs. The same ordering bug affects the SET, MERGE, CONTENT and PATCH clauses of update-variant statements (UPDATE, UPSERT-update, INSERT ON …
SurrealDB offers http::* functions that can access external network endpoints, with the –allow-net and –deny-net capabilities used to restrict the set of network targets that can be reached. An authenticated user of SurrealDB can bypass a port-scoped –deny-net <host>:<port> rule by chaining an HTTP redirect: the initial request goes to an –allow-net-permitted hostname, the response's 3xx Location header points at the denied host:port, and the redirect is followed even though …
A LIVE SELECT subscription records the user's auth state ($auth, $token, $session, $access) when it is registered, and the server uses that recorded state to evaluate the table- and row-level PERMISSIONS clauses for every subsequent notification. The recorded state is never refreshed. When something changes the user's effective auth state — the originating session is invalidated, the session's TTL expires, or the user signs in, signs up, or authenticates as …
The HTTP /rpc endpoint has a time-of-check/time-of-use (TOCTOU) race condition on internal session state. When authenticated and unauthenticated requests are processed concurrently, the unauthenticated request can inherit the authenticated user's session and privileges. The /rpc endpoint is the primary interface used by all official SurrealDB SDKs. The HTTP /rpc handler does not bind each incoming request to an isolated session context. Instead, concurrent requests share mutable authentication state. When an …
The HTTP /rpc sessions method returned every attached session UUID without authentication, and the /rpc handler accepted an arbitrary session field with no ownership check. An anonymous caller could enumerate UUIDs and impersonate any authenticated session. "Attached" means sessions registered via {"method":"attach"} — the only writer to the HTTP session map. Ordinary stateless /rpc requests use ephemeral per-request sessions that are filtered from sessions() and destroyed at end-of-request, so they …
An authenticated record or scope user could read records on any table reachable through a graph edge or REFERENCES TO back-reference, regardless of that table's PERMISSIONS FOR select clause. Traversing SELECT * FROM source->edge->target returned full documents from target even when target was defined as PERMISSIONS FOR select NONE. The same bypass extended through multi-hop chains, so any table reachable by a sequence of edges from a readable starting point …
A record user could learn the value of a hidden field by counting how many records match a guess. When DEFINE FIELD … PERMISSIONS FOR select WHERE … hides a field's contents from a caller, and that field is indexed, running SELECT count() FROM t WHERE hidden_field = "guess" GROUP ALL returned a count greater than zero whenever a record actually had that value — even though the caller was …
When a user configures ALGORITHM ES512 for any JWT access method (DEFINE ACCESS … TYPE JWT ALGORITHM ES512), SurrealDB silently substitutes ES384 at all four internal algorithm conversion points. This occurs because the underlying jsonwebtoken crate (v10.x) does not include an ES512 algorithm variant, so the mapping defaults to ES384 without raising an error, warning, or log message. Users who provide the correct P-521 key type for ES512 will experience …
In SurrealDB, records can be connected as a graph: a RELATE statement creates an edge record between two node records. If either endpoint node is deleted, SurrealDB automatically removes the edge row to keep the graph consistent. A user with permission to delete a node could also delete the edges connected to that node, even when the edge table's PERMISSIONS FOR delete clause should have stopped them. The automatic edge …
A LIVE query whose WHERE clause evaluates to an error caused the source data modifier (the user creating, updating, or deleting a record on the watched table) to fail instead. Calling any arbitrary SurrealQL function with a typed parameter and passing a value of the wrong type — for example LIVE SELECT * FROM t WHERE string::trim(deny) — triggered an evaluation error inside the LIVE notification path. That error then …
The KILL statement is used to terminate LIVE SELECT subscriptions that capture real-time changes to data within a table. The KILL statement implementation in core/src/expr/statements/kill.rs verifies that the requesting user has database-level access, but does not verify that the requesting user is the owner of the live query being terminated. After passing the valid_for_db() check, the KILL statement resolves the live query UUID, looks up the corresponding live query entry, …
A record user could read records the table's SELECT permission expression should have hidden, when that expression referenced $value, $before, $after, or $event. Binding a chosen value to that name before registering a LIVE SELECT caused notifications to evaluate the permission against the attacker's input instead of the real document.
A record user with UPDATE access could read field values that field-level SELECT permissions hid from them. Arithmetic operators and extend embedded the raw operand into their error messages, and UPDATE permission checks evaluate against the unreduced document — so triggering such an error against a hidden field returned its value in the resulting error.
RELATE creates an edge record between two existing records, and SurrealDB enforces the CREATE permission on the edge table for this operation. When the statement included a SET id = edge:existing clause, however, the new edge's id ended up pointing at an record that was already in storage. Rather than failing because the target already existed — which is what a create operation should do — the storage layer silently …
An anonymous caller could degrade /sql availability by streaming WebSocket frames many times larger than the operator-configured per-connection limit. The /sql upgrade handler accepted anonymous connections and did not propagate SURREAL_WEBSOCKET_MAX_MESSAGE_SIZE to the WebSocket protocol layer — incoming bytes accumulated in the per-connection read buffer before check_anon could reject the query, so the memory cost was incurred regardless of whether the caller could ever execute SurrealQL. The same upgrade path …
The SurrealDB type/kind parser did not enforce the configured recursion depth limit when parsing nested type annotations. The expression parser already enforced the limit for analogous constructs; the kind parser omitted it. An authenticated attacker could send a query with deeply nested type annotations (e.g., array<option<array<option<…>>>>) and exhaust server memory, crashing the process.
A single unauthenticated WebSocket message to /rpc crashed the SurrealDB server. Sending use { db: "x" } without first selecting a namespace hit .expect("namespace should be set") in the use handler; because surrealdb-core is built with panic = 'abort', the panic terminated the process. use is callable before signin, and the per-method capability check passes by default for guest callers — so no credentials, token, or –allow-guests flag are required.
The SurrealDB value and JSON parser did not enforce the configured recursion depth limit when parsing nested {, [, or ( tokens. The expression parser already enforced the limit for these tokens; the value/JSON parser omitted it. An unauthenticated attacker could send a deeply nested JSON payload to the WebSocket /rpc endpoint and exhaust server memory, crashing the process.
SurrealDB lets callers modify records using JSON Patch operations via the UPDATE … PATCH statement (and SDK equivalents such as db.patch()). One of those operations is copy, which duplicates one field's value into another field of the same record. A PATCH with an empty from — for example, UPDATE thing:1 PATCH [{ op: 'copy', from: '', path: '/leak' }] — was treated as "copy the entire record" and duplicated every …
An authenticated user could bypass permission rules that gated access on parts of a record's id — most commonly tenant-isolation rules of the form PERMISSIONS FOR select WHERE id.tenant = $auth.id.tenant. The same defect also let UNIQUE constraints defined on parts of an id admit duplicate entries. When a query referenced part of a composite record id (id.tenant, id.uid, …), SurrealDB read the value from the record's editable body fields …
SurrealDB fetches the JWKS document for a JWT or record access method using a bare reqwest client that follows HTTP redirects by default. The network capability check in core/src/iam/jwks.rs (check_capabilities_url) is applied only to the originally configured URL; redirect targets are not re-validated. An –allow-net-permitted JWKS host that returns a 3xx Location can therefore redirect the request to an address the allowlist was meant to block, resulting in a server-side …
A field can be hidden from a user with a field-level SELECT permission (DEFINE FIELD code ON secret PERMISSIONS FOR select WHERE owner = $auth.id). When that field is indexed, a record user who cannot read it could still recover the relative ordering of its values across every record by issuing ORDER BY <field>: the field came back null as intended, but the rows were returned in the hidden values' …
A record user could read field values hidden from them by field-level SELECT permissions by reaching the records through a graph-edge (->) or back-reference (<~) traversal instead of a direct SELECT. When a table was readable at the table level but carried a field hidden by a field-level permission (DEFINE FIELD secret ON knows PERMISSIONS FOR select NONE), a direct SELECT * FROM knows hid secret — but reaching the …
An authenticated user could crash a SurrealDB server with a single query containing a long chain of operators. Such a query — for example RETURN 1 + 1 + 1 + … with tens of thousands of terms — is parsed into an expression tree one level deep per operator. Because the chain is flat and the pratt parser appends to it iteratively, the configured query- and object-recursion limits never …
SurrealDB's full-text search lets you define a text analyzer whose mapper filter loads a term-mapping file from disk (DEFINE ANALYZER … FILTERS mapper('<path>')). A database user with the EDITOR or OWNER role could point that filter at any file the SurrealDB process can read and have its content returned in the query's error message. File access is meant to be restricted by the SURREAL_FILE_ALLOWLIST setting, but an empty allowlist applied …
In SurrealDB instances with the scripting capability enabled (–allow-scripting), users with the ability to run arbitrary queries can trigger a server crash due to a memory-safety bug in the underlying JS engine. The SurrealDB instance terminates instantly, requiring a manual restart. The query consists of using built-in string functions to construct a large string and passing it to the JavaScript runtime for compilation. The exact string size required to trigger …
Unprivileged users (for example, those with the database editor role) can create or modify fields in records that contain functions or futures. Futures are values which are only computed when the value is queried. The query executes in the context of the querying user, rather than the user who originally defined the future. Likewise, fields containing functions or custom-defined logic (closures) are executed under the privileges of the invoking user, …