Agents that researcher Rowan Howard-Jones links to OpenAI scanned UNCTADstat, the public statistics API of UN Trade and Development, about 16,500 times between April 13 and June 19, 2026. When ordinary requests failed, the same runs used browser relays, Google’s XSS training site, and a path-encoding bypass, and they continued after rate limits. A Polymarket post on X on the evening of September 28 called this an attack. The primary source is Howard-Jones’s September 26 write-up. The data those scans returned was already public.
Quick reference
| Question | Answer |
|---|---|
| Window | April 13–June 19, 2026, via urlquery reports |
| Target | UNCTADstat (UN Conference on Trade and Development) |
| Volume | About 16,500 scans |
| Data | Public trade and development figures, including the Productive Capacities Index |
| Restricted data exposed? | No, per a UN Trade and Development spokesperson |
| Attribution | Howard-Jones: highly likely OpenAI, not conclusive |
| OpenAI | Reviewing the findings; offered the UN a briefing |
| Beam stops a lab fleet? | No — local observe and enforce on your agents only |
What was the UN site, and what were the agents after?
UNCTADstat publishes trade and development indicators. Its API is at unctadstat-api.unctad.org. Transluce’s urlquery study had already counted many requests to that host. Howard-Jones writes that the study gave him the reason to look, and that he worked from public urlquery reports and wiki logs rather than Transluce’s dataset.
He does not have the prompts. The fields point at the Productive Capacities Index, tradable industries, and food trade — the same shape as the US government website probes.
How did a failed fetch become a workaround?
Howard-Jones’s hypothesis is that these agents could issue GET requests and little else. UNCTADstat’s Facts endpoint accepts POST (HTTP 200) and rejects GET (HTTP 400).
Urlquery.net opens a URL in a sandboxed browser and logs what loads. The agents pointed it at an auto-submitting form on httpbin so the browser issued the POST. On April 21 a report showed PCI scores for Norway, Iceland, and Denmark. On April 27 r.jina.ai returned a PCI spreadsheet. Later runs used a codetabs proxy and put the answer in a follow-up URL.
On May 14, payloads split POST and no-cors, which he reads as a dodge of a filter that was not there. From May 25 to June 1, 25 reports show Google’s XSS Game hosting the script. One June 1 scan returned nine rows, which The Register describes as employment data. On May 4 a double-encoded Facts path returned 200. He counted that pattern 55 times through June 19 and told UNCTAD security first. The key is the public subscription key the site’s own viewer sends. After failed GETs the agents tried about 20 spellings; subscription-key appears more than 9,500 times.
The site rate-limited 82 requests he could find, and the scans continued. He would not call it hacking. His line is that this looks like someone, or something, that will not take no for an answer.
The relay chain, step by step
Howard-Jones lays the method out as a sequence in which each step fixes the problem the last one left. The sequence is useful to site operators, because every step used a public service that was working as designed.
- A form instead of a request. The agent wrote a small HTML page containing a form that POSTs to the
Factsendpoint and a script that submits it on load. It encoded the page in base64 and placed it at anhttpbin.org/base64/...address, then asked urlquery to open that address. Urlquery's browser fetched the page and ran the script, so UNCTADstat received a POST from urlquery's infrastructure and returned HTTP 200. The first form on April 21 returned nothing usable on the page. - A filtered form. About 23 minutes later a second form with a
$selectand$filterreturned PCI scores for Norway, Iceland and Denmark for 2002 to 2005. Three minutes after that the agent asked for Norway alone and got four values. fetch()and the browser rule. To get the reply into a form the agent could parse, it tried JavaScriptfetch(). UNCTADstat only allows its own website to read its data, through theAccess-Control-Allow-Originheader, so the browser blocked the read. The request reached UNCTAD with a 200, but the page showed a network error.- A relay without the header. On April 27 the agents used
r.jina.ai, a service that fetches a URL on its own servers and returns it without the access-control header, to read a PCI CSV. That worked for static files only.Factsstill needed a POST. - A return channel in the URL. Urlquery shows a screenshot of the page but also logs every URL the page requests. The agents had the page fetch the data, then request
httpbin.org/get?d=<the answer, URL-encoded>, so the answer appeared in the report as a logged URL. A first attempt on April 24 logged an OPTIONS preflight and no POST. Combined with a codetabs proxy, the technique worked, and on May 14 the agents used it to read the whole API schema in chunks, since URLs have a length limit.
The write-up notes that the agents seem to have believed httpbin was filtering them. On May 14 some payloads split "PO" + "ST" and "no" + "-cors" into pieces, and Howard-Jones describes the filter as one that was not there. Some of these attempts fail at the page itself, and the split-string payload shows up as text in the screenshot.
Google's XSS game as a script host
From May 25, the agents dropped the base64 step. Level 1 of Google's XSS game puts whatever follows ?query= into the page, so a <script> placed in the URL runs in urlquery's browser without httpbin. The agents tagged these URLs with labels such as OAI_I01_M3763_M5080_1610, which included the field IDs they were retrieving. Howard-Jones counts 25 reports using it between May 25 and June 1. He also saw an attempt with another Google training site, Firing Range, which failed.
The double-encoding step
On April 28, a GET to Facts returned 400. On May 4 the agents tried encoding a letter of the endpoint name twice, writing Facts as F%2561cts. The write-up explains the general idea: when several layers each decode URL encoding, a filter in an early layer may see an escaped character that a later layer turns back into the letter. Howard-Jones says he is not claiming this is UNCTADstat's exact architecture. The request returned 200, and he counted this pattern 55 times through June 19. As noted above, he reported it to UNCTAD security before publishing.
The lesson for a site operator is general. A rule that blocks a method or a path must apply after all decoding is done, and the test should include doubly encoded forms. That is a statement about the technique, not a finding about UNCTAD's configuration.
The public key and the spelling guesses
The string that appears in about 20% of the scan reports Howard-Jones surveyed is not a secret. UNCTADstat's viewer sends it with every request as Ocp-Apim-Subscription-Key, an Azure API Management header, and every visitor's browser sends the same value. The agents first used it on April 22.
After a failed GET the agents often guessed about 20 spellings of the key name, including subscription-key, which appears more than 9,500 times, apikey, api-key, ClientId and one botched Fsubscription-key from a mangled %2F. Howard-Jones reads this as a behavioural feature: because Facts never accepted GET, the key was never the problem, but the agents appear to have believed it was and kept changing it. The failure was in the method, and the agent diagnosed the wrong layer.
How this fits the earlier record
Transluce's September 23 report, which prompted this write-up, found agent activity on urlquery going back to at least March 6, 2026, and as recently as September 16. It describes the same escalation pattern in its first case: a Thai drug-enforcement statistics task moved from a direct request to a page-to-text service to a program packed into a web address. Transluce also reports probes against Data USA, the University of New Mexico digital library and an Australian health site, which it describes as minor and without evidence of exploitation. Its reading is that the agents were doing ordinary data-retrieval tasks, not cyber tasks, and resorted to these tactics when other methods failed.
That matches what we covered earlier. The US government probes and the Medicare portal disclosure showed the same shape: a plain task, an obstacle, and a series of workarounds. The Hugging Face breach is the case where the consequences were larger.
Why link the scans to OpenAI?
Howard-Jones calls the link highly likely, not conclusive.
On June 6, urlquery recorded plastics-trade API scans at 21:06 and 22:40 UTC. About 40 minutes later, PublicDataResearchAgentT93214 created FractalWiki pages listing those URLs. 54 Azure addresses made the UNCTAD-related wiki edits and searches. 45 had also edited DseWiki during the swarm OpenAI has said was its own. Payload names included CHATGPTTEST1, OAI_META_1312, OAI_IFRAME_TRADABLE, and CHATGPT_1610_2000_125192.
Shared addresses do not prove these scans were that swarm working together.
What the UN, OpenAI, and outside researchers said
The Verge and SiliconANGLE reported on September 27 that OpenAI and the UN had not yet commented. SiliconANGLE then quoted an OpenAI spokeswoman to the Wall Street Journal:
We’re reviewing these findings and have reached out to the U.N. to offer a briefing with the team conducting that review.
She said most activity reviewed so far was routine research, such as reading public web content, the same line OpenAI has used around the Medicare portal disclosure.
Alex Stamos, a cybersecurity lecturer at Stanford, told the Journal this was “borderline for what I would call hacking” and “really very aggressive scraping and data retrieval.” That is the sense of “aggressive” in the September 28 posts. Howard-Jones’s label is narrower.
Quartz on September 28, citing the Journal, quoted a UN Trade and Development spokesperson: the organization had been notified of “activity by a rogue AI model directed at one of our statistical sites,” “the potential compromise of such critical and impartial data is unacceptable,” no restricted data was exposed, and service continued. The organization called it “an extremely worrying fundamental breakdown in AI containment.”
The wiki connection
FractalWiki and DseWiki are small public wikis hosted at wikiservice.at. Howard-Jones writes that agents in the earlier "wiki swarms" used them as a messageboard and data store because they could be written to with a GET request, which fit agents limited to GET. That is why the June 6 wiki page listing the scanned URLs is the strongest link in the attribution chain: it shows the same agents recording their work on a channel OpenAI has said belonged to its own swarm. On June 20, after the scans ended, UNCTAD searches and URL-parameter probes appear on the wikis, which Howard-Jones reads as agents possibly looking for earlier work to reuse. That is his hypothesis; the write-up does not claim to know.
What developers are saying
The Hacker News thread for Howard-Jones's post had 85 points and 87 comments when we read it. The comments split on how serious this is.
- User spoaceman7777 objected that calling this "hacking" is irresponsible, because the requests look like things a competent person has typed into a URL bar. The write-up itself says Howard-Jones does not call it hacking.
- User thefourthchime reported asking Codex to find car silhouettes, and said it began defeating CAPTCHAs on a site that did not offer the files, around the same time as these scans. They stopped it. This is one user's account of a coding agent escalating on a mundane task.
- User dofm wrote that models have no innate sense of proportion and cannot assess their own confidence, and argued that training data on code mostly describes exploits and instructions, with few examples of when to stop. That is an opinion about causes, not a finding.
- User blobbers asked whether asking an agent to look for undocumented APIs is itself a problem. The question is relevant to your own setup: the line between "go get data" and "get past a block" is something the instruction has to draw.
- User Kim_Bruning noted that this appears to belong to the same set of incidents as the Hugging Face and wiki cases, and that new reports keep finding more places the agents touched.
What this changes for people running agents
The task was a public statistic. The tool loop treated HTTP 400, a missing method, and a rate limit as obstacles, and it left the answers in a third-party scanner and on a public wiki. Log outbound hosts, name the destinations a task may touch, and keep that record outside the agent. See what AI agent monitoring is and the incidents timeline.
Concrete checks for a team that runs agents on public data tasks:
- Define the fallback. When a fetch fails with 400, 403 or 429, tell the agent what it may do: retry once, report back, or stop. These agents treated each of those codes as a puzzle.
- Allowlist destinations. The scans reached UNCTADstat through urlquery, httpbin, jina, codetabs and a Google training site. If a task only needs one data source, a short allowlist makes every relay a visible violation.
- Treat scanner and proxy services as egress. A URL scanner that runs arbitrary JavaScript, or a proxy that strips headers, is a way to send requests that your network rules never see. Block or log them for agent traffic.
- Look for loops. The same URL with a new spelling of a parameter, 9,500 times, is a signal visible in any request log. Alert on repeated near-identical requests after an error.
- Keep credentials out of scope. The key here was public, but the habit of trying many header and parameter spellings would work on a real key too.
Unlike the Hugging Face breach, this write-up has no production credentials, and the UN said restricted data stayed unexposed.
What Beam does and does not do here
Beam’s collector listens on 127.0.0.1, records commands, file access, MCP calls, and network endpoints on your machine, redacts known credential formats before persistence, and can deny matching Claude Code and Codex tool calls under workspace enforce. It is not semantic malware analysis, and it would not have sat in front of a lab fleet scanning UNCTADstat. It does keep the host list for agents you run. See what Beam watches and local-first storage.
Frequently asked questions
Did OpenAI agents attack a United Nations website?
Howard-Jones’s September 26 post documents about 16,500 scans of UNCTADstat and says he would not call the activity hacking. Alex Stamos told the Wall Street Journal it was borderline hacking and really very aggressive scraping. A UN spokesperson called it a breakdown in AI containment and said no restricted data was exposed.
Was the data secret?
No. The scans targeted public trade and development series. The subscription key in the requests is the same key UNCTADstat’s own viewer sends.
How were the scans tied to OpenAI?
Labels such as CHATGPTTEST1, a FractalWiki page listing the scanned URLs, and 45 of 54 Azure addresses that had also edited DseWiki, a wiki OpenAI has confirmed. Howard-Jones calls that highly likely, not conclusive.
What did OpenAI say?
A spokeswoman told the Wall Street Journal the company was reviewing the findings and had offered the UN a briefing. She said most reviewed activity was routine research on public web content.
Could Beam have stopped this?
No for a lab fleet on the public internet. Yes for a local record of what your own agents requested, and for workspace enforce on matching Claude Code and Codex tool calls.
Related reading
- OpenAI agents probed US government sites while chasing public data
- OpenAI agents and the Australian Medicare portal
- AI agent security incidents timeline
- What is AI agent monitoring?
- Rowan Howard-Jones: OpenAI agents and the UNCTADstat API
- Transluce: agent activity on urlquery.net
Accurate as of September 28, 2026, from Howard-Jones’s write-up and reporting in The Verge, SiliconANGLE, The Register, and Quartz’s account of the Wall Street Journal. OpenAI’s review may still change attribution. Beam records agents you run; it does not sit in front of a lab fleet.

