The 30 minute security checklist I run on every AI built app before it goes live
If posts like these are not allowed on here, then please forgive me mods. I have been lurking on this page for some time now, and know that many people on here building apps with use of AI tools (Claude/Lovable/Cursor, etc.). I have just seen many of the same security issues within the apps that I have audited thus far, and figured that a quick PSA styled post would be unequivocally beneficial :)
That said, I have been auditing apps built with AI tools such as Cursor/Bolt/Lovable for quite some time now, and I have always noticed that the same security issues keep coming up in various different domains. With respect to AI generated code more broadly, regardless of the platform or medium that you choose to utilize in your vibe coding journey, I have noticed across the board that many of the exact same issues keep popping up all around.
Citing what I have personally rendered from all of this, here is the exact checklist that I have distilled down and run myself on every build that I have encountered. This whole sequence takes ~30 to pull off end to end, and doesn't require any fancy tooling or deep technical knowledge; most of this is extremely rudimentary, yet high ROI all around.
Security headers check: ~2 min (securityheaders.com)
This check is one that is fairly straight forward to pull off, all you need is your live site link and access to the above URL. Running the check, what you are looking for is any grade above B; anything less than this from a security standpoint is a huge issue. In this case, improperly implemented headers mean that you are leaving your app open to a whole slew of possible exploits that simply do not need to happen; things such as clickjacking, content injection and cross site scripting attacks all become radically easier to pull off without any headers present to pose as a resistance layer.
The fix here is most always a simple one line patch in your config, and given the risk that improperly configured headers pose, this is quite possibly one of the simplest yet high ROI patches that you could implement to galvanize your apps security. In my experience, missing X-Frame-Options and CSP headers seem to be the two most frequently overlooked in AI output.
SSL: ~2 mins (ssllabs.com/ssltest)
Similar to the prior security headers check, this is also just a simple plug-and-play maneuver that you can pull off with a considerably high ROI. From the above link, as before paste your link and allow the site to complete a full SSL test on your domain. In this case, what you are looking for is a grade of A and nothing below; as it is an immediate issue if you're on a custom domain and are still using HTTP somewhere unexpected, as HTTP means that all data transferred between both your users and your server is left completely unencrypted, thus being totally readable in transit. Thus, everything from login credentials, session tokens, form submissions, pretty much anything travelling between both the user and server is left completely exposed.
Frontend bundle search (~10min):
Open DevTools (Ctrl+Shift+I / Cmd+Option+I) → Sources → Search (Ctrl+Shift+F / Cmd+Option+F)
From here, search for each of the following strings, one by one:
sk-
eyJ
anon
service_role
VITE_
REACT_APP_
apikey
Bearer
Any of the following searches showing up hardcoded in your JS bundle is an immediate high severity finding. More peculiarly, with vibe coded apps in specific I have come to notice that Supabase anon keys seem to almost always be present somewhere within here; whether or not this is a real problem is highly dependant on your RLS config, but knowing whether or not it is exposed in the first place is a crucial bit of information to know nonetheless. Given that this is the exact code that your browser runs to actually run your application, what this means is that it will most certainly be accessible to anyone who opens DevTools and knows where to look. Last week, 7/8 apps that I audited had this exact issue, so I would highly recommend checking on this specifically.
localStorage Inspection (~5min):
Open DevTools (Ctrl+Shift+I / Cmd+Option+I) → Application → Local Storage
Check what exists here, seeing session JWTs in localStorage means that any XSS vulnerability is exploitable from here; and thus, full account takeover is within the realm of possibility. This matters, since localStorage is accessible to any JavaScript running on the page; so this could very well be anything from a compromised dependency, a malicious ad, or really anything that you can think of. Cookies with the HttpOnly flag are far safer, since JavaScript cannot touch these at all.
Network tab (~5min):
Open DevTools (Ctrl+Shift+I / Cmd+Option+I) → Network → filter to Fetch/XHR
From here, reload your page and observe what is being called from here. As well, be sure to look out for what data is coming back unauthenticated (things such as table names, user data, and internal endpoints all seem to be commonly exposed here). Endpoints being unauthenticated mean that attackers don't even need to have an account tied to your app to pull data from it, all they need is to open DevTools and pull it from the network tab directly.
Rate limiting on Auth (~5min):
Go to your applications web page, and spam false login credentials 10-15 times in a row in rapid succession. If, after this many attempts there is no mechanism preventing you from doing this (i.e: an account lockout, slowdown, or CAPTCHA), then this means that your app does not have rate limiting in place. For an attacker, this means that a potential brute force attack is left wide open; so, an automated tool can cycle through common password lists against any username/email present on your platform within about a night's worth of time with zero resistance measures in place to prevent it.
Password reset enumeration (~1 min):
Lastly, this step is straightforward enough but is of equal importance. All you need to do is enter an email that you know is not registered to your app on your login screen, and surveil the response message that comes up after your login attempt. If the response says something such as "no account found with that email address" instead of something like "if XYZ email exists, you will receive a link", then this means that you have email enumeration. This allows an attacker to confirm whether or not an email address is tied to your platform, and if it does exist then it can be targeted in phishing, credential stuffing, or brute force attacks.
I hope this helps someone. This is a very quick process to pull off with very basic tooling and minimal technical know how required, and covers most of the important bases that AI tools seem to almost always overlook in some capacity.
30
64 comments
Kj Hutchinson
4
The 30 minute security checklist I run on every AI built app before it goes live
AI Automation Society
skool.com/ai-automation-society
Learn to get paid for AI solutions, regardless of your background.
Leaderboard (30-day)
Powered by