Your AI Shipped the App. Did It Leave the Keys in the Repo?
Your AI Shipped the App. Did It Leave the Keys in the Repo?
Last month, security firm UpGuard told TechCrunch it had found around 16,000 Supabase-hosted databases exposing personal data — names, addresses, phone numbers, even passwords — queryable by anyone on the open web. Not hacked. Just... left open.
The mechanism behind almost all of it: AI coding tools write SQL migrations directly, and in that path Postgres row-level security defaults to off. Supabase's dashboard turns RLS on when you click through the Table Editor, but AI tools don't click through dashboards. A founder types a prompt, the AI ships a working app in an afternoon, and nobody ever flips the switch that keeps one user from reading every other user's rows.
That is the vibe-coding security gap in one sentence: the app works, so nobody checks the configuration.
What I built
vibe-shipcheck — a zero-dependency Python CLI that runs the pre-publish security checklist vibe-coded apps never get:
pip install vibe-shipcheck vibe-shipcheck ./my-app vibe-shipcheck 0.1.0 — pre-publish security check Scanning: /home/hao/my-app ERRORS: [env-committed] .env — .env file is tracked by git — its secrets ship with the repo fix: Add it to .gitignore, run `git rm --cached .env`, rotate every key it held. [rls-disabled] supabase/migrations/001_init.sql — migration creates table(s) profiles without ENABLE ROW LEVEL SECURITY — readable by anyone with the anon key fix: Add `ALTER TABLE <table> ENABLE ROW LEVEL SECURITY;` plus policies for every table, or enable RLS in the dashboard. WARNINGS: [supabase-url-exposed] src/lib/supabase.ts:3 — Supabase project URL in source fix: The URL itself is public, but anyone with it + your anon key can query every table whose RLS is off. [cors-wildcard] api/main.py:12 — wildcard CORS origin — any website can call this API fix: Restrict origins to your own domains before publishing. 2 error(s), 2 warning(s) BLOCKED — fix the errors above before publishing. What it checks:
- Committed
.envfiles — tracked by git, untracked-but-unignored, or unverifiable. The classicgit add .leak. - Hardcoded secrets — AWS, GitHub, Stripe, OpenAI-style keys, PEM blocks, plus generic
password=/api_key=literals. Proper env references (os.environ[...],process.env...) and placeholders are never flagged. - Supabase exposure — project URLs in source, and it actually decodes JWTs to tell the public
anonkey fromservice_role(which bypasses all RLS and must never be in code). - Missing RLS — scans your migration SQL; any
CREATE TABLEwithoutENABLE ROW LEVEL SECURITYis an error. This is the exact UpGuard failure mode. - Wildcard CORS and debug/dev flags left on.
Every finding ships with a one-sentence fix line — the audience is someone who prompted an app into existence, not someone who reads CVE feeds.
Exit code 1 on errors, so it drops straight into CI or a deploy script. --strict fails on warnings too, --json gives machine-readable output.
Why not just use Trivy / Gitleaks?
Those tools scan for vulnerabilities in code — CVEs, secret patterns in history. That's a different moment. vibe-shipcheck owns the pre-publish checklist: the ten seconds between "the AI says it's done" and "it's live on the internet." Nobody hand-writing an app forgets RLS on every table; AI tools do it by default. The failure mode is configuration, not code, and it needs a checker that thinks in terms of shipping, not CVEs.
Use both: Gitleaks in CI for deep secret history, vibe-shipcheck as the gate right before you hit publish.
Try it
- GitHub: https://github.com/hahahahahahahahah6/vibe-shipcheck
- PyPI: https://pypi.org/project/vibe-shipcheck/
pip install vibe-shipcheck and run it against your own vibe-coded projects — I'd genuinely like to hear what it finds. If it catches a real leak before you ship, tell me in the comments.
tags: python, security, supabase, vibecoding
canonical: https://github.com/hahahahahahahahah6/vibe-shipcheck
原文:https://www.a8q9.cn/en/article/your-ai-shipped-the-app-did-it-leave-the-keys-in-the-repo-781ae9.html