|
12 | 12 | it { is_expected.to eq(valid_signature) } |
13 | 13 | end |
14 | 14 |
|
15 | | - # Address OpenSSL 3.0 errors with empty hmac_secret - https://github.com/jwt/ruby-jwt/issues/526 |
| 15 | + # GHSA-c32j-vqhx-rx3x: empty/nil keys must be rejected before reaching OpenSSL, |
| 16 | + # so a forged token signed with "" cannot verify. |
16 | 17 | context 'when nil hmac_secret is passed' do |
17 | 18 | let(:hmac_secret) { nil } |
18 | | - context 'when OpenSSL 3.0 raises a malloc failure' do |
19 | | - before do |
20 | | - allow(OpenSSL::HMAC).to receive(:digest).and_raise(OpenSSL::HMACError.new('EVP_PKEY_new_mac_key: malloc failure')) |
21 | | - end |
22 | 19 |
|
23 | | - it 'raises JWT::DecodeError' do |
24 | | - expect { subject }.to raise_error(JWT::DecodeError, 'OpenSSL 3.0 does not support nil or empty hmac_secret') |
25 | | - end |
| 20 | + it 'raises JWT::DecodeError' do |
| 21 | + expect { subject }.to raise_error(JWT::DecodeError, 'HMAC key expected to be a String') |
26 | 22 | end |
27 | 23 |
|
28 | | - context 'when OpenSSL raises any other error' do |
29 | | - before do |
30 | | - allow(OpenSSL::HMAC).to receive(:digest).and_raise(OpenSSL::HMACError.new('Another Random Error')) |
31 | | - end |
32 | | - |
33 | | - it 'raises the original error' do |
34 | | - expect { subject }.to raise_error(OpenSSL::HMACError, 'Another Random Error') |
35 | | - end |
36 | | - end |
37 | | - |
38 | | - context 'when other versions of openssl do not raise an exception' do |
39 | | - let(:response) { Base64.decode64("Q7DO+ZJl+eNMEOqdNQGSbSezn1fG1nRWHYuiNueoGfs=\n") } |
40 | | - before do |
41 | | - allow(OpenSSL::HMAC).to receive(:digest).and_return(response) |
42 | | - end |
43 | | - |
44 | | - it { is_expected.to eql(response) } |
| 24 | + it 'does not call OpenSSL::HMAC.digest' do |
| 25 | + expect(OpenSSL::HMAC).not_to receive(:digest) |
| 26 | + expect { subject }.to raise_error(JWT::DecodeError) |
45 | 27 | end |
46 | 28 | end |
47 | 29 |
|
48 | 30 | context 'when blank hmac_secret is passed' do |
49 | 31 | let(:hmac_secret) { '' } |
50 | | - context 'when OpenSSL 3.0 raises a malloc failure' do |
51 | | - before do |
52 | | - allow(OpenSSL::HMAC).to receive(:digest).and_raise(OpenSSL::HMACError.new('EVP_PKEY_new_mac_key: malloc failure')) |
53 | | - end |
54 | 32 |
|
55 | | - it 'raises JWT::DecodeError' do |
56 | | - expect { subject }.to raise_error(JWT::DecodeError, 'OpenSSL 3.0 does not support nil or empty hmac_secret') |
57 | | - end |
| 33 | + it 'raises JWT::DecodeError' do |
| 34 | + expect { subject }.to raise_error(JWT::DecodeError, 'HMAC key cannot be empty') |
58 | 35 | end |
59 | 36 |
|
60 | | - context 'when OpenSSL raises any other error' do |
61 | | - before do |
62 | | - allow(OpenSSL::HMAC).to receive(:digest).and_raise(OpenSSL::HMACError.new('Another Random Error')) |
63 | | - end |
64 | | - |
65 | | - it 'raises the original error' do |
66 | | - expect { subject }.to raise_error(OpenSSL::HMACError, 'Another Random Error') |
67 | | - end |
| 37 | + it 'does not call OpenSSL::HMAC.digest' do |
| 38 | + expect(OpenSSL::HMAC).not_to receive(:digest) |
| 39 | + expect { subject }.to raise_error(JWT::DecodeError) |
68 | 40 | end |
| 41 | + end |
69 | 42 |
|
70 | | - context 'when other versions of openssl do not raise an exception' do |
71 | | - let(:response) { Base64.decode64("Q7DO+ZJl+eNMEOqdNQGSbSezn1fG1nRWHYuiNueoGfs=\n") } |
72 | | - before do |
73 | | - allow(OpenSSL::HMAC).to receive(:digest).and_return(response) |
74 | | - end |
| 43 | + context 'when non-String hmac_secret is passed' do |
| 44 | + let(:hmac_secret) { 123 } |
75 | 45 |
|
76 | | - it { is_expected.to eql(response) } |
| 46 | + it 'raises JWT::DecodeError' do |
| 47 | + expect { subject }.to raise_error(JWT::DecodeError, 'HMAC key expected to be a String') |
77 | 48 | end |
78 | 49 | end |
79 | 50 |
|
|
124 | 95 |
|
125 | 96 | it { is_expected.to be(false) } |
126 | 97 | end |
| 98 | + |
| 99 | + # GHSA-c32j-vqhx-rx3x: empty/nil keys must be rejected before reaching OpenSSL, |
| 100 | + # so a forged token signed with "" cannot verify. |
| 101 | + context 'when verification_key is nil' do |
| 102 | + let(:signature) { valid_signature } |
| 103 | + let(:hmac_secret) { nil } |
| 104 | + |
| 105 | + it 'raises JWT::DecodeError' do |
| 106 | + expect { subject }.to raise_error(JWT::DecodeError, 'HMAC key expected to be a String') |
| 107 | + end |
| 108 | + |
| 109 | + it 'does not call OpenSSL::HMAC.digest' do |
| 110 | + expect(OpenSSL::HMAC).not_to receive(:digest) |
| 111 | + expect { subject }.to raise_error(JWT::DecodeError) |
| 112 | + end |
| 113 | + end |
| 114 | + |
| 115 | + context 'when verification_key is an empty string' do |
| 116 | + let(:signature) { valid_signature } |
| 117 | + let(:hmac_secret) { '' } |
| 118 | + |
| 119 | + it 'raises JWT::DecodeError' do |
| 120 | + expect { subject }.to raise_error(JWT::DecodeError, 'HMAC key cannot be empty') |
| 121 | + end |
| 122 | + |
| 123 | + it 'does not call OpenSSL::HMAC.digest' do |
| 124 | + expect(OpenSSL::HMAC).not_to receive(:digest) |
| 125 | + expect { subject }.to raise_error(JWT::DecodeError) |
| 126 | + end |
| 127 | + end |
| 128 | + |
| 129 | + context 'when verification_key is not a String' do |
| 130 | + let(:signature) { valid_signature } |
| 131 | + let(:hmac_secret) { 123 } |
| 132 | + |
| 133 | + it 'raises JWT::DecodeError' do |
| 134 | + expect { subject }.to raise_error(JWT::DecodeError, 'HMAC key expected to be a String') |
| 135 | + end |
| 136 | + end |
127 | 137 | end |
128 | 138 |
|
129 | 139 | context 'backwards compatibility' do |
|
0 commit comments