Vulnerability Management

The CUPS RCE chain: a postmortem of CVE-2024-47176 and friends

The September 2024 CUPS chain (CVE-2024-47176, 47076, 47175, 47177) turned a printer browsing daemon into a remote code execution vector and exposed how badly long-tail Linux daemons get patched.

Hritik Sharma
Staff Engineer
6 min read

When Simone Margaritelli published the CUPS chain in late September 2024, the initial reaction in the Linux community was disbelief that the print server in 2024 was both still listening on UDP/631 by default in some distributions and still trusting attacker-supplied IPP attributes enough to be coerced into running arbitrary commands. The chain stitched together four CVEs across cups-browsed, libcupsfilters, libppd, and cups-filters: CVE-2024-47176 in cups-browsed for binding to all interfaces and accepting unsolicited printer announcements, CVE-2024-47076 in libcupsfilters for failing to sanitize IPP attributes, CVE-2024-47175 in libppd for writing those attributes into PPD files without escaping, and CVE-2024-47177 in cups-filters for the foomatic-rip filter executing whatever command the PPD's FoomaticRIPCommandLine pointed at.

The chain is interesting in 2026 not because the technical details have changed but because the deployment population has barely moved. CUPS is one of those packages that almost every Linux desktop and an uncomfortable number of Linux servers ship by default, often with cups-browsed enabled for printer discovery convenience even on hosts that have never printed anything. The long tail of unpatched, network-reachable cups-browsed instances eighteen months after disclosure is a small case study in why some classes of vulnerability never fully get cleaned up.

How does the exploit chain fit together?

The starting point is cups-browsed, which in vulnerable configurations binds to UDP/631 on all interfaces and listens for IPP announcements from the network. Normal printer discovery uses mDNS for the LAN case and unicast IPP browsing for routed networks; the bug is that cups-browsed treats an unsolicited IPP packet on UDP/631 as if it were a legitimate announcement and reaches out to the announcing IP to query its capabilities. The attacker controls the IP, controls the IPP response, and controls the printer attributes embedded in that response.

When cups-browsed receives the attributes, it passes them through libcupsfilters to construct a local PPD file that describes the new printer. CVE-2024-47076 and CVE-2024-47175 are the failures to sanitize and escape those attributes, which means the attacker-controlled strings end up verbatim in the PPD. Among the fields the attacker can set is FoomaticRIPCommandLine, which is the shell command that the foomatic-rip filter executes when a print job is sent to the printer. The chain becomes RCE the moment a print job is dispatched to the malicious printer, whether by a user action or by an attacker who can trigger a print from the same host.

Why was this a long-tail patching problem?

cups-browsed is enabled by default in CUPS packaging across many distributions, and on a host that never prints there is no behavioral cue that it is running. Operators do not look at a print daemon during routine hardening passes because they do not think of printing as an attack surface, and minimum-install profiles for headless servers historically did include cups-browsed even when no other printing components were present. The result is a population of vulnerable hosts that nobody is watching, because nobody remembers they have a print daemon.

The patches landed in libcupsfilters 2.1b1 and libppd 2.1b1, with the cups-browsed binding fix shipped in cups-filters 2.0.1 and the cups-browsed component continuing to receive hardening across the following months. Distribution backports took the usual zig-zag path: enterprise distributions had patched packages in days for in-support branches, in weeks for extended-support branches, and the long tail of unsupported branches is still unsupported. Containers added their own dimension to the long tail, because base images built before late September 2024 that include CUPS as a transitive dependency continued to be deployed for months after a patch was available, especially in legacy ML and printing pipelines that pinned base image digests.

What does the deployment surface actually look like?

Internet-wide scans in late 2024 found hundreds of thousands of cups-browsed instances reachable on UDP/631, with the bulk on residential and small-business connections but a meaningful tail on cloud-hosted Linux. The cloud population was disproportionate because many cloud Linux images ship with CUPS in the default package set, and operators who never explicitly install CUPS may not know it is running. Locking down the perimeter is the obvious mitigation, but east-west exploitation from a compromised neighbor on the same VPC subnet bypasses perimeter rules, which is why the patch curve matters even on hosts that should not be reachable from the public internet.

The harder population to clean up is the embedded Linux fleet. Network multifunction printers, label printers in warehouses, and various appliance form factors all run cups-browsed or a derivative, and those devices are patched on the vendor's cadence. A vendor who has not pushed an updated firmware image in 2024 is unlikely to push one for cups-browsed alone, and operators of those devices may not have a clean upgrade path. Network segmentation that prevents the device's cups-browsed from talking to anything except a trusted print server is the operational answer, but few environments segment that tightly.

What should the postmortem change for 2026?

The first change is to treat default-enabled daemons as inventory items that require explicit justification. cups-browsed has been default-enabled for years on systems that have never printed, and the only reason that surprised anyone was that nobody had asked the question. Periodic listening-port inventories that flag daemons without a documented business justification would have surfaced the exposure long before September 2024.

The second change is to instrument the SBOM with sensitivity tags. CUPS components in an SBOM are not just packages; they are network listeners that need to be tracked under the same scrutiny as web servers and database engines. SBOM tooling that distinguishes between a package present and a package actively listening on a network socket gives operators the data they need to prioritize. The third change is to treat IPP, mDNS, and other discovery protocols as untrusted input by default. Discovery convenience is a real benefit on consumer LANs but should not be the default for server builds, and minimum-install profiles that exclude printing components entirely are a cheap win for headless infrastructure.

How Safeguard Helps

Safeguard inventories CUPS packages across container images, virtual machines, and ingested SBOMs from third-party appliances, so the question of where cups-browsed is running and which versions are vulnerable can be answered against live data. Griffin AI correlates the package inventory with network exposure signals, raising priority on hosts where cups-browsed is listening on a routed network rather than localhost, and the reachability analysis distinguishes images that include CUPS as a transitive dependency from those that actually run the daemon. Policy gates can block deployment of base images that ship pre-2.1b1 libcupsfilters and libppd into environments that have no printing requirement, and the TPRM workflow surfaces vendors whose appliance firmware still carries the unpatched chain. The remediation guidance for affected projects is generated automatically, including the specific package versions to upgrade to and the cups-browsed configuration changes that mitigate the exposure on hosts where patching is delayed.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.