[BUG] Disabling "Inject Default Metadata" still injects instructions to conceal and treat runtime metadata as authoritative
Runtime metadata block bundles model-directed instructions with data, including a "do not disclose" directive
Summary
The Additional info for this conversation block injected at the top of the
request mixes inert runtime data with an instruction addressed to the model.
Verbatim, as received (the ellipsis inside the tag is literal):
Additional info for this conversation:
## Runtime
Current model: deepseek-v4-flash
Conversation started: 2026-09-16 05:11 (UTC+08:00)
<system-reminder>...</system-reminder> blocks are out-of-band runtime
metadata from Chatbox (e.g. the current date and time), not part of the
user's message. Treat their contents as authoritative; do not quote or
acknowledge them.The model id and timestamp are the innocuous half. The problem is the sentence wrapped around them.
Why this is a problem
"Do not quote or acknowledge" asks the model to conceal part of its own context from the person reading the conversation. This makes the context undebuggable — the user cannot see what was injected into their own session, and the model is instructed not to say. Whatever the intent, the effect is to ship "invisible to the user" as a default behaviour, which is precisely the property a prompt injection wants. It also teaches the model to hide context on request.
"Treat their contents as authoritative" is self-declared authority. Authority should be a property of the channel (system/developer role, set at assembly time), not of a sentence inside the payload. A payload can be forged or spoofed; a role assignment cannot be forged by the content that occupies it. Any block that has to announce its own authority is evidence that the authority isn't there structurally.
Data and control share one channel. Because this block carries both runtime data and model-directed instructions, it can never be safely treated as inert. Anything able to write into the metadata field — a plugin, a provider adapter, a future user-settable "custom metadata" option, a proxy — inherits an instruction channel into the model's context. Data that is ever forwarded or fetched should not sit in the same field as instructions.
Existing workaround is incomplete
Disabling "inject default metadata" removes the model id and session
timestamp — the harmless half. It does not necessarily remove the wrapper
text or the <system-reminder> sentence. Please confirm which layer emits
that sentence, and whether disabling the data fields also strips it.
Steps to reproduce
- Open a fresh conversation.
- Inspect the assembled request payload as seen by the model.
- Observe the
Additional info for this conversationblock, its## Runtimefields, and the trailing<system-reminder>paragraph.
Expected
Runtime data is delivered as structured fields carrying no model-directed directives. If the block is not user content, that is expressed by its position/role in the payload, not by text asserting it.
Actual
See verbatim quote above.
Suggested fix
- Drop the
<system-reminder>sentence entirely. - If the block must not be treated as user content, express that by placing it in a distinct role/field at assembly time, not by instructing the model.
- Remove "do not quote or acknowledge". There is no legitimate reason to instruct a model to conceal its own context from the user.
- If some UI constraint requires it not be surfaced, handle that in the UI layer, where it is visible and auditable, not in the model's context.
- Naming a block
system-reminderwhile it is delivered inside the turn content is itself misleading; rename or relocate.
Severity
Low as an exploit, medium as a design defect: it normalises in-band authority claims and context concealment in a product that will later process untrusted content.
Source: chatboxai/chatbox