CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



GHSA-3V2X-9XCV-2V2V
7.70.04%

SurrealDB Privilege Escalation: The Future is Root

Amit Schendel
Amit Schendel
Senior Security Researcher

Feb 14, 2026·6 min read·27 visits

PoC Available

Executive Summary (TL;DR)

Unprivileged users can define malicious 'future' fields or functions. When a privileged admin queries these records, the malicious code executes with the admin's full permissions, leading to total database takeover.

A critical Confused Deputy vulnerability in SurrealDB allows unprivileged users to execute arbitrary logic with Root privileges by injecting malicious 'futures' or closures. The database engine failed to capture the creation context of these definitions, executing them instead with the permissions of the invoker—often an administrator.

The Hook: When Features Become Bugs

SurrealDB is the cool kid on the database block. It promises to be the database for everything—relational, document, graph, you name it. One of its killer features is the ability to embed logic directly into the data model. We aren't just talking about simple stored procedures; we are talking about futures, closures, and embedded functions that evaluate dynamically when data is accessed.

Imagine a database field that isn't just a static string, but a living, breathing piece of code that says, "Hey, calculate my value right now based on the current state of the universe." It is powerful. It is flexible. And as it turns out, it was a gaping security hole.

This vulnerability (GHSA-3v2x-9xcv-2v2v) is a classic "Confused Deputy" scenario. The database engine, in its eagerness to be helpful, forgot to ask a very important question: "Who wrote this code?" Instead, it only asked, "Who is running this code?" If you are a lowly editor, and you trick the Root Owner into running your code, guess what? You just became the Root Owner.

The Flaw: Identity Crisis

The root cause here is a failure to snapshot permissions at the time of definition. In security engineering, we often talk about the difference between creation context and execution context.

In a secure system, if User A (Editor) creates a function, that function should run with User A's permissions, even if User B (Root) calls it. SurrealDB, prior to version 2.5.0, did not track this distinction for futures and closures. It treated the code as part of the data, agnostic to its creator.

Here is the logic flow of the failure:

  1. Definition: Low-privilege User A defines a field secret_backdoor with a FUTURE value containing a malicious payload (e.g., DEFINE USER attacker ON ROOT ...).
  2. Storage: The database stores this logic. It checks if User A has permission to write to that field. They do. It passes.
  3. Trigger: High-privilege User B (Admin) runs SELECT * FROM table.
  4. Execution: The query engine sees the FUTURE. It needs to compute the value to show it to User B. It executes the payload.

The Critical Error: The engine executes the payload using User B's session context. Because User B is Root, the DEFINE USER command succeeds. The engine acted as the "Confused Deputy," performing a privileged action on behalf of an attacker who couldn't do it themselves.

The Code: Fixing the Memory

The fix involved teaching SurrealDB to remember. The developers introduced a new struct called AuthLimit. This struct is essentially a sticky note attached to every piece of stored logic, recording the AuthLevel (Root, Namespace, Database, or Record) and the Role of the user who defined it.

Let's look at the concept behind the patch in f515c91363ee.

Before (Conceptual Rust):

// The computation just ran with whatever context was active
fn compute(ctx: &Context, code: &Code) -> Result<Value> {
    // If ctx.user is Root, code runs as Root
    return code.execute(ctx);
}

After (Conceptual Rust):

// Now we have limits
struct AuthLimit {
    level: AuthLevel,
    role: Role,
}
 
fn compute(ctx: &Context, code: &Code, limit: &AuthLimit) -> Result<Value> {
    // Calculate the INTERSECTION of privileges
    let effective_permissions = intersect(ctx.permissions, limit);
    
    // If the creator was an Editor, code runs as Editor,
    // even if ctx.user is Root.
    return code.execute_with_permissions(effective_permissions);
}

The patch ensures that the execution privilege is the lowest common denominator between the invoker and the creator. If an Admin runs an Editor's script, it runs with Editor privileges. If an Editor runs an Admin's script, it runs with Editor privileges. This creates a sandbox that prevents upward escalation.

The Exploit: Trojan Horse

To exploit this, an attacker needs editor permissions (or any role that can write to a record) and a bit of patience. The goal is to plant a landmine that a privileged user will inevitably step on.

Step 1: The Setup

The attacker identifies a table that administrators frequently query or audit. Let's say audit_logs.

Step 2: The Injection

The attacker inserts a record with a malicious FUTURE. The payload uses SurrealQL to create a new root user.

UPDATE audit_logs:123 SET message = <future> {
    -- This code sits dormant until read
    DEFINE USER pwned ON ROOT PASSWORD 'hacker123' ROLES OWNER;
    RETURN "Nothing to see here";
};

Step 3: The Lure

The attacker waits. Alternatively, they can try to trigger an error or a report that forces an administrator to inspect that specific record.

Step 4: The Detonation

The Administrator logs in and runs:

SELECT * FROM audit_logs;

SurrealDB iterates through the records. When it hits audit_logs:123, it evaluates the message field. The DEFINE USER command executes under the Administrator's session.

Result

The attacker can now log in as pwned with full Root access. They own the database, the data, and potentially the underlying server if they can leverage further file-system access features available to Root users.

The Fix: A Dangerous Migration

Mitigation seems simple: Upgrade to version 2.5.0 or 3.0.0-beta.3. But there is a massive catch that could leave you vulnerable even after patching.

> [!WARNING] > The Legacy Trap

When you upgrade, SurrealDB has to decide what permissions to assign to existing futures and functions defined before the patch. Since it didn't track the creator before, it doesn't know who wrote them.

The decision? It defaults old definitions to Root/Owner level permissions to avoid breaking existing applications.

What this means: If an attacker planted a backdoor before you upgraded, and you upgrade without cleaning up, that backdoor is now officially sanctioned as a Root-level script by the migration logic. The patch fixes the hole for new definitions, but it essentially "grandfathers in" the exploit.

Required Remediation Steps

  1. Upgrade the binary.
  2. Audit all futures, functions, and closures.
  3. Redefine them. You must run DEFINE FIELD ... again for every schema definition to stamp them with the correct, current AuthLimit.

Simply restarting the server with the new version is not enough to clear existing malware.

Official Patches

SurrealDBOfficial Release Notes for v2.5.0

Fix Analysis (1)

Technical Appendix

CVSS Score
7.7/ 10
CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
EPSS Probability
0.04%
Top 100% most exploited

Affected Systems

SurrealDB

Affected Versions Detail

Product
Affected Versions
Fixed Version
SurrealDB
SurrealDB
< 2.5.02.5.0
SurrealDB
SurrealDB
3.0.0-alpha.1 - < 3.0.0-beta.33.0.0-beta.3
AttributeDetail
Attack VectorNetwork
CVSS v4.07.7 (High)
Privileges RequiredLow (Editor)
User InteractionPassive (Required)
ImpactPrivilege Escalation / Full Takeover
Bug ClassConfused Deputy

MITRE ATT&CK Mapping

T1068Exploitation for Privilege Escalation
Privilege Escalation
T1059Command and Scripting Interpreter
Execution
CWE-611
Improper Restriction of XML External Entity Reference

Vulnerability Timeline

Patch Commit Merged
2026-01-20
Advisory Published
2026-01-22
CVSS 4.0 Analysis Added
2026-02-03

References & Sources

  • [1]GitHub Security Advisory

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.