OAuth/OIDC token-validation gaps: nonce not enforced when absent, at_hash alg, inbound bearer not signature/aud/exp-validated + unverified email used for authz
I maintainer di solito rispondono entro 1 giorno
@michaelrsweet ci sta già lavorando.
Dal 27/6/2026.
Valutazione
Questa issue non è ancora stata valutata.
Descrizione
Describe the bug
While reviewing the new (2.5) OAuth/OpenID Connect support I noticed three token-validation gaps. These are hardening / spec-compliance issues (2.5 is unreleased, so filing here per SECURITY.md rather than as an advisory); their real-world impact depends on the configured Identity Provider (IdP), so I'm raising them for discussion rather than asserting a concrete bypass.
1. nonce not enforced when the id_token omits the claim — cups/oauth.c
// cups/oauth.c:1358-1364 (cupsOAuthGetTokens)
jwt = cupsJWTImportString(id_value, CUPS_JWS_FORMAT_COMPACT);
jnonce = cupsJWTGetClaimString(jwt, "nonce");
nonce = oauth_load_value(auth_uri, resource_uri, _CUPS_OTYPE_NONCE, false);
// Check nonce
if (!jwt || (jnonce && nonce && strcmp(jnonce, nonce)))
goto done;
When CUPS sent a nonce (it is persisted whenever the openid scope is requested), OIDC Core §3.1.3.7 requires the returned id_token to contain a matching nonce. Here, if the id_token omits the claim (jnonce == NULL), the jnonce && nonce && ... test short-circuits and the nonce check is skipped, so the token is accepted on signature alone. Suggested fix: if a nonce was sent (stored value exists), require jnonce != NULL && !strcmp(jnonce, nonce).
2. at_hash only validated for SHA-256-class id_tokens — cups/oauth.c:1377-1391
The access-token hash is always computed with sha2-256 and the code requires exactly 16 decoded at_hash bytes. For an id_token signed with an RS/ES/PS-384 or -512 algorithm the correct at_hash is 24/32 bytes, so a legitimate token is rejected (at_hash_bytes != 16 → goto done). The hash algorithm should follow the id_token's signing algorithm.
3. cupsd does not cryptographically validate inbound Bearer tokens; authorization uses the unverified email claim — scheduler/auth.c
In the Bearer branch (scheduler/auth.c:725-782), cupsd passes the token to cupsOAuthGetUserId(), which (when no cached identity exists) forwards it to the IdP userinfo_endpoint and trusts the JSON response (cups/oauth.c:1454-1518). On this inbound path there is no local verification of the token signature, iss, aud/azp, exp, or nbf (the existing cupsJWTHasValidSignature() / JWKS code is only used in the client-side token-exchange flow). Consequently a token minted by the same IdP for a different relying party can authenticate to CUPS (audience confusion), since CUPS never checks the token was issued for it.
Additionally, authorization matches the unverified email claim:
// scheduler/auth.c:1893
else if (!_cups_strcasecmp(username, name) || (con->email[0] && !_cups_strcasecmp(con->email, name)))
// scheduler/auth.c:1887,1920 -> cupsArrayFind(og->members, con->email)
email_verified is never consulted. If the configured IdP issues tokens with a user-settable/unverified email, a user could set email to a value listed in a policy's Require user ... or an OAuthGroup member file and gain that identity's access.
Suggested fixes: validate inbound tokens (signature via the IdP JWKS, plus iss/aud/exp) before trusting them, and require email_verified before using email for authorization decisions.
Expected behavior
Token and claim validation should follow the OIDC spec (enforce nonce when sent, algorithm-appropriate at_hash, and audience/expiry/email_verified checks).
System Information:
- OS and its version: Ubuntu 24.04 (x86_64)
- CUPS version: master / 2.5b1 (OAuth/OIDC support is 2.5-only)
Additional context
These are validation/hardening gaps rather than a demonstrated exploit; severity is IdP-dependent. Happy to split into separate issues if the maintainers prefer.
- Lingua principale
- C
- Stelle
- 1.8k
- Fork
- 354
- Merge medio
- 20h 6m
- PR unite (30g)
- 18
Preparare l'ambiente
- Include un Dockerfile o un file Docker Compose
- Nessun modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di OpenPrinting/cups
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 66/100
OpenPrinting/cups#1795 ·
I maintainer di solito rispondono entro 1 giorno
-
Don't use xgettext sort option (-s) when generating POT fileForse già presa @michaelrsweet l’ha presa 20 giorni fa. Apertainvestigating
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
OpenPrinting/cups#1721 · 4 commenti · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 4/5 1-2 giorni Idoneità per principianti 15/100
OpenPrinting/cups#1804 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 3/5 1-2 giorni Idoneità per principianti 20/100
OpenPrinting/cups#1802 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 3/5 1-2 giorni Idoneità per principianti 35/100
OpenPrinting/cups#1796 ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di OpenPrinting/cups
Issue simili
-
XPM values line with more than one space between numbers raises ValueErrorForse già presa Una pull request collegata a questa issue è aperta o già unita. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 86/100
python-pillow/Pillow#10429 ·
I maintainer di solito rispondono entro 1 giorno
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 83/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 85/100
I maintainer di solito rispondono entro 9 giorni
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
containers/bubblewrap#826 ·
I maintainer di solito rispondono entro 1 giorno