LikePrompts

AI Prompts for Web App Security: The Ownership Check Your Model Skips

LikePrompts Editorial September 20, 2026
AI Prompts for Web App Security: The Ownership Check Your Model Skips

Image generated with AI.

The model writes CRUD that works on the first try and skips the ownership check every time. Access control is a boundary you have to state in the prompt: who may read this row, which route needs a permission callback, and what the test must assert.

Your app works. Then someone edits ?id=104 to ?id=105 in the URL and reads another user's project, in full. Nothing crashed - the model wrote correct CRUD and skipped the line that says whose row it is. AI prompts for web app security start there.

This guide covers where that boundary gets written in three kinds of work: an API contract, a framework feature and a WordPress route. It also covers which clause to ask for, and which test proves the boundary actually exists.

Why Working Code Leaks the Wrong Row

A generated endpoint is not wrong because it is broken. It is wrong because it answers a question you never asked and skips one you never wrote. The request is authenticated, so the middleware lets it through; the query finds a row, so the controller returns it. Every layer did what it was told, and the failure lives in the gap between "logged in" and "allowed".

What the 2026 Reports Publish

This year's numbers look like 2021's, which is the interesting part. A 2026 GenAI code security report from Veracode puts roughly 44% of code generation tasks as producing code with a known vulnerability, close to the earlier editions of that series, meaning better models did not move the needle much. An independent 2026 study of 534 samples from six models, scored against the OWASP Top 10:2025 taxonomy, reports about 25% with security findings. The Cloud Security Alliance published a note about a university radar project that tracked 35 CVEs attributable to AI coding tools in a single month. Present these as what those reports publish and revalidate them; they are vendor and practitioner studies, not a standards body. The official OWASP Top 10 still ranks broken access control first in its 2025 edition.

Authentication Is in Every Tutorial, Ownership Is Not

The IDOR and BOLA literature repeats one diagnosis: generated endpoints include authentication because every tutorial the model trained on includes it, and omit the per-resource ownership check because those same tutorials omit it. It is not a decision to be insecure; it is a gap filled with the most probable default. Practitioner scans published in 2026 report that most of the AI-built apps they reviewed had at least one endpoint exploitable this way. Treat those as observations of the ecosystem, not official statistics, but treat the mechanism as real.

AI Prompts for Web App Security: Where the Boundary Goes in the Ask

The fix is not a longer prompt. It is three short sentences that state the rule the model would otherwise invent.

Three Sentences You Write Before Generating Anything

First: who may read this row. Second: who may call this route. Third: which fields may come back in the response. All three are plain language and cost almost nothing in tokens. One rule holds the rest together: an undeclared boundary is a boundary the model decides for you, and it will decide by the path of least resistance, which is "authenticated means permitted".

Step 1 - Design the Contract With Permission in It

Access control is cheapest to fix on paper, which is why it belongs to the contract step rather than the code step.

Nested Resources and the Line That Scopes Them

A prompt like REST API Design System asks for a resource map that separates nested entities from first-level ones, and that is where the problem lives. On a route like projects/tasks, the question "may I touch this task" has two possible answers: the task exists, or the task belongs to a project I own. Only one of them protects anything. The same prompt asks for endpoints with request and response shapes, for consistent status codes, and for an auth and permissions block covering mechanism, roles and rate limiting. Deciding to return 404 instead of 403 for someone else's resource is a contract decision, taken while mapping the API, not a detail to improvise later. What you add is the ownership dimension, in one clause: "for every endpoint that returns a record, state whether the caller must own it, belong to the same workspace, or be an admin, and if the resource is nested, name the parent that scopes it." That sentence turns a resource map into a permission map.

Step 2 - Put the Check in the Feature, Not in Your Memory

Design intent decays. Implementation is where it survives as code or dies as a comment.

The FormRequest Is Where authorize() Lives

A prompt like Laravel Feature Builder builds a feature in seven blocks: migration with indexes and foreign keys, model with casts and relations, validation through a FormRequest with rules, messages and authorization, a minimal controller, views, Pest tests covering success, validation failure, authorization (403) and 404, and a security block where the model must state which authorization, mass assignment or XSS risks it wrote and how it handled them. Two things matter here. Authorization lives in the FormRequest rather than in your memory, and when authorize() returns false the framework answers 403 and the controller method never runs, as documented in the official Laravel validation docs. The security block is the second: it forces the model to say out loud what it did.

The Negative Test Is the One That Matters

The same prompt asks for tests, and the trap is who writes the case. A test the model writes proves the case the model thought of. What you add by hand, or in a second pass, is the negative test: user B authenticated, requesting user A's record, receives 403 or 404, and A's record is untouched. If that test passes on a feature that never implemented ownership, the test is lying. A feature is not done because its tests are green; it is done when the test that should fail does.

Step 3 - The WordPress Version of the Same Question

The same boundary, written in a different idiom.

Nonce and Capability Answer Different Questions

A prompt like PHP & WordPress Developer returns namespaced code with sanitization and escaping, a hooks map, a security block covering nonces in forms, capability checks, prepared statements and output escaping, plus performance notes, asset enqueueing and a manual test checklist. The editorial point is that nonce and capability are not the same thing. A nonce proves the request arrived through the expected path. A capability proves the current user is entitled to do it. A form with a nonce and no current_user_can() still lets the wrong person act.

The REST Route Needs a permission_callback

If the feature exposes a route, registering it without a permission_callback is declared misuse by WordPress, flagged since version 5.5 in the official register_rest_route reference. Missing does not mean closed; it means undefined. For routes that are public on purpose you declare the callback that returns true, so the intent is written rather than assumed. The clause to add is one line: "every registered REST route must declare its permission_callback, and say which capability or ownership rule it enforces."

What a Prompt Cannot Audit

Scope, honestly. The model sees what you paste. It does not see your environment file, your server, your WAF, your dependency versions or the CVEs they carry. It can be wrong about the exact API of your framework version. It is not a penetration test and does not replace a scanner or a second pair of human eyes; it is a multiplier for a checklist you still have to know how to write. One hygiene rule is not negotiable: never paste production credentials, database dumps or real customer data into the prompt to "help it debug permissions". The prompt does not need the data to reason about the rule.

A 30-Minute Pass Before You Push

  1. Write the three boundary sentences: who reads, who calls, what comes back.
  2. Ask for the contract with the role mapper and the ownership clause.
  3. Ask for the feature with the FormRequest and its authorization.
  4. Demand the negative ownership test, using two users.
  5. Grep by hand for the three patterns models leave behind: queries built by concatenation, user output without escaping, and routes registered without a permission_callback.
  6. Run the tests you were given, the model's included, and check that the security block says something concrete instead of "handled properly".

The three prompts behind this guide are REST API Design System for the contract, Laravel Feature Builder for the feature and its tests, and PHP & WordPress Developer for the plugin and route layer. Pick the one that matches the work in front of you, then add the ownership clause yourself. The boundary was never the model's to draw: it is drawn by whoever writes the prompt, one sentence per resource, before a single line of code exists.

LikePrompts Editorial

Practical guides for getting the most out of AI prompts — written by the LikePrompts team.