Skip to main content

The Supabase deploy-gate that runs where you vibe-code — block the RLS and secret leaks before deploy.

Project description

rlsgate — the Supabase deploy-gate that runs where you vibe-code

rlsgate

The Supabase deploy-gate that runs where you vibe-code — and blocks only on the holes that are truly dangerous.

In 2026, a wave of AI-built ("vibe-coded") apps shipped to production with the same handful of security holes. CVE-2025-48757 and the Lovable disclosure cataloged 170+ live apps leaking user PII — most through one anti-pattern: a Row Level Security policy that lets any logged-in user read everyone's rows. Studies of vibe-coded apps found ~80% repeat the same RLS mistake and ~72% ship a hardcoded secret somewhere.

rlsgate is a local-first, static scanner that reads your Supabase migrations, RLS policies, env files, and frontend bundle and blocks the deploy when it finds the finite set of high-signal holes that actually leak. No database connection, no telemetry, no account. It runs in seconds, as a CLI, a Claude Code skill, or a GitHub Action.

$ rlsgate scan
rlsgate  ·  1 migrations, 1 env, 2 source files scanned

✖ CRITICAL  Table public.profiles holds personal data but Row Level Security is never enabled
    where: supabase/migrations/0001_init.sql:2
    why:   With RLS off in a client-reachable schema, anyone holding the public anon key can read every row.
    fix:   ALTER TABLE public.profiles ENABLE ROW LEVEL SECURITY; then add an ownership policy.

✖ CRITICAL  RLS policy 'read all posts' grants every authenticated user access to public.posts
    where: supabase/migrations/0001_init.sql:15
    fix:   Bind the policy to the row owner, e.g. USING (auth.uid() = user_id).

▲ HIGH      Webhook handler does not verify the request signature (app/api/stripe/webhook/route.ts)
    ...
  3 critical  2 high
$ echo $?
1

Why it's different

Plenty of tools scan vibe-coded apps. rlsgate is the one that is local-first, runs inside your build loop, and blocks at deploy — not a dashboard you visit, not a sidecar you run in production.

  • vs hosted SaaS scanners — they guess at your security from outside your live URL and want a token to your repo. rlsgate reads your actual migrations and RLS policies locally. No DB connection, no account, no token handoff, no telemetry.
  • vs runtime sidecars / firewalls — they filter requests after deploy, in front of your app. rlsgate catches the hole before deploy, in your repo, where it's a one-line fix instead of an incident.
  • vs broad scanners — they compete on rule count (hundreds to thousands), which means noise, which means you turn them off. rlsgate ships a finite, high-precision set of checks for the holes that actually leak — including the CVE-2025-48757 "any authenticated user can read any row" class that breadth scanners miss — so it's a gate you'll actually leave on.

It's the same checks across three surfaces with full parity: a CLI, a Claude Code skill that fires mid-build (inside the AI tool generating your app), and a GitHub Action that blocks the merge. Works across any builder — Lovable, Bolt, Cursor, v0, or hand-rolled.

Install

pip install rlsgate         # or: uv tool install rlsgate
rlsgate scan                # scan the current directory

No Python project? A zero-install run:

uvx rlsgate scan ./my-app

Usage

rlsgate scan [PATH]              # scan a project (default: .)
rlsgate scan --json             # machine-readable output
rlsgate scan --fail-on critical # only CRITICAL fails the gate (default: high)
rlsgate scan --ai               # add AI-drafted fix snippets (needs ANTHROPIC_API_KEY)
rlsgate rules                   # list the checks

Exit codes: 0 clean (or only findings below --fail-on) · 1 blocking findings · 2 usage error. The non-zero exit is what makes it a gate.

What it checks (v1)

Rule Severity The hole
rls-authenticated CRITICAL RLS policy authorizes any authenticated user instead of the row owner — the CVE-2025-48757 class
rls-disabled CRITICAL/HIGH A user/PII table created without ENABLE ROW LEVEL SECURITY (wide open to the anon key)
anon-access CRITICAL/HIGH Data reachable by the unauthenticated anon role via a permissive policy or grant
public-bucket HIGH A Supabase Storage bucket created public (every object served to anyone with the URL)
exposed-secret CRITICAL/HIGH A real secret committed to .env, or a service-role key / sk- key shipped to the browser bundle
unverified-webhook HIGH A webhook endpoint that acts on the body without verifying the provider's signature

The Supabase anon key (a public JWT with role: anon) is intentionally public and is never flagged — only the dangerous service_role key is.

GitHub Action

# .github/workflows/rlsgate.yml
name: rlsgate
on: [pull_request]
jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: GerardoRdz96/rlsgate@v0.1.0
        with:
          path: .
          fail-on: high

Claude Code skill

Copy skill/ into your project's .claude/skills/rlsgate/ (or install the repo as a plugin). Then, in the agent loop before deploy:

/rlsgate

The skill runs the gate and brings the findings into the conversation so the agent fixes them before shipping.

What rlsgate is NOT

  • Not a full security audit. It checks a finite, high-signal ruleset, statically. It will not catch logic bugs, business-rule auth flaws, or holes that only appear at runtime.
  • Not a database scanner. v1 reads files only — it never connects to your Supabase project. A policy that looks correct but behaves differently at runtime is out of scope.
  • Not an auto-fixer. The deterministic finding is the source of truth. The optional --ai fix is clearly labeled AI-drafted and must be reviewed before you apply it.

A clean rlsgate run means "none of the known high-signal holes are present," not "this app is secure."

License

MIT © 2026 Penguin Alley

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

rlsgate-0.1.0.tar.gz (25.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

rlsgate-0.1.0-py3-none-any.whl (33.6 kB view details)

Uploaded Python 3

File details

Details for the file rlsgate-0.1.0.tar.gz.

File metadata

  • Download URL: rlsgate-0.1.0.tar.gz
  • Upload date:
  • Size: 25.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for rlsgate-0.1.0.tar.gz
Algorithm Hash digest
SHA256 54e0994940578fb4901f6f4de3a4e5a0057252863e3207712d6cb49f23d4471e
MD5 80c1c28ba96cee9080c041e0faed059a
BLAKE2b-256 f6aaf367f354c55763f0ddcdf2cb8e5a0f35778377f722a4d08dbddacde514f2

See more details on using hashes here.

File details

Details for the file rlsgate-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: rlsgate-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 33.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for rlsgate-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9e2567dbef8c931b873405681ff56c573ead8e990f7ef8823475bf04a45d25c4
MD5 ca6b97ac7d862d28b2946d85ed4de19b
BLAKE2b-256 0d009d34b1f6d1b703278be65e92baa2cd580e37c1312c3a5d9cfa5a4b8f49e7

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page