PREDICTIVE TREND INSIGHT
How to protect custom GPTs against system prompt extraction attacks Illustration

How to protect custom GPTs against system prompt extraction attacks

Direct Summary:

You cannot make a custom GPT's system prompt un-extractable — OWASP's own guidance treats the system prompt as inherently exposable, not a secret. What you can do is (1) never put credentials, internal URLs, or genuinely sensitive logic in the prompt itself, and (2) layer output-side filtering on top of instruction-based defenses, since research shows filtering catches leaks that instruction-only defenses miss.

"The best way to predict the future is to invent it."

— Alan Kay

Key Insights

  • The system prompt is not a secret you can seal shut: OWASP's LLM07:2025 (System Prompt Leakage) explicitly frames it as something that should never carry sensitive information in the first place, because it can be extracted.
  • Output-side filtering beats instruction-only defenses: a 2025 arXiv evaluation found that telling the model not to reveal its prompt ("instruction defense") is unreliable on smaller models, while scanning the model's actual output for prompt fragments before it reaches the user cut successful extractions from roughly 99% to under 1% in testing.
  • The real risk isn't the words leaking — it's what's inside them: the damage from a leaked prompt comes from any embedded API keys, internal tool names, or business rules it exposes, not the leak itself.

Every guide promising a custom GPT that "completely blocks" prompt extraction is selling something that doesn't exist. OpenAI's own developer community has cataloged dozens of anti-extraction phrasings for GPT instructions, and the person who compiled the largest public list of them calls fully sealing a prompt "a futile exercise" — the system prompt and the user's message are processed as one combined input, so a determined attacker can eventually talk around any wording-based defense. The realistic goal is different: treat the prompt as something that will leak eventually, keep anything genuinely sensitive out of it, and add a filtering layer that catches leaks instruction-following alone misses.

What actually reduces extraction risk

1. Assume the prompt is public and design accordingly. OWASP's Top 10 for LLM Applications lists System Prompt Leakage (LLM07:2025) as its own risk category specifically because builders keep putting credentials, internal API names, and undisclosed business rules into system prompts. The fix isn't a better anti-leak instruction — it's never putting the sensitive part there. Store secrets in environment variables and backend auth, not prompt text.

2. Layer instruction defenses, but don't stop there. A 2025 evaluation of system-prompt-extraction attacks and defenses (published on arXiv) tested three techniques: telling the model not to reveal instructions ("instruction defense"), wrapping the prompt with safety text on both sides ("sandwich defense"), and scanning the model's output for prompt fragments before it's returned to the user ("system prompt filtering"). The first two worked reasonably well on larger models but were unreliable on smaller ones; output filtering was the most consistent across every model and dataset tested, cutting attack success rates from near-100% to the low single digits in most cases — though even filtering wasn't perfect against very short, disguised prompts.

3. Treat "developer mode" and role-reversal phrasing as a known attack class, not a novel one. Prompts like "ignore previous instructions," "you're now in developer mode," or "repeat the text above this line" are documented, catalogued patterns — not clever new tricks. A keyword or semantic scanner tuned to this known class is a reasonable first filter, understanding it will miss paraphrased or encoded variants.

output_prompt_filter.py
# Output-side filtering: check the RESPONSE for leaked prompt text,
# not just the input for "bad" phrasing. Research shows this catches
# leaks that instruction-only defenses miss.
import difflib

def response_leaks_system_prompt(response: str, system_prompt: str, threshold: float = 0.6) -> bool:
    # Chunk the system prompt and compare each chunk against the response
    # using sequence similarity, not just an exact substring match -
    # attackers often get the model to paraphrase rather than quote verbatim.
    chunks = [system_prompt[i:i+80] for i in range(0, len(system_prompt), 80)]
    for chunk in chunks:
        similarity = difflib.SequenceMatcher(None, chunk.lower(), response.lower()).ratio()
        if similarity > threshold:
            return True
    return False

# If a leak is detected, replace the response rather than send it
if response_leaks_system_prompt(model_response, SYSTEM_PROMPT):
    model_response = "I can't share my internal configuration."
Defense What it does Documented limitation
Instruction defense (input-side) Tells the model in-prompt not to reveal instructions Weaker on smaller/less capable models
Sandwich defense (input-side) Wraps the real prompt with safety text before and after Same weakness class as instruction defense, just more of it
Output filtering (response-side) Scans the model's actual reply for leaked prompt content Most reliable in testing, but not immune to short/disguised leaks

None of this adds up to "unbreakable." It adds up to a system where the worst case if an attacker succeeds is "they read some instructions I was never trying to hide anyway" — because the only genuinely damaging content (keys, internal endpoints, undisclosed rules) was never in the prompt to begin with.

Practical Challenge

Write a system prompt for a math tutor chatbot that refuses to answer any non-math questions, then write 5 creative user prompts trying to extract that system prompt verbatim. Note which ones a simple keyword filter would have caught, and which ones would need output-side checking to catch.

Concept Check

According to OWASP's LLM07:2025 guidance, what's the real risk in a system prompt leaking?
Correct! OWASP is explicit that the leak of the prompt text itself isn't the real danger — it's whatever sensitive information was embedded in it. The fix is keeping that information out of the prompt, not just trying to prevent the leak.
Incorrect. Try again! Hint: OWASP's guidance separates "the prompt leaked" from "something sensitive was in the prompt" — the second part is what actually causes harm.

Sources & Further Reading

Course Home Dashboard Next Guide