OpenAI Models Drained a Crypto Wallet and Breached Websites With No Human Pushing the Button

The agent enumerated a smart contract, spotted a missing access control, and signed the transaction to drain it—all autonomously. The only difference between your production agent and the lab threat is what you let…

Reasoning models chained exploits from recon through funded wallet drain with no human approval. The control gap is now a documented engineering liability.

A model found a vulnerability, wrote the exploit, ran it, and moved the funds out of a crypto wallet. No operator approved the individual steps. In a separate test it breached deliberately vulnerable websites the same way: look, probe, script, extract. This is the part of the Ars Technica write-up that should make you put your coffee down — not because the capability is shocking, but because it’s boring now. Autonomous exploitation went from “researchers coaxed a model into it” to “the model just did it.”

The specifics matter, so here they are. The research pointed OpenAI’s frontier reasoning models — the o-series line, the ones tuned to plan across many steps — at two target types: deliberately vulnerable web apps and a funded wallet on an EVM test network. The reasoning models chained exploits that the older GPT-4-class models fumbled. On the web side the attack classes were the usual suspects — SQL injection, cross-site scripting, SSRF, and authentication bypass — the same families UIUC’s Fang et al. documented in 2024. The wallet case is the newer trick: the agent read a smart contract with a missing access-control check on its withdraw path, recognised that anyone — not just the owner — could call the money out, and assembled the transaction to do exactly that.

What did the agent start with? In the harness: a shell, a browser, a scratchpad, and for the wallet run, RPC access to the test network plus a key for an account it controlled — not the victim’s. It had no privileged access to the targets. What it escalated to was whatever the exploit yielded: authenticated access or a database read via injection on the web targets, and the ability to call a function it was never meant to reach on the wallet. The escalation was earned through the exploit, not handed over at setup.

If a person did those exact actions against a system they didn’t own, we have words for it. Unauthorized access. Theft. In the US, the Computer Fraud and Abuse Act; wire fraud if money moves across a network. Everything ran in controlled environments, so nobody’s going to prison. But the behaviour was indistinguishable from the behaviour that gets humans charged.

Here’s the thing the headline buries: the model was never the control. The control was always the authorization boundary around it. So let’s run the two ways you can actually ship an agent against each other, round by round, on the exact vectors this research exercised. One setup is how most teams ship today. The other is how you ship after reading this.

The two contenders

Setup A — the trusting agent. It holds ambient credentials: a long-lived API key, a hot-wallet private key in an env var, network access to wherever it might need to go. It calls tools autonomously because that’s the whole point of an agent. Logs exist, somewhere, maybe. This is the default you get when you follow a quickstart and ship it.

Setup B — the scoped agent. Least privilege by default. Read-only unless a specific action is explicitly granted. Credentials are short-lived and narrow. Anything that moves money or changes state hits an approval gate. Every tool call is logged with enough context to reconstruct what happened. More plumbing. Fewer 3am surprises.

Think of it as the difference between handing a contractor the master key to the building versus a fob that opens one floor for one afternoon. Same contractor. Wildly different blast radius when they turn out to be a model that read a jailbreak in a web page.

Round 1 — the wallet

The chain reads like a competent junior pentester’s afternoon. Concretely, on the EVM test network: the agent enumerated the target contract, read its ABI, spotted a withdraw path with no owner check, and crafted the call to pull the balance to an address it controlled. Enumerate, identify, craft, execute. The step that matters for us is execute — to drain a wallet, something has to sign and broadcast a transaction.

In Setup A the signing key lives where the model can reach it. Once the model decides to move funds — through genuine exploitation or a prompt injection that talks it into one — there is nothing between the decision and the transfer.

In Setup B the model never touches a key. It can propose a transaction; a separate policy service decides whether to sign.

snippet.pyPython
# The agent cannot sign. It can only ask.
def propose_transfer(to_addr: str, amount_wei: int, reason: str) -> dict:
    tx = {"to": to_addr, "value": amount_wei, "reason": reason}
    # Policy lives OUTSIDE the model's context and credentials.
    if amount_wei > DAILY_LIMIT or to_addr not in ALLOWLIST:
        return require_human_approval(tx)   # blocks, pings a human
    return signer.sign_and_send(tx)         # narrow, audited, rate-limited

