<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Hack Safe</title>
    <description>The latest articles on DEV Community by Hack Safe (@hacksafe).</description>
    <link>https://dev.to/hacksafe</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3978712%2Fcdfff703-9b68-4b23-bd74-c2a8ef35987e.png</url>
      <title>DEV Community: Hack Safe</title>
      <link>https://dev.to/hacksafe</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hacksafe"/>
    <language>en</language>
    <item>
      <title>The Vibe Coder's Pre-Launch Security Checklist: 25 Checks for Cursor, Lovable, Bolt &amp; Replit Apps</title>
      <dc:creator>Hack Safe</dc:creator>
      <pubDate>Thu, 11 Jun 2026 05:22:05 +0000</pubDate>
      <link>https://dev.to/hacksafe/the-vibe-coders-pre-launch-security-checklist-25-checks-for-cursor-lovable-bolt-replit-apps-12i</link>
      <guid>https://dev.to/hacksafe/the-vibe-coders-pre-launch-security-checklist-25-checks-for-cursor-lovable-bolt-replit-apps-12i</guid>
      <description>&lt;h2&gt;
  
  
  The Vibe Coder's Pre-Launch Security Checklist: 25 Checks for Cursor, Lovable, Bolt &amp;amp; Replit Apps
&lt;/h2&gt;

&lt;p&gt;I scanned 62 Lovable apps in early 2026.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;63% had critical or high severity vulnerabilities. The average app had 10 findings.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;These weren't obscure edge-case bugs. They were the same mistakes, over and over: exposed API keys, disabled row-level security, missing authentication on routes, no rate limiting on login endpoints.&lt;/p&gt;

&lt;p&gt;The apps looked great. They worked perfectly. They were completely open to anyone who knew where to look.&lt;/p&gt;

&lt;p&gt;This is the vibe coding security problem in one sentence: &lt;strong&gt;AI tools optimise for working, not safe. Those aren't the same thing.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you built your app with Cursor, Lovable, Bolt, Replit, or any AI coding tool — this checklist is for you. No security background required. Every item is written in plain English with a specific, actionable fix.&lt;/p&gt;

&lt;p&gt;Run through this before you share the link.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why AI-built apps keep getting hacked
&lt;/h2&gt;

&lt;p&gt;AI coding assistants generate functional code fast. That's the point. But there are three structural reasons why they consistently produce insecure code:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. They optimise for the happy path.&lt;/strong&gt; When you prompt "build me a login system," the AI builds something that works for a legitimate user. It doesn't automatically think about what an attacker would do.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. They're trained on tutorials and demos.&lt;/strong&gt; Most training data comes from documentation examples and beginner tutorials — content written to be simple and readable, not production-secure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. They don't know your full context.&lt;/strong&gt; The AI doesn't know that your &lt;code&gt;/api/admin&lt;/code&gt; route shouldn't be public. It doesn't know your Supabase tables contain payment data. It builds what you asked for, not what you actually need.&lt;/p&gt;

&lt;p&gt;The result is a consistent set of vulnerabilities that show up in almost every vibe-coded app. This checklist covers the 25 most common ones.&lt;/p&gt;




&lt;h2&gt;
  
  
  The 8 categories
&lt;/h2&gt;

&lt;p&gt;The vulnerabilities cluster in the same eight areas almost every time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔑 &lt;strong&gt;Secrets &amp;amp; Keys&lt;/strong&gt; — API keys, credentials, environment variables&lt;/li&gt;
&lt;li&gt;🔐 &lt;strong&gt;Auth &amp;amp; Access&lt;/strong&gt; — Route protection, RLS, admin access, session management&lt;/li&gt;
&lt;li&gt;🗄️ &lt;strong&gt;Data &amp;amp; Database&lt;/strong&gt; — SQL injection, IDOR, data exposure&lt;/li&gt;
&lt;li&gt;🌐 &lt;strong&gt;API Security&lt;/strong&gt; — Rate limiting, CORS, input validation, file uploads&lt;/li&gt;
&lt;li&gt;🚀 &lt;strong&gt;Deployment&lt;/strong&gt; — Production config, HTTPS, security headers, source maps&lt;/li&gt;
&lt;li&gt;🖥️ &lt;strong&gt;Frontend&lt;/strong&gt; — XSS, localStorage misuse, client-side secret exposure&lt;/li&gt;
&lt;li&gt;📦 &lt;strong&gt;Third-Party&lt;/strong&gt; — Dependency CVEs, script integrity, webhook verification&lt;/li&gt;
&lt;li&gt;📊 &lt;strong&gt;Monitoring&lt;/strong&gt; — Logging, alerting, incident readiness&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The checklist — first 10 items free
&lt;/h2&gt;

