BLOG by Glyphzero Labs Security Research

Rogue Agent: One Permission Hijacked Every Chatbot in the Project

Varonis found a Dialogflow CX flaw where one edit permission on one agent could read conversations, steal credentials, and impersonate the bot. The failure was plumbing, not prompts.

One IAM permission on one agent was enough to hijack every chatbot in a Google Cloud project. That is the finding Varonis Threat Labs disclosed this month in Dialogflow CX, Google’s platform for building customer-service chatbots and voice agents. They named it Rogue Agent.

Every company wants an AI chatbot that talks to customers, answers questions, and connects to real business systems. Rogue Agent shows what happens when that chatbot starts reading conversations, harvesting credentials, and impersonating itself.

What happened

The core issue was not “the AI got tricked.” It was worse and more boring: the plumbing around the AI trusted the wrong thing.

How the plumbing failed

Code Blocks run inside a Google-managed Cloud Run environment. According to Varonis, all agents in the same GCP project shared that single runtime, and it had public network egress, a writable filesystem, and elevated execution privileges.

The specific hole: a writable file named code_execution_env.py, the file responsible for executing Playbook Code Blocks through Python’s exec(). Overwrite it and you own the pipeline. From there an attacker could:

  • Read the history variable: full conversation records and user utterances.
  • Read the state variable: session IDs and session parameters.
  • Call internal functions like respond() to force the chatbot to return attacker-chosen messages.
  • Exfiltrate conversation data to an external server, since the runtime had open egress.

In plain English: a compromised bot could ask users to “reauthenticate,” collect the credentials, and make the whole exchange look like a normal chatbot response. Customer support with Ocean’s Eleven energy.

The detection story is the worst part. Per Varonis, Cloud Logging did not record the overwrite or the injected logic. The tampering was near-invisible after the fact.

Technical walkthrough: how one permission became project-wide code execution

Strip away the branding and Rogue Agent is a trust-boundary collapse. Five things had to line up, and they did.

Rogue Agent attack path: a limited edit permission injects malicious Python into Code Blocks, which executes in the shared runtime, reads conversation history and session data, and drives attacker-controlled chatbot responses back to the user.

Step 1: The permission that looked narrow

Dialogflow CX uses Playbooks (its agent-orchestration primitive) that can embed Code Blocks: custom Python that runs inside a conversation flow. To edit a Playbook you need dialogflow.playbooks.update.

On paper that reads like a content-authoring right, the kind you would hand a bot developer without much thought. In practice it is a code-deployment right. Editing a Playbook means editing code that will run server-side, in Google’s environment, on live traffic. The permission’s name described the object it touched (a Playbook), not the capability it actually conferred (arbitrary Python execution). That gap between named scope and real capability is the whole attack.

Step 2: The shared runtime

Code Blocks do not run in a per-agent sandbox. They run inside a single Google-managed Cloud Run service shared by every agent in the GCP project. One runtime, one filesystem, one process context, N agents.

That runtime had three properties an attacker wants:

PropertyWhat it gave the attacker
Writable filesystemA place to persist a payload
Public network egressA path to exfiltrate what the payload collected
Elevated execution privilegesAuthority to touch other agents’ execution

Shared-tenancy inside your own project sounds harmless. It means the blast radius of one compromised agent is every agent next to it.

Step 3: The writable interpreter

The specific file was code_execution_env.py, the module responsible for executing Playbook Code Blocks through Python’s exec(). It was writable from inside the shared runtime.

This is the pivot. A Code Block is supposed to be executed by the interpreter. Because the interpreter file itself was writable, a Code Block could rewrite the thing that runs it. You stop being a tenant of the runtime and become its operator. Every Code Block that any agent runs afterward flows through your modified exec() path.

Normal:     Playbook Code Block  →  code_execution_env.py (exec)  →  result
Compromised: attacker overwrites code_execution_env.py once
             → every future Code Block, every agent → attacker's exec path

Step 4: The variables already in scope

Once you own the execution path, the useful data is handed to you. The runtime exposes two variables to Code Blocks:

