Nutzer kann sich selbst Rechte geben (Selbst-Beförderung)
Prüfregel · RSC-SEC-111
- Sicherheit
- Schweregrad: Kritisch
- CWE-269
- OWASP A01-2021
Findet UPDATE-Policies, die den Eigentümer binden, auf Tabellen mit Privileg-Spalte (`role`, `is_admin`, `plan`, `credits`, `balance`, `verified` …), ohne Spaltenrecht, ohne Vergleich in `with check` und ohne schützenden Trigger.
Warum das zählt
Eine Policy wie `for update using (auth.uid() = id)` beantwortet nur, WESSEN Zeile geändert werden darf — nicht, WELCHE Spalten. Steht in derselben Zeile die Rolle, der Tarif oder das Guthaben, ändert der Nutzer sie einfach mit: `update profiles set role = 'admin' where id = auth.uid()`, abgeschickt aus dem Browser.
Row Level Security kennt keine Spalten. Der Schutz muss deshalb anders kommen: über Spaltenrechte (`grant update (display_name) …`), einen Vergleich in `with check` mit dem bisherigen Wert oder einen Trigger. Ein `revoke update (role)` allein wirkt übrigens nicht, solange das Tabellenrecht besteht.
Wir melden das anhand der Migrationen, wenn keiner dieser drei Schutzwege für die Spalte zu finden ist. Am saubersten ist es, Rollen gar nicht in der Profil-Tabelle zu führen, sondern in einer eigenen Tabelle, die nur Admins beschreiben.
Prüfstufe
- Repo-Zugang (Deep-Scan)
So behebt ihr es
`revoke update on <tabelle> from authenticated` und nur die harmlosen Spalten per `grant update (…)` freigeben — oder ein BEFORE-UPDATE-Trigger, der Änderungen an der Privileg-Spalte ablehnt.