&lt;p&gt;I'm sharing the first 10 items in full here. The complete 25-item checklist (including 2 full AI audit prompts you can paste directly into Cursor or Claude) is available as a free download at the end of this article.&lt;/p&gt;




&lt;h3&gt;
  
  
  🔑 SECRETS &amp;amp; KEYS
&lt;/h3&gt;




&lt;p&gt;&lt;strong&gt;01 — No API keys in client-side code&lt;/strong&gt; &lt;code&gt;HIGH&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Search your entire repo for strings matching &lt;code&gt;sk-&lt;/code&gt;, &lt;code&gt;pk-&lt;/code&gt;, &lt;code&gt;AIza&lt;/code&gt;, &lt;code&gt;Bearer&lt;/code&gt;, or &lt;code&gt;_KEY=&lt;/code&gt;. Any key visible in your browser's DevTools Network tab or in your JavaScript bundle is already compromised — anyone can steal it and run up your bill.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Move all API keys server-side. In Next.js, never use &lt;code&gt;NEXT_PUBLIC_&lt;/code&gt; prefix on secret keys. In Vite, never use &lt;code&gt;VITE_&lt;/code&gt; prefix on anything sensitive. Keys that start with these prefixes get bundled into the JavaScript every user downloads.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;02 — &lt;code&gt;.env&lt;/code&gt; file is gitignored and not in git history&lt;/strong&gt; &lt;code&gt;HIGH&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Your &lt;code&gt;.env&lt;/code&gt; file might be gitignored &lt;em&gt;now&lt;/em&gt; — but was it always? Run this in your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git log &lt;span class="nt"&gt;--all&lt;/span&gt; &lt;span class="nt"&gt;--full-history&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; .env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If that command returns results, your secrets have been committed to git history at some point. Even if you deleted the file later, the secrets are still there in the history and visible to anyone with access to the repo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Rotate every secret that was ever in your &lt;code&gt;.env&lt;/code&gt;. Then run &lt;code&gt;git filter-branch&lt;/code&gt; or use BFG Repo Cleaner to purge the file from history.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;03 — No hardcoded credentials in AI-generated code&lt;/strong&gt; &lt;code&gt;HIGH&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;AI tools frequently write demo credentials inline. Search your codebase for these strings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;password&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;
&lt;span class="py"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;
&lt;span class="py"&gt;token&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;
&lt;span class="py"&gt;api_key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;
&lt;span class="py"&gt;apikey&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;
&lt;span class="py"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look specifically inside component files, API route handlers, and any config files. I find hardcoded credentials in roughly 1 in 3 vibe-coded codebases.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Every credential goes in &lt;code&gt;.env&lt;/code&gt;. Reference it as &lt;code&gt;process.env.YOUR_SECRET&lt;/code&gt;. Never in the code itself.&lt;/p&gt;




&lt;h3&gt;
  
  
  🔐 AUTH &amp;amp; ACCESS
&lt;/h3&gt;




&lt;p&gt;&lt;strong&gt;04 — All routes check authentication before serving data&lt;/strong&gt; &lt;code&gt;HIGH&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This is the most commonly missed check. Manually test every API endpoint by opening your browser's DevTools, deleting your authentication cookie, and making the same request again.&lt;/p&gt;

&lt;p&gt;If you still get data back — auth is either missing or bypassable.&lt;/p&gt;

&lt;p&gt;In Next.js App Router, check that every &lt;code&gt;route.ts&lt;/code&gt; file that returns user data calls &lt;code&gt;getServerSession()&lt;/code&gt; or equivalent at the top. In Supabase Edge Functions, verify every function checks the JWT.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Add an auth check as the very first thing in every protected route handler. If there's no valid session, return 401 immediately before any database query runs.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;05 — Row-Level Security (RLS) is enabled on every Supabase table&lt;/strong&gt; &lt;code&gt;HIGH&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This is the vulnerability behind CVE-2025-48757 — the Lovable breach that exposed 170 production apps and tens of thousands of user records.&lt;/p&gt;

