A security critique of the most popular open-source coding agent went viral on Hacker News this week, racking up hundreds of points within days. The target is OpenCode, the TypeScript-based coding agent now sitting at 161,000 GitHub stars. The critique walks through two buckets, "annoying things" and "alarming things", and while it is deliberately hard on the project, its practical value is real. This is the audit guide for anyone already running OpenCode, or planning to.
Why the critique matters
OpenCode is broadly described as the most popular open-source coding agent on the market. A tool this widespread becomes a target, and the critique argues its security posture has not kept pace with its adoption. The author is careful to say none of the findings qualify as a formal disclosure, describing OpenCode as fundamentally a web-stack tool for piping LLM output into your local shell. Every issue discussed lives in that pipe, and the outcome, in the author's words, was foregone from the start.
That framing matters for how you read the rest. The complaints are not about whether the model writes good code. They are about whether the harness between the model and your machine can be trusted with your filesystem and your shell.
Start with the permission model, the most actionable finding. When the agent tries to touch a file outside the project directory, you are asked to grant permission. The three answers are Yes, No, or Always. Notice the missing fourth option: there is no Never.
The issue is that permission given once is persisted. If you click Always on a python3 command, the approval is written to disk for future sessions. Approve python3 to run a harmless print statement and the same prefix can later read ~/.ssh/id_rsa, because the permission now covers the entire python3 prefix, not the single command you inspected. Decision fatigue does the rest: when every productive answer is "yes", developers eventually nod through a command they would never approve on their own.
The interaction with subagents is especially rough. If a spawned subagent tries to reach a script output under /tmp and you answer No, the subagent is killed and its context is lost. The practical pressure is to say Yes so partially completed work survives, which again teaches the tool to widen your approvals.
The bash filter cannot save you
The deeper problem is that OpenCode attempts to screen shell commands with textual filtering, and the critique argues that approach is unsound. Bash is parsed into a tree-sitter AST, paths resolved and validated. But the filter is trivial to sidestep, and the author shows several ways the same intent slips through.
A git checkout . can be denied by policy while an encoded Z2l0IHJlc2V0IC0taGFyZAo= piped through base64 decodes to git reset --hard and is allowed. A python3 subprocess call can run git checkout . without matching the git deny rule at all. The conclusion is blunt: textual command filtering fits no purpose except a false sense of security.
The permission prompts can also be bypassed outright. Certain bash and PowerShell commands are assumed to be side-effect-free and never trigger a prompt, including cd, chdir, popd, pushd and others, even under a permissions block set to deny. Commands like echo are not in the file-access list, so redirecting output can target outside the audited paths. A native approach, the author argues, would block the git executable and make .git read-only rather than sanitise free-form shell.
Remote-first by default is the core risk
Several alarming behaviours trace back to one design decision: OpenCode is remote-first. On a clean install, running opencode and typing a single letter plus Enter is enough to connect a remote model to a local shell with no user configuration. The default model URL is not a static part of the distribution; it is downloaded from models.dev at runtime, which is affiliated with the project.
The self-upgrade path draws scrutiny too. For anyone who installed through the curl-bash installer, the upgrade command fetches the installer script from the project site and pipes it straight into bash, production curlbash in action. The RCE history adds to the concern. One notable CVE involved OpenCode exposing an HTTP server on a well-known default port, letting any website you visited get user-level access to the system. The developers later disabled the server by default and promised to do better, but the issue was closed by a stale bot, which the author flags as part of a wider pattern of reports being silently aged out.
If you run OpenCode, here is a concrete hardening list from the findings.
- Audit every persisted permission before the next session and remove broad prefix approvals such as a blanket python3 or echo grant.
- Never approve Always for anything touching network, filesystem or your home directories; treat each approval as granted for the whole command family.
- Sandbox the bash tool in Docker or a container, and never hand it a root filesystem.
- Disable pruning and compaction if your sessions hit frequent prompt cache misses, and write explicit handoff notes to a fresh session instead of relying on the internal summariser.
- Know which installer you used; a curl-bash install means upgrades run unvetted scripts from the network.
- Keep the local HTTP server off unless you explicitly need it.
The critique closes on a wider point than OpenCode. Security should be the number one concern of every coding agent, and the right response is to build on native OS constructs such as Landlock or Seatbelt, rather than textually sanitising bash. The "just use Docker" defence is refuted: if everything you care about lives inside the container and the shell inside it is connected to the internet, little is actually protected.
For now the practical takeaway is straightforward. Popularity is not a security model, and an agent with shell access deserves the same scrutiny as any privilege-bearing software. Whether you harden OpenCode or switch, the integrity of the pipe between the model and your machine is your responsibility, not the tool's.
Comments