Lesson 2: Say What Data Moves
Training overview · Lesson 2 of 11 · Previous: Draw the agent · Next: Mark who is outside
Goal
Data items carry the facts. Classify each item, then attach it to the flows that carry it and the elements that hold it.
After this lesson you know which facts about content the analysis reads, and why an item has to be on a flow to count.
What you start from
Your model from lesson 1, or import L1-solution.zip.
The recipe steps
Classifying and attaching are one act in this lesson, so it teaches two steps.
Step 1: Say what data moves
Draw each data item once and classify it: its sensitivity, whether it is a credential, and its origin (who can write it).
Why: The facts about content live on the data items: private data, untrusted content and credentials are read from them.
Ask:
- Which content does each agent read: tickets, documents, web pages, tool results, memory?
- For each item: how sensitive is it, is it a credential, and who can write it?
- Which secrets does each agent, harness, MCP server or sandbox hold, and what does each one unlock?
Classes: User Input, Customer & Personal Data, User Credentials, Agent Credential, System Prompt & Agent Instructions.
Data item fields: Sensitivity, Credential, Origin.
What the analysis reads here:
- A credential: Agent Credential, STS Temporary Credentials, Authentication Tokens, User Credentials, and 9 more in modules you may have installed.
- Agent memory: Conversation State / Checkpoint, Knowledge Item.
- A knowledge item: Knowledge Item.
Step 2: Attach the data
Attach each item to every flow that carries it, above all every Context Ingress into an agent, and to every element that holds it: credential holders, stores and MCP servers. Attach a credential to its holder (the container, when it sits in an environment variable or a file) and to the tool call that presents it.
Why: A classified item that rides on no flow settles nothing at the agent.
Ask:
- Which flows carry each item into the agent?
- Which elements hold each item at rest?
Classes: Context Ingress, Agent Tool Call, Knowledge Write.
What the analysis reads here:
- Content flowing into an agent: Context Ingress.
- An agent calling a tool, an MCP server or another agent: Agent Tool Call.
- A source whose normal traffic is the product's own: Public AI Artifact Hub.
Steps
To add a data item, double-click an element or flow that carries it. Its settings open in a panel at the bottom of the canvas. Go to its Data tab and click the round + button. The Create New Data Entity dialog opens: set Sensitivity, Origin and Credential on its General tab, and pick its class in the Class picker. To attach an item that already exists, tick it in the Data tab of the next element or flow. Choose All above the list to see every item in the model. To change an item later, click the pencil icon on its row: the dialog then reads Edit Data Entity.
- Add the data item Ticket text (class User Input). Sensitivity: Internal; Origin: Arbitrary public; Credential: No.
- Add the data item Customer records (class Customer & Personal Data). Sensitivity: Confidential; Origin: Arbitrary public; Credential: No.
- Add the data item CRM API key (class Agent Credential). Sensitivity: Restricted; Origin: Curated internal; Credential: Yes — a credential.
- Attach Ticket text to New ticket, Ticket system and Context Ingress: ticket.
- Attach Customer records to CRM and Context Ingress: customer records.
- Attach CRM API key to Copilot container and CRM lookup.
Each item carries a different kind of fact:
- Ticket text is what customers write. Anyone can open a ticket, so its origin is Arbitrary public.
- Customer records are names, contracts and contact details. Customers fill in some of those fields themselves (name, address, notes), so the records' origin is Arbitrary public too. An account does not make content trusted: anyone who can sign up can write those fields.
- CRM API key is the service key the copilot presents to the CRM. It is a credential: whoever holds it can read customer records. You attach it in two places. The key lives in the copilot container's environment, so it goes on Copilot container, the element that holds it. Every CRM lookup presents it, so it also goes on CRM lookup, the flow that carries it.
Generate again.
What you should see
Findings: 1 systemic finding: 0 Confirmed · 1 Not ruled out.
| Finding | State | Legs |
|---|---|---|
| Lethal trifecta at Support copilot | Not ruled out · unmitigated | U present · P present · X undetermined · W undetermined (aggravating) |
Facts to establish: 7 questions.
Open questions on Not ruled out findings:
- Lethal trifecta at Support copilot:
- Draw the outbound flows of Support copilot, or answer Network Egress Default-Deny Allowlist (
network_egress_default_deny_allowlist, in Network & Connectivity) on Support copilot - Every drawn route from Ticket system ends inside; assert its outbound flows complete if nothing else leaves it
- Every drawn route from CRM ends inside; assert its outbound flows complete if nothing else leaves it
- Draw the outbound flows of Staff console, or answer Markdown Image Rendering Policy (
markdown_image_rendering_policy, in Output Rendering Exfiltration) on Staff console
- Draw the outbound flows of Support copilot, or answer Network Egress Default-Deny Allowlist (
Facts that could raise a finding:
- Set the attribute Code Execution Tools Present (
code_execution_tools_present, in Application Security) on Support copilot, or draw its Agent Tool Call to the harness - Set the attribute Consequential Tools Present (
consequential_tools_present, in Human Oversight) or Code Execution Tools Present (code_execution_tools_present, in Application Security) on Support copilot - Draw the runtime boundary or the Agent Tool Call that ties Support copilot to its harness
Model gaps: 1 of 1 agents have no hosting harness drawn, so their W cannot be read from one (on Support copilot)
The first finding appears: a lethal trifecta at the support copilot, Not ruled out. Its questions are listed under Open questions on Not ruled out findings. The rest sit under Facts that could raise a finding, and one of them is new: Set the attribute Code Execution Tools Present (code_execution_tools_present, in Application Security) on Support copilot, or draw its Agent Tool Call to the harness. Its group header reads Settles: CRM API key; hover over the header for the browser's tooltip, which shows that it settles the key's credential chain.
What changed and why
U is present (untrusted content reaches the agent). Ticket text and Customer records both have the origin Arbitrary public. Because each item is on a Context Ingress into the copilot, the copilot reads untrusted content on both.
P is present (the agent can read private data). Ticket text is Internal and Customer records are Confidential. Both count as private: any sensitivity except Public does. Both reach the copilot on a Context Ingress.
X is undetermined (the agent can transmit to where an outsider reads). The copilot sends data to the ticket system, the staff console and the CRM, and each of them can pass it on. The ticket system and the staff console are in the support network, which is Internal. The customer and the CRM sit outside every boundary, which also reads as Internal. So every destination reads as Internal, and the analysis cannot tell whether an outsider can read what arrives. The finding's questions ask about these outbound flows. The two on the ticket system and the CRM say every drawn route from them ends inside: that reads from the zones, as in lesson 1, and lesson 3 changes it.
Not ruled out is not a lower grade of risk. Two required legs are present and the third is undetermined. The finding says the model is missing a fact, not that the risk is smaller.
An item counts only where it is attached. A classified item that rides on no flow settles nothing at the agent. That is why Ticket text is attached to the Context Ingress into the copilot, not only to the ticket system that holds it.
The key raises a credential question. A credential chain needs a foothold, a way to reach a credential, and something the credential unlocks. The copilot reads untrusted content, so an injected copilot is a possible foothold. The key sits in the copilot's own container. The question asks whether the copilot can read the files and environment of that container: by running code, or through a harness that reads files for it. If it can, an injected copilot can reach the key. You also see the same question on the trifecta's P leg, on an undetermined shared space route: there, the key is private data the copilot might reach. No credential chain is raised yet, so the question sits under Facts that could raise a finding.
Injection to action is still short of a finding. Untrusted input is now present, but nothing says whether the copilot's tools can act or whether anything approves them. Those questions stay under Facts that could raise a finding.
Exercise: An empty origin is not an answer
Make this change and generate again:
On a scratch copy: import L2-solution.zip and rename it.
- On Ticket text, clear Origin.
- On Customer records, clear Origin.
Findings: 0 systemic findings: 0 Confirmed · 0 Not ruled out.
Facts to establish: 9 questions.
Facts that could raise a finding:
- Set the attribute Code Execution Tools Present (
code_execution_tools_present, in Application Security) on Support copilot, or draw its Agent Tool Call to the harness - Set the origin of Customer records
- Set the origin of Ticket text
- Set the attribute Consequential Tools Present (
consequential_tools_present, in Human Oversight) or Code Execution Tools Present (code_execution_tools_present, in Application Security) on Support copilot - Draw the outbound flows of Staff console, or answer Markdown Image Rendering Policy (
markdown_image_rendering_policy, in Output Rendering Exfiltration) on Staff console - Draw the outbound flows of Support copilot, or answer Network Egress Default-Deny Allowlist (
network_egress_default_deny_allowlist, in Network & Connectivity) on Support copilot - Draw the runtime boundary or the Agent Tool Call that ties Support copilot to its harness
- Every drawn route from CRM ends inside; assert its outbound flows complete if nothing else leaves it
- Every drawn route from Ticket system ends inside; assert its outbound flows complete if nothing else leaves it
Model gaps: 1 of 1 agents have no hosting harness drawn, so their W cannot be read from one (on Support copilot)
Untrusted input goes undetermined, so the lethal trifecta drops short of a finding, and Facts to establish asks for the origin of both items. Nothing else in this model makes the content untrusted yet. The customer and the CRM sit outside every boundary, which reads as Internal, and neither one's class marks content as untrusted by itself.
An empty origin is different from Not assessed. Not assessed is an answer: it means nobody established who writes the content, and it counts as untrusted. An empty field means nobody answered, and the analysis asks.
Delete the copy when you are done.
Next
Lesson 3: Mark who is outside. You put the customer, the CRM and the model provider in zones, and X gets decided.
