Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extremely dangerous bug: Partial .rpc(...) execution when client is called from Next14 Server Actions. Breaks ACID guarantee. #1002

Open
2 tasks done
sudowoodo200 opened this issue Mar 30, 2024 · 0 comments
Labels
bug Something isn't working

Comments

@sudowoodo200
Copy link

Bug report

  • I confirm this is a bug with Supabase, not with my own application.
  • I confirm I have searched the Docs, GitHub Discussions, and Discord.

Describe the bug

A RPC call that only partially runs when called from a server action.

To Reproduce

I have a form that takes in two values: id and value, then calls the server action update defined below.

Server action file

"use server":
import {createClient} from @supabase/supabase-js

const admin = createClient(supabaseUrl, supabaseServiceRoleKey);
export async function update(id: string, value: number) {
   const { data, error } = await admin.rpc("update", {
      id: id,
      value: value,
  });
  return data
}

Table and Stored Procedure

create table users (
   id uuid references auth.users not null primary key,
   balance numeric default 0 not null
);
alter table users enable row level security;
create policy "Can view own user data." on users for select using (auth.uid() = id);

create or replace function public.update(id uuid, value numeric) 
returns numeric as $$
declare
  valid_value numeric;
begin
  select least(value, balance) into valid_value
  from users
  where id = id;

  update users
  set balance = balance - valid_value
  where id = id;

  return valid_value;
end;
$$ language plpgsql security definer;

Think of this as a deposit withdrawal. What happens?

  • rpc call succeeds with the correct value of valid_value returned. No error.
  • The update clause of the stored procedure does not run, so the balance is not updated for the withdrawal.

This is not an RLS failure. I turned off RLS entirely for the users table and problem persists. The problem disappears when the Server Action block is moved to an API route and called from an API invocation.

Expected behavior

RPC runs entirely or not at all. In this case, RPC should always run, regardless of RLS, given the service_role key.

System information

  • OS: MacOs
  • Browser (if applies) Chrome
  • Version of supabase-js: 2.23.0
  • Version of Nextjs: 14.0.4

Additional context

Add any other context about the problem here.

@sudowoodo200 sudowoodo200 added the bug Something isn't working label Mar 30, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant