A PERMISSIONS ... WHERE clause is evaluated with permission enforcement disabled, so it can't recurse into its own checks. But the clause could also contain data-modifying statements, and these ran with enforcement still off — so evaluating a permission check could write to tables the caller cannot write.
For example:
DEFINE TABLE post PERMISSIONS FOR update
WHERE (CREATE log SET at = time::now()) OR true;
Any user allowed to update a post now also creates a log record, even with no permission on log. The clause is evaluated once per matched record, so one statement can cause several writes.
Only databases with a PERMISSIONS clause that contains a write are affected; FULL, NONE, and read-only clauses are not.
What an attacker can do:
What it can't do:
Permission clauses must now be read-only: defining or importing one that contains a write is rejected, and any write attempted while a clause is evaluated is blocked at runtime, including writes reached through a called function. Read-only clauses are unaffected.
Users unable to patch should consider the following workarounds:
PERMISSIONS clauses and remove any containing CREATE, UPDATE, DELETE, RELATE, INSERT, or UPSERT.fix(core): reject writes in PERMISSIONS clauses and block writes during permission evaluation (included in SurrealDB 3.2.0)Thank you to sondt99 for reporting this issue.
{
"cwe_ids": [
"CWE-863"
],
"github_reviewed": true,
"github_reviewed_at": "2026-09-04T20:50:40Z",
"nvd_published_at": null,
"severity": "MODERATE"
}