{"slug": "12-things-to-check-before-you-ship-your-vibe-coded-app", "title": "12 things to check before you ship your vibe-coded app", "summary": "A security analysis by Symbiotic Security found that 98% of 1,072 Supabase-backed vibe-coded apps had at least one security issue, with 16% containing critical flaws. An academic study by Deng et al. identified recurring vulnerability patterns unique to these apps, while Xint.io reported 434 exploitable flaws concentrated in secrets exposure, broken authorization, and denial of service. A developer recommends a 15-minute checklist including checking for exposed .env and .git files, hardcoded secrets, missing security headers, and unauthenticated debug routes.", "body_md": "Getting an app to *work* has stopped being the hard part. You describe what you want, Lovable or Bolt or v0 builds it, and forty minutes later there's something on a real URL that real people can click.\n\nThe hard part moved. It's now everything between \"it works\" and \"it survives contact with the internet.\"\n\nThat gap isn't a vibe. It's measurable. [Symbiotic Security](https://www.symbioticsec.ai/research) crawled 65,643 URLs and fully scanned 1,072 Supabase-backed vibe-coded apps in June 2026: 98% had at least one security issue, 16% had something critical. A separate [academic study by Deng et al.](https://arxiv.org/abs/2606.23130) found that vibe-coded apps show *recurring* vulnerability patterns that differ from the ones traditional codebases produce — meaning these aren't random mistakes, they're structural. And an Xint.io analysis reported by SecurityWeek turned up 434 exploitable flaws concentrated in secrets exposure, broken authorization and denial of service.\n\nSame handful of failure modes, over and over. Which is good news, because it means you can check for them in about fifteen minutes.\n\nBelow is the list I actually walk through. Everything here you can run against your own domain with curl and browser devtools. No tooling required.\n\n`.env`\n\nreachable over HTTP?\nThe single most common catastrophic finding. It happens when the build output directory and the project root end up being the same thing.\n\n```\ncurl -sI https://yourapp.com/.env | head -1\ncurl -sI https://yourapp.com/.env.local | head -1\ncurl -sI https://yourapp.com/.env.production | head -1\n```\n\nAnything other than `404`\n\nis an emergency. Rotate every key in that file before you do anything else — assume it's already been scraped, because bots hit these paths constantly.\n\n`.git`\n\ndirectory exposed?\nWorse than `.env`\n\n, because it hands over your entire history including keys you *thought* you'd removed.\n\n```\ncurl -sI https://yourapp.com/.git/HEAD | head -1\ncurl -s  https://yourapp.com/.git/config\n```\n\nIf `HEAD`\n\nreturns 200, the whole repository is reconstructable by a stranger.\n\nOpen devtools, go to Sources, and search across all files. You're looking for `sk-`\n\n, `service_role`\n\n, `SECRET`\n\n, `PRIVATE_KEY`\n\n, and long strings starting with `eyJ`\n\n(those are JWTs).\n\nThe nuance that trips people up: a Supabase *anon* key in the browser is fine by design. A *service_role* key is not — it bypasses row-level security entirely. AI assistants confuse the two constantly, because both are \"the Supabase key\" from the prompt's point of view.\n\nHaving an anon key in the browser is only safe if RLS is enabled on every table. Default-off is the trap. Go through your tables one by one and confirm policies exist. \"I'll add policies later\" is how the 16% happens.\n\n```\ncurl -sI https://yourapp.com | grep -iE 'content-security-policy|strict-transport-security|x-frame-options|x-content-type-options|referrer-policy|permissions-policy'\n```\n\nMost vibe-coded deploys return none of these. The two that matter most immediately are `Content-Security-Policy`\n\n(or at minimum `frame-ancestors`\n\n) to stop clickjacking, and `Strict-Transport-Security`\n\nso a downgrade attack can't strip your TLS.\n\n```\ncurl -sI https://yourapp.com/_next/static/chunks/main.js.map | head -1\n```\n\nSource maps in production hand attackers your original, readable source — comments, internal function names, dead code paths and all. Turn them off in your build config, or restrict them to authenticated access.\n\nGrep your own bundle for `console.log`\n\nand check whether anything sensitive is being printed on page load. Then try the routes nobody meant to ship: `/api/debug`\n\n, `/api/test`\n\n, `/admin`\n\n, `/api/seed`\n\n. AI-generated scaffolding loves to leave these behind, unauthenticated.\n\nAlmost never present unless explicitly asked for. Without it, your login endpoint is a free credential-stuffing target and your LLM-backed API route is somebody else's free inference budget. Check whether your host gives you rate limiting at the edge — often it's a config flag you just haven't flipped.\n\nTrigger a failure deliberately: malformed JSON to a POST endpoint, a bad ID in a path parameter. If you get back a stack trace, a file path, or an ORM error naming your tables and columns, that's free reconnaissance for anyone probing you.\n\n```\ncurl -s https://yourapp.com | grep -iE '<title>|og:image|og:description'\n```\n\nIf it still says \"Create Next App\", or there's no Open Graph image, you're broadcasting that nobody reviewed this. It's not a vulnerability, but it changes how everything else about your product gets judged — including by the security researcher deciding whether you're worth poking at.\n\nOpen the Network tab, hard-reload, and watch what leaves the page before you've clicked anything. If Google Analytics, Meta Pixel or a session recorder fires on load, you have a consent problem in the EU — and a \"we didn't know it was there\" problem generally, because AI-generated templates ship with analytics snippets baked in.\n\nRelated and easy to miss: Google Fonts loaded at runtime from Google's CDN transmits visitor IP addresses to a third country. A German court ruled on exactly this in 2022 and it kicked off a wave of warning letters. Self-host your fonts. It's faster anyway.\n\nIf you have users in Germany or Austria, an imprint is a legal requirement, not a nice-to-have, and the privacy policy has to actually describe what you're collecting. This is the check that costs nothing and gets skipped the most, because it's boring and nobody's prompt asked for it.\n\n```\nDOMAIN=\"https://yourapp.com\"\n\nfor path in /.env /.env.local /.env.production /.git/HEAD /.git/config \\\n            /api/debug /api/test /admin; do\n  code=$(curl -s -o /dev/null -w \"%{http_code}\" \"$DOMAIN$path\")\n  echo \"$code  $path\"\ndone\n\necho \"--- headers ---\"\ncurl -sI \"$DOMAIN\" | grep -iE 'content-security-policy|strict-transport-security|x-frame-options|x-content-type-options|referrer-policy'\n```\n\nEvery `200`\n\nin that first block is a finding. Every missing header in the second block is a gap. Run it against your own domain only — this is a self-audit, not a scanner to point at other people's sites.\n\nSort into three buckets and be honest about which one you're in.\n\nExposed secrets, an open `.git`\n\n, or a service_role key in the bundle means **stop**. Rotate keys, fix, redeploy, and don't announce anything until it's clean.\n\nMissing headers, source maps, debug routes and boilerplate metadata mean **iterate** — real issues, fixable in an afternoon, not reasons to delay a soft launch to a small audience.\n\nEverything clean means **go**, with the caveat that this is a point-in-time snapshot. The next AI-generated feature can reintroduce any of it, so re-run before each meaningful deploy.\n\n*Disclosure: I work at decivo, where we do exactly this kind of review for teams shipping AI-built products. We wrapped the outside-in portion of this checklist into a free scan called Vibe Code Rescue — you paste a URL, it runs the external checks and gives you a Go / Iterate / Stop verdict. No signup, no code access, nothing stored. The manual checklist above covers the same ground if you'd rather do it yourself, which is genuinely fine by me.*", "url": "https://wpnews.pro/news/12-things-to-check-before-you-ship-your-vibe-coded-app", "canonical_source": "https://dev.to/decivo/12-things-to-check-before-you-ship-your-vibe-coded-app-n0p", "published_at": "2026-07-25 15:16:54+00:00", "updated_at": "2026-07-25 15:34:00.448135+00:00", "lang": "en", "topics": ["ai-tools", "ai-products", "ai-safety", "developer-tools"], "entities": ["Symbiotic Security", "Supabase", "Deng et al.", "Xint.io", "SecurityWeek", "Lovable", "Bolt", "v0"], "alternates": {"html": "https://wpnews.pro/news/12-things-to-check-before-you-ship-your-vibe-coded-app", "markdown": "https://wpnews.pro/news/12-things-to-check-before-you-ship-your-vibe-coded-app.md", "text": "https://wpnews.pro/news/12-things-to-check-before-you-ship-your-vibe-coded-app.txt", "jsonld": "https://wpnews.pro/news/12-things-to-check-before-you-ship-your-vibe-coded-app.jsonld"}}