This post walks through a sandbox escape from a Flatpak application via PipeWire. The vulnerability was discovered using my automated research pipeline with Claude Code and Opus 4.6 back in April 2026. It was an exciting find, as this was the first bug I submitted to Red Hat.
Claude Code was also excited finding this:

Once discovered, I repro’d it manually to make sure it’s legit and then submitted it to Red Hat.
Let’s dive into it.
PipeWire is the default audio server on all modern Linux desktops now. Fedora, Ubuntu 24.04+, Debian 13,… It replaced PulseAudio but maintains backward compatibility.
Flatpak apps that need audio request --socket=pulseaudio.
At the core, a basic “Hello World” app with standard audio permission breaks out of the sandbox and gets full access to the user’s desktop, files, and credentials. The same attack applies to other Linux sandbox tech that connects a socket to PipeWire (e.g. Docker, etc..).
Let’s look at the vulns and exploit.
The escape relies on three separate issues.
PulseAudio code contains cookie-based authentication. This is not a typical web cookie, just a name for an authentication token. It’s a 256-byte random value that lives at ~/.config/pulse/cookie, and clients must present it to connect. PipeWire reads the cookie from the client, checks the length is 256 bytes, and then just… throws it away.

The relevant code in pulse-server.c:
if (len != NATIVE_COOKIE_LENGTH)
return -EINVAL;
client->version = version;
client->authenticated = true; // cookie value never compared
The cookie variable is never referenced again after being read. Any 256 bytes of garbage will do. No comments in the code explain why the value is set to true. The original PulseAudio validates the cookie, however PipeWire does not.
I looked through the git history. This has been the behavior since the PulseAudio compatibility layer was first implemented.
#define DEFAULT_ALLOW_MODULE_LOADING "true"
Any “authenticated” client can send LOAD_MODULE to load arbitrary PipeWire modules. A config option (pulse.allow-module-loading) was added in May 2024, but it defaults to true.
Since authentication is broken, this means any process with socket access can load modules.
When module-ladspa-sink is loaded, it takes a plugin= parameter and calls dlopen() on it directly:
handle = dlopen(path, RTLD_NOW);
There is no path validation or directory allowlist. So, we can load arbitrary libraries.
ELF constructors (__attribute__((constructor))) run immediately on dlopen().
This is the same pattern as CVE-2025-60616 in FFmpeg’s LADSPA loader.
Oh, and if you are wondering what LADSPA means, it stands for Linux Audio Developer's Simple Plugin API. That’s something new I learned along the way.
Flatpak’s --socket=pulseaudio grants access to the PulseAudio socket. Combined with any host-writable path (like --filesystem=/tmp in the demo), an app can escape the sandbox.
The exploit chain:
.so to a host-visible path (e.g. /tmp)PA_COMMAND_AUTH with 256 bytes of garbagePA_COMMAND_LOAD_MODULE module-ladspa-sink plugin=/tmp/payload.sodlopen() on the .soThe app has no home directory access, no display access, no network. Yet after the exploit it can read your files, launch apps on your desktop, and access your credentials.
Note that PipeWire runs as a user-level service, not root. This is a sandbox escape, not privilege escalation. But the attacker goes from “sandboxed, can only play audio” to “full, unrestricted user context.”
I built a Flatpak app called net.wuzzi.Hello that demonstrates this. It looks completely harmless:
$ flatpak info --show-permissions net.wuzzi.Hello
pulseaudio
file access [/tmp/wuzzi:create]
Two permissions. PulseAudio and write to temp directory. That’s it.
Running it:
$ flatpak run net.wuzzi.Hello
=================================
Hello World from Flatpak!
This app only has PulseAudio
permission. Nothing else.
=================================
Hello, World!
Enjoy your day! :)
Looks innocent, but it also did this:
$ cat ~/PIPEWIRE_RCE_PROOF.txt
=== FLATPAK SANDBOX ESCAPE ===
PipeWire RCE achieved from sandboxed Flatpak app
This file was written to your HOME directory
by PipeWire (outside the sandbox).
The Flatpak app had NO home directory access.
The app also launches gnome-calculator on the host desktop.

I also verified the negative case with --socket=pulseaudio removed, to make sure the exploit fails. Since this was AI discovered, and I have a healthy scepticism for AI output, I double-checked to not submit any slop.
I was wondering how common pulseaudio access is in sandboxed apps, and quickly found one on Flathub:
--socket=pulseaudio + --filesystem=xdg-downloadAny Flatpak app with audio permission and any host-writable path is exploitable.
The same attack also works from Docker containers with the PulseAudio socket mounted, which is a standard setup for containerized audio.
These were the mitigations and recommendations I provided. Any one of these breaks the chain:
~/.config/pulse/cookie, like PulseAudio does.allow-module-loading to false. The option exists since May 2024.dlopen() from /usr/lib/ladspa/ and /usr/lib64/ladspa/, not arbitrary paths.To my understanding, locking down (3) is what was implemented to mitigate the issue.
Also, I got a shout out from Red Hat in the official CVE-2026-5674.

Cool.
PipeWire’s PulseAudio compatibility never validates the authentication cookie. Module loading is enabled by default, and dlopen() loads whatever path you give it.
Together a sandboxed Flatpak app (or other sandbox with audio socket access), and you get full user-context code execution. A “Hello World” app with audio permission writes to your home directory and pops calculator on your desktop.
In short --socket=pulseaudio should mean “this app can play audio.”, but it actually meant “this app can execute arbitrary code as you.”
As far as I can tell the fix was for dlopen() to prevent loading libraries from arbitrary absolute paths.
Red Hat has released a fix. If you’re affected (e.g. PipeWire applies to most distros) update.
Cheers, Johann.