cups-browsed held UDP 631 open to the world. Two years after the CVEs, the architecture finally changed.
Published by RodHat

Two years ago today, Simone Margaritelli published the first of a series of posts detailing four CVEs in the Linux printing stack that most desktop users had no idea they were running. The vulnerabilities themselves were serious. The more interesting story is what they exposed about how old, trusted software accumulates trust without anyone checking whether that trust still makes sense.
What the attack was
CVE-2024-47176 is the load-bearing one. cups-browsed, the daemon responsible for automatic network printer discovery, bound to UDP port 631 and accepted printer creation packets from any source with no authentication. One crafted UDP packet was enough to make cups-browsed reach out to an attacker-controlled server to retrieve IPP printer attributes. The attacker returned a PPD file. When a user on the machine attempted to print to that printer, cups-filters executed the command embedded in the PPD file.
Three more CVEs (47076, 47175, 47177) covered the adjacent libcupsfilters and libppd parsing failures that completed the chain. The attack required cups-browsed to be running and the attacker to have network access to UDP 631. On default Ubuntu desktop installs, cups-browsed ran. On servers, usually not. On FreeBSD, not applicable.
The CVSS scoring debate that followed was the usual argument: does the local-network requirement reduce severity? On the target systems, which were desktop Linux installs with cups-browsed autostarted at login, the requirement was satisfied by default. An attack surface that only works under conditions that are true out of the box is still an attack surface.
The architectural problem
cups-browsed is not a service with a fixable bug. It is a service whose function required trusting arbitrary network input.
The job of cups-browsed was to implement IPP Everywhere / Bonjour printer
autodiscovery: you connect to the office Wi-Fi, your printers appear, you print.
The problem is that IPP Everywhere relies on mDNS/DNS-SD broadcast announcements
to advertise printer existence, and cups-browsed had no mechanism to verify that
an announcement came from a real printer rather than from a laptop on the same
subnet running nc -u -l 631. The design said “trust everything that claims to
be a printer.” The CVE was a natural consequence.
PPD files (PostScript Printer Description format, inherited from Adobe in 1993,
carried through decades of CUPS) contain a FoomaticRIPCommandLine field that
specifies a command to run. This is how custom printer filters work. It is also a
command injection surface if you can control what PPD file gets installed, which
the CVE made trivial. PPD files as an executable configuration format have been
the wrong answer since the format was designed. Exposing them to network-sourced
content made that clear.
What changed
The patches for the original CVEs restricted which packet sources cups-browsed would accept and added validation in libcupsfilters and libppd. Those landed in distribution updates within days of the disclosure. cups-browsed has been disabled by default on the major desktop Linux distributions since their first post-CVE releases.
The structural fix arrived with CUPS 3.x, which the OpenPrinting project under Michael Sweet had been building in parallel with the 2.4.x maintenance track. CUPS 3.x drops legacy PPD file support from the core entirely, which eliminates the FoomaticRIPCommandLine execution surface, and requires all printer communication to go through IPP Everywhere attributes. cups-browsed remains available as a separate component but ships with no autostart by default. The autodiscovery model is still mDNS-based and still has the same network trust problem in principle, but without PPD command execution there is no payload delivery mechanism. You can still be steered toward a malicious printer. You cannot be made to execute arbitrary commands simply by being steered there.
The 2.4.x series still runs in a lot of enterprise environments. It is not going anywhere fast. The cups-browsed-disabled-by-default default from the patches is the operative protection there.
The pattern
This is the same lifecycle the xz backdoor showed at the social engineering layer: old, trusted, running-by-default software with an assumption baked in that stopped being safe at some point in the past. Nobody audited cups-browsed because it was the printing daemon. Printing works. Printing has always worked. Why would you look at the printing daemon?
The answer to “why would you look at it” is that any long-lived daemon listening on a network port is an attack surface, and the age that gives it unearned trust is the same age that makes its underlying assumptions increasingly difficult to justify. LPD shipped in BSD 4.3 in 1986 for serial and parallel port printers. The concept that a printer daemon should accept network input from arbitrary sources, without authentication, was grafted onto that model. Every generation added features without revisiting what the original model was trusting.
CUPS 3.x is the first time in twenty-plus years that someone went back to the architectural assumptions and changed them rather than patching the consequences. That is worth something. It took a working remote code execution disclosure to get there, which is also true of most architectural fixes in software with real installed base.
The NVD/OSV vulnerability feed changes matter in context: the cups-browsed CVEs were heavily debated in the scoring period, partly because “network-adjacent” reads as lower severity than “remote” in CVSS until you account for what “network-adjacent” means on a laptop on a coffee shop network. Feed quality and scoring accuracy affect whether these debates go the right way.
If you are still running CUPS 2.4.x
systemctl status cups-browsed
If it is running and you do not have a specific reason for network printer
autodiscovery, disable it. systemctl disable --now cups-browsed is the command.
Three seconds. The printer you configured manually still works.
If you are running CUPS 3.x, cups-browsed is not your problem until you explicitly opt into it. That is the correct default.
See also: CVE scoring inflation and what “medium” actually means in practice for the scoring debate context.
Sources
- Attacking UNIX Systems via CUPS, Part I (original CVE-2024-47176 disclosure) (Simone Margaritelli (evilsocket))
- CVE-2024-47176 detail (National Vulnerability Database, NIST)