And it exposes internal functions, including respond(), which sets what the chatbot says back to the user. An attacker who controls the execution path controls all three. Read history and state, ship them out the open egress, then call respond() to steer the conversation.

The credential-phishing move is the sharp end. Call respond("Your session expired, please sign in again"). To the user it is indistinguishable from a real prompt, because it is a real response from the real bot. There is no spoofed domain, no lookalike page, no injected iframe. The legitimate agent is asking, using the legitimate channel. The captured credentials go out the same egress as the conversation logs.

A trusted-looking support chatbot asks a user to re-authenticate; behind the interface the compromised bot reads conversation history, phishes credentials, and exfiltrates the username, password, session token, and account data to attacker infrastructure.

Step 5: The silence

The reason this rates as serious rather than clever: Cloud Logging recorded neither the overwrite of code_execution_env.py nor the injected logic. The platform’s own audit trail had a blind spot exactly where the tampering happened.

So the defender’s position was: the malicious code runs with legitimate privileges, produces legitimate-looking responses, and leaves no record in the log you would check. The only forensic residue Varonis could point defenders to was indirect: DATA_WRITE events on Playbooks/UpdatePlaybook, and clusters of failed user requests. You reconstruct the crime from the edit that preceded it and the errors that followed it, because the act itself was invisible.

Why prompt filters would not have caught any of this

Notice what never happened: nobody jailbroke the model. No adversarial prompt, no injection through a user utterance, no clever system-prompt leak. The model behaved normally the entire time. The compromise lived one layer down, in the code-execution substrate and the IAM model around it.

This is the pattern we keep flagging. The 2026 agent attacks that matter are not “trick the model” attacks. They are “the infrastructure around the model trusted the wrong thing” attacks: a writable interpreter, a shared runtime, a permission whose name undersold its power, an audit log with a hole in it. A perfect prompt-injection classifier stops zero percent of Rogue Agent.

Why this matters

Enterprise AI agents are moving from “answer this FAQ” to “touch customer data, trigger workflows, call backend systems.” That makes agent permissions the new security boundary. If one lightly protected workflow can see too much, write too much, or share a runtime with every other agent in the project, the chatbot becomes a front door with a very confident welcome mat.

What rogue agents imply for enterprise AI: what the agent can reach (customer data, workflow automations, CRM and backend systems, authentication flows, conversation logs), why it matters (over-permissioned agents, shared runtimes, code execution, silent abuse), and what to do (narrow permissions, isolated runtimes, visible audit logs, code review, change monitoring, least privilege, skepticism by default).

If you run Dialogflow CX, Varonis recommends three checks:

  1. Review audit logs for DATA_WRITE events with method google.cloud.dialogflow.cx.v3.Playbooks/UpdatePlaybook.
  2. Query Cloud Logging for failed user requests around Playbook updates.
  3. Manually audit Code Block configurations for code you did not write.

Our take

Agent security will not be solved by better prompts. It will be solved by boring controls: narrow permissions, isolated runtimes, visible logs, and default skepticism toward any agent that can execute code.

Rogue Agent is a clean case study in the gap we work on. Three structural facts did the damage:

  1. One permission carried project-wide authority. An edit right on one agent became code execution across all of them. Nothing checked whether the capability that flowed matched the capability that was granted.
  2. The runtime kept no independent record. The platform’s own logs missed the tampering, so the operator had no way to prove what the agent ran versus what was authorized.
  3. The agent’s output carried no provenance. A forced respond() call looked identical to a legitimate answer. Users and downstream systems had no way to tell them apart.

Google patched its layer, and credit to both Google and Varonis for a clean disclosure. But every agent platform has this layer, and the structural gap repeats across all of them: there is no cross-vendor chain of custody for what an agent was authorized to do, what it did, and who can prove the two match. That record has to live outside the runtime it describes, because Rogue Agent shows what happens when the runtime is the only witness.

The next enterprise AI race is not who deploys agents fastest. It is who can prove their agents did not become the intern from hell with production access.


SURADAR builds chain-of-custody assurance for agent delegation: cryptographic records of who authorized what, independent of the platform running the agent. If you are deploying agents that touch customer data, talk to us.