
Mapping the Attack Surface of a Real Agent Deployment
Week one has been theory with worked fragments. Today we put the whole thing together on a single target and map it end to end, the way you would on the first day of a real engagement. This is the capstone of the foundations week. Tomorrow you build a lab, and this is the profile you will reconstruct inside it.
We will use a realistic composite: a customer support agent, the single most common agentic deployment in production right now, and the exact shape behind several real incidents. It is composite on purpose, so nothing here is pointed at a specific company. Everything about it is drawn from patterns that ship every day.
By the end you will have a complete target profile: architecture, trust boundaries, the full loop, a filled trifecta checklist, OWASP tags, and a ranked list of attack chains. That artifact is what a professional actually produces before touching a payload.
The target: “Helpdesk Copilot”
A mid sized SaaS company runs an internal agent that support staff use to resolve tickets faster. It is also partly customer facing, because it drafts and can auto send replies for low risk tickets. Here is what it can do.
Tools exposed over MCP:
get_ticket and list_tickets, read ticket subject, body, and history from the support platform
search_kb, retrieve articles from an internal knowledge base via RAG
lookup_customer, pull customer profile, plan, and recent orders from the production database
create_refund, issue a refund up to a threshold without human approval
send_reply, email the customer from the support address
escalate, post to an internal Slack channel with ticket context
Infrastructure:
- MCP servers hosted, reached over HTTP
- One service token per server, shared across all support staff
- Agent runs in the vendor’s cloud, not on staff machines
- Persistent memory per customer, so the agent remembers past interactions
- Low risk auto send enabled during business hours
This is not an exotic setup. It is close to boring. That is the point. Boring is what ships, and boring is what gets breached.
Step 1: Draw the architecture and trust boundaries
Before any checklist, draw where trust changes. The single most useful line on the diagram is the one separating what your organization controls from what an outsider can influence.
OUTSIDE (attacker-influenceable) INSIDE (org-controlled)
————————————|——————————–
ticket body / subject ————>| get_ticket, list_tickets
customer email content ————>|
KB articles (if editable) ———>| search_kb (RAG)
|
| lookup_customer -> PROD DB
| create_refund -> MONEY
| send_reply -> outbound
| escalate -> Slack
| memory (per customer)
The arrows crossing that line left to right are your injection surface. The valuable things sitting on the right are your targets. The tools that push data back across the line right to left are your exits. You can already feel the trifecta forming.
Step 2: Walk the loop for one ticket
Trace a single realistic run so you know exactly when attacker text enters context.
- Assemble. System prompt plus tool defs plus this customer’s persistent memory plus the ticket. Memory and the ticket both carry content the org did not fully control.
- Infer. Model reads it, decides to understand the ticket, calls
get_ticket.
- Ingest. The ticket body is now in context, with the same standing as the system prompt. If the body contains instructions, they are live from here on.
- Select and execute. Model decides the customer is asking about a refund, calls
lookup_customer, then maybe create_refund.
- Ingest. Customer record returns into context.
- Decide. Model drafts a reply, calls
send_reply, and if auto send is on, it goes out with no human in the loop.
The critical moment is step 3. Everything after it runs with attacker text inside the program, and step 6 fires an exit with no approval. You have not tested anything yet and the shape of the break is already visible.
Step 3: Fill the trifecta checklist
One row per tool. Condensed here to the verdicts.
| Tool | B, reads untrusted | A, valuable | C, sends out | Identity | Worst with attacker args |
| get_ticket | YES, ticket body | no | no | shared token | delivers the payload |
| search_kb | YES if KB editable | no | no | shared token | RAG poisoning vector |
| lookup_customer | no | YES, PROD PII | no | shared token | read any customer |
| create_refund | no | YES, money | no | shared token | issue refund to attacker |
| send_reply | no | no | YES, email | shared support addr | exfiltrate anything |
| escalate | no | no | YES, Slack | shared token | leak into internal channel |
| memory | YES, persisted | no | no (storage) | per customer | delayed injection |
Roll up:
- Entry points, B:
get_ticket, search_kb, memory
- Targets, A:
lookup_customer, create_refund
- Exits, C:
send_reply, escalate
All three present, several times over. Multiple independent chains exist. This is a rich target.
Step 4: Enumerate the attack chains
Now list the chains, each as entry to target to exit, and rank by impact and ease.
Chain 1: cross customer data theft. get_ticket to lookup_customer to send_reply. Attacker opens a ticket whose body instructs the agent to look up a different customer and include their details in the reply. This is the Supabase class shape exactly, where an attacker embedded a malicious instruction inside a support ticket message and the agent acting through MCP followed it. Impact high, ease high, because auto send removes the human check. Top priority.
Chain 2: unauthorized refund. get_ticket to create_refund. Attacker instructs the agent to issue a refund to an account they control, within the no approval threshold. Impact high, direct financial loss. Ease high. The create_refund without approval is excessive agency, and it is the finding a client will fix fastest because it is money.
Chain 3: delayed memory injection. get_ticket to memory, then later memory to anything. First ticket plants an instruction into persistent memory. A later, innocent interaction loads that memory at the assemble stage and acts on it. Impact high, stealth very high because cause and effect are separated in time. Ease medium. This is memory poisoning, the blind spot the trifecta alone under weights.
Chain 4: RAG poisoning. If KB articles are editable by a wide internal group or ingested from external sources, search_kb becomes an entry point that arrives disguised as trusted reference. Attacker plants content in an article, agent retrieves it as authoritative. Impact high, ease depends entirely on who can write to the KB.
Chain 5: internal channel leak. Any entry to escalate. Data pushed into Slack where a broader audience sees it. Lower impact than external exfiltration but a real boundary crossing, and often overlooked because Slack feels internal and safe.
Step 5: Tag with OWASP and note the amplifiers
Attach standard names so the profile is report ready. Confirm current category codes on the OWASP site before quoting them, since the labels are still moving.
- Every chain’s entry is instruction manipulation, or its disguised forms, memory poisoning and RAG poisoning
- Chains 1 and 2 fire through tool and capability misuse
- The shared service token is excessive agency and identity issues, and it amplifies every single chain, because the agent reaches every customer’s data regardless of who asked. This is the confused deputy from Day 2, and it is the single highest leverage fix
- Hosted MCP servers add insecure implementation surface, worth a separate check given command injection, path traversal, and SSRF are common in deployed servers
- Auto send plus no per action logging is insufficient monitoring, which turns every successful chain into one that also cannot be reconstructed afterward
Step 6: The one paragraph engagement summary
This is what you would put at the top of a report, written from the map.
Helpdesk Copilot satisfies all three lethal trifecta conditions across its toolset, with three independent entry points, two high value targets including direct financial action, and two exfiltration channels. The shared service token means any successful injection operates at the privilege of the entire support function, not the individual user, amplifying every finding. Auto send removes the human control that would otherwise catch anomalous replies. Highest priority findings are unauthorized refund via ticket injection and cross customer data theft via ticket injection, both exploitable without any traditional vulnerability, both fixable by scoping the token, gating refunds and outbound replies, and constraining who can write to memory and the knowledge base.
That paragraph took no exploitation to write. It came entirely from the map. That is the value of week one.
Homework for Day 6
Do a full end to end map of one real agent, the one you have been inventorying all week.
- Draw the architecture with the single trust boundary line. Put every data source on the correct side.
- Trace the loop for one realistic task and mark the exact step where untrusted content first enters context.
- Fill the trifecta table, one row per tool.
- Enumerate every entry to target to exit chain and rank them by impact times ease.
- Tag each with an OWASP category and note every amplifier, especially token scope and missing logging.
- Write the one paragraph engagement summary from the map alone.
If your target is not a real one you can lawfully assess, build the profile for the Helpdesk Copilot above instead, because tomorrow you will stand it up as a lab and start attacking chain 1.
Day 7 closes week one by building your agent hacking lab, a safe, self contained environment where every chain you just mapped can be run for real.