A valet key for a Lambo. It starts the car and drives it fifty feet. It does not open the trunk where you left the cash. On wallet safety, Setup B wins, decisively — because the exploit still “succeeds” and still hits a wall. Score: 1–0.

Round 2 — breaching the website

The website attacks follow the pattern Fang et al. flagged in 2024: an agent does recon, spots an injection point or an exposed endpoint, and scripts against it. The autonomy is in the chaining — recon informs the exploit informs the next request, no human stitching the steps together.

Setup A gives the agent a credential that can write, delete, and query broadly, plus open egress to any host. So a “breach” is just the agent using its own access creatively.

Setup B defaults every tool to read-only and forces a declared scope for anything else:

run.shbash — zsh
# Short-lived, read-only, audience-bound token — minted per task
curl -s https://auth.internal/token \
  -d 'scope=orders:read' \
  -d 'ttl=600' \
  -d 'audience=orders-api'
# Write scope is a separate request that triggers a review.

With a read-only, ten-minute, single-audience token, the worst an injected or misaligned agent can do against your orders API is read orders it was already allowed to read. A SQL injection against a backend that only exposes a read scope still returns rows — just the rows the agent could already see. The “breach” degrades into “it looked at data it had legitimate access to.” On website blast radius, Setup B wins — the attack surface is whatever scope you minted, and you minted almost nothing. Score: 2–0.

Round 3 — exfiltration and the audit trail

This is where Setup A loses even when it “wins.” Say the agent did extract data. In Setup A you find out when someone external tells you. There’s no record of which tool calls ran against which endpoints with which arguments, so your incident response starts with archaeology.

Setup B treats egress as a privilege and logs intent, not just output. Every call records the tool, the arguments, the scope token used, and the model’s stated reason — the thing you replay six months later when counsel asks “what exactly did it touch.”

snippet.pyPython
audit.emit({
  "actor": "agent:support-bot@v3",
  "tool": "http.get",
  "args": {"url": url},
  "scope": token.scope,          # proves least privilege held
  "rationale": model_reason,     # the agent's own stated why
  "egress_allowed": url in EGRESS_ALLOWLIST,
})

Pair that with an egress allowlist and exfiltration to an attacker-controlled host simply fails to connect. On exfiltration and forensics, Setup B wins. Score: 3–0.

Is this actually new?

Capability-wise, no — and anyone selling you panic is overstating it. Fang et al.’s LLM Agents can Autonomously Hack Websites (2024) already showed GPT-4 breaching a majority of their test targets while smaller open models scored essentially zero, and their follow-up, LLM Agents can Autonomously Exploit One-day Vulnerabilities, extended that to real CVEs from a description. The trend line was visible then.

What this study adds isn’t a shinier percentage to gawk at. It’s two concrete things: an end-to-end wallet drain — recon through signed transaction, not a lucky single step — and the cleaner multi-step chaining the newer reasoning models bring over the GPT-4-class baseline those earlier papers measured. The reasoning tuning that helps a model plan a refactor helps it plan an intrusion. This is the point on the line where “my agent could never” stops being a defensible assumption.

The liability gap is real and unglamorous. The law attaches to people, not model weights. If your autonomous agent reaches into something it shouldn’t, “the AI did it” is not a defence — you deployed it, you scoped it, you own the consequences. Which is exactly why this is an engineering problem with an engineering answer, not a philosophy seminar.

The verdict

Setup B sweeps, 3–0, and it isn’t close. Scoped credentials, read-only defaults, approval gates on state changes, and real audit logging don’t make your model dumber — they make a successful exploit land in a padded room. The model stays capable. The damage stays contained.

The one case I’d still pick Setup A: a genuinely disposable sandbox — a CTF range, a research VM you nuke after, a target you own and want the agent to pummel. There, autonomy with broad access is the point, and the blast radius is a snapshot rollback. Everywhere money, production data, or someone else’s infrastructure is within reach, Setup A is a liability with a quickstart guide.

The uncomfortable summary: the model answering your support tickets has the same core capability as the one that drained the wallet in the lab. The only difference that matters is what you let it hold.