&lt;p&gt;RLS is &lt;strong&gt;off by default&lt;/strong&gt; in Supabase. This means any logged-in user can read every row in every table, including other users' data, using the public API key that's visible in your frontend code.&lt;/p&gt;

&lt;p&gt;Go to your Supabase dashboard → Table Editor → select each table → check the RLS toggle. It must be ON for every table that contains user data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Enable RLS on a table&lt;/span&gt;
&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;your_table&lt;/span&gt; &lt;span class="n"&gt;ENABLE&lt;/span&gt; &lt;span class="k"&gt;ROW&lt;/span&gt; &lt;span class="k"&gt;LEVEL&lt;/span&gt; &lt;span class="k"&gt;SECURITY&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- Allow users to only read their own rows&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="n"&gt;POLICY&lt;/span&gt; &lt;span class="nv"&gt;"Users can only see their own data"&lt;/span&gt;
&lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;your_table&lt;/span&gt; &lt;span class="k"&gt;FOR&lt;/span&gt; &lt;span class="k"&gt;SELECT&lt;/span&gt;
&lt;span class="k"&gt;USING&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uid&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;06 — Admin routes are not accessible to regular users&lt;/strong&gt; &lt;code&gt;MEDIUM&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Test this manually: log in as a regular user account, then try to access &lt;code&gt;/admin&lt;/code&gt;, &lt;code&gt;/dashboard/admin&lt;/code&gt;, &lt;code&gt;/api/admin&lt;/code&gt;, or any privileged endpoint. If you get data instead of a 403 or redirect, you have a privilege escalation vulnerability.&lt;/p&gt;

&lt;p&gt;The most common cause: the admin check only runs client-side (hiding the button in the UI) but the API endpoint itself has no server-side permission check.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Every admin API route needs a server-side check that verifies the user's role from a trusted source (your database), not from a value passed in the request body or JWT claims the user could modify.&lt;/p&gt;




&lt;h3&gt;
  
  
  🗄️ DATA &amp;amp; DATABASE
&lt;/h3&gt;




