Skip to main content
interlace
SecurityPlugin: supabase-securityRules

require-auth-error-check

Read `error` from a Supabase auth result

Read error from a Supabase auth result.

Why

supabase.auth.getUser() does not throw when the token is missing, expired or forged. It resolves:

{ data: { user: null }, error: AuthApiError }

Code that destructures only data therefore reads an authentication failure as an anonymous request. That is fine when the next line is a login prompt and wrong when it is an authorisation decision — and the failure is silent either way, because user is null on both paths. Any if (!user) redirect('/login') guard downstream cannot tell "no session" from "the auth service errored".

Rule details

Fires only in files importing a @supabase/* package. Reports a destructuring declaration whose initialiser is a call to .auth.getUser(), .auth.getSession(), .auth.refreshSession() or .auth.exchangeCodeForSession() and whose pattern does not bind error.

error, error: renamed, 'error': e and a rest element all count as bound. A computed key counts as bound too — const k = 'error' does bind it, and the node cannot tell that from any other computed key, so the rule abstains rather than flag correct code.

A .then() chain is not reported: the result is not destructured at the declarator, so there is no omission to read.

Incorrect

import { createClient } from '@supabase/supabase-js';

const { data } = await supabase.auth.getUser();
if (!data.user) redirect('/login'); // an auth outage takes this branch too

Correct

import { createClient } from '@supabase/supabase-js';

const { data, error } = await supabase.auth.getUser();
if (error) throw error;
if (!data.user) redirect('/login');

Further reading

Did this rule catch something? Star the repo to get new CWE coverage as we ship it — or follow the AI-code-security benchmarks behind these rules.