This issue: Some practical notes for attacking vibe coded apps.
If you like practical stories about AI and offensive security, subscribe to Cred Relay.
I came across a bug where the app enforced authentication with a JWT. But it only checked that the JWT existed and didn’t validate it’s signature. To make it worse it would determine your identity and permissions based off the JWT. I was able to forge a JWT and takeover the application. Because of the nature of this particular app it became a full Entra tenant compromise. I was able to become the service principal and used that access to add a secret to another SP account and eventually got to one with global administrator privileges.
Vibe coding is everywhere. I keep finding bad stuff. Mostly exposed secrets but tons of authorization issues too.
I’m not the only one seeing this. Georgia Tech’s April write-up on Vibe Security Radar says researchers scanned more than 43,000 public security advisories and confirmed dozens of AI-linked vulnerabilities, including authentication bypass, command injection, and SSRF.
Escape says it scanned 5,600 public vibe-coded apps and reported more than 2,000 vulnerabilities, 400-plus exposed secrets, and 175 instances of exposed PII.
Agents write code token by token with no model of who's allowed to do what. The controls that depend on holding a boundary across requests are exactly the ones that break.
Can you just adjust your prompts to fix this?
You can reduce the rate of these errors being introduced but its a silent failure and easy to miss. You can have it check for all the things mentioned in this article and it will be good at detecting those for that session but as other team members contribute code from their agents these things can return. It will happily write an ownership check that looks right and enforces the wrong thing, because it has no ground truth for whose data is whose. How do we fix this? Pen testing. It’s built for and thrives on these edge cases.
This is great news if you’re a pentester like me. Let’s cover where to find these bugs.
1. Token signing
This one feels like slinging NTLM creds with SMB signing disabled. It’s an easy win and it’s pervasive. Grab /.well-known/openid-configuration if it's there. It maps out much of the identity attack surface: the issuer, supported ID-token signing algorithms, and the jwks_uri where verification keys are published. Then just forge your own JWT and see what happens.
Forging a JWT is easy and you may have covered them in CTFs, DVWA or crAPI. If you aren’t familiar with attacking them I suggest you start with TrustedSec’s resource on the topic here: https://trustedsec.com/blog/keys-to-jwt-assessments-from-a-cheat-sheet-to-a-deep-dive and OWASP has a good article here.
2. Exposed secrets and convenience endpoints
Secrets are pretty straightforward. Check for an .env served straight from web root, look at the bundled JS for keys baked into the frontend, and read the source maps if they shipped, since those hand you the pre-build code with secrets still in it. The .env file is the big one.
Many developers create convenience endpoints to generate JWTs in test environments and forget about them. I’ve seen a ton of endpoints that return a JWT without authentication. Usually /api/token or similar. And hey if it gives you the token then you don’t need to forge one. Be sure to check the permissions and claims of the JWT for lateral movement possibilities. I typically use jwt.ms.
Many vibe coded apps will just assume if a session is present then the authorization is good. Authentication, authorization, it’s all the same thing right? This is what the agent thinks and if authentication is good then the rest is probably fine.
Test it in two directions. Horizontal first: as a normal user, try to reach another normal user's data. Swap the identifier the app trusts (user ID, org ID, project ID, tenant ID) in the path, body, or query, and see if the server objects or just serves it. That's IDOR / BOLA, and vibe-coded apps are full of these because the agent wired up the query but never the ownership check. Then vertical: from that same low-priv user, try to reach admin routes and admin actions directly. Often nothing stands between a logged-in user and /admin except the frontend not showing the link.
Each row is the same failure.
What is present | What must be proved | Fast abuse case |
|---|---|---|
JWT or bearer token | Signature, issuer, audience, expiry, and subject | Tamper the payload, use an expired token, or swap identity claims |
Authenticated session | Object ownership and role authorization | Swap user, org, project, or tenant IDs |
Tenant ID or public anon key | Server-side tenant scope and effective RLS | Query or modify another tenant’s rows directly |
User-controlled URL | Allowed scheme, destination, redirects, and egress policy | Fetch localhost, private IP space, or redirect to it |
File path or upload name | Canonical path boundary and ownership | Try traversal, absolute paths, symlink escapes, or cross-user files |
AI/tool request | Constrained capability before fetch, files, shell, plugins, or eval | Use prompt or parameter injection to cross the intended tool boundary |
Agents struggle with boundaries. At least they do for now. Better prompting and guardrails mitigate some of it. But this still leaves a goldmine of edge cases for pentesters.
Cred Relay is where I write about AI, offensive security, and the messy work behind real findings. Subscribe if you want the next one.
Got questions, corrections, or want to argue? Hit reply. I read everything.
— Jeff
