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

bug : cupsd crashes / misbehaves on malformed Authorization: Negotiate header (unchecked malloc + decode in GSSAPI path)

Open Beginner friendly
#1,772 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
70/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
c

Research direction

Read the Negotiate handling around scheduler/auth.c:847-851 and the decoder behavior in cups/http-support.c:463-464, :509. Build cupsd with HAVE_GSSAPI and AuthType Negotiate, then try the malformed Authorization token described in the issue. Done means invalid input is rejected before it reaches gss_accept_sec_context, with no daemon crash or misbehavior.

Written by the indexing model from the issue text.

Description

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:

  1. malloc() at :848 is never NULL-checked. authorization here is the remainder of the client-sent Authorization: Negotiate ... header, so a remote client controls its length.
  2. httpDecode64_2() at :849 can return NULL (see cups/http-support.c:463-464 — it returns NULL when !outlen || *outlen < 1, and httpDecode64_3 underneath returns NULL on bad input at :509). That NULL is assigned straight back over input_token.value with 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:

  1. Save as repro_gss.c and build:
cc -O0 repro_gss.c -o repro_gss && ./repro_gss
  1. 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
  1. Full daemon path: send Authorization: Negotiate !!!not-base64!!! (or a very long token to pressure malloc) to a cupsd built with HAVE_GSSAPI and AuthType Negotiate — the NULL token reaches gss_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: :404 and :602 use stack buffers with size init, only this :848-849 site uses unchecked heap allocation. So this looks like a one-off miss, not a pattern.
Dominant language
C
Stars
1.8k
Forks
349
Avg merge
2d 14h
Merged PRs (30d)
12

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.