nov/json-jwt

Minimum ruby version?

futureperfect opened this issue · 7 comments

I was curious to know what minimum version of ruby you were targeting with this library. I noticed your use of url_safe_base64 might be related to attempting to support older rubies?

The reason I ask is that there's at least one corner case in decoding Base64-encoded data that is incorrectly handled in url_safe_base64 that I'd either like to address or remove the dependency on the library.

nov commented

officially ruby 2.2.2 is the minimum, but I don't want to hardly break 2.1.0 support at current period.

btw, url_safe_base64 isn't for legacy ruby support.

nov commented

BTW, what is the "corner case"?
Currently, I don't have any strong motivation to remove url_safe_base64 gem dependency.

There was some work released in ruby 2.3.0 to enhance URL-safe encoding.

https://github.com/ruby/ruby/pull/815/files

When adapting the added tests into url_safe_base64, they do not behave consistent with either ruby 2.3.0 or what RFC4648 or RFC 7515 suggest.

I also noticed in https://tools.ietf.org/html/rfc7515#appendix-C the note

if the length mod 4 is 1, the input is malformed.

If I'm reading the tests I've adapted correctly, this case is incorrectly treated as valid by url_safe_base64 and decoded.

I was curious before if it was a historical reason related to older ruby support that this library was introduced, because as it stands it does not appear to be a standards-conformant url-safe Base64 decoder.

nov commented

2.2 support is still needed.

Plus, malformed base64 input shouldn't become valid jwt if it's integrity protected.

What about backporting the 4 functions from Base64 module in ruby-2.3.0 into its own class/module and jettisoning the incorrect version from your library dependency?

nov commented

It also works.
I still do not think malformed base64 handling is important in jwt context though.

A note for anyone running Ruby 2.1:

json-jwt creates symbols (using #to_sym) from the 'alg' field at an early stage of JWS verification. For user supplied JWTs (which is almost always the case), this will create a memory leak (aka Symbol DoS) in the event of malicious JWTs.

@nov, I'd recommend formally adding Ruby 2.2 as a minimum version to the README along with a note that while 2.1 may function, it is at risk of a Symbol DoS.

Proof of concept (on Ruby 2.1) which basically generates JWTs with arbitrary values for 'alg' and then attempts to decode them:

[12] pry(main)> Symbol.all_symbols.size
=> 26631
[13] pry(main)> 10000.times{|n| j=JSON::JWT.new a: 1 ; j.alg = "#{n}" ; s=j.to_s ; (JSON::JWT.decode(s, 'some-key') rescue nil) }
=> 10000
[14] pry(main)> Symbol.all_symbols.size
=> 36631