AI coding tools are genuinely good at shipping features. They are noticeably worse at the invisible work: the checks that make a feature safe once strangers, money, and production data are involved. VibeGuard's free scan runs deterministic static rules over every project we see — secrets, auth, database, payments, uploads, configuration, dependencies, and AI-agent usage. The same findings keep coming back, almost regardless of which tool wrote the code.
Here are the ten we keep finding, in roughly the order they hurt.
1. Live secrets hardcoded in the code
The classic, and still the most common critical finding: a live payment secret key, an AI provider key, or a database password sitting in a source file or committed .env. AI tools love a working end-to-end example, and "paste the key here" is the fastest path to one. Once it is in the repo, it is in your git history, your collaborators' laptops, and every deployment artifact. Move secrets to server-only environment variables — and if a live key ever touched the repo, rotate it now, not after launch.
2. Session tokens stored in localStorage
Putting a JWT or session token in localStorage feels natural — it survives refreshes and the code is two lines. It is also readable by any JavaScript running on your page, which means one XSS bug or one compromised npm package becomes full account takeover. Use httpOnly cookies set by the server, so the token never exists in script-readable space.
3. Admin checks that only exist in the UI
if (user.role === "admin") deciding whether to render the admin panel — while the API routes behind it accept requests from anyone. The frontend check is decoration; an attacker calls the endpoint directly with curl. Every privileged route needs its own server-side authorization check. The UI check is for user experience, never for security.
4. JWTs that never expire
Tokens signed with no expiresIn are valid forever. Leak one — through a log line, a paste, an old laptop — and it works until you rotate your signing secret, which logs out every user at once. Set short expirations and use refresh tokens for longevity.
5. SQL assembled with string interpolation
F-strings and template literals dropping user input straight into a query. This is SQL injection, the same vulnerability that has topped lists for twenty years, freshly regenerated by tools optimizing for "code that runs." Use parameterized queries everywhere — every driver and ORM supports them, and the fix is usually mechanical.
6. The service-role key in the browser
A special Supabase flavor of mistake #1, severe enough to count separately: the service-role key — the credential that bypasses Row Level Security entirely — shipped to the client, often via a NEXT_PUBLIC_ variable. Anyone who opens devtools can read and write your whole database. The service-role key is backend-only, always. Its cousin is leaving RLS disabled on user tables: with no row-level policy, any authenticated user can often read every other user's rows.
7. Checkout that trusts the frontend's price
The client sends { amount: 4900 } and the server charges it. An attacker edits the request and buys your product for one cent. The price must be looked up server-side from the product or quote ID; the client should only ever send what it is buying, never how much it costs.
8. Payment webhooks accepted without signature verification
The webhook handler reads the event body and marks orders paid — without verifying the provider's signature. Anyone who finds the URL can POST a fake "payment completed" event and receive your product for free. Verify signatures on every event, and treat "the success page loaded" as untrusted too: client-side redirects are not payment confirmation. Only a verified server-side event should flip an order to paid.
9. File uploads with no limits or validation
Upload handlers with no size limit, no count limit, and no type validation. The polite failure mode is a disk-filling denial of service; the impolite one is someone uploading executable content that your stack later serves or processes. Enforce size and count limits at the framework level and validate types server-side — the dropzone's accept attribute is a suggestion, not a control.
10. Over-privileged AI agents
The newest category, growing fastest. Three patterns stand out: agent tools that can execute shell commands or arbitrary SQL exposed to user-driven input; user input concatenated directly into the system prompt, making prompt injection trivial; and model output rendered as raw HTML, turning the LLM into an XSS vector. Treat a model the way you treat a user: least-privilege tools, structured inputs, and escape its output before rendering.
Honorable mentions that show up constantly but rarely alone: wildcard CORS on credentialed APIs, debug mode left on in production, secrets exposed through NEXT_PUBLIC_-style frontend variables, missing lockfiles, and unpinned dependencies.
The pattern behind the patterns
None of these are exotic. What makes AI-built apps special is density and confidence: the code looks finished, runs perfectly in the demo, and carries five of these issues at once — because the tool was optimizing for "works" and nobody asked it about "safe."
That gap is exactly what VibeGuard exists for. The free scan finds patterns like these in minutes — statically, without executing your code, with detected secrets masked and never stored in full. If you have shipped something fast lately, it is worth two minutes to find out which of these ten you are carrying.