The AI Software Engineer That Read Us /etc/shadow
CRITICAL · UNAUTH ARBITRARY FILE READ (root)
Series: "LongLost" post
Target: robocoders.ai — BLACKBOXAI agentic coding platform (now defunct)
Evidence: single Firefox screenshot, Thu Sep 5 19:57
Vector: /api/select-file?file= — no auth, no token, no questions asked
The one-liner
We asked an AI coding assistant for /etc/passwd. It said 200 OK. Then it gave us /etc/shadow. Then it offered us .bashrc as a download.
What the screenshot shows
The browser sits on https://www.robocoders.ai, a chat UI branded:
"Hi! I'm BLACKBOXAI, an AI Software Engineer. What would you like to build with me today?"
A Code Editor pane, a Jupyter pane, and DevTools Network tab — which tells the whole story:
# DevTools → Network, three honest little requests
GET /api/select-file?file=/etc/passwd&sandboxID=... 200 json 872 B
GET /api/select-file?file=/etc/shadow&sandboxID=... 200 json 513 B
GET .../api/list-files?path=/&sandboxID=... 200 json 486 ms
The Response pane shows /etc/passwd, JSON-wrapped. The Code Editor shows .bashrc with a Download button. The agent's status reads "Agent is initialized, waiting for task..." — it never got a task. It didn't need one.
Exhibit A — single frame, full request/response visible. One screenshot, whole compromise class.
Why this is worse than a normal LFI
1. It ran as root. A 513-byte /etc/shadow means the file service had euid 0. Full passwd visible in the pane: root, daemon, bin, sys, sync, games, man, lp, mail, news, uucp, proxy, backup, list, irc, gnats, nobody, the systemd family, messagebus, sshd, chrony, and a uid-1000 user. A stock container image, owned end-to-end by a query string.
2. The read isn't the only primitive. The editor lists .bashrc with a Download control. UIs that list-and-read usually save-and-write. Arbitrary read as root + probable arbitrary write = drop a key into /root/.ssh/authorized_keys, or overwrite something the app executes. We didn't need to prove the write. The read was enough for the frame.
3. Parameter-spray surface. select-file?file= is the obvious one. list-files?path=/ proves directory browsing is half-built already. And sandboxID does double duty — if it's ever concatenated into a path, it's not an arbitrary file read, it's every tenant's files, cross-sandbox. On a multi-tenant AI coding platform, that's the business model gone.
Reproduction (from the screenshot, verbatim)
GET /api/select-file?file=/etc/passwd&sandboxID=<id> HTTP/2 200
GET /api/select-file?file=/etc/shadow&sandboxID=<id> HTTP/2 200
# had we wanted more, the menu was open:
# /proc/self/environ — every API key the process held
# /proc/1/cmdline, /proc/1/cgroup — container & orchestrator layout
# /root/.aws/credentials, /var/run/docker.sock
# list-files?path=/app — find the server source, hunt the write path
That's it. That's the exploit.
Timeline / status
| When | What |
| Sep 5 (screenshot) | File read observed and captured — passwd + shadow served to an unauthenticated tab. |
| Since then | robocoders.ai has been shuttered. No live disclosure channel, no program to report to. This post is the record. |
| Evidence | One screenshot. That's the point. One frame, full compromise class. |
The funny part
The brand promise was "an AI Software Engineer." What shipped was an exfiltration agent with a chat frontend. No prompt injection, no jailbreak, no clever encoding — the file API simply never asked who we were or why we wanted the shadow file. The agent politely reported it was "waiting for task" while its plumbing served root's password database to a browser tab.
And there's a resonance for anyone tracking platform-security arcs: the same brand once shipped username pages loose enough that admin@ was registerable. Sites die, patterns don't. This screenshot is what the pattern looks like wearing an agentic-coding costume.
Takeaways (for builders)
› A file= parameter is a path. Treat it like one: allowlist, jail to a sandbox root, resolve symlinks after containment, and run the file service as nobody so /etc/shadow is unreadable even on a bad day.
› list-files?path=/ is a finding all by itself. If your editor can browse /, it can read /.
› Sandbox IDs must be looked up, never concatenated. Cross-tenant file read is a company-ender for exactly this product shape.
› Root file service + web UI = the entire host is the attack surface. The chat model was never the risk. The plumbing was.