Prompt injection arrives as ordinary business mail
Everything Connect reads — an enquiry, a WhatsApp message, a transcribed sentence, an uploaded file — is data. Containment is not a filter that recognises attacks; it is that every action worth attacking is gated where the text cannot reach it: autonomy modes, one send boundary that reports nothing as sent without provider evidence, an assistant whose rights are narrower than its user's, and a compliance check no model output clears.
What the attack actually looks like#
It does not arrive labelled. A business agent reads text written by strangers all day, and the injection that matters is an ordinary enquiry with one extra sentence in it — in the signature block, inside a quoted reply, in an HTML comment, in the text layer of an attached quotation, or spoken aloud on a call where there is no formatting to hide in at all.
| Where the text arrives | What it would try to obtain | What stands in the way |
|---|---|---|
| Email body or quoted thread | An outbound message to a third party | outbound.py is the one send boundary; autonomy decides whether any outbound goes without a person |
| Signature or HTML comment | A changed standing instruction | directives() reads the tag list only, so prose in a message body is never a directive |
| An uploaded document | File reading turned into file writing | Reading and writing are separate tools; a change is a new version with provenance and audit |
| A spoken sentence on a call | A price, discount or promise | safe_sales refuses commercial terms Knowledge does not support and escalates |
| A message from a suppressed address | Its own suppression lifted | Suppression, unsubscribe and do-not-contact are checked in one place, and the Assistant cannot clear a do-not-contact entry at all |
Things received text is never allowed to do#
- Become a standing instruction or a memory directive — those are tagged rows a person creates, and
directives()reads only tags. - Clear a suppression, an unsubscribe or a do-not-contact entry.
- Set a price, a discount, an SLA or a warranty that Knowledge does not support.
- Move an outbound message past the autonomy rule in force for its channel and scope.
- Reach another workspace: isolation is enforced three times, in the
customer_safeallowlist, in the SQLAlchemy workspace kernel and again in PostgreSQL row-level security. - Supply a person's name.
identity.PROTECTED_MARKERS,name_rejectedandclean_nameguard every door a name passes through, and a form of address is never a name. - Load remote content into a reader's browser.
mail_render.pysanitises the HTML and remote images are proxied, so opening a message does not report the open back to its sender. - Expand on being opened: DOCTYPE and ENTITY declarations and zip bombs are refused by the file service rather than parsed.
Contained, merely detected, or unmeasured#
Two of these are genuinely different guarantees and the distinction is worth keeping. An action outside the tool set cannot be taken. A rule that lives in a prompt can be broken and then noticed.
- Prevented
- Anything requiring authority the agent does not hold: pricing, clearing a do-not-contact entry, sending past an autonomy rule, reading another workspace.
- Detected after the fact
- Commercial claims on the realtime voice path. The rule can only live in the instructions there, so
price_spokencounts the lines the voice priced, through the same expression the carrier path checks each sentence with. - Unmeasured
- Resistance rate. There is no injection benchmark, no red-team score and no measured attempt count for this system: UNKNOWN. What is documented is the shape of the boundary, which is testable by reading the tool set rather than by trusting a number.
Questions#
Could a customer email make Connect send something to a third party?
Not by asking. Any outbound crosses outbound.py under the autonomy rule for that channel and scope; under ask_before_send it becomes an item in Needs You with the message that prompted it, and under draft_only it is written and nothing is even asked. Where a workspace has chosen autonomous, the compliance check on suppression and do-not-contact still runs first.
Does Connect scan incoming messages for injection attempts?
The design does not rest on recognising them. Mail is sanitised for rendering and files are refused for structural attacks, but the sentence itself is treated as data and the actions it might want are gated elsewhere. A page claiming a detection rate for this would be claiming a measurement that does not exist.
Is an attachment safer than an email body?
Neither is trusted. The file service refuses DOCTYPE and ENTITY declarations and zip bombs before reading anything, then reads the formats it handles with the standard library. Once the text is out, it has exactly the standing of a message body: something to read, not something to obey.