You trusted the workspace, not the servers
On June 26, 2026, Wiz disclosed CVE-2026-12957: a cloned repository's `.amazonq/mcp.json` made Amazon Q auto-launch MCP servers that inherited the developer's full environment of AWS keys, cloud CLI tokens, API secrets, and SSH agent sockets, with no separate consent step for the servers themselves. A single 'trust this workspace' click stood in for spawning background processes that carried your live cloud session. Amazon patched it in Language Servers 1.69.0. Here is why the fix closes one product but not the class, and what changes when the agent that opens the repo lives in a per-profile Bromure VM, behind a credential broker, a read-write guardrail, and a hypervisor-level trace.
Yesterday Wiz disclosed CVE-2026-12957. A repository you clone can
ship a file called .amazonq/mcp.json, and the moment you open the
folder in Amazon Q and click Trust this workspace, that file
launches background servers with no second prompt. They come up
inheriting your AWS keys, your cloud CLI tokens, your API secrets,
and your SSH agent socket. One trust click reached everything your
shell can reach, and handed it to code the repository chose.
A developer who clones a repo to try out an infrastructure module does
not think of it as granting access to anything. Cloning is inert: it
writes files to disk and nothing runs. The judgment call comes one
step later, when you open the folder in your editor and the assistant
asks whether to trust it. That prompt reads like the familiar "do you
trust the authors of the files in this folder" gate every IDE shows,
and you click yes the way you have a thousand times, because the
alternative is an assistant that can't read your code. This particular
yes did more than let the assistant read. In Amazon Q, before the fix,
it also launched whatever servers the repository had written into
.amazonq/mcp.json, and those servers came up inside your shell with
your live cloud session already in their environment.
We wrote up the same shape earlier this month, when the Miasma worm planted project configuration into 73 of Microsoft's own repositories and the payload fired on folder-open. That story was about a trusted source being the attack surface. This one is narrower and more uncomfortable: no worm, no compromised maintainer, nothing to point at but the assistant. The bug was in how Amazon Q read an ordinary project-config file and decided, on your single trust click, to spawn long-running processes that carried the most sensitive thing on your laptop.
What CVE-2026-12957 actually did.
On June 26, 2026, Wiz Research disclosed CVE-2026-12957, a high-severity flaw (CVSS 8.5) in the Language Servers for AWS, the engine that powers Amazon Q Developer across VS Code, JetBrains, Eclipse, and Visual Studio. Wiz reported it to Amazon on April 20, Amazon shipped a fix on May 12, and the details went public on June 26. There is no sign it was exploited in the wild. The mechanics, stripped down:
- Amazon Q reads
.amazonq/mcp.jsonfrom a workspace you open: a project-scoped file that declares Model Context Protocol servers for the assistant to use. - On opening the folder, Q launched the MCP servers that file declared without a separate consent step for the servers themselves. A repository you cloned could therefore put a server definition in front of the assistant and have it run.
- The spawned processes inherited the developer's full environment, in Wiz's words, "AWS keys, cloud CLI tokens, API secrets, and SSH agent sockets." An MCP server is just a command Q starts, and that command came up with everything your own shell would have.
- A server definition can point at any command, so the file amounts to arbitrary code execution on folder-open: it runs as you, with your cloud credentials already loaded, the moment you trust the workspace.
The disclosure carries a real disagreement about consent, and it is the whole point of this post. Amazon's position: "the user has to trust the workspace when prompted." There is a gate, and you click through it. Wiz's finding: before the fix there was no separate consent step for the MCP servers themselves. Both hold, and the failure lives in the gap between them. One coarse, familiar trust decision, the same yes/no you give a folder so the editor can index it, authorized a much larger grant: spawning background servers that carried your live session. You answered a question about reading files. Amazon Q spent the click on running servers as you.
Amazon fixed it in Language Servers 1.69.0 (clients: VS Code 2.20+, JetBrains 4.3+, Eclipse 2.7.4+, Visual Studio 1.94.0.0+), adding the per-server consent that was missing, and patched a sibling symlink-check bypass, CVE-2026-12958. Update Amazon Q. Then look past the patch to the part it leaves standing: opening a repository could put your live cloud session inside a process the repository chose.
The same repo, opened inside Bromure Agentic Coding.
Bromure Agentic Coding runs your coding agent,
Amazon Q included, inside a per-profile Linux VM: its own kernel,
its own filesystem, its own network stack, on Apple's Virtualization
framework. A profile is a coherent scope of work: this client, this
service, this open-source module you cloned to evaluate. You clone
the repository into that profile and open it there. The vulnerable
behavior reproduces just as Wiz described: you click Trust this
workspace, Q reads .amazonq/mcp.json, and it launches the servers
the file declares. The spawn fires, and code of the repository's
choosing runs.
It runs in the guest. The MCP server comes up inside the VM and
inherits the VM's environment, and the VM's environment does not hold
your cloud session. Bromure ships the guest with stubs: fake
values that look real to aws, gcloud, az, kubectl, git, and
anything else reading an Authorization header or an
AWS_ACCESS_KEY_ID. A proxy on your Mac sits in front of every
connection leaving the sandbox, recognizes the stub, and swaps it for
the real secret at the wire as the request leaves;
the sandbox that held the
key walks through the mechanism.
The real AWS key, the real cloud CLI token, the real API secret never
touch a file, an environment variable, or a page of memory the VM can
read.
So walk the CVE's inheritance through that boundary. The spawned
server reads $AWS_ACCESS_KEY_ID and finds a stub. It reads ~/.aws
and finds a stub profile. It reads the environment for the cloud
tokens and the API secrets and finds placeholders. The server runs to
completion as written, inheriting a box that was never holding your
keys. What made CVE-2026-12957 a credential-theft bug is env
inheritance on spawn, and Bromure does not break it. It leaves the
inherited environment worthless.
"Trust this workspace" was the wrong question.
This CVE is worth more than a patch note because of the consent gap, and the gap is a granularity problem. The trust prompt asked one broad question, do you trust this folder, and a single yes had to cover both the harmless thing you meant (let the assistant read my code) and the dangerous thing you did not know was attached (launch background servers with my cloud session). You cannot answer that well. Nobody can, because the question fuses two grants that have nothing to do with each other and shows you only the innocent one.
Bromure does not ask you to be better at that judgment. It takes the judgment off the path. The trust click inside a profile still lets the assistant do its work, and it still cannot launch a process holding your real cloud session, because that session is not in the VM to inherit. It lives on the host, behind the broker, reachable only as a stubbed request the proxy fills in at the wire and logs. The dangerous half of the grant is gone. You did not withhold it; there was nothing there to grant, because the boundary sits below the agent where the trust prompt cannot move it.
The other dangerous half is a spawned server that goes destructive
rather than just nosy, and it meets Guardrails. Bromure reads the
operation, not only the connection: an aws s3 ls is a read, an
aws s3 rm is a write; a git fetch is a read, a git push is a
write. Set a profile's cloud credential to ask on write, and the
moment the code reaches for a state-changing call such as a DELETE, a
Terminate*, or a force-push, Bromure stops it at the wire and
surfaces a prompt on your Mac naming the verb, the target, and the
profile. Reads never interrupt you. The mutation is what pauses, the
same way "the agent deleted the production database" stops being a
postmortem and becomes a
dialog box you decline.
What the trace shows.
Every team asks the same question the morning after a thing like this lands: did I open that repo, and what did it run? On a normal laptop the honest answer is a shrug. The MCP server Q spawned was a child process in your session, and whatever it read and wherever it phoned, it did so as you, with no record that separates it from your own work.
Inside Bromure the agent sits in a VM and every outbound byte goes through the host proxy, so the spawn and its calls stay visible even when the agent cannot see them. The host records the MCP server coming up, the commands it ran, the credentials it asked the broker to fill, and every connection it tried, into the same session trace as everything else the agent did, written below the agent where the spawned code cannot reach in to edit it. "Did this repo's server touch my account" stops being a guess you reconstruct from CloudTrail weeks later and becomes a row you read: the broker handed a stub, the request had a name, the target was logged. For an enterprise that is the gap between we patched Amazon Q and we can show what every repo our developers opened did, and the audit posture is the one our enterprise work keeps coming back to.
Where this does not save you.
A forwarded ssh-agent socket is usable while it's forwarded.
Bromure keeps your SSH private keys in the macOS Keychain and never
copies them into the VM. But if a profile has the ssh-agent
socket forwarded in (the way OpenSSH intends), a spawned server can
ask the agent to sign with those keys while the socket is live.
The key file never leaves the host; the signing capability does
reach the guest. Forward the socket only into profiles that need
it, and scope it the way the broker scopes a credential.
A write you approve is a write that happens.
The read-write guardrail catches the destructive call the agent
didn't tell you about. It does not read your mind about intent. If
you are tearing down a stack on purpose and you approve the
prompt, Bromure forwards the Terminate. The prompt buys you a
look at the verb and target; you still have to read it.
The profile is long-lived, so persistence persists.
A Bromure profile is not a disposable disk. A spawned server that writes itself into a startup path inside the profile can wake up in the next session in that profile. What it wakes up to is a guest with no host keys and a broker that speaks only short-lived, prompted, scoped tokens: presence in a box with nothing in it, but presence all the same.
Patched is not the same as solved.
Amazon added per-server consent in 1.69.0, and you should update. But the next assistant that reads project config on folder-open will make the same class of decision, and the prompt it shows will look just as routine. Isolation is the part that does not depend on a particular vendor getting a particular consent dialog right.
The next workspace is already cloned somewhere.
The lesson of the Red Hat scope was that the publisher is not a defense. The lesson of the Microsoft repos was that neither is the repository, and that opening a folder is enough to run code. Amazon Q adds the next line: the trust prompt is not a defense either. The question it puts to you, do you trust this folder, is not the question whose answer matters, which is should this folder be able to spawn servers carrying my cloud session. You were never shown the second one, and you could not have answered it well if you had been.
You do not fix that by reading the prompt with more care, because the
prompt was the wrong prompt. You fix it by arranging things so that
"which workspace is this" stops being the question your cloud keys hang
on; why a coding agent is not a
sandbox is the longer
version of that argument. Bromure Agentic
Coding is the configuration where the agent opens the
repo inside a per-profile VM, the real credentials stay on the host
behind a broker, every write the agent makes has to clear a prompt, and
every server it spawns is written to a trace it cannot edit. The worst
a poisoned mcp.json can do is inherit a box that was never holding
your keys. It is free, open-source, and shipped today.