&lt;p&gt;&lt;strong&gt;07 — User inputs are never inserted directly into queries&lt;/strong&gt; &lt;code&gt;HIGH&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;AI-generated database code often uses string concatenation to build queries. This is SQL injection — one of the oldest and most dangerous vulnerabilities in web applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Never do this:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Dangerous — user input goes straight into the query&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`SELECT * FROM users WHERE id = &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Do this:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Safe — parameterised query&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SELECT * FROM users WHERE id = $1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you're using Supabase's JavaScript client with &lt;code&gt;.eq()&lt;/code&gt;, &lt;code&gt;.filter()&lt;/code&gt;, and similar methods, you're already using parameterised queries. But if you're running raw SQL anywhere, check every query.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;08 — Users can only access their own data&lt;/strong&gt; &lt;code&gt;HIGH&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This is called an Insecure Direct Object Reference (IDOR) — and it's the #1 most missed vulnerability in vibe-coded apps.&lt;/p&gt;

&lt;p&gt;Test it yourself: Log in as User A. Copy the URL or ID of any resource you own — a post, a document, an order, a profile. Log out. Log in as User B. Try to access that resource by its ID.&lt;/p&gt;

&lt;p&gt;If User B can see User A's data, you have an IDOR vulnerability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Every database query that fetches a resource by ID must also filter by the current user's ID:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Wrong — fetches the document if it exists, regardless of who owns it&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;documents&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;docId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// Right — only fetches the document if the current user owns it&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;documents&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;docId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user_id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;09 — Sensitive data is not logged&lt;/strong&gt; &lt;code&gt;MEDIUM&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;AI debugging code commonly adds &lt;code&gt;console.log&lt;/code&gt; statements that print full request bodies, authentication tokens, and user emails to your server logs. In production, these logs are often sent to third-party services like Sentry, Datadog, or LogRocket.&lt;/p&gt;

&lt;p&gt;Search your codebase for &lt;code&gt;console.log&lt;/code&gt; in production code paths (not just dev files). Look specifically for logs that print &lt;code&gt;req.body&lt;/code&gt;, &lt;code&gt;req.headers&lt;/code&gt;, JWT tokens, or anything containing user emails or names.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Remove debug logs before deploying. If you need logging, use a structured logger that explicitly allows-lists which fields to include.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;10 — Rate limiting on auth and payment endpoints&lt;/strong&gt; &lt;code&gt;HIGH&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Without rate limiting, your login endpoint can be brute-forced (attackers try thousands of passwords per minute). Your AI API endpoints can be abused to generate massive bills. Your email/OTP endpoints can be used to spam users.&lt;/p&gt;

&lt;p&gt;Check whether your &lt;code&gt;/api/login&lt;/code&gt;, &lt;code&gt;/api/register&lt;/code&gt;, &lt;code&gt;/api/reset-password&lt;/code&gt;, and any AI or payment endpoint has rate limiting applied.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; In Next.js with Vercel, use &lt;code&gt;@upstash/ratelimit&lt;/code&gt;. In Express, use &lt;code&gt;express-rate-limit&lt;/code&gt;. Minimum: 10 requests per minute per IP on auth endpoints.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Ratelimit&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@upstash/ratelimit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ratelimit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Ratelimit&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromEnv&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;limiter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Ratelimit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slidingWindow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1 m&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The remaining 15 checks
&lt;/h2&gt;

&lt;p&gt;Items 11–25 cover:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CORS misconfiguration (a wildcard &lt;code&gt;*&lt;/code&gt; lets any website make requests as your logged-in users)&lt;/li&gt;
&lt;li&gt;File upload validation (frontend-only validation is bypassed in seconds)&lt;/li&gt;
&lt;li&gt;Production environment configuration (dev mode exposes stack traces to anyone)&lt;/li&gt;
&lt;li&gt;HTTPS enforcement and cookie security flags&lt;/li&gt;
&lt;li&gt;Security headers (most AI-built apps score F at securityheaders.com)&lt;/li&gt;
&lt;li&gt;Source map exposure (lets anyone reverse-engineer your code)&lt;/li&gt;
&lt;li&gt;XSS via &lt;code&gt;dangerouslySetInnerHTML&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Sensitive data in &lt;code&gt;localStorage&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Third-party script integrity&lt;/li&gt;
&lt;li&gt;Dependency CVEs (&lt;code&gt;npm audit&lt;/code&gt; before every deploy)&lt;/li&gt;
&lt;li&gt;Webhook signature verification&lt;/li&gt;
&lt;li&gt;Failed login attempt logging&lt;/li&gt;
&lt;li&gt;API usage spike alerting&lt;/li&gt;
&lt;li&gt;Incident response readiness&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The 2 AI audit prompts
&lt;/h2&gt;

&lt;p&gt;The free checklist also includes 2 full AI audit prompts — one for a complete codebase sweep, one specifically for Supabase/database access. Copy either one into Cursor, Claude, or ChatGPT with your codebase open and run it before you launch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prompt 01 gives you:&lt;/strong&gt; severity rating, exact file and line number, plain-English explanation, and the actual corrected code for every vulnerability it finds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prompt 02 gives you:&lt;/strong&gt; a full RLS policy audit, SQL injection check, and service role key exposure check for your database layer.&lt;/p&gt;




&lt;h2&gt;
  
  
  Get the complete checklist — free
&lt;/h2&gt;

&lt;p&gt;The full 25-item checklist is available as a free PDF download.&lt;/p&gt;

&lt;p&gt;It includes all 25 items with risk levels, exact checks, and one-line fixes — plus the 2 full AI audit prompts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;→ &lt;a href="https://store.dodopayments.com/hack-safe" rel="noopener noreferrer"&gt;Download free at store.dodopayments.com/hack-safe&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No email required.&lt;/p&gt;




&lt;h2&gt;
  
  
  Want the full audit system?
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;HackSafe Audit Kit&lt;/strong&gt; ($3.99) turns this checklist into a live Notion workspace — track every fix, run all 25 targeted AI audit prompts (one per attack category), filter by risk level, and sign off your pre-launch gate.&lt;/p&gt;

&lt;p&gt;One-click Notion duplicate. Setup in 20 minutes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;→ &lt;a href="https://store.dodopayments.com/hack-safe" rel="noopener noreferrer"&gt;Get the HackSafe Audit Kit&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Found a vulnerability type I missed? Drop it in the comments — I update this article every 60 days with new findings from real vibe-coded app audits.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>vibecoding</category>
      <category>webdev</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
