ModelEngine-Group / ModelEngine-Group/nexent

SERVICE_ROLE_KEY silently falls back to SUPABASE_KEY — privilege boundary erased

Open
#3,819 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
5.9k
Forks
731
Avg merge
19h 34m
Merged PRs (30d)
172

Description

In backend/consts/const.py:74:

SUPABASE_URL = os.getenv('SUPABASE_URL')
SUPABASE_KEY = os.getenv('SUPABASE_KEY')
SERVICE_ROLE_KEY = os.getenv('SERVICE_ROLE_KEY', SUPABASE_KEY)

The fallback is dangerous in either direction:

  • If SERVICE_ROLE_KEY is unset (a common config mistake), the anon key is used for admin operations — meaning everything that calls get_supabase_admin_client() (backend/utils/auth_utils.py:240) will silently fall back to anon-level access. RLS-protected operations will mysteriously fail, often with cryptic 401s buried inside service code.
  • If only SERVICE_ROLE_KEY is set (e.g. a developer setting up locally and not realising they need both), SUPABASE_KEY is None, but SERVICE_ROLE_KEY is now anchored to the actually-set value. Then get_supabase_client() (line 232) tries to create a client with key=None and create_client raises.

The two keys carry fundamentally different privileges in Supabase — the anon key is intended to be public-readable, the service role key bypasses RLS. Conflating them via a silent default is exactly the kind of mistake that's easy to ship and hard to find in production.

Suggested fix
SUPABASE_KEY = os.getenv('SUPABASE_KEY')
SERVICE_ROLE_KEY = os.getenv('SERVICE_ROLE_KEY')

if SERVICE_ROLE_KEY is None:
    # Don't silently fall back to the anon key — that erases the privilege boundary.
    # In speed/demo mode it's fine to be unset; admin clients will refuse to construct.
    logger.warning("SERVICE_ROLE_KEY is not configured; admin-scoped Supabase operations will fail")

…and have get_supabase_admin_client raise a clear RuntimeError (or domain exception) when called with SERVICE_ROLE_KEY is None, instead of create_client failing inside a generic except.

Category: H (security hardening). Severity: High.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with backend/consts/const.py:74 and trace the clients in backend/utils/auth_utils.py at lines 232 and 240. Verify the behavior when either key is unset and identify the existing exception handling around admin client creation. Done means the two keys remain distinct and an unset SERVICE_ROLE_KEY produces a clear admin-client failure rather than silently falling back or failing generically.

Written by the indexing model from the issue text.

Assessment

Tech stack
python, supabase
Domain
backend, security
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.