VYPR
High severityNVD Advisory· Published Nov 12, 2025· Updated Nov 13, 2025

CVE-2025-63811

CVE-2025-63811

Description

An issue was discovered in dvsekhvalnov jose2go 1.5.0 thru 1.7.0 allowing an attacker to cause a Denial-of-Service (DoS) via crafted JSON Web Encryption (JWE) token with an exceptionally high compression ratio.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

JWE tokens with extremely high compression ratios can cause a denial of service via resource exhaustion in jose2go before 1.7.

Vulnerability

In dvsekhvalnov/jose2go versions 1.5.0 through 1.7.0, the decompression step for JSON Web Encryption (JWE) tokens does not place adequate limits on memory allocation. By crafting a JWE token with an exceptionally high compression ratio — a "deflate bomb" attack — an attacker can cause the server to allocate an excessive amount of memory and processing time during decoding [1][2][3].

Exploitation

To exploit this, an attacker must submit a specially formed JWE token to a server that uses the jose2go library to decrypt and decompress the payload. No additional authentication is required if the server accepts JWEs from untrusted sources. The Proof of Concept in the issue tracker shows that a compression ratio of orders of magnitude can be achieved, leading to extreme memory consumption [3].

Impact

Successful exploitation results in a Denial of Service (DoS), as the server becomes unresponsive or crashes due to memory exhaustion. This affects any application using the affected library versions that processes untrusted JWE tokens [1][2].

Mitigation

The fix is included in jose2go version 1.7.0, which introduces deflate decompression memory limits. Users should update immediately to version 1.7.0 or later. No workaround is provided other than upgrading [1][4].

AI Insight generated on May 19, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
github.com/dvsekhvalnov/jose2goGo
< 1.7.01.7.0

Affected products

1
  • dvsekhvalnov/jose2godescription

Patches

1
0a0673dd7f28

Merge pull request #34 from dvsekhvalnov/issue-33-deflate-limit

