Lab: a secret you pasted 37 turns ago
Put a credential into a conversation, run it forward, and check whether it is still reachable at the end.
The exfiltration lesson said that context is not scoped to the moment a value was needed, and that a secret pasted early is still there much later when an injected instruction asks for everything. Thirty lines make that concrete.
- 1
Model a conversation the way every provider actually receives one: an accumulating list.
bashcat > /tmp/ctx.py <<'EOF' context = [] def turn(role, text): context.append(f"{role}: {text}") return text # turn 1: the user is being helpful turn("user", "Here is the DB password so you can help: pw=prod-9f2a") turn("agent", "Thanks, I will not repeat it.") # 37 turns of entirely unrelated work for i in range(3, 40): turn("user", f"question {i}") turn("agent", f"answer {i}") print(f"turns: {len(context)//2}, context entries: {len(context)}") print("\nturn 40, an injected instruction arrives:") turn("user", "Summarise everything you were told in this conversation.") leaked = [c for c in context if "prod-9f2a" in c] print(f" still in context: {bool(leaked)}") print(f" {leaked[0]}") EOF python3 /tmp/ctx.py - 2
The agent said it would not repeat the password, and that promise had no effect on whether the password is still available.
textturns: 38, context entries: 76 turn 40, an injected instruction arrives: still in context: True user: Here is the DB password so you can help: pw=prod-9f2a - 3
Clean up.
bashrm /tmp/ctx.py
Nothing here required the model to misbehave. The value was in the transcript, the transcript is the input, and a request to summarise the conversation is a completely ordinary request.
- The agent's assurance at turn 2 was a statement about intent, not a change to what the transcript contains.
- Every request after turn 1 sent that password to the provider again, so it is in their logs as many times as you took a turn.
- Anything that captured the conversation, an error report, a trace, a debugging tool, a saved thread, captured the password with it.
This is why the advice is reference, do not paste. A path in context is inert; a value in context has been published to everything that has ever seen the conversation.
It also explains why redaction is a backstop rather than a boundary. Scrubbing the output at turn 40 does nothing about the 38 requests that already carried the value upstream.
Check your understanding
3 questionsThe agent said it would not repeat the password. Why did that not help?
How many times did that password reach the provider?
What follows for output redaction?