GHSA-98FX-66CF-FC7C
Vulnerability from github – Published: 2026-07-01 20:06 – Updated: 2026-09-04 20:23A 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 DUPLICATE KEY UPDATE, RELATE-update).
This vulnerability is confined to the attacker's current database. It does not cross namespace or database isolation boundaries.
Impact
An authenticated user — including Record and Scope users — can read the full contents of any table in the database they are authenticated against, bypassing PERMISSIONS FOR SELECT WHERE restrictions on those tables.
The most direct exfiltration method requires scripting functions to be enabled (--allow-scripting / -A). However, exfiltration via SurrealQL's THROW statement is also feasible without scripting functions, and timing-based side-channel extraction is possible in all configurations.
All tables within the attacker's current database, regardless of table-level PERMISSIONS FOR SELECT WHERE restrictions on those tables, are vulnerable to this attack. Tables in other databases within the same namespace, or within other namespaces, are not vulnerable.
Patches
A patch has been introduced that runs check_permissions_table before any user-supplied expression is evaluated against the record. A new check_pre_update helper centralises this ordering on every update-variant code path. Regression tests covering WHERE, SET, MERGE, CONTENT, INSERT ON DUPLICATE KEY UPDATE, and RELATE with THROW side-effects are included.
- Versions 3.1.0 and later are not affected by this issue.
Workarounds
Affected users who are unable to update may want to:
- Disable scripting functions if not required — remove the
-A/--allow-scriptingflag. This blocks the most direct exfiltration method but does not fully mitigate the vulnerability, asTHROW-based and timing-based exfiltration remain possible. - Limit query access — restrict the ability of untrusted principals to run arbitrary
SELECTqueries with user-controlledWHEREclauses. - Use namespace/database isolation instead of table-level permissions as the primary security boundary where feasible, since the vulnerability is in table-level permission enforcement, not namespace or database isolation.
{
"affected": [
{
"package": {
"ecosystem": "crates.io",
"name": "surrealdb"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "3.1.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-63755"
],
"database_specific": {
"cwe_ids": [
"CWE-863"
],
"github_reviewed": true,
"github_reviewed_at": "2026-07-01T20:06:08Z",
"nvd_published_at": null,
"severity": "MODERATE"
},
"details": "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 DUPLICATE KEY UPDATE`, `RELATE-update`).\n\nThis vulnerability is confined to the attacker\u0027s current database. It does not cross namespace or database isolation boundaries.\n\n### Impact\n\nAn authenticated user \u2014 including Record and Scope users \u2014 can read the full contents of any table in the database they are authenticated against, bypassing `PERMISSIONS FOR SELECT WHERE` restrictions on those tables.\n\nThe most direct exfiltration method requires scripting functions to be enabled (`--allow-scripting` / `-A`). However, exfiltration via SurrealQL\u0027s `THROW` statement is also feasible without scripting functions, and timing-based side-channel extraction is possible in all configurations.\n\nAll tables within the attacker\u0027s current database, regardless of table-level `PERMISSIONS FOR SELECT WHERE` restrictions on those tables, are vulnerable to this attack. Tables in other databases within the same namespace, or within other namespaces, are not vulnerable.\n\n### Patches\n\nA patch has been introduced that runs `check_permissions_table` before any user-supplied expression is evaluated against the record. A new `check_pre_update` helper centralises this ordering on every update-variant code path. Regression tests covering `WHERE`, `SET`, `MERGE`, `CONTENT`, `INSERT ON DUPLICATE KEY UPDATE`, and `RELATE` with `THROW` side-effects are included.\n\n- Versions 3.1.0 and later are not affected by this issue.\n\n### Workarounds\n\nAffected users who are unable to update may want to:\n\n- **Disable scripting functions** if not required \u2014 remove the `-A` / `--allow-scripting` flag. This blocks the most direct exfiltration method but does not fully mitigate the vulnerability, as `THROW`-based and timing-based exfiltration remain possible.\n- **Limit query access** \u2014 restrict the ability of untrusted principals to run arbitrary `SELECT` queries with user-controlled `WHERE` clauses.\n- **Use namespace/database isolation** instead of table-level permissions as the primary security boundary where feasible, since the vulnerability is in table-level permission enforcement, not namespace or database isolation.",
"id": "GHSA-98fx-66cf-fc7c",
"modified": "2026-09-04T20:23:47Z",
"published": "2026-07-01T20:06:08Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/surrealdb/surrealdb/security/advisories/GHSA-98fx-66cf-fc7c"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-63755"
},
{
"type": "WEB",
"url": "https://github.com/surrealdb/surrealdb/commit/500f4060349580b9cbb9c07b8112a487551c4616"
},
{
"type": "PACKAGE",
"url": "https://github.com/surrealdb/surrealdb"
},
{
"type": "WEB",
"url": "https://www.vulncheck.com/advisories/surrealdb-before-permission-bypass-via-where-clause"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N",
"type": "CVSS_V3"
}
],
"summary": "SurrealDB: Scraping a TABLE with no available PERMISSIONS to current auth level"
}
Drag nodes to arrange them. Double-click a related vulnerability to open it, or a source to visit its link. The Physics button on the left tunes the layout and the simulation; the legend at the bottom left hides or shows nodes by kind and by sighting type.
Sightings
| Author | Source | Type | Date | Other |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.
Vulnerability timeline
Sightings and recorded dates, grouped by day · UTC
How durations are calculated
Following the VTEM framework (Black Hat USA 2015), time to patch starts when the vendor or a coordinator was informed, total time to patch at discovery, and disclosure to patch at public disclosure; vendor response time runs from the report to its acknowledgement. Time to exploit and time unpatched start at the earliest discovery or report, falling back to public disclosure. Unpatched time ends at the first recorded patch, or the calculation time when no patch is recorded. Exploitation to patch shows the interval between those two events; a published proof of concept is a public exploit, not exploitation.
Each result shows its source dates. A negative interval means the end event came first; when date-only inputs leave the order open, the result says so. Date-only inputs are approximate. The earliest evidence wins: KEV report dates and sightings are labelled as such. Records describing another vulnerability are listed but never calculated from, and a PoC alone does not establish exploitation. Missing patch evidence does not prove that no patch exists. Filters below change the event list only.
Loading timeline…
The approach is described in our paper Mapping CVEs to MITRE ATT&CK Techniques: A Curated Gold-Set Classifier and the Limits of LLM-Assisted Label Expansion.
Browse all ATT&CK techniques and the vulnerabilities related to each.
Related by attack behaviour
Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.