GHSA-hv6h-hc26-q48p

Suggest an improvement
Source
https://github.com/advisories/GHSA-hv6h-hc26-q48p
Import Source
https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/06/GHSA-hv6h-hc26-q48p/GHSA-hv6h-hc26-q48p.json
JSON Data
https://api.osv.dev/v1/vulns/GHSA-hv6h-hc26-q48p
Aliases
  • CVE-2026-63738
Published
2026-06-19T22:10:53Z
Modified
2026-09-04T20:25:35Z
Severity
  • 4.3 (Medium) CVSS_V3 - CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N CVSS Calculator
Summary
SurrealDB: Field-level SELECT permissions bypassed via graph and reference traversals
Details

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 same records through a traversal that yields full objects — person:bob->(SELECT * FROM knows), person:bob<~(SELECT * FROM comment), or a projected target vertex ->knows->(SELECT * FROM person) — returned it intact.

The root cause: the shared resolve_record_batch helper used by GraphEdgeScan (FullEdge) and ReferenceScan (FullRecord) enforced only the table-level SELECT permission and pushed raw record data, never running the field-level filtering (build_field_state / filter_fields_by_permission) that ordinary table scans and fetch_record apply.

Impact

A record user can read the values of fields hidden by field-level SELECT permissions, on tables they already hold table-level SELECT on, by materialising the records through a graph-edge, back-reference, or target-vertex traversal — recovering the values directly, for every record the traversal returns.

The disclosure is confined to the field-permission layer: it grants no unauthorised cross-table, cross-record, or cross-namespace/database access. The table's own SELECT permission — including any row-level WHERE predicate — is still enforced, so the caller only reaches records they were already entitled to read; only the per-field SELECT filtering within those records is skipped. Root and record-owner sessions are unaffected, and data cannot be modified (confidentiality only).

Table-level enforcement on these traversals landed in 3.1.0 (the fix for GHSA-vjjx-rfw4-rmfc); releases before 3.1.0 additionally exposed whole records on tables the caller could not read, and are covered by that advisory.

Patches

resolve_record_batch (the shared helper that materialises full records for graph and reference traversals) now applies field-level SELECT permissions and read-time COMPUTED fields to each record, matching the regular table-scan and fetch_record paths.

Versions 3.1.5 and later are not affected.

Workarounds

  • Force the unaffected legacy executor with --planner-strategy compute-only (env SURREAL_PLANNER_STRATEGY).
  • Do not rely on field-level SELECT permissions to hide values on tables reachable as a graph edge, reference target, or traversal vertex; restrict at the table level instead.
  • Use namespace / database isolation as the primary boundary where feasible.

Resources

Database specific
{
    "cwe_ids":  [
        "CWE-863"
    ],
    "github_reviewed":  true,
    "github_reviewed_at":  "2026-06-19T22:10:53Z",
    "nvd_published_at":  null,
    "severity":  "MODERATE"
}
References

Affected packages

crates.io / surrealdb

Package

Name
surrealdb
View open source insights on deps.dev
Purl
pkg:cargo/surrealdb

Affected ranges

Type
SEMVER
Events
Introduced
3.1.0
Fixed
3.1.5

Database specific

source
"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/06/GHSA-hv6h-hc26-q48p/GHSA-hv6h-hc26-q48p.json"