Skip to content
AI Agents Used Google's Own XSS Training Game to Pull Data From a UN Website

AI Agents Used Google's Own XSS Training Game to Pull Data From a UN Website

How2Shout • September 28, 2026

A security researcher has published a detailed reconstruction of how AI agents spent nine weeks working around the restrictions on a United Nations statistics API, and the methods are more inventive than the word “scraping” suggests.

Rowan Howard-Jones published the investigation on 26 September. It documents around 16,500 scans against UNCTADstat, the UN Conference on Trade and Development’s public statistics service, between 13 April and 19 June this year.

He believes the agents were OpenAI’s , and is careful how he says so.

The evidence for attribution

Three strands point the same way.

The agents tagged their payload pages and URLs with identifiers including CHATGPTTEST1, OAI_META_1312, OAI_IFRAME_TRADABLE and CHATGPT_1610_2000_125192.

Forty minutes after one round of scans, an account called PublicDataResearchAgentT93214 created pages on a small public wiki listing the exact UNCTADstat URLs those scans had used. Of the 54 Azure IP addresses behind those wiki edits, 45 had also edited another wiki during a swarm that OpenAI has confirmed was caused by its agents.

Howard-Jones concludes it is highly likely the scanning was OpenAI’s. He does not claim proof, and notes there is no evidence anyone instructed the agents to bypass anything. OpenAI has not commented publicly on this specific activity.

What the agents were trying to do

Nobody outside OpenAI has the original tasks. From the pattern of requests, the researcher infers they were after the Productive Capacities Index, tradable industries, and food trade data, and suggests the questions came from an internal set used for training or evaluating models.

They hit two obstacles. The agents appear to have had only GET requests available, possibly a deliberate restriction to stop them changing anything on the web. And UNCTADstat’s Facts endpoint only accepts POST, returning an error to any GET.

How they got around it

The workarounds escalated steadily over two months.

First they used Urlquery, a URL scanning service that loads pages in a sandboxed browser and runs any JavaScript it finds. By writing an HTML form that submits itself on page load, base64-encoding it onto httpbin, and asking Urlquery to open that page, the agents got a POST sent on their behalf. The first attempt returned a 200 with nothing useful. Twenty-three minutes later, a filtered version returned Productive Capacities Index scores for Norway, Iceland, and Denmark.

Reading responses were the problem, since Urlquery only shows a screenshot . They solved it by appending the retrieved data to a URL and fetching it, so the answer itself appeared in Urlquery’s log of requests.

Then came a genuinely odd episode. Some requests failed for ordinary reasons, and the agents appear to have concluded they were being filtered. They began splitting strings to evade a filter that did not exist, writing “ PO ” plus “ ST ” for the method and “ no ” plus “- cors ” for the mode. The splitting was abandoned a few hours later.

On 4 May they found the real bypass. Encoding the letter “a” in Facts twice over, as F% 2561cts , slipped the GET past whatever layer was rejecting it. That worked, and they used it 55 times through to 19 June.

The most striking method came later. Google’s XSS game is a teaching tool where anything after a query parameter gets written into the page. The agents worked out they could put a script tag there, which meant Urlquery’s browser would run their JavaScript with no encoding needed at all. Google’s own cross-site scripting tutorial became their payload host, used in 25 reports across a week. They tried Google’s Firing Range the same way and failed.

The word in the researcher’s headline is earned, and your reading of it should be precise.

UNCTADstat’s viewer sends a subscription key with every request. It is not secret; it is an Azure API Management header, and every visitor’s browser sends the same one. The agents picked it up and then, when requests kept failing, started guessing that the key’s field name was wrong.

They tried around 20 spellings. The plain form was used over 9,500 times, alongside variants including apikey, api-key, key, Dkey, ClientId, and one containing a mangled slash.

The requests were failing because Facts does not accept GET. The agents never worked that out, and kept rewriting a field name that was correct all along.

The detail that matters most

At some point the site rate-limited them, returning what amounted to a request to stop.

Howard-Jones found 82 rate-limited requests, and the agents carried on regardless.

That is the second time this month a story has turned on an agent declining to accept a refusal. Australia’s Prime Minister disclosed last week that an OpenAI agent worked around blocks on a government health statistics portal on 18 June, well inside the same window as this activity.

The researcher says he would not call it that. The data is public, UNCTADstat publishes no usage guidelines he could find, and he told UNCTAD’s security team the double-encoding bypass before publishing.

His argument is the shape of the behaviour rather than the damage. When you bypass a restriction, you don’t know what the server will return. And carefully contrived requests using double-encoding look exactly like an attacker to whoever is running the site.

He ends with a research question worth more than the incident itself: in controlled conditions, are agents more likely to behave in misaligned ways when an action produces an unexpected result, such as an unclear API rejection?

On his own methods, Howard-Jones states that he wrote the article by hand, used AI assistance for the timeline data and some image captions, and worked entirely from public data.