Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

CUPS Network Backends SNMP Supply Injection -> PPD Modification

Open
#1,786 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
48/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Active
Tech stack
c
Domain
backend, security

Research direction

Start with backend/snmp-supplies.c, especially backend_walk_cb and the code that writes marker names to the status stream; trace how scheduler/statbuf.c and job.c classify and retain PPD lines, then inspect printers.c where keywords are written to the queue PPD. Compare the SNMP path with the control character handling in backend/ipp.c added by the cited fix. Done means SNMP supply descriptions cannot inject scheduler status or PPD keywords; add focused coverage for the path.

Written by the indexing model from the issue text.

Description

CUPS network backends: SNMP supply names reach the scheduler status stream unfiltered - a malicious printer or LAN SNMP spoofer can inject "PPD:" lines and change the
queue PPD (CVE-2026-55453 chain through the SNMP path; not fixed upstream on 2.4.x head; static read only)

Components: cups 2.4.7-1.2ubuntu7.14 (C8b876128848b, 7A34) and cups 2.4.16-1ubuntu1.3 (Ce8ddde6699cf, 7C56): socket and lpd
backends; cups-daemon 2.4.7-1.2ubuntu7.14 (Ccf49f64dc34c) and 2.4.16-1ubuntu1.3 (Cb8d63a2c1dbe): ipp backend and the
scheduler side (statbuf.c, job.c, printers.c). Sources: git-ubuntu applied/2.4.7-1.2ubuntu7.14 and applied/2.4.16-1ubuntu1.3;
upstream OpenPrinting/cups branch 2.4.x head. Copies in raw/level2/explorer-a-cups-bsd-cups-ubuntu/ (*-ubuntu-,
*-2.4.x-head). Line numbers: Ubuntu 2.4.7 / Ubuntu 2.4.16 / 2.4.x head.

Path from SNMP reply to PPD write

  1. The backend walks the printer's supply table over SNMPv1 (community "public").
    socket.c:273 and :429, lpd.c:945 and :1225, ipp.c:676 and :2199 (2.4.7) call backendSNMPSupplies() ->
    backend_init_supplies() (snmp-supplies.c:217 / 218) -> _cupsSNMPWalk(..., backend_walk_cb).
    The gate is only snmp-supplies.c:515-521 / 516-522: return if the PPD sets cupsSNMPSupplies to a value other than "true";
    if the attribute is absent, polling runs (classic driver and vendor PPDs).
    _cupsSNMPWalk (cups/snmp.c) does not compare the reply's request-id or source address with the query (loop reads
    _cupsSNMPRead, then checks only the OID prefix and error fields), so a LAN host that answers the backend's UDP port can
    supply the values (same weakness that GHSA-g863 and GHSA-5cpc describe).

  2. The reply string is copied raw. cups/snmp.c asn1_decode_snmp():1040-1046 / 1045-1051 calls
    asn1_get_string(&bufptr, bufend, length, (char *)packet->object_value.string.bytes, sizeof(...));
    and asn1_get_string():1406-1440 / 1411-1445 is a memcpy plus a NUL. No byte is filtered.

  3. The supply name keeps control characters. snmp-supplies.c backend_walk_cb(), prtMarkerSuppliesDescription branch,
    charset csASCII/csUTF8/csUnicodeASCII (863-867 / 864-868 / 869-873):
    strlcpy(supplies[i - 1].name, (char *)packet->object_value.string.bytes, sizeof(supplies[0].name));
    The Latin-1, Shift-JIS, UTF-16 and UTF-32 branches convert without filtering too. Only the "unknown charset" default
    branch replaces bytes < ' ' with '?'. The charset is the printer's prtLocalizationCharacterSet (snmp-supplies.c:649 / 650).

  4. The name goes to the backend's stderr status stream. snmp-supplies.c:715-739 / 716-740 / 721-745:
    for (name_ptr = supplies[i].name; *name_ptr;)
    {
    if (*name_ptr == '\' || *name_ptr == '"' || *name_ptr == ''')
    { *ptr++ = '\'; *ptr++ = '\'; *ptr++ = '\'; }
    *ptr++ = *name_ptr++;
    }
    ...
    fprintf(stderr, "ATTR: marker-names=%s\n", value);
    LF (0x0A) and CR pass through, so one supply name can end the ATTR line and start new status lines.
    The same names are written to the backend's .snmp cache (snmp-supplies.c:670-680 / 671-681) and read back on later runs
    (575-583 / 576-584), so the injection repeats on every job without more attacker traffic while the description matches.

  5. The scheduler splits backend stderr at each '\n' (scheduler/statbuf.c:123 / 124, strchr(sb->buffer, '\n')) and classifies
    a line that starts with "PPD:" as CUPSD_LOG_PPD (statbuf.c:258-261 / 259-262 / head 262).

  6. job.c update_job(): CUPSD_LOG_PPD (5461-5486 / 5475-5500 / head 5458-5482) runs cupsParseOptions(message, ...) and adds every
    keyword except cupsFilter, cupsFilter2, cupsFinishingTemplate, cupsIPPFinishings, cupsIPPReason, cupsMarkerName,
    cupsMaxSize, cupsMediaQualifier*, cupsMinSize, cupsPageSizeCategory, cupsPortMonitor, cupsPreFilter, cupsPrintQuality,
    APPrinterPreset to job->keywords. FoomaticRIPCommandLine is kept (strcmp in Ubuntu, _cups_strcasecmp on head).

  7. At job end job.c:3618-3621 / 3631-3634 / head 3646 calls cupsdUpdatePrinterPPD(job->printer, job->num_keywords,
    job->keywords), and printers.c:2873 / 2853 / head 2869 writes each one into /etc/cups/ppd/.ppd:
    cupsFilePrintf(dst, "*%s: %s\n", keyword->name, keyword->value);

  8. If the queue uses foomatic-rip, the next job runs the injected FoomaticRIPCommandLine as lp (the GHSA-7hqf-mfhx-7r3v /
    CVE-2026-55453 demonstration, which used the ipp backend's marker-message instead of an SNMP supply name).
    Example supply name shape (not tested): "x\nPPD: FoomaticRIPCommandLine=cat;/usr/bin/id>/tmp/m;#\nDEBUG: y". The
    payload must avoid \ " ' (they are escaped) - the GHSA payload already does (${IFS}).

Why the CVE-2026-55453 fix does not cover it

The fix (2.4.x d41cf0616, master 806e1b483) changes only backend/ipp.c quote_string() (control characters -> space). The
2.4.x head snmp-supplies.c differs from Ubuntu 2.4.16 only in buffer sizes and the marker-levels clamp; head job.c and
printers.c still accept and write the keyword. No OpenPrinting advisory in cups-ghsa.json (41 read by reader-k) describes
this SNMP path.

Preconditions and reach

  • A queue on socket://, lpd:// or ipp:// to a printer the attacker controls, or on a LAN where the attacker can answer the
    backend's SNMP queries; the PPD does not set *cupsSNMPSupplies: False (IPP Everywhere PPDs set False; classic driver PPDs
    do not); a job runs on that queue. Code execution additionally needs a foomatic-rip queue (other PPD keyword changes still
    alter the queue).
Dominant language
C
Stars
1.8k
Forks
353
Avg merge
19h 41m
Merged PRs (30d)
18

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from OpenPrinting/cups

All issues in OpenPrinting/cups

Similar issues

More C issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.