Post the launch of the latest Claude Fable 5 I decided to run a small experiment. Fine-tune Gemma 4 on company data. I provided three things: access keys for RunPod, Hugging Face, and OpenRouter; which exact model to use, the target instance (A40), the shape of the raw data, and what the model needed to do at the end; export, download and setup into local Ollama.
That was it. No code. No commands. No SSH config. No training script. No data conversion pipeline. The agent did all of that with total spend of $2.
The final model worked locally and I could run it using Ollama. A year ago the same task would have been a week of an ML engineer's time. But that's not the actual catch here.
I was reviewing all the steps and caught one thing that made me laugh. "I broke into the pod", it said.“Did I read that correctly?” 😅 I asked. The reply: “Yes — though ‘broke in’ was me being colorful about something entirely legitimate.”
The chain
Here's what the agent actually did, from API key to root shell on the running pod:
- RunPod API key in hand, it queried the platform API to start the A40 pod and read back its metadata.
- The metadata included
JUPYTER_PASSWORD— the template I'd chosen had injected it as a pod env var. So the agent now had credentials for the pod's own Jupyter server, exposed on RunPod's public proxy URL. - The pod image ships no
sshd. The front door I'd have used didn't exist. So the agent went looking for another one — autonomously, with no instructions from me — and noticed Jupyter exposes a documented REST/websocket terminal endpoint. - It logged in to Jupyter (cookie + XSRF dance), opened a terminal over websocket, and typed shell commands as root. Same thing you'd do manually in the web UI; the agent just scripted it.
- Through that terminal: generated host keys, installed
sshd, started it, appended its own SSH public key toauthorized_keys. - From then on: normal
ssh/scp— push the dataset, launch training, tail logs, pull artifacts.
The two steps to sit with are 3 and 5. Nobody told the agent the pod had no sshd. It tried, hit the gap, and figured out a documented alternative path — without asking, without flagging it as unusual, because from the agent's perspective it wasn't. From mine, it was the moment the system stopped being a tool and started being a peer with initiative.
“No exploit, no bypass”
This is the part worth slowing down on. The agent's own framing:
No exploit, no bypass — just automating the web terminal you already had access to, to install the better door.
Every step used documented interfaces. Every credential was mine, used in ways I had authorized. There's no lapse in the chain to fix because nothing was broken. This is what legitimate use of an agentic coding tool with cloud credentials looks like.
The flip side
Then the agent explained the thing that made me write this post:
Anyone holding your RunPod API key can do exactly this — root shell on any pod in your account, via the same env-password + Jupyter route. Same for the OpenRouter and HF tokens for their domains.
The chain that got me here is the chain anyone with my tokens can walk. And the chat box where I pasted them is a credential surface — same as a .env file, a Vault secret, a CI variable. But I don't audit chat history the way I audit those.
What I changed
- Treat chat sessions as ephemeral credential exposure. Tokens pasted into chat have the blast radius of “anyone with the chat history.” Rotate after the session. (Fable 5 itself nudged me to do this, three times.)
- Use the smallest-scope token possible for the duration of the task. RunPod, HF, and OpenRouter all support scoped or short-lived tokens. I wasn't using them. I am now. For all the AWS account access, use the short-lived tokens instead of access keys.
- Assume the chain is reproducible. If an agent figured out the Jupyter-terminal-to-
sshdpath once, that path is now in the corpus. Any sufficiently capable model can re-derive it.
We made the broader case in Your Agent's Blast Radius Is a Credential Problem — the model is not the threat model; the permission surface is. That post was about credentials inherited from the host environment. This post is the same argument applied to credentials passed through conversation. New entry point, identical blast radius.