bug : cupsd crashes / misbehaves on malformed Authorization: Negotiate header (unchecked malloc + decode in GSSAPI path)
Los mantenedores suelen responder en 1 día
@michaelrsweet ya está trabajando en esto.
Desde el 18/10/2026.
Evaluación
- Dificultad
- 2/5
- Tiempo estimado
- 1-3 horas
- Aptitud para principiantes
- 70/100
- Tipo de issue
- Error
- Claridad
- Bien especificado
- Estado de actividad
- Activo
- Stack tecnológico
- c
- Área
- authentication, backend, security
Línea de trabajo
Lee el manejo de Negotiate en scheduler/auth.c:847-851 y el comportamiento del decodificador en cups/http-support.c:463-464, :509. Compila cupsd con HAVE_GSSAPI y AuthType Negotiate y luego prueba el token Authorization malformado descrito en el issue. Se considera terminado cuando las entradas no válidas se rechazan antes de llegar a gss_accept_sec_context, sin que el daemon se bloquee ni se comporte de forma incorrecta.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Before you write the report
I read REPORTING_ISSUES.md before filing this. This is a code defect in the daemon's auth path, so no printer was needed — I verified the logic locally with a small repro mirroring the exact calls.
I searched open + closed issues and PRs for GSSAPI, Negotiate, gss_accept_sec_context, httpDecode64_2, Kerberos to avoid a duplicate. The closest I found were #1609 (OAuth/OIDC token-validation gaps) and #1766 (ipp backend musl stack crash) — both are different subsystems and neither touches this Negotiate decode path. So I believe this is fresh.
Describe the bug
Hey, while looking at the Kerberos / Negotiate handling in scheduler/auth.c I noticed the input token setup does not check for failures at all.
On current master (b37c10e8, v2.5b1), scheduler/auth.c:847-851:
len = (int)strlen(authorization) + 0;
input_token.value = malloc((size_t)len);
input_token.value = httpDecode64_2(input_token.value, &len,
authorization);
input_token.length = (size_t)len;
Two problems stacked on top of each other:
malloc()at:848is never NULL-checked.authorizationhere is the remainder of the client-sentAuthorization: Negotiate ...header, so a remote client controls its length.httpDecode64_2()at:849can returnNULL(seecups/http-support.c:463-464— it returnsNULLwhen!outlen || *outlen < 1, andhttpDecode64_3underneath returnsNULLon bad input at:509). ThatNULLis assigned straight back overinput_token.valuewith no check.
Right after that, the token goes directly into:
major_status = gss_accept_sec_context(&minor_status,
&context,
ServerCreds,
&input_token, // <- possibly NULL .value here
...);
So a malformed (or huge, OOM-inducing) Negotiate header can push a NULL / garbage token buffer into gss_accept_sec_context() inside cupsd itself, which runs as root and pre-auth. At best the daemon logs a confusing GSS error, at worst it trips over the bad buffer in the GSS library.
What made me look twice is that the Basic path just above (:600-602) decodes into a fixed stack buffer username[] safely, while this path uses a heap allocation with no checks. Felt like an oversight worth flagging.
To Reproduce
I could not spin up a Kerberos KDC here, so I extracted the exact 3-line sequence into a tiny repro that mirrors the real httpDecode64_2 NULL contract:
char *v = malloc((size_t)len); // mirrors :848, no check
v = fake_httpDecode64_2(v, &len, "!!!not-base64!!!");
// mirrors :849, returns NULL on bad input
printf("after decode: value=%p len=%d\n", (void*)v, len);
Steps:
- Save as
repro_gss.cand build:
cc -O0 repro_gss.c -o repro_gss && ./repro_gss
- You will see:
after decode: value=0x0 len=16
REPRODUCED: input_token.value==NULL fed to gss_accept_sec_context -> root cupsd robustness bug
Matches scheduler/auth.c:847-851: malloc unchecked + httpDecode64_2 NULL unchecked
- Full daemon path: send
Authorization: Negotiate !!!not-base64!!!(or a very long token to pressuremalloc) to acupsdbuilt withHAVE_GSSAPIandAuthType Negotiate— theNULLtoken reachesgss_accept_sec_context()instead of being rejected cleanly.
Honestly the malloc-OOM half needs memory pressure to trigger, but the malformed-base64 NULL half triggers on demand — that is the part I actually reproduced above.
Expected behavior
Reject the bad token cleanly before touching GSS, something like:
len = (int)strlen(authorization);
input_token.value = malloc((size_t)len);
if (!input_token.value)
return;
if (!httpDecode64_2(input_token.value, &len, authorization))
{
free(input_token.value);
return;
}
input_token.length = (size_t)len;
Even better long term would be moving this to httpDecode64_3 like the rest of the tree, since httpDecode64_2 is already marked deprecated. But the NULL checks alone fix the crash path with no behavior change.
Screenshots
N/A — daemon auth path, repro output pasted above.
System Information:
- OS and its version: macOS arm64 (clang 17) for the logic repro — affects any Linux cupsd built with GSSAPI/Kerberos
- Application:
cupsd(scheduler/auth.c),AuthType Negotiate - CUPS version: master 2.5b1 @
b37c10e8
Additional context
A couple of notes from my digging:
- Impact is daemon robustness — pre-auth remote header reaches root
cupsd. Not claiming RCE, just a genuine NULL-into-GSS path that should be a clean reject. - I checked the sibling decode sites:
:404and:602use stack buffers with size init, only this:848-849site uses unchecked heap allocation. So this looks like a one-off miss, not a pattern.
- Lenguaje dominante
- C
- Estrellas
- 1.8k
- Forks
- 352
- Merge medio
- 2 d 5 h
- PR fusionados (30 d)
- 14
Preparar el entorno
- Incluye un Dockerfile o un archivo de Docker Compose
- Sin plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de OpenPrinting/cups
-
Potential integer overflow when using atoi() In cgi-bin/var.cPosiblemente ocupada @lynayur la tomó hace 14 días. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
OpenPrinting/cups#1748 ·
Los mantenedores suelen responder en 1 día
-
Don't use xgettext sort option (-s) when generating POT filePosiblemente ocupada @michaelrsweet la tomó hace 7 días. Abiertoinvestigating
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
OpenPrinting/cups#1721 · 4 comentarios · 1 asignado ·
Los mantenedores suelen responder en 1 día
-
`lp` (and other libcups clients) send `print-color-mode=<default>` alongside `ColorModel=Gray`, defeating the b0f1a00 "Don't override ColorModel" fixPosiblemente ocupada @michaelrsweet la tomó hace 1 día. Abiertoinvestigating
Dificultad 4/5 1-2 días Aptitud para principiantes 55/100
OpenPrinting/cups#1778 · 1 asignado ·
Los mantenedores suelen responder en 1 día
-
investigating platform issue printer specific issue
Dificultad 3/5 1-2 días Aptitud para principiantes 65/100
OpenPrinting/cups#1727 · 5 comentarios ·
Los mantenedores suelen responder en 1 día
-
Dificultad 4/5 3-5 días Aptitud para principiantes 30/100
OpenPrinting/cups#1726 · 1 comentario ·
Los mantenedores suelen responder en 1 día
Todos los issues de OpenPrinting/cups
Issues similares
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
polhenarejos/pico-fido#302 ·
-
开发板墙缺少 ESP32_S31_MOSAICOAbierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 67/100
espressif/esp-vision#16 · 1 comentario ·
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 74/100
libsdl-org/SDL#16577 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 66/100
Los mantenedores suelen responder en 1 día
-
halt_error adds a trailing newline for non-string input, contrary to the manualPosiblemente ocupada @Huang-404-Q la tomó hoy. Abierto
Dificultad 1/5 1-3 horas Aptitud para principiantes 88/100
Los mantenedores suelen responder en 2 días