5 files changed · +188 17
  • deflate.go+47 13 modified
    @@ -3,37 +3,71 @@ package jose
     import (
     	"bytes"
     	"compress/flate"
    -	"io/ioutil"
    +	"errors"
    +	"io"
     )
     
    +var ErrSizeExceeded = errors.New("Deflate stream size exceeded limit.")
    +
     func init() {
    -	RegisterJwc(new(Deflate))
    +	// 250Kb limited decompression buffer
    +	RegisterJwc(NewDeflate(250 * 1024))
     }
     
     // Deflate compression algorithm implementation
    -type Deflate struct {}
    +type Deflate struct {
    +	maxBufferSizeBytes int64
    +}
    +
    +func NewDeflate(maxBufferSizeBytes int64) JwcAlgorithm {
    +	return &Deflate{
    +		maxBufferSizeBytes: maxBufferSizeBytes,
    +	}
    +}
     
     func (alg *Deflate) Name() string {
     	return DEF
     }
     
     func (alg *Deflate) Compress(plainText []byte) []byte {
     	var buf bytes.Buffer
    -	deflate,_ := flate.NewWriter(&buf, 8) //level=DEFLATED
    -	
    +	deflate, _ := flate.NewWriter(&buf, 8) //level=DEFLATED
    +
     	deflate.Write(plainText)
     	deflate.Close()
    -	
    +
     	return buf.Bytes()
     }
     
    -func (alg *Deflate) Decompress(compressedText []byte) []byte {	
    -	
    -	enflated,_ := ioutil.ReadAll(
    -					flate.NewReader(
    -						bytes.NewReader(compressedText)))
    -	
    -	return enflated
    +func (alg *Deflate) Decompress(compressedText []byte) ([]byte, error) {
    +	enflated, err := io.ReadAll(
    +		newMaxBytesReader(alg.maxBufferSizeBytes,
    +			flate.NewReader(
    +				bytes.NewReader(compressedText))))
    +
    +	return enflated, err
     }
     
    +// Max bytes reader
    +type maxBytesReader struct {
    +	reader io.Reader
    +	limit  int64
    +}
    +
    +func newMaxBytesReader(limit int64, r io.Reader) io.Reader {
    +	return &maxBytesReader{reader: r, limit: limit}
    +}
     
    +func (mbr *maxBytesReader) Read(p []byte) (n int, err error) {
    +	if mbr.limit <= 0 {
    +		return 0, ErrSizeExceeded
    +	}
    +
    +	if int64(len(p)) > mbr.limit {
    +		p = p[0:mbr.limit]
    +	}
    +
    +	n, err = mbr.reader.Read(p)
    +	mbr.limit -= int64(n)
    +	return
    +}
    
  • .github/workflows/go.yml+32 0 added
    @@ -0,0 +1,32 @@
    +name: Build and test jose2go project 
    +
    +on:
    +  push:
    +    branches: [ "master" ]
    +  pull_request:
    +    branches: [ "master" ]
    +
    +jobs:
    +
    +  build-and-test:
    +    runs-on: ${{ matrix.os }}
    +    strategy:
    +      fail-fast: false
    +      matrix:
    +        os: [windows-latest, ubuntu-latest, macos-latest]
    +        version: ['1.20', '1.21', '1.22']
    +    steps:
    +    - name: Checkout library sources
    +      uses: actions/checkout@v3
    +
    +    - name: Set up Go
    +      uses: actions/setup-go@v4
    +      with:
    +        go-version: ${{ matrix.version }}
    +
    +    - name: Build
    +      run: go build -v ./...
    +
    +    - name: Test
    +      run: go test ./...
    +
    
  • jose.go+4 2 modified
    @@ -140,7 +140,7 @@ type JwsAlgorithm interface {
     // JwcAlgorithm is a contract for implementing compression algorithm
     type JwcAlgorithm interface {
     	Compress(plainText []byte) []byte
    -	Decompress(compressedText []byte) []byte
    +	Decompress(compressedText []byte) ([]byte, error)
     	Name() string
     }
     
    @@ -427,7 +427,9 @@ func decrypt(parts [][]byte, key interface{}) (plainText []byte, headers map[str
     							return nil, nil, errors.New(fmt.Sprintf("jwt.decrypt(): Unknown compression algorithm '%v'", zip))
     						}
     
    -						plainBytes = zipAlg.Decompress(plainBytes)
    +						if plainBytes, err = zipAlg.Decompress(plainBytes); err != nil {
    +							return nil, nil, err
    +						}
     					}
     
     					return plainBytes, jwtHeader, nil
    
  • README.md+16 0 modified
    @@ -15,6 +15,8 @@ Extensively unit tested and cross tested (100+ tests) for compatibility with [jo
     Used in production. GA ready. Current version is 1.6.
     
     ## Important
    +v1.7 introduced deflate decompression memory limits to avoid denial-of-service attacks aka 'deflate-bomb'. See [Customizing compression](#customizing-compression) section for details.
    +
     v1.6 security tuning options
     
     v1.5 bug fix release
    @@ -997,7 +999,21 @@ test, headers, err := Decode(token, func(headers map[string]interface{}, payload
     })
     ```
     
    +### Customizing compression
    +There were denial-of-service attacks reported on JWT libraries that supports deflate compression by constructing malicious payload that explodes in terms of RAM on decompression. See for details: [#33](https://github.com/dvsekhvalnov/jose2go/issues/33)
    +
    +As of v1.7.0 `jose2go` limits decompression buffer to 250Kb to limit memory consumption and additionaly provides a way to adjust the limit according to specific scenarios:
    +
    +```Go
    +    // Override compression alg with new limits (10Kb example)
    +    jose.RegisterJwc(RegisterJwc(NewDeflate(10240)))
    +```
    +
     ## Changelog
    +### 1.7
    +- 250Kb limit on decompression buffer
    +- ability to register deflate compressor with custom limits
    +
     ### 1.6
     - ability to deregister specific algorithms
     - configurable min/max restrictions for PBES2-HS256+A128KW, PBES2-HS384+A192KW, PBES2-HS512+A256KW
    
  • sec_test/security_vulnerabilities_test.go+89 2 modified
    @@ -2,12 +2,18 @@ package sec_test
     
     import (
     	"crypto/ecdsa"
    +	"crypto/rsa"
    +	"encoding/json"
     	"fmt"
    -	"github.com/dvsekhvalnov/jose2go"
    +	"strings"
    +	"testing"
    +	"time"
    +
    +	jose "github.com/dvsekhvalnov/jose2go"
     	"github.com/dvsekhvalnov/jose2go/arrays"
     	"github.com/dvsekhvalnov/jose2go/keys/ecc"
    +	Rsa "github.com/dvsekhvalnov/jose2go/keys/rsa"
     	. "gopkg.in/check.v1"
    -	"testing"
     )
     
     func Test(t *testing.T) { TestingT(t) }
    @@ -93,8 +99,89 @@ func (s *SecurityTestSuite) Test_AAD_IntegerOverflow(c *C) {
     	c.Assert(test, IsNil)
     }
     
    +func (s *SecurityTestSuite) Test_DeflateBomb(c *C) {
    +	strU := strings.Repeat("U", 400000000)
    +	strUU := strings.Repeat("U", 100000000)
    +
    +	payloadMap := map[string]string{
    +		"U":  strU,
    +		"UU": strUU,
    +	}
    +
    +	payloadBytes, _ := json.Marshal(payloadMap)
    +
    +	fmt.Println("Uncompressed payload length", len(payloadBytes))
    +	test, _ := jose.Encrypt(string(payloadBytes), jose.RSA_OAEP, jose.A256GCM, PubKey(), jose.Zip(jose.DEF))
    +	fmt.Println("Encoded & Compressed token length", len(test))
    +
    +	start := time.Now()
    +	payload, headers, err := jose.Decode(test, PrivKey())
    +	timeElapsed := time.Since(start)
    +	fmt.Printf("The `decode` took %s\n", timeElapsed)
    +
    +	c.Assert(payload, Equals, "")
    +	c.Assert(headers, IsNil)
    +	c.Assert(err, Equals, jose.ErrSizeExceeded)
    +}
    +
     func Ecc256() *ecdsa.PrivateKey {
     	return ecc.NewPrivate([]byte{193, 227, 73, 203, 97, 236, 112, 36, 140, 232, 1, 3, 76, 56, 52, 225, 184, 142, 190, 17, 97, 203, 37, 175, 56, 116, 31, 120, 95, 207, 196, 196},
     		[]byte{123, 201, 103, 8, 239, 128, 149, 43, 83, 248, 210, 85, 95, 231, 43, 132, 30, 208, 69, 136, 98, 139, 29, 55, 138, 89, 73, 57, 80, 14, 201, 201},
     		[]byte{84, 73, 131, 102, 144, 215, 92, 175, 41, 240, 221, 2, 157, 219, 49, 179, 221, 184, 171, 169, 210, 213, 21, 197, 1, 36, 101, 232, 23, 212, 169, 220})
     }
    +
    +func PubKey() *rsa.PublicKey {
    +	key, _ := Rsa.ReadPublic([]byte(pubKey))
    +	return key
    +}
    +
    +func PrivKey() *rsa.PrivateKey {
    +	key, _ := Rsa.ReadPrivate([]byte(privKey))
    +	return key
    +}
    +
    +var pubKey = `-----BEGIN CERTIFICATE-----
    +MIICnTCCAYUCBEReYeAwDQYJKoZIhvcNAQEFBQAwEzERMA8GA1UEAxMIand0LTIw
    +NDgwHhcNMTQwMTI0MTMwOTE2WhcNMzQwMjIzMjAwMDAwWjATMREwDwYDVQQDEwhq
    +d3QtMjA0ODCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKhWb9KXmv45
    ++TKOKhFJkrboZbpbKPJ9Yp12xKLXf8060KfStEStIX+7dCuAYylYWoqiGpuLVVUL
    +5JmHgXmK9TJpzv9Dfe3TAc/+35r8r9IYB2gXUOZkebty05R6PLY0RO/hs2ZhrOoz
    +HMo+x216Gwz0CWaajcuiY5Yg1V8VvJ1iQ3rcRgZapk49RNX69kQrGS63gzj0gyHn
    +Rtbqc/Ua2kobCA83nnznCom3AGinnlSN65AFPP5jmri0l79+4ZZNIerErSW96mUF
    +8jlJFZI1yJIbzbv73tL+y4i0+BvzsWBs6TkHAp4pinaI8zT+hrVQ2jD4fkJEiRN9
    +lAqLPUd8CNkCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAnqBw3UHOSSHtU7yMi1+H
    +E+9119tMh7X/fCpcpOnjYmhW8uy9SiPBZBl1z6vQYkMPcURnDMGHdA31kPKICZ6G
    +LWGkBLY3BfIQi064e8vWHW7zX6+2Wi1zFWdJlmgQzBhbr8pYh9xjZe6FjPwbSEuS
    +0uE8dWSWHJLdWsA4xNX9k3pr601R2vPVFCDKs3K1a8P/Xi59kYmKMjaX6vYT879y
    +gWt43yhtGTF48y85+eqLdFRFANTbBFSzdRlPQUYa5d9PZGxeBTcg7UBkK/G+d6D5
    +sd78T2ymwlLYrNi+cSDYD6S4hwZaLeEK6h7p/OoG02RBNuT4VqFRu5DJ6Po+C6Jh
    +qQ==
    +-----END CERTIFICATE-----`
    +
    +var privKey = `-----BEGIN RSA PRIVATE KEY-----
    +MIIEpAIBAAKCAQEAqFZv0pea/jn5Mo4qEUmStuhlulso8n1inXbEotd/zTrQp9K0
    +RK0hf7t0K4BjKVhaiqIam4tVVQvkmYeBeYr1MmnO/0N97dMBz/7fmvyv0hgHaBdQ
    +5mR5u3LTlHo8tjRE7+GzZmGs6jMcyj7HbXobDPQJZpqNy6JjliDVXxW8nWJDetxG
    +BlqmTj1E1fr2RCsZLreDOPSDIedG1upz9RraShsIDzeefOcKibcAaKeeVI3rkAU8
    +/mOauLSXv37hlk0h6sStJb3qZQXyOUkVkjXIkhvNu/ve0v7LiLT4G/OxYGzpOQcC
    +nimKdojzNP6GtVDaMPh+QkSJE32UCos9R3wI2QIDAQABAoIBAQCUmHBvSkqUHaK/
    +IMU7q2FqOi0KWswDefEiJKQhRu9Wv5NOgW2FrfqDIXrDp7pg1dBezgeExHLX9v6d
    +FAOTwbj9/m6t3+r6k6fm7gp+ao3dfD6VgPd12L2oXQ0t5NVQ1UUBJ4/QUWps9h90
    +3AP4vK/COG1P+CAw4DDeZi9TlwF/Pr7e492GXcLBAUJODA6538ED2nYw8xQcbzbA
    +wr+w07UjRNimObtOfA0HCIpsx/6LkIqe6iGChisQNgt4yDd/fZ4GWOUIU1hqgK1P
    +6avVl7Q5Mk0PTi9t8ui1X4EEq6Uils45J5WkobuAnFkea/uKfs8Tn9bNrEoVWgdb
    +fBHq/8bNAoGBANKmjpE9e+L0RtxP+u4FN5YDoKE+i96VR7ru8H6yBKMcnD2uf5mV
    +RueEoL0FKHxlGBBo0dJWr1AIwpcPbTs3Dgx1/EQMZLg57QBZ7QcYETPiMwMvEM3k
    +Zf3G4YFYwUwIQXMYPt1ckr+RncRcq0GiKPDsvzzyNS+BBSmR5onAXd7bAoGBAMyT
    +6ggyqmiR/UwBn87em+GjbfX6YqxHHaQBdWwnnRX0JlGTNCxt6zLTgCIYxF4AA7eR
    +gfGTStwUJfAScjJirOe6Cpm1XDgxEQrT6oxAl17MR/ms/Z88WrT73G+4phVvDpVr
    +JcK+CCESnRI8xGLOLMkCc+5NpLajqWCOf1H2J8NbAoGAKTWmTGmf092AA1euOmRQ
    +5IsfIIxQ5qGDn+FgsRh4acSOGE8L7WrTrTU4EOJyciuA0qz+50xIDbs4/j5pWx1B
    +JVTrnhBin9vNLrVo9mtR6jmFS0ko226kOUpwEVLgtdQjobWLjtiuaMW+/Iw4gKWN
    +ptxZ6T1lBD8UWHaPiEFW2+MCgYAmfSWoyS96YQ0QwbV5TDRzrTXA84yg8PhIpOWc
    +pY9OVBLpghJs0XlQpK4UvCglr0cDwGJ8OsP4x+mjUzUc+aeiKURZSt/Ayqp0KQ6V
    +uIlCEpjwBnXpAYfnSQNeGZVVrwFFZ1VBYFNTNZdLmRcxp6yRXN7G1ODKY9w4CFc3
    +6mHsxQKBgQCxEA+KAmmXxL++x/XOElOscz3vFHC4HbpHpOb4nywpE9vunnHE2WY4
    +EEW9aZbF22jx0ESU2XJ1JlqffvfIEvHNb5tmBWn4HZEpPUHdaFNhb9WjkMuFaLzh
    +cydwnEftq+3G0X3KSxp4p7R7afcnpNNqfneYODgoXxTQ4Q7ZyKo72A==
    +-----END RSA PRIVATE KEY-----`
    

Vulnerability mechanics

Generated 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.