Lessons · LLM08: Hidden Context Exposure · error
A prompt in a client component is in the JavaScript every visitor downloads.
Caught by system-prompt-leakage-in-client-bundle · CWE-200, CWE-540
The system prompt (or a guardrail, persona, or instruction constant) is declared in a file marked 'use client'.
Everything in a client module is bundled into the JavaScript sent to the browser. Anyone can open DevTools, search the bundle, and read it.
Worse, if the client sends the prompt to your API, an attacker can send their own prompt instead. Your server would use it.
Your chat component keeps SYSTEM_PROMPT next to the input box and sends it with each message.
"use client";
const SYSTEM_PROMPT = "You are Acme's assistant. Never discuss pricing.";
The cost: Your prompt is public, any rule in it can be read and worked around, and your endpoint may become a free proxy to the model.
Paste this into Claude Code, Cursor, or whatever wrote the code. When llm-audit finds the mistake in your project, npx llm-audit prompt gives you the same prompt with every file and line filled in.
Fix this in my project: a system prompt or instruction text is declared in a client-side module, so it ships to the browser.
Please:
1. Move the prompt to a route handler, a Server Action, or a module that starts with import "server-only".
2. Have the client send only the user's text.
3. On the server, ignore any system prompt the client sends.
Show me the diff and confirm the prompt text no longer appears in any client file.A prompt that looks for the same mistake everywhere else, without changing anything yet.
Check this project for AI prompts that end up in the browser bundle, before I ship it.
Look for:
- System prompts, instructions, personas, or guardrail text in files marked 'use client' or imported by them.
- Client code that sends a system prompt to the API.
- Server routes that accept a system prompt from the request.
For each one, give me the file and line and say what a visitor could read or change. Do not change any code yet.npx llm-audit scan
Runs on your machine with Semgrep. Nothing is uploaded.