I sat in on a discussion recently about a plugin vulnerability that traced back, as far as anyone involved could reconstruct afterward, to AI-generated code that got merged into a release without a proper security-focused review. Nobody involved was malicious. It was simply a developer who trusted a suggestion that looked entirely reasonable on the surface, and shipped it without the specific kind of scrutiny that WordPress permission and capability checks actually require. This is worth talking about plainly and in detail, because as AI-assisted development becomes the default across the plugin ecosystem, this exact pattern is going to keep showing up, and it’s worth understanding precisely why.

The specific pattern that makes this genuinely dangerous

AI-generated code tends to be syntactically confident and structurally correct-looking, while occasionally being subtly wrong about permissions in ways that don’t announce themselves. A nonce check that’s technically present in the code, but checking against the wrong action name, so it passes a superficial review while not actually protecting the endpoint it’s attached to. An AJAX handler that’s technically secured with a capability check, but checking against the wrong capability — verifying edit_posts when the operation being performed actually requires something closer to manage_options, meaning a lower-privileged user, like a Subscriber-level account or a Contributor, can trigger an action that should have required Administrator access.

This category of mistake looks correct at a glance specifically because it follows the recognizable shape of correct, secure code. It has a nonce check. It has a capability check. Both of those things are present and both of them execute without throwing an error. That surface-level correctness is exactly what makes this more dangerous than obviously bad code with no security checks at all, because obviously bad code tends to get caught in even a cursory review — someone notices there’s no current_user_can() call anywhere near a sensitive action. This kind of subtle permission mismatch doesn’t get caught that way. It only surfaces when someone actually tests the specific permission boundary by hand, logged in as a genuinely lower-privileged account, and confirms the action correctly fails.

What I’ve concretely changed in my own development process because of this

Every AJAX handler and every REST API endpoint I ship now gets manually tested against a lower-privilege user account, every single time, without exception, regardless of whether I wrote the underlying code entirely by hand or had an AI assistant draft the first pass of it. In practice this takes maybe five extra minutes per endpoint — create or reuse a Subscriber-level test account, log in as that account in a separate browser profile, attempt the sensitive action directly, and confirm it correctly fails with an appropriate error rather than silently succeeding.

I’ll be honest that I wasn’t always quite this rigorous about this specific check back when I was writing every line of every plugin entirely by hand myself. The review habit has genuinely sharpened specifically because I know AI-assisted code needs this particular kind of scrutiny in a way that fully hand-written code, written slowly enough to think through each permission boundary as you type it, sometimes didn’t require as explicitly. The speed AI-assisted development provides is real and valuable, but it shifts where the risk concentrates, and being honest about that shift is the responsible way to actually use these tools rather than pretending the risk isn’t there.

A concrete example of how this catches something real

On a recent internal plugin build, an AI-drafted AJAX handler for updating a settings value included a nonce check that passed correctly, and a capability check that was present but set to read — a capability every logged-in user has by default, including Subscribers, rather than the manage_options capability the action actually needed. The code looked entirely correct in review. It only failed when I logged in as a test Subscriber account and successfully triggered a settings change that should have required Administrator access. That’s a five-minute test that caught a genuine privilege escalation vulnerability before it ever reached a live site, and it’s exactly the kind of thing that a quick visual code review, no matter how careful, tends to miss because the code reads as correct.

The honest framing, not the alarmist one

This isn’t an argument against using AI tools for development. I use them constantly across nearly every project now, and I’m not walking that back. It’s an argument for treating AI-generated code exactly the way you’d treat a genuinely capable junior developer’s first pass at a security-sensitive feature — frequently useful, often structurally sound, and never assumed correct on permission-sensitive code paths without someone actually testing the boundary by hand. That discipline costs a handful of extra minutes per endpoint. The alternative costs considerably more.

Bixily Digital