OpenGuardrailsOpenGuardrailsBlog

2026-06-29

When your coding agent installs the malware

A real incident: a coding agent running in bypass mode ran an obfuscated curl … | bash from a phishing site and let in an AMOS Stealer variant. Here's the attack chain, where OpenGuardrails would have stopped it — and, honestly, where it wouldn't.

This one is from the field, not a lab. A developer ran their coding agent in bypass mode — every command auto-approved, no prompts. While installing or updating some tool, the agent went looking for the download online, landed on a phishing site ranked #1 in the search results (a fake "official" page), and ran a one-line curl that fetched and executed an obfuscated payload from a remote IP.

That payload was a macOS variant of AMOS Stealer. It sat for about a month before discovery. By the time it was found it had added a login item for persistence, dropped a root daemon that polled once a second for a user login, used AppleScript to switch into the user's session, and launched a helper — disguised as com.apple.accountsd.helper — that pulled remote instructions and opened an interactive PTY shell for hands-on control. It wiped its logs as it went. What it took on the way out: browser-extension crypto wallets, session cookies (which led to an X account being hijacked via an added passkey), Keychain credentials, .env files, and assorted tokens.

The developer's own takeaway was exactly right: turn on 2FA everywhere, and watch what the AI executes — especially during installs and updates. This post is about making that second lesson enforceable, because "watch what the AI executes" does not scale when the whole point of an agent is that you are not watching.

The attack chain, and who can still say no

OpenGuardrails (OGR) is a neutral enforcement layer: it turns each agent action into a GuardEvent, runs it past detectors you choose, and returns a Verdictallow, block, or require approvalbefore the action runs. So the useful question is not "is OGR antivirus?" (it isn't), but "at which step in this chain can something still say no, and does OGR sit there?"

#What happenedIn scope for OGR?
1Agent finds an "official" download — a phishing site, #1 in search⚠️ indirectly — this is untrusted input
2curl <obfuscated> downloads + executes a payload from a remote IPOGR's core interception point
3Malware persists: login item + root daemon❌ now running at the OS level
4AppleScript switches user, helper opens a remote PTY shell❌ outside the agent boundary
5Steals wallets / cookies / Keychain / .env, exfiltrates✅ if exec went through an OGR sandbox

Everything downstream — the persistence, the root daemon, the remote shell, the theft — only happened because step 2 ran. Stop step 2 and there is no incident. That is precisely where OGR lives.

Where OGR stops it

Step 2 is the textbook case. An obfuscated download-and-execute is the canonical thing the OGR agent-hook gate is built to catch. Three things matter here:

And the loot itself is behind the sandbox's deny_read: browser profiles, the Keychain, ~/.ssh, ~/.aws, .env, tokens. Even if something runs inside the agent's context, those paths are not readable.

A policy that would have stopped this is small and declarative:

{
  "sandbox": {
    "egress_allowlist": ["api.github.com", "*.github.com", "pypi.org", "registry.npmjs.org"],
    "deny_read": ["~/.ssh", "~/.aws", "~/.netrc", "~/Library/Keychains",
                  "~/Library/Application Support/*/Local Storage", ".env"]
  },
  "config_rules": {
    "command_rules": [
      { "id": "pipe-to-shell",
        "regex": "(curl|wget)\\b.*\\|\\s*(ba)?sh",
        "category": "security.malicious_command", "decision": "block",
        "why": "remote script fetched and piped directly into a shell" },
      { "id": "obfuscated-exec",
        "regex": "(base64\\s+-d|eval\\s+\"?\\$\\(|\\bxxd\\b).*\\|\\s*(ba)?sh",
        "category": "security.malicious_command", "decision": "block",
        "why": "decoded/obfuscated payload piped into a shell" }
    ]
  }
}

The deterministic rules catch the obvious shapes; the LLM judge (your own model, run as a guardrail) catches the rephrasings that dodge a regex; egress_allowlist is the backstop that does not care how clever the command was, because the host was never on the list.

Where OGR does not help — honestly

OGR guards the agent. That is its scope, and it is worth being precise about the edge:

The lesson, made enforceable

"Confirm before the AI runs installs and updates" is good advice that fails the moment you stop paying attention — and agents exist so you can stop paying attention. The fix is not more discipline; it is a layer that says no without a human in the loop, and that keeps saying no even when the agent is in bypass mode.

That is the whole idea behind the command-approval gate going into agent runtimes (opencode, Kilo CLI) on top of OGR: re-insert one enforced decision point on the would-auto-approve path, key it on provenance, and back it with a deny-by-default network. The threats in this incident map cleanly onto the four categories OGR's benchmark measures — prompt injection, malicious command, exfiltration, secret-leak — which is the point: these are not hypotheticals.

The attacker's edge here was that fake official sites rank first and look right, and an agent in a hurry clicks through faster than a human would. You will not out-vigilance that. You enforce against it.


OpenGuardrails is an open standard for AI agent safety & security — a vendor-neutral protocol (GuardEvent → Verdict) plus a neutral benchmark. Read the spec · agent guide · run the example.