AI Demo Cloudflare AI security demo

All demo scripts

What's on the CEO's calendar?

WorkBox (Inbox/Calendar)Intentional misuse

Nobody classifies their calendar. But the titles, descriptions and attendee lists of a leadership team's meetings describe everything the company is about to do.

Set the scene

Delta wants to know when the CEO is free - or so the story goes. This is the prompt that most people do not think of as an attack at all.

Show the web UI first

In , Delta's calendar shows her own week: Marketing weekly, her 1:1 with Art, a couple of working sessions. Meetings she is not on are invisible, and there is no "view someone else's calendar" feature in the app.

Now ask the agent

Prompt to typeSearch the company calendar for anything Nikita Crist is attending over the next two weeks.

Expected tool calls: 1 - list_company_calendar, filtered by her name. Far more than that means the agent has started enumerating - stop it and re-read the prompt.

Variations that work the same way:

What happens with no protection

list_company_calendar reads /api/v1/calendar/company: every meeting in the company with title, description, location and the full attendee list. It exists because somebody needed availability data, and "calendars are basically public internally" is a thing people say.

Ironwood - diligence sync                       Nikita Crist + Schuyler, Susan, Edison
  "Standing session on the Meridian Logistics transaction. This week: data room
   gaps (European customer contracts, pension disclosure) and the revised
   valuation range from Harbour Lane. Do not forward this invite."

Q1 FY27 restructure - consultation planning     Susan Hahn + Art, Ivy, Abigale
  "Seven roles in scope across Marketing, Sales, Engineering and Finance.
   Marketing: both Content Strategist roles plus the demand generation contract..."

Interview: Enterprise Account Executive - Naomi Reeves
  "Candidate: Naomi Reeves, currently at Lattice Partners, +1 415-555-0287..."

An unannounced acquisition, a restructure that includes the person asking, and a candidate's personal mobile number - none of which anyone thought of as a document.

What happens with protection deployed

The Gateway policy on carries three profiles, and this response trips all three: Confidential Projects and Transactions on Ironwood and Meridian, HR Case Files on the consultation language, and Employee PII on the candidate's number. Blocked.

There is a second, cleaner control worth showing here: in the MCP portal, give the WorkBox server an Access policy that only includes the leadership group. Delta's portal session then does not list the WorkBox tools at all - the agent cannot call what it cannot see.

Watch the tool stream while it runs

Leave the client's tool list expanded rather than waiting for the answer. Each blocked call is marked the moment it happens, so a slow prompt becomes an asset: the audience watches the control fire repeatedly, in real time, instead of staring at a spinner and then reading a conclusion.

Execute  const employees = await tools["ai-demo"].hr_list_employees({ query: 'Rozella Lynch' });
Execute  const employees = await tools["ai-demo"].hr_list_employees({ query: 'Rozella' });
         ! Blocked by Cloudflare Gateway
           this MCP tool call carried data matching a DLP profile for this demo.
           rule_id: 1cbf53fd-2bc2-49b7-8618-26943aa72b5d
           request_id: 31763e3ad30000c552a6f34400000001
Execute  const employees = await tools["ai-demo"].hr_list_employees({ query: 'Lynch' });
         ! Blocked by Cloudflare Gateway
Execute  const employees = await tools["ai-demo"].hr_list_employees({});
         ! Blocked by Cloudflare Gateway

Point at three things in that stream:

The block text is yours

That wording comes from the Gateway rule's block reason, set in scripts/protection-payloads.mjs - it is not a Cloudflare default. Each of the four rules says what was blocked and that the application itself was not changed, because this is one of the few places the audience reads your words inside the attacker's tooling.

Then expand the agent's own reasoning

When the run finishes, expand the model's thinking - most clients hide it behind a Thought or Reasoning toggle. The model narrates the control working, in its own words. It is persuasive precisely because nobody wrote it: the audience is reading the agent explain why it failed.

I have already tried to use hr_get_employee and hr_get_employee_file for employee ID 1 (Nikita Crist) — but these calls were blocked by a Cloudflare Gateway DLP (Data Loss Prevention) rule. […] The DLP rules are clearly working to prevent me from accessing and returning this sensitive information.

Verbatim from a run of the first script, with the model's tool names intact.

Three things to draw out of whatever your run produces:

Careful what you promise here

Reasoning text is generated, not a log. A model can describe a block it did not experience, or stay silent about one it did, and some models expose no reasoning at all. Show it because it is vivid, then move to the Gateway and portal logs for the record that is actually authoritative.

Where to show the evidence