fix: reject an oversized guest bearer before building the cache key

The length guard ran after the cache key was built from the token (a copy and a
hash of the whole bearer), so cap it before that work. Also correct the
strip_prefix comment: it prevents a repeated-prefix bearer from reducing to a
valid token cached under a non-canonical key, not the oversized case the length
guard handles.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VF3v6LA9399gNphmZaHYG3
This commit is contained in:
Ruben Fiszel
2026-09-04 16:46:37 +02:00
co-authored by Claude Opus 4.8
parent 58eccf0a80
commit dbae7a0ce0
+10 -6
View File
@@ -175,6 +175,13 @@ impl AuthCache {
if is_no_auth() {
return Some(OptJobAuthed { authed: no_auth_admin_authed(), job_id: None });
}
// Reject an oversized guest bearer before the cache key is built from it: the key
// copies and hashes the whole token, so the cap should bound that work too.
if token.starts_with(windmill_common::guest_jwt::BEARER_PREFIX)
&& token.len() > windmill_common::guest_jwt::MAX_GUEST_JWT_LEN
{
return None;
}
let key = (
w_id.as_ref().unwrap_or(&"".to_string()).to_string(),
token.to_string(),
@@ -222,12 +229,9 @@ impl AuthCache {
let Some(w_id) = w_id.as_deref() else {
return None;
};
// The cache keys on the whole bearer, so bound it here before verify or caching;
// strip exactly one prefix, or repeated prefixes would shrink an oversized
// bearer past the length check while it is still cached at full size.
if token.len() > windmill_common::guest_jwt::MAX_GUEST_JWT_LEN {
return None;
}
// Strip exactly one prefix: `trim_start_matches` would strip repeated prefixes,
// so `jwt_guest_jwt_guest_<jwt>` would reduce to a valid token that verifies and
// is then cached under the full, non-canonical bearer key.
let jwt = token
.strip_prefix(windmill_common::guest_jwt::BEARER_PREFIX)
.unwrap_or(token);