← Back to blogs

Vibe Coding Almost Shipped a Security Hole in My IELTS Platform

Aug 29, 2026·6 min read

Vibe coding gets talked about like it's either the future of building software or a reckless way to end up on the news. My honest experience sits in a less exciting place in the middle. It's fast, it works most of the time, and once it almost let me ship a real authorization gap into CrimsonWatch because everything looked done.

Here's what actually happened, and what I think the vibe coding conversation keeps getting wrong in both directions.

The feature that looked finished

I was adding a route that lets a user view their own past IELTS test attempts, pull up the responses and scores tied to their account. Straightforward CRUD on the surface. I described what I wanted, let the AI generate the route handler, the query, and the response shaping, and moved fast because it's exactly the kind of feature where moving fast makes sense, low complexity, well understood shape.

It ran. It returned the right data when I tested it with my own account. The UI rendered it correctly. By every surface level signal, the feature was done.

What it didn't do was check that the attempt ID being requested actually belonged to the user making the request. The query fetched by attempt ID alone. Change the ID in the request, and you could pull up someone else's test attempt, their responses, their scores. A textbook broken access control issue, the kind that shows up near the top of every web security checklist that's existed for a decade.

Why it slipped through, and why that's the actual lesson

This is the part I want to be honest about instead of just telling a scary story. The AI didn't ignore security because it doesn't know what authorization checks are. It generated code that correctly solved the task as I described it, fetch an attempt by ID, return the data. I never said "and verify the ID belongs to the requesting user," because in my head that was implied, obvious, the kind of thing I wouldn't forget if I were typing every line myself.

That's the actual failure mode of vibe coding, and it's not really about the AI being bad at security. It's that moving fast on a described outcome skips the part of manual coding where you're forced to touch every line, and touching every line is exactly where a developer's security instincts usually fire without being consciously invoked. When you're not the one writing the query, "am I filtering by the right owner" isn't a conscious check anymore, it's a background hum that only exists because you're the one typing. Vibe coding turns that hum off.

I caught this one because reviewing for exactly this class of bug is part of my routine now on anything touching user data, a habit from building CrimsonWatch as a solo project where there's no second engineer to catch what I miss. If I'd been moving as fast as vibe coding tempts you to move, testing only the happy path with my own account, this ships.

What I actually changed after this

I didn't stop vibe coding features like this. It's genuinely useful for the shape of work where speed matters more than depth of review, prototypes, internal tools, first drafts of a feature you're going to harden later. What changed is I added one non negotiable step for anything touching user owned data. Before I consider a feature done, I explicitly test it as a different user trying to access another user's resource. Not as an afterthought, as a required step before merge, the same way I wouldn't skip checking that a form actually submits.

I also stopped trusting "it returned the right data when I tested it" as a signal that authorization is correct. Returning the right data for the right user proves the happy path works. It says nothing about whether the wrong user can get the same data by changing an ID in the URL. Those are two completely different tests, and vibe coding's fast feedback loop makes it easy to only run the first one.

The actual takeaway, not the hot take

The loud version of this story online is either "vibe coding is dangerous, don't do it" or "this is a skill issue, real developers wouldn't have this problem." Both miss what's actually going on. Vibe coding didn't introduce a new kind of vulnerability. Broken access control has been on security checklists forever, long before AI wrote a line of code. What vibe coding changes is the rate at which you can produce a feature that looks finished without the specific habits that used to catch this stuff for free, just by virtue of typing every line yourself.

The fix isn't slowing down everywhere. It's knowing exactly which categories of mistake go quiet when you're not the one typing, and building a deliberate check back in for those specific categories. For me on CrimsonWatch, that's anything touching another user's data, every time, no exceptions, regardless of how fast the rest of the feature moved.