{"slug": "show-hn-rlsgate-block-the-supabase-rls-leak-before-you-deploy-cli", "title": "Show HN: Rlsgate – Block the Supabase RLS leak before you deploy (CLI)", "summary": "Rlsgate, a new open-source CLI tool, blocks Supabase Row Level Security leaks before deployment by scanning local migrations, policies, and env files for critical vulnerabilities like the CVE-2025-48757 class that exposed 170+ apps. The tool runs as a local-first static scanner with no database connection or telemetry, and integrates as a CLI, Claude Code skill, or GitHub Action to catch holes before they reach production.", "body_md": "**The Supabase deploy-gate that runs where you vibe-code — and blocks only on the holes that are truly dangerous.**\n\nIn 2026, a wave of AI-built (\"vibe-coded\") apps shipped to production with the same handful of security holes. [CVE-2025-48757](https://nvd.nist.gov/) 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.\n\n`rlsgate`\n\nis 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.\n\n``` bash\n$ rlsgate scan\nrlsgate  ·  1 migrations, 1 env, 2 source files scanned\n\n✖ CRITICAL  Table public.profiles holds personal data but Row Level Security is never enabled\n    where: supabase/migrations/0001_init.sql:2\n    why:   With RLS off in a client-reachable schema, anyone holding the public anon key can read every row.\n    fix:   ALTER TABLE public.profiles ENABLE ROW LEVEL SECURITY; then add an ownership policy.\n\n✖ CRITICAL  RLS policy 'read all posts' grants every authenticated user access to public.posts\n    where: supabase/migrations/0001_init.sql:15\n    fix:   Bind the policy to the row owner, e.g. USING (auth.uid() = user_id).\n\n▲ HIGH      Webhook handler does not verify the request signature (app/api/stripe/webhook/route.ts)\n    ...\n  3 critical  2 high\n$ echo $?\n1\n```\n\nPlenty of tools scan vibe-coded apps. `rlsgate`\n\nis 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.\n\n**vs hosted SaaS scanners**— they guess at your security from*outside*your live URL and want a token to your repo.`rlsgate`\n\nreads 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`\n\ncatches 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`\n\nships 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.\n\nIt'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.\n\n```\npip install rlsgate         # or: uv tool install rlsgate\nrlsgate scan                # scan the current directory\n```\n\nNo Python project? A zero-install run:\n\n```\nuvx rlsgate scan ./my-app\nrlsgate scan [PATH]              # scan a project (default: .)\nrlsgate scan --json             # machine-readable output\nrlsgate scan --fail-on critical # only CRITICAL fails the gate (default: high)\nrlsgate scan --ai               # add AI-drafted fix snippets (needs ANTHROPIC_API_KEY)\nrlsgate rules                   # list the checks\n```\n\n**Exit codes:** `0`\n\nclean (or only findings below `--fail-on`\n\n) · `1`\n\nblocking findings · `2`\n\nusage error. The non-zero exit is what makes it a gate.\n\n| Rule | Severity | The hole |\n|---|---|---|\n`rls-authenticated` |\nCRITICAL | RLS policy authorizes any authenticated user instead of the row owner — the CVE-2025-48757 class |\n`rls-disabled` |\nCRITICAL/HIGH | A user/PII table created without `ENABLE ROW LEVEL SECURITY` (wide open to the anon key) |\n`anon-access` |\nCRITICAL/HIGH | Data reachable by the unauthenticated `anon` role via a permissive policy or grant |\n`public-bucket` |\nHIGH | A Supabase Storage bucket created `public` (every object served to anyone with the URL) |\n`exposed-secret` |\nCRITICAL/HIGH | A real secret committed to `.env` , or a service-role key / `sk-` key shipped to the browser bundle |\n`unverified-webhook` |\nHIGH | A webhook endpoint that acts on the body without verifying the provider's signature |\n\nThe Supabase **anon** key (a public JWT with `role: anon`\n\n) is intentionally public and is **never** flagged — only the dangerous `service_role`\n\nkey is.\n\n```\n# .github/workflows/rlsgate.yml\nname: rlsgate\non: [pull_request]\njobs:\n  scan:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: GerardoRdz96/rlsgate@v0.1.0\n        with:\n          path: .\n          fail-on: high\n```\n\nCopy `skill/`\n\ninto your project's `.claude/skills/rlsgate/`\n\n(or install the repo as a plugin). Then, in the agent loop before deploy:\n\n```\n/rlsgate\n```\n\nThe skill runs the gate and brings the findings into the conversation so the agent fixes them before shipping.\n\n**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`\n\nfix is clearly labeled AI-drafted and must be reviewed before you apply it.\n\nA clean `rlsgate`\n\nrun means \"none of the known high-signal holes are present,\" not \"this app is secure.\"\n\nMIT © 2026 [Penguin Alley](https://penguinalley.com)", "url": "https://wpnews.pro/news/show-hn-rlsgate-block-the-supabase-rls-leak-before-you-deploy-cli", "canonical_source": "https://github.com/GerardoRdz96/rlsgate", "published_at": "2026-06-21 00:15:31+00:00", "updated_at": "2026-06-21 00:37:10.547071+00:00", "lang": "en", "topics": ["ai-tools", "developer-tools", "ai-safety"], "entities": ["Supabase", "Rlsgate", "Claude Code", "GitHub", "Lovable", "CVE-2025-48757"], "alternates": {"html": "https://wpnews.pro/news/show-hn-rlsgate-block-the-supabase-rls-leak-before-you-deploy-cli", "markdown": "https://wpnews.pro/news/show-hn-rlsgate-block-the-supabase-rls-leak-before-you-deploy-cli.md", "text": "https://wpnews.pro/news/show-hn-rlsgate-block-the-supabase-rls-leak-before-you-deploy-cli.txt", "jsonld": "https://wpnews.pro/news/show-hn-rlsgate-block-the-supabase-rls-leak-before-you-deploy-cli.jsonld"}}