forked from lestrrat-go/jwx
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Changes
513 lines (423 loc) · 24.6 KB
/
Changes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
Changes
=======
v2 has many incompatibilities with v1. To see the full list of differences between
v1 and v2, please read the Changes-v2.md file (https://github.com/lestrrat-go/jwx/blob/develop/v2/Changes-v2.md)
v2.1.0 18 Jun 2024
[New Features]
* [jwt] Added `jwt.ParseCookie()` function
* [jwt] `jwt.ParseRequest()` can now accept a new option, jwt.WithCookieKey() to
specify a cookie name to extract the token from.
* [jwt] `jwt.ParseRequest()` and `jwt.ParseCookie()` can accept the `jwt.WithCookie()` option,
which will, upon successful token parsing, make the functions assign the *http.Cookie
used to parse the token. This allows users to further inspect the cookie where the
token came from, should the need arise.
* [jwt] (BREAKING CHANGE) `jwt.ParseRequest()` no longer automatically looks for "Authorization" header when
only `jwt.WithFormKey()` is used. This behavior is the same for `jwt.WithCookieKey()` and
any similar options that may be implemented in the future.
# previously
jwt.ParseRequest(req) // looks under Authorization
jwt.ParseReuqest(req, jwt.WithFormKey("foo")) // looks under foo AND Authorization
jwt.ParseReuqest(req, jwt.WithHeaderKey("Authorization"), jwt.WithFormKey("foo")) // looks under foo AND Authorization
# since this release
jwt.ParseRequest(req) // same as before
jwt.ParseRequest(req, jwt.WithFormKey("foo")) // looks under foo
jwt.ParseReuqest(req, jwt.WithHeaderKey("Authorization"), jwt.WithFormKey("foo")) // looks under foo AND Authorization
* [jwt] Add `jwt.WithResetValidators()` option to `jwt.Validate()`. This option
will allow you to tell `jwt.Validate()` to NOT automatically check the
default validators (`iat`, `exp`, and `nbf`), so that you can completely customize
the validation with the validators you specify using `jwt.WithValidator()`.
This sort of behavior is useful for special cases such as
https://openid.net/specs/openid-connect-rpinitiated-1_0.html. However, you SHOULD NOT
use this option unless you know exactly what you are doing, as this will pose
significant security issues when used incorrectly.
* [jwk] Provide a _stop-gap_ measure to work with PEM format ASN.1 DER encoded secp256k1 keys.
In order to enable this feature, you must compile jwx with TWO build tags:
`jwx_es256k` to enable ES256K/secp256k1, and `jwx_secp256k1_pem` to enable PEM handling.
Not one, but BOTH tags need to be present.
With this change, by suppliying the `WithPEM(true)` option, `jwk.Parse()` is now
able to read sep256k1 keys. Also, `jwk.Pem()` should be able to handle `jwk.Key` objects
that represent a secp256k1 key.
Please do note that the implementation of this feature is dodgy at best. Currently
Go's crypto/x509 does not allow handling additional EC curves, and thus in order to
accomodate secp256k1 keys in PEM/ASN.1 DER format we need to "patch" the stdlib.
We do this by copy-and-pasting relevant parts of go 1.22.2's crypto/x509 code and
adding the minimum required code to make secp256k1 keys work.
Because of the above, there are several important caveats for this feature:
1. This feature is provided solely as a stop-gap measure until such time Go's stdlib
provides a way to handle non-standard EC curves, or another external module
is able to solve this issue.
2. This feature should be considered unstable and not guaranteed by semantic versioning
backward compatibility. At any given point we may drop or modify this feature. It may be
because we can no longer maintain the code, or perhaps a security issue is found in the
version of the code that we ship with, etc.
3. Please always remember that we are now bundling a static set of code for handling
x509 formats. You are taking a possible security risk by code that could be outdated.
Please always do your own research, and if possible, please notify us if the bundled
code needs to be updated. Unless you know what you are doing, it is not recommended
that you enable this feature.
4. Please note that because we imported the code from go 1.22's src/crypto/x509,
it has some go1.20-isms in its code. Therefore you will not be able to use the
`jwx_secp256k1_pem` tag to enable secp256k1 key PEM handling against codebases
that are built using go 1.19 and below (the build will succeed, but the feature
will be unavailable).
5. We have no plans to include more curves this way. One is already one too many.
* [jwe] Fixed a bug when using encryption algorithms involving PBES2 along with the
jwx.WithUseNumber() global option. Enabling this option would turn all values
stored in the JSON content to be of type `json.Number`, but we did not account for
it when checking for the value of `p2c` header, resulting in a conversion error.
v2.0.21 07 Mar 2024
[Security]
* [jwe] Added `jwe.Settings(jwe.WithMaxDecompressBufferSize(int64))` to specify the
maximum size of a decompressed JWE payload. The default value is 10MB. If you
are compressing payloads greater than this and want to decompress it during
a call to `jwe.Decrypt`, you need to explicitly set a value large enough to
hold that data.
The same option can be passed to `jwe.Decrypt` to control this behavior on
a per-message basis.
* [jwe] Added documentation stating that `jwe.WithMaxBufferSize` option will be
renamed in future versions, i.e. v3
v2.0.20 20 Feb 2024
[New Features]
* [jwe] Added `jwe.Settings(WithMaxBufferSize(int64))` to set the maximum size of
internal buffers. The default value is 256MB. Most users do not need to change
this value.
* [jws] Allow `jws.WithCompact()` and `jws.WithJSON()` to be passed to `jws.Parse()` and
`jws.Verify()`. These options control the expected serialization format for the
JWS message.
* [jwt] Add `jwt.WithCompactOnly()` to specify that only compact serialization can
be used for `jwt.Parse()`. Previously, by virtue of `jws.Parse()` allowing either
JSON or Compact serialization format, `jwt.Parse()` also alloed JSON serialization
where as RFC7519 explicitly states that only compact serialization should be
used. For backward compatibility the default behavior is not changed, but you
can set this global option for jwt: `jwt.Settings(jwt.WithCompactOnly(true))`
[Miscellaneous]
* Internal key conversions should now allow private keys to be used in place of
public keys. This would allow you to pass private keys where public keys are
expected.
v2.0.19 09 Jan 2024
[New Features]
* [jws] Added jws.IsVerificationError to check if the error returned by `jws.Verify`
was caused by actual verification step or something else, for example, while fetching
a key from datasource
[Security Fixes]
* [jws] JWS messages formated in full JSON format (i.e. not the compact format, which
consists of three base64 strings concatenated with a '.') with missing "protected"
headers could cause a panic, thereby introducing a possiblity of a DoS.
This has been fixed so that the `jws.Parse` function succeeds in parsing a JWS message
lacking a protected header. Calling `jws.Verify` on this same JWS message will result
in a failed verification attempt. Note that this behavior will differ slightly when
parsing JWS messages in compact form, which result in an error.
v2.0.18 03 Dec 2023
[Security Fixes]
* [jwe] A large number in p2c parameter for PBKDF2 based encryptions could cause a DoS attack,
similar to https://nvd.nist.gov/vuln/detail/CVE-2022-36083. All users who use JWE via this
package should upgrade. While the JOSE spec allows for encryption using JWE on JWTs, users of
the `jwt` package are not immediately susceptible unless they explicitly try to decrypt
JWTs -- by default the `jwt` package verifies signatures, but does not decrypt messages.
[GHSA-7f9x-gw85-8grf]
v2.0.17 20 Nov 2023
[Bug Fixes]
* [jws] Previously, `jws.UnregisterSigner` did not remove the previous signer instance when
the signer was registered and unregistered multiple times (#1016). This has been fixed.
[New Features]
* [jwe] (EXPERIMENTAL) `jwe.WithCEK` has been added to extract the content encryption key (CEK) from the Decrypt operation.
* [jwe] (EXPERIMENTAL) `jwe.EncryptStatic` has been added to encrypt content using a static CEK.
Using static CEKs has serious security implications, and you should not use
this unless you completely understand the risks involved.
v2.0.16 31 Oct 2023
[Security]
* [jws] ECDSA signature verification requires us to check if the signature
is of the desired length of bytes, but this check that used to exist before
had been removed in #65, resulting in certain malformed signatures to pass
verification.
One of the ways this could happen if R is a 31 byte integer and S is 32 byte integer,
both containing the correct signature values, but R is not zero-padded.
Correct = R: [ 0 , ... ] (32 bytes) S: [ ... ] (32 bytes)
Wrong = R: [ ... ] (31 bytes) S: [ ... ] (32 bytes)
In order for this check to pass, you would still need to have all 63 bytes
populated with the correct signature. The only modification a bad actor
may be able to do is to add one more byte at the end, in which case the
first 32 bytes (including what would have been S's first byte) is used for R,
and S would contain the rest. But this will only result in the verification to
fail. Therefore this in itself should not pose any security risk, albeit
allowing some illegally formated messages to be verified.
* [jwk] `jwk.Key` objects now have a `Validate()` method to validate the data
stored in the keys. However, this still does not necessarily mean that the key's
are valid for use in cryptographic operations. If `Validate()` is successful,
it only means that the keys are in the right _format_, including the presence
of required fields and that certain fields have proper length, etc.
[New Features]
* [jws] Added `jws.WithValidateKey()` to force calling `key.Validate()` before
signing or verification.
* [jws] `jws.Sign()` now returns a special type of error that can hold the
individual errors from the signers. The stringification is still the same
as before to preserve backwards compatibility.
* [jwk] Added `jwk.IsKeyValidationError` that checks if an error is an error
from `key.Validate()`.
[Bug Fixes]
* [jwt] `jwt.ParseInsecure()` was running verification if you provided a key
via `jwt.WithKey()` or `jwt.WithKeySet()` (#1007)
v2.0.15 19 20 Oct 2023
[Bug fixes]
* [jws] jws.Sign() now properly check for valid algorithm / key type pair when
the key implements crypto.Signer. This was caused by the fact that when
jws.WithKey() accepted keys that implemented crypto.Signer, there really
is no way to robustly check what algorithm the crypto.Signer implements.
The code has now been modified to check for KNOWN key types, i.e. those
that are defined in Go standard library, and those that are defined in
this library. For example, now calling jws.Sign() with jws.WithKey(jwa.RS256, ecdsaKey)
where ecdsaKey is either an instance of *ecdsa.PrivateKey or jwk.ECDSAPrivateKey
will produce an error.
However, if you use a separate library that wraps some KMS library which implements
crypto.Signer, this same check will not be performed due to the fact that
it is an unknown library to us. And there's no way to query a crypto.Signer
for its algorithm family.
v2.0.14 17 Oct 2023
[New Features]
* [jwk] jwk.IsPrivateKey(), as well as jwk.AsymmetricKey has been added.
The function can be used to tell if a jwk.Key is a private key of an
asymmetric key pair.
[Security]
* golang.org/x/crypto has been updated to 0.14.0. The update contains a fix for HTTP/2
rapid reset DoS vulnerability, which some security scanning softwares may flag.
However, do note that this library is NOT affected by the issue, as it does not have
the capability to serve as an HTTP/2 server. This is included in this release
document so that users will be able to tell why this library may be flagged
when/if their scanning software do so.
v2.0.13 26 Sep 2023
[New Features]
* [jwk] jwk.Equal has been added. Please note that this is equivalent to
comparing the keys' thumbprints, therefore it does NOT take in consideration
non-essential fields.
[Miscellaneous]
* Various documentation fixes and additions.
v2.0.12 - 11 Aug 2023
[Bug fixes]
* [jwt] jwt.Serializer was ignoring JWE flags (#951)
[Miscellaneous]
* [jwk] Check for seed length on OKP JWKs to avoid panics (#947)
* [jws] Documentation for jws.WithKeySet()
v2.0.11 - 14 Jun 2023
[Security]
* Potential Padding Oracle Attack Vulnerability and Timing Attack Vulnerability
for JWE AES-CBC encrypted payloads affecting all v2 releases up to v2.0.10,
all v1 releases up to v1.2.25, and all v0 releases up to v0.9.2 have been reported by
@shogo82148.
Please note that v0 versions will NOT receive fixes.
This release fixes these vulnerabilities for the v2 series.
v2.0.10 - 12 Jun 2023
[New Features]
* [jwe] (EXPERIMENTAL) Added `jwe.KeyEncrypter` and `jwe.KeyDecrypter` interfaces
that works in similar ways as how `crypto.Signer` works for signature
generation and verification. It can act as the interface for your encryption/decryption
keys that are for example stored in an hardware device.
This feature is labeled experimental because the API for the above interfaces have not
been battle tested, and may need to changed yet. Please be aware that until the API
is deemed stable, you may have to adapat our code to these possible changes,
_even_ during minor version upgrades of this library.
[Bug fixes]
* Registering JWS signers/verifiers did not work since v2.0.0, because the
way we handle algorithm names changed in 2aa98ce6884187180a7145b73da78c859dd46c84.
(We previously thought that this would be checked by the example code, but it
apparently failed to flag us properly)
The logic behind managing the internal database has been fixed, and
`jws.RegisterSigner` and `jws.RegisterVerifier` now properly hooks into the new
`jwa.RegisterSignatureAlgorithm` to automatically register new algorithm names
(#910, #911)
[Miscellaneous]
* Added limited support for github.com/segmentio/asm/base64. Compile your code
with the `jwx_asmbase64` build tag. This feature is EXPERIMENTAL.
Through limited testing, the use of a faster base64 library provide 1~5% increase
in throughput on average. It might make more difference if the input/output is large.
If you care about this performance improvement, you should probably enable
`goccy` JSON parser as well, by specifying `jwx_goccy,jwx_asmbase64` in your build call.
* Slightly changed the way global variables underneath `jwk.Fetch` are initialized and
configured. `jwk.Fetch` creates an object that spawns wokers to fetch JWKS when it's
first called.
You can now also use `jwk.SetGlobalFetcher()` to set a fetcher object which you can
control.
v2.0.9 - 21 Mar 2023
[Security Fixes]
* Updated use of golang.org/x/crypto to v0.7.0
[Bug fixes]
* Emitted PEM file for EC private key types used the wrong PEM armor (#875)
[Miscellaneous]
* Banners for generated files have been modified to allow tools to pick them up (#867)
* Remove unused variables around ReadFileOption (#866)
* Fix test failures
* Support bazel out of the box
* Now you can create JWS messages using `{"alg":"none"}`, by calling `jws.Sign()`
with `jws.WithInsecureNoSignature()` option. (#888, #890).
Note that there is no way to call
`jws.Verify()` while allowing `{"alg":"none"}` as you wouldn't be _verifying_
the message if we allowed the "none" algorithm. `jws.Parse()` will parse such
messages witout verification.
`jwt` also allows you to sign using alg="none", but there's no symmetrical
way to verify such messages.
v2.0.8 - 25 Nov 2022
[Security Fixes]
* [jws][jwe] Starting from go 1.19, code related to elliptic algorithms
panics (instead of returning an error) when certain methods
such as `ScalarMult` are called using points that are not on the
elliptic curve being used.
Using inputs that cause this condition, and you accept unverified JWK
from the outside it may be possible for a third-party to cause panics
in your program.
This has been fixed by verifying that the point being used is actually
on the curve before such computations (#840)
[Miscellaneous]
* `jwx.GuessFormat` now returns `jwx.InvalidFormat` when the heuristics
is sure that the buffer format is invalid.
v2.0.7 - 15 Nov 2022
[New features]
* [jwt] Each `jwt.Token` now has an `Options()` method
* [jwt] `jwt.Settings(jwt.WithFlattenedAudience(true))` has a slightly
different semantic than before. Instead of changing a global variable,
it now specifies that the default value of each per-token option for
`jwt.FlattenAudience` is true.
Therefore, this is what happens:
// No global settings
tok := jwt.New()
tok.Options.IsEnabled(jwt.FlattenAudience) // false
// With global settings
jwt.Settings(jwt.WithFlattenedAudience(true))
tok := jwt.New()
tok.Options.IsEnabled(jwt.FlattenAudience) // true
// But you can still turn FlattenAudience off for this
// token alone
tok.Options.Disable(jwt.FlattenAudience)
Note that while unlikely to happen for users relying on the old behavior,
this change DOES introduce timing issues: whereas old versions switched the
JSON marshaling for ALL tokens immediately after calling `jwt.Settings`,
the new behavior does NOT affect tokens that have been created before the
call to `jwt.Settings` (but marshaled afterwards).
So the following may happen:
// < v2.0.7
tok := jwt.New()
jwt.Settings(jwt.WithFlattenedAudience(true))
json.Marshal(tok) // flatten = on
// >= v2.0.7
tok := jwt.New() // flatten = off
jwt.Settings(jwt.WithFlattenedAudience(true))
json.Marshal(tok) // flatten is still off
It is recommended that you only set the global setting once at the
very beginning of your program to avoid problems.
Also note that `Clone()` copies the settings as well.
[Miscellaneous]
* WithCompact's stringification should have been that of the
internal indentity struct ("WithSerialization"), but it was
wrongly producing "WithCompact". This has been fixed.
* Go Workspaces have been enabled within this module.
- When developing, modules will refer to the main jwx module that they
are part of. This allows us to explicitly specify the dependency version
in, for example, ./cmd/jwx/go.mod but still develop against the local version.
- If you are using `goimports` and other tools, you might want to upgrade
binaries -- for example, when using vim-go's auto-format-on-save feature,
my old binaries took well over 5~10 seconds to compute the import paths.
This was fixed when I switched to using go1.19, and upgraded the binaries
used by vim-go
v2.0.6 - 25 Aug 2022
[Bug fixes][Security]
* [jwe] Agreement Party UInfo and VInfo (apv/apu) were not properly being
passed to the functions to compute the aad when encrypting using ECDH-ES
family of algorithms. Therefore, when using apu/apv, messages encrypted
via this module would have failed to be properly decrypted.
Please note that bogus encrypted messages would not have succeed being
decrypted (i.e. this problem does not allow spoofed messages to be decrypted).
Therefore this would not have caused unwanted data to to creep in --
however it did pose problems for data to be sent and decrypted from this module
when using ECDH-ES with apu/apv.
While not extensively tested, we believe this regression was introduced
with the v2 release.
v2.0.5 - 11 Aug 2022
[Bug fixes]
* [jwt] Remove stray debug log
* [jwk] Fix x5u field name, caused by a typo
* [misc] Update golangci-lint action to v3; v2 was causing weird problems
v2.0.4 - 19 Jul 2022
[Bug Fixes]
* [jwk] github.com/lestrrat-go/httprc, which jwk.Cache depends on,
had a problem with inserting URLs to be re-fetched into its queue.
As a result it could have been the case that some JWKS were not
updated properly. Please upgrade if you use jwk.Cache.
* [jwk] cert.Get could fail with an out of bounds index look up
* [jwk] Fix doc buglet in `KeyType()` method
[New Features]
* [jws] Add `jws.WithMultipleKeysPerKeyID()` sub-option to allow non-unique
key IDs in a given JWK set. By default we assume that a key ID is unique
within a key set, but enabling this option allows you to handle JWK sets
that contain multiple keys that contain the same key ID.
* [jwt] Before v2.0.1, sub-second accuracy for time based fields
(i.e. `iat`, `exp`, `nbf`) were not respected. Because of this the code
to evaluate this code had always truncated any-subsecond portion
of these fields, and therefore no sub-second comparisons worked.
A new option for validation `jwt.WithTruncation()` has been added
to workaround this. This option controls the value used to truncate
the time fields. When set to 0, sub-second comparison would be
possible.
FIY, truncatation will still happen because we do not want to
use the monotonic clocks when making comparisons. It's just that
truncating using `0` as its argument effectively only strips out
the monotonic clock
v2.0.3 - 13 Jun 2022
[Bug Fixes]
* [jwk] Update dependency on github.com/lestrrat-go/httprc to v1.0.2 to
avoid unintended blocking in the update goroutine for jwk.Cache
v2.0.2 - 23 May 2022
[Bug Fixes][Security]
* [jwe] An old bug from at least 7 years ago existed in handling AES-CBC unpadding,
where the unpad operation might remove more bytes than necessary (#744)
This affects all jwx code that is available before v2.0.2 and v1.2.25.
[New Features]
* [jwt] RFC3339 timestamps are also accepted for Numeric Date types in JWT tokens.
This allows users to parse servers that errnously use RFC3339 timestamps in
some pre-defined fields. You can change this behavior by setting
`jwt.WithNumericDateParsePedantic` to `false`
* [jwt] `jwt.WithNumericDateParsePedantic` has been added. This is a global
option that is set using `jwt.Settings`
v2.0.1 - 06 May 2022
* [jwk] `jwk.Set` had erronously been documented as not returning an error
when the same key already exists in the set. This is a behavior change
since v2, and it was missing in the docs (#730)
* [jwt] `jwt.ErrMissingRequiredClaim` has been deprecated. Please use
`jwt.ErrRequiredClaim` instead.
* [jwt] `jwt.WithNumericDateParsePrecision` and `jwt.WithNumericDateFormatPrecision`
have been added to parse and format fractional seconds. These options can be
passed to `jwt.Settings`.
The default precision is set to 0, and fractional portions are not parsed nor
formatted. The precision may be set up to 9.
* `golang.org/x/crypto` has been upgraded (#724)
* `io/ioutil` has been removed from the source code.
v2.0.0 - 24 Apr 2022
* This i the first v2 release, which represents a set of design changes
that were learnt over the previous 2 years. As a result the v2 API
should be much more consistent and uniform across packages, and
should be much more flexible to accomodate real-world needs.
For a complete list of changes, please see the Changes-v2.md file,
or check the diff at https://github.com/lestrrat-go/jwx/compare/v1...v2
[Miscellaneous]
* Minor house cleaning on code generation tools
[jwt]
* `jwt.ErrMissingRequiredClaim()` has been added
v2.0.0-beta2 - 16 Apr 2022
[jwk]
* Updated `jwk.Set` API and reflected pending changes from v1 which were
left over. Please see Changes-v2.md file for details.
* Added `jwk.CachedSet`, a shim over `jwk.Cache` that allows you to
have to write wrappers around `jwk.Cache` that retrieves a particular
`jwk.Set` out of it. You can use it to, for example, pass `jwk.CachedSet`
to a `jws.Verify`
cache := jwk.NewCache(ctx)
cache.Register(ctx, jwksURL)
cachedSet := jwk.NewCachedSet(cache, jwksURL)
jws.Verify(signed, jws.WithKeySet(cachedSet))
v2.0.0-beta1 - 09 Apr 2022
[Miscellaneous]
* Renamed Changes.v2 to Changes-v2.md
* Housecleaning for lint action.
* While v2 was not affected, ported over equivalent test for #681 to catch
regressions in the future.
* Please note that there is no stability guarantees on pre-releases.
v2.0.0-alpha1 - 04 Apr 2022
* Initial pre-release of v2 line. Please note that there is no stability guarantees
on pre-releases.