TLDR: my self-orchestrating team of vulnerability hunting agents discovered two issues in CUPS, CVE-2026-34980 and CVE-2026-34990 , chainable into unauthenticated remote attacker -> unprivileged RCE -> root file (over)write . See below for the prerequisites, details, and mitigation options. Intro # CUPS is the standard way to do printing on Linux and other Unix(-like) systems. It’s been on my mind as a research target ever since doing incident response to Simone Margaritelli’s 2024 unauth’d RCE finding , where he chained several CUPS vulnerabilities into an unauth’d RCE as lp , the default CUPS service user. CUPS is complex – there are: a network-exposable HTTP/IPP print server that accepts untrusted jobs/printer metadata, legacy PPD ( PostScript Printer Description ) files that describe printer capabilities, “filters” (helpers to convert jobs into printer-ready data), and “backends” that send the print data to “printer-like” destinations (including files, which will matter below). Most of the filters run as lp , but the scheduler normally runs as root – and so do some of the backends. This makes for a rich attack surface. Findings # CVE-2026-34980 : Shared PostScript queue lets anonymous Print-Job requests reach lp code execution over the network CVE-2026-34990 : Local print admin token disclosure using temporary printers At a high level, in the first vulnerability, the attacker: Submits a malicious print job to a shared PostScript queue, Gets CUPS to treat attacker-controlled text as a trusted queue config by abusing a parsing bug, and Gets code execution as the CUPS service user, lp (vim in the PoC) And in the second vulnerability, the attacker: Uses any* unprivileged local user to set up a localhost listener, Creates a local printer object in CUPS, pointing it at the listener above, Gets CUPS to authenticate to it and captures the auth token, Creates another queue pointing at file:///... for the target rootful write, Uses the token to race against CUPS validation logic’s cleanup of the dangerous queue, and Writes what they want into the target file:///... ( /etc/sudoers.d/... in the PoC) * any unprivileged local user that can bind on some TCP port and reach the local CUPS listener. Are you affected? + Mitigation # The unauth’d RCE as lp ( CVE-2026-34980 ) requires the CUPS server to be reachable over the network and expose a shared PostScript queue (these are legacy, but still used). This would be a deliberate config choice – realistic for, say, networked printing servers in your corporate environment, but not for your desktop (unless you for some reason set it up to be a remote printing server). The LPE to root file (over)write ( CVE-2026-34990 ), on the other hand, works on the stock CUPS config. For both issues, the harm can be limited by a security module that confines CUPS (e.g., SELinux, AppArmor, etc.). So, if you run CUPS under a sane security policy (default on some distributions), the impact of both vulnerabilities is much less severe – e.g., no rootful file writes outside the paths CUPS is constrained to touch. As of 4/5/2026, there are public commits with fixes to both issues but no fixed release (latest being 2.4.16 ). So, your best mitigations are: Do not expose CUPS over the network with a shared PostScript queue – or at all If you must use a shared queue, require auth for job submissions to that queue Make sure your CUPS runs under a reasonable AppArmor/SELinux/etc. policy, so that the impact is minimized even if you are targeted Technical details # The advisories ( CVE-2026-34980 , CVE-2026-34990 ) and the PoCs in them go into full detail. Below is a summary of the particularly interesting pieces. CVE-2026-34980: turning a print option into scheduler control data # Under the default policy , CUPS will accept anonymous Print-Job requests, and it only blocks remote printing when the queue is not shared: < Limit Create - Job Print - Job Print - URI Validate - Job > Order deny,allow </ Limit > if ( ! printer -> shared && ...) { send_ipp_status (..., _ ( "The printer or class is not shared." )); return (NULL); } This gives us the ability to target all the rich escaping/parsing logic on a shared queue without any auth layer by default. When CUPS serializes job attributes for filters, it escapes newlines by prefixing them with a backslash . Later, when it parses that option string back, it strips the backslash back out. So, an embedded newline survives the round trip. if ( strchr ( " \t\n\\\'\" " , * valptr)) * optptr ++ = '\\' ; if ( * ptr == '\\' && ptr[ 1 ]) _cups_strcpy (ptr, ptr + 1 ); This matters when using a PostScript queue. pstops logs an invalid page-border value if it encounters one, and the helper it uses prefixes only the first line . So if the attacker smuggles a newline into the value, the second line can begin with PPD: (think HTTP PPD request smuggling): _cupsLangPrintFilter (stderr, "ERROR" , _ ( "Unsupported page-border value %s, using " "page-border=none." ), val); snprint...
Two chained vulnerabilities in CUPS (CVE-2026-34980 and CVE-2026-34990, CVSS 7.8 HIGH) enable an unauthenticated remote attacker to achieve remote code execution as the 'lp' user and subsequently escalate privileges to root for arbitrary file writes. The attack requires a network-exposed CUPS server with a shared PostScript queue for the initial RCE, while the local privilege escalation works on default configurations. Impact can be mitigated by running CUPS under a restrictive security module like SELinux or AppArmor.