TypeError in LFS token validation when JWT header is malformed

Summary

A TypeError: no implicit conversion of String into Integer is raised in Gitlab::LfsToken#token_valid? when a malformed token with an invalid JWT header is passed for validation.

Sentry Error

https://new-sentry.gitlab.net/organizations/gitlab/issues/3211045

Root Cause

When a malformed token has:

  1. Exactly 2 segments (missing signature)
  2. A header that decodes to a JSON Array instead of a Hash (e.g., ["HS256"]) The JWT gem calls header['alg'] to check for the none algorithm. Since Array#[] expects an Integer index, passing a String key raises:
TypeError: no implicit conversion of String into Integer

Stack trace:

token.header['alg']
             ^^^^^
from jwt/decode.rb:117:in `[]'
from jwt/decode.rb:117:in `alg_in_header'
from jwt/decode.rb:113:in `none_algorithm?'
from jwt/decode.rb:107:in `validate_segment_count!'
from jwt/decode.rb:31:in `decode_segments'
from jwt.rb:51:in `block in decode'
from lib/json_web_token/hmac_token.rb:17:in `decode'
from lib/gitlab/lfs_token.rb:99:in `token_valid?'

Reproduction

user = User.first
lfs_token = Gitlab::LfsToken.new(user, nil)
encoded_header = Base64.urlsafe_encode64('["HS256"]', padding: false)
encoded_payload = Base64.urlsafe_encode64('{}', padding: false)
malformed_token = "#{encoded_header}.#{encoded_payload}"
lfs_token.token_valid?(malformed_token)
# => TypeError: no implicit conversion of String into Integer

Proposed Fix

Rescue TypeError alongside JWT::DecodeError in HMACToken#token_valid?:

def token_valid?(token_to_check)
  decoded_token = JSONWebToken::HMACToken.decode(token_to_check, secret).first
  # ...
rescue JWT::DecodeError, TypeError
  false
end

Invalid tokens should return false regardless of the specific error type.

Edited Feb 03, 2026 by 🤖 GitLab Bot 🤖
Assignee Loading
Time tracking Loading