Skip to main content
A coding agent on a VM is risky for a specific, well-understood reason. To do its job it needs three things at once: access to your secrets and source, the ability to read untrusted content (issues, PRs, web pages, dependency docs), and the ability to reach the network. Any one of those is fine. All three together is the problem — a prompt-injected agent can read a secret, be told to leak it, and have a channel to send it out. This is Simon Willison’s lethal trifecta: an agent that simultaneously has (a) access to private data, (b) exposure to untrusted content, and (c) the ability to communicate externally is exposed to data theft, and prompt-injection detection is too unreliable to depend on. Remove any one leg and the data-theft class collapses. Meta’s Agents Rule of Two makes it a rule: an agent session should satisfy at most two of these three — processes untrusted input, accesses sensitive data, or can communicate externally; if it genuinely needs all three, keep a human in the loop. Google DeepMind’s CaMeL (paper: Defeating Prompt Injections by Design) pushes the same principle into a capability-enforcing interpreter. This page maps each leg to the controls you have in Murmur — what you decide, what you configure, and what the platform enforces underneath so you don’t have to.

Leg 1 — Secret access

You decide which credentials an agent can reach, and Murmur guarantees those credentials never leave the VM in usable form. What you control:
  • Scope secrets to where they’re needed. Tenant secrets are only injected into the workspaces whose secret_refs list them — keep a secret out of a workspace and no agent there ever sees it. Pass one-off credentials as spawn-time secrets (murmur spawn -e) that live only for that single agent.
  • Run agents under a narrowed identity. A service profile gives an automated agent its own bot credentials and its own access grants, so a Flight or bot gets exactly the access it needs instead of inheriting a developer’s full scope.
  • Secret values are write-only. The API never returns a stored secret value — murmur secret ls shows names only, and a value can’t be read back once set. RBAC governs who can manage secrets (secret.create, secret.edit, secret.delete) through roles and bindings; which agents actually receive a secret is set by the workspace’s secret_refs, above.
What the platform enforces for you:
  • End-to-end encryption to the specific VM. Credentials are encrypted at rest under your tenant’s KMS key, re-sealed with NaCl box to the target VM’s ephemeral key, decrypted only in memory, and destroyed with the VM. See Encryption.
  • Per-tenant isolation. Each tenant has its own KMS key, and AAD binding makes a secret encrypted for one tenant (or developer) impossible to decrypt for another.
  • Secret scrubbing on the way out. As a backstop, murmur-vm redacts any session-event field or task response that exactly equals an unsealed profile secret, replacing it with [REDACTED] before it leaves the VM — so an agent that is tricked into echoing a credential can’t ship it back through the control plane.
    Scrubbing is exact-match only — it catches a string equal to a secret in its entirety, not a secret embedded in a larger string or transformed (e.g. base64-encoded). It is a conservative backstop, not a guarantee, and it does not inspect traffic the agent sends directly to the network — that’s the egress leg.

Leg 2 — Trusted input

A coding agent has to read untrusted content — that’s the job — so you can’t stop injected content from reaching it. What you can control is who is allowed to steer the agent: whose instructions it will act on. Murmur gives you two layers of this.

Who in your org can drive an agent (RBAC)

Steering a running agent — queueing follow-ups, updating its task list, killing it — requires the agent.edit permission; acting as an agent requires agent.assume. You grant these through roles, groups, and tenant-bindings, and you can scope them with name patterns so a developer drives only their own agents. An org member without agent.edit on an agent simply cannot send it instructions.

Which external identities can steer an agent (steering policies)

The riskier input path is events from outside your org — a PR comment, a review, or an issue/PR that opens and triggers a Flight. Murmur gates these with steering policies, so a stranger commenting on a public PR can’t drive your agent. A steering policy sets a minimum tier of trust for the event’s author, plus optional allowlists of specific usernames:
TierWho may steer
OPENAny author
COLLABORATORSOwners, members, and repo collaborators (write/triage)
MEMBERSOrg owners and members
ALLOWLIST_ONLYOnly the named allowlists (plus a user-owned agent’s own owner)
You attach a policy in two places, and the narrower of the two always wins:
  • Per repo — set a steering policy on a repo’s config to govern events coming from that repo. If you set nothing, Murmur auto-selects by repo visibility: public repos default to COLLABORATORS, private repos to OPEN (every commenter is already org-vetted).
  • Per service profile — set a policy on a service profile to gate every agent that runs under it, regardless of which repo the event came from. A locked-down profile can’t be loosened by a permissive repo.
Allowlists (named sets of usernames, scoped by identity provider) let you admit specific trusted outsiders or approved bots — e.g. dependabot[bot] — without opening the tier for everyone.
Enforcement is fail-closed and auditable: an event whose author fails the effective policy is recorded on the agent’s timeline as BLOCKED and is never delivered — no follow-up, no checklist task, no wake, no Flight spawn. The agent’s own owner can always steer their own agent.

Leg 3 — Egress control

Egress control — restricting where an agent VM can send traffic — is the highest-leverage leg, because it’s the one you can cut on a coding agent without taking away its job. In Murmur, egress control is a feature of customer placements. When you run agents in a customer placement, each VM boots in your own GCP project or AWS account, on your subnet — so the network the VM lives in is yours, and you apply whatever native egress controls your cloud provides. There’s nothing Murmur-specific to learn:
  • VPC firewall rules / security groups that default-deny outbound and allow only the destinations you choose
  • A forced egress proxy, NAT gateway, or VPN
  • DNS-resolution allowlists and SNI/Host filtering at a managed firewall
  • Cloud-native network policy, flow logs, and your own incident response
Because the VM is in your account, you own the network path end to end — your rules, your routes, your egress, your logs. If a VM misbehaves it’s in your project: you can capture logs, snapshot the disk, or shut it down directly. See Customer placements for setup and Placements for the concept.
On the default platform placements, agent VM egress is not restricted — VMs can reach the public internet. If your threat model requires cutting the egress leg, run your agents in a customer placement and apply your own network controls there.