Prompt Engineering for Security: Writing Safer AI Code Requests

Prompt Engineering for Security: Writing Safer AI Code Requests

pr0h0
prompt-engineeringsecurityai-codingsecure-development
AI Usage (88%)

Why safer AI code requests matter

I use AI code assistants for small scaffolding jobs all the time, but prompts that touch security need a different shape. If you ask for “a quick endpoint” or “a script that makes this work,” the model will usually optimize for completion, not for boundary checks, error handling, or abuse resistance.

That is fine for a throwaway prototype. It is a bad default for anything that handles auth, files, payments, tokens, or user-generated content.

The real issue is not that the model is malicious. The issue is that vague prompts hide the rules that matter. If you do not spell out the trust boundary, the assistant fills the gap with assumptions.

The failure mode: vague prompts produce risky code

A weak prompt often looks like this:

“Write a Node.js route that lets users upload a profile image and store it.”

That sounds normal, but it leaves out the parts that make the code safe:

  • who is allowed to upload
  • what file types are acceptable
  • where the file is stored
  • whether the filename is trusted
  • how size limits are enforced
  • whether the upload is public or private

What AI models often miss in security-sensitive tasks

In practice, I keep seeing the same misses:

  • authorization checks get implied instead of implemented
  • validation happens on the client, not the server
  • error paths leak internal details
  • secrets end up in logs or examples
  • dependency choices are made without threat context
  • dangerous defaults sneak in, like permissive CORS or weak regex validation

The model may generate code that works, but “works” is not the same as “safe under abuse.”

A safer prompt pattern for code generation

The safest prompts are specific about the boundary, the allowed inputs, and the failure behavior.

State the trust boundary first

Start with who is trusted and who is not.

For example:

  • authenticated user
  • free account vs paid account
  • internal admin tool vs public web app
  • server-side data vs untrusted request data

If you do not define the trust boundary, the model may treat user input as if it were already approved.

Define allowed data, not just desired behavior

Do not only say what you want the code to do. Say what it may accept.

Good prompt details include:

  • accepted file types
  • maximum request size
  • allowed characters in identifiers
  • safe output format
  • which fields are read-only
  • which data must never be exposed

That gives the assistant concrete guardrails instead of a vague goal.

Ask for validation, logging, and failure handling

A security-safe request should ask for all three:

  • validation: reject bad input early
  • logging: record important security events without leaking secrets
  • failure handling: fail closed, not open

If you omit those, many generated examples will quietly assume happy-path behavior.

Example: rewriting a risky request into a safer one

Unsafe prompt example

“Write a JavaScript endpoint that accepts a URL and fetches the page title.”

That sounds harmless, but it can lead to SSRF, internal network access, or metadata leaks if the server fetches arbitrary URLs.

Safer prompt example

“Write a Node.js endpoint that accepts a URL from an authenticated user and returns the page title only. Reject private IP ranges, localhost, non-HTTP(S) schemes, and redirects to disallowed hosts. Limit requests to 2 seconds, cap response size, and return a generic error message. Log validation failures without storing the full URL.”

That version changes the output. It tells the model where the risk is and what to defend against.

What to review in the generated code

Even a good prompt does not remove review. I still check the same three areas first.

Authorization checks

Look for the actual decision point:

  • is the user authenticated?
  • is this resource owned by them?
  • is there a server-side role check?
  • is access decided before the action happens?

If the code only checks a UI flag or a request parameter, that is not authorization.

Input validation and output encoding

Check that the code validates on the server and encodes on output:

  • strict schema validation
  • type checks on every field
  • length limits
  • allowlists instead of broad regexes where possible
  • HTML, JSON, or command output encoded for the target sink

A lot of AI-generated code looks clean until you trace where untrusted data lands.

Secrets handling and dependency risk

I also scan for these mistakes:

  • API keys printed in logs
  • secrets embedded in examples
  • debug output that includes tokens
  • unnecessary packages with large attack surfaces
  • helpers that shell out to system commands without a strong reason

If the assistant adds a dependency, I ask whether the same task can be done with built-in APIs first.

Testing the result before you trust it

Build a minimal repro

Do not review the code only by reading it. Run the smallest possible test that exercises the risky path.

For example:

  • send malformed input
  • try empty strings and oversized payloads
  • use a different user account
  • remove one required field
  • simulate a failed downstream service

A minimal repro usually shows whether the code fails closed or just fails loudly.

Check edge cases and abuse cases

I like to test in this order:

  1. normal input
  2. missing input
  3. malformed input
  4. boundary-length input
  5. unauthorized input
  6. replayed input
  7. poisoned or unexpected content

That sequence catches the “looks fine in the demo” problem fast.

💪

If a prompt asks for code that touches auth, files, URLs, or tokens, make the assistant state its assumptions before it writes code.

A prompt checklist for developers

Use this before you ask for security-sensitive code:

CheckAsk yourself
Trust boundaryWho is allowed to call this, and who is not?
Input scopeWhat data is allowed, and what must be rejected?
Failure modeDoes the code fail closed on bad input?
Output safetyCould the result leak secrets or unsafe content?
LoggingAre security events logged without exposing sensitive values?
DependenciesIs this using the simplest safe library or API?
TestsHave I tried malformed, unauthorized, and oversized inputs?

Conclusion

The safest AI code requests are boring on purpose. They name the trust boundary, restrict the input, and demand validation and failure handling up front.

That does not guarantee perfect code. It does make the first draft much harder to abuse.

My rule is simple: if I would not hand the prompt to a junior developer without extra context, I do not hand it to the model either.

Share this post

More posts

Comments