VYPR
High severity7.5NVD Advisory· Published Mar 31, 2026· Updated Apr 6, 2026

CVE-2026-34240

CVE-2026-34240

Description

JOSE is a Javascript Object Signing and Encryption (JOSE) library. Prior to version 0.3.5+1, a vulnerability in jose could allow an unauthenticated, remote attacker to forge valid JWS/JWT tokens by using a key embedded in the JOSE header (jwk). The vulnerability exists because key selection could treat header-provided jwk as a verification candidate even when that key was not present in the trusted key store. Since JOSE headers are untrusted input, an attacker could exploit this by creating a token payload, embedding an attacker-controlled public key in the header, and signing with the matching private key. Applications using affected versions for token verification are impacted. This issue has been patched in version 0.3.5+1. A workaround for this issue involves rejecting tokens where header jwk is present unless that jwk matches a key already present in the application's trusted key store.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
josePub
< 0.3.5+10.3.5+1

Affected products

1

Patches

1
b07799aac1f5

fix: improved key resolution in JsonWebKeyStore

https://github.com/appsup-dart/joserikbellensMar 27, 2026via ghsa
2 files changed · +38 13
  • lib/src/jwk.dart+4 13 modified
    @@ -463,24 +463,15 @@ class JsonWebKeyStore {
       }
     
       Stream<JsonWebKey> _allKeys(JoseHeader header) async* {
    -    // The key provided by the 'jwk'
    -    if (header.jsonWebKey != null) yield header.jsonWebKey!;
    -    // Other applicable keys available to the application
    +    // The keys added with `addKey`
         yield* Stream.fromIterable(_keys);
     
    +    // The keys added with `addKeySet`
         for (var s in _keySets) {
           yield* Stream.fromIterable(s.keys);
         }
    -/*
    -    // TODO trust keys from header?
    -    // Keys referenced by the 'jku'
    -    if (header.jwkSetUrl != null) yield* _keysFromSet(header.jwkSetUrl);
    -    // The key referenced by the 'x5u'
    -    // TODO
    -    // The key provided by the 'x5c'
    -    // TODO
    -*/
    -    // Other applicable keys available to the application
    +
    +    // The keys added with `addKeySetUrl`
         for (var url in _keySetUrls) {
           yield* _keysFromSet(url).where((v) => v != null).cast();
         }
    
  • test/jwt_test.dart+34 0 modified
    @@ -1,5 +1,7 @@
    +import 'package:jose/src/jose.dart';
     import 'package:jose/src/jwk.dart';
     import 'package:jose/src/jwt.dart';
    +import 'package:jose/src/jws.dart';
     import 'package:test/test.dart';
     
     void main() {
    @@ -159,6 +161,38 @@ void main() {
         expect(claims.expiry, DateTime.fromMillisecondsSinceEpoch(1300819380000));
       });
     
    +  group('Verification key selection', () {
    +    test('JWT with header jwk is rejected when no matching trusted key exists',
    +        () async {
    +      final trustedKey = JsonWebKey.generate('RS256');
    +      final keyStore = JsonWebKeyStore()..addKey(trustedKey);
    +
    +      final alternateKey = JsonWebKey.generate('RS256');
    +      final claims = JsonWebTokenClaims.fromJson({
    +        'sub': 'user-2',
    +        'iss': 'https://trusted-issuer.example.com',
    +        'aud': 'my-application',
    +        'exp': DateTime.now().add(const Duration(hours: 1)).millisecondsSinceEpoch ~/ 1000,
    +        'iat': DateTime.now().millisecondsSinceEpoch ~/ 1000,
    +      });
    +      final builder = JsonWebSignatureBuilder()
    +        ..jsonContent = claims.toJson()
    +        ..setProtectedHeader('typ', 'JWT')
    +        ..addRecipient(alternateKey, algorithm: 'RS256')
    +        ..setProtectedHeader(
    +            'jwk',
    +            JsonWebKey.fromCryptoKeys(
    +                    publicKey: alternateKey.cryptoKeyPair.publicKey)
    +                .toJson());
    +      final jwtCompact = builder.build().toCompactSerialization();
    +
    +      expect(
    +        () => JsonWebToken.decodeAndVerify(jwtCompact, keyStore),
    +        throwsA(isA<JoseException>()),
    +      );
    +    });
    +  });
    +
       group('JWT with ES256K signature', () {
         test('JWT with ES256K signature', () async {
           var key = JsonWebKey.fromJson({
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

4

News mentions

0

No linked articles in our index yet.