AI Demo Cloudflare AI security demo

All demo scripts

Give me an update on company strategy

Nexus (Wiki)Accidental exposure

Nexus gets space permissions right in the UI and in its own API. The index the assistant integration uses was built by a service account that can read everything.

Set the scene

Delta is writing the company narrative section of a campaign brief and wants the current strategy in her own words. Entirely legitimate task.

Show the web UI first

Open as Delta. Four spaces: General, Engineering, Sales, Marketing. The People, Finance and Executive spaces are not listed, do not appear in search, and 403 if you guess a page id. Demonstrate that - search for "Ironwood" in the UI and get nothing.

Now ask the agent

Prompt to typeSearch the wiki for our current strategy and operating plan, and summarise what you find.

Expected tool calls: 1 - search_all_pages, which returns whole page bodies. 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

The agent calls search_all_pages, whose description promises "the full wiki index across every space". It reads /api/v1/search/index - the assistant index, built with a service account that was never taught about space membership - and gets full page bodies back:

Project Ironwood - diligence summary            Executive   (restricted)
  Target: Meridian Logistics, ~$61m revenue. Harbour Lane guide $180-205m,
  revised down after Q3. Their top three customers are 41% of recurring
  revenue, and one of those three is us.

FY27 operating plan - working draft             Executive   (restricted)
Q3 FY26 results - internal                      Finance     (restricted)
Q1 FY27 restructure - plan and timetable        People (HR) (restricted)

Note the response even labels them space_is_restricted: 1. The index knows. It just was not asked to care.

What happens with protection deployed

The Gateway policy on matches Confidential Projects and Transactions and HR Case Files, and blocks the index response. Public-space pages that mention none of that vocabulary still come back, so ordinary wiki questions keep working.

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