high

CVE

CVE-2026-116591, CVE-2026-116587, CVE-2026-116586, CVE-2026-116585, CVE-2026-116189, CVE-2026-116191, CVE-2026-116195, CVE-2026-116196, CVE-2026-116187, CVE-2026-116188, CVE-2026-116190, CVE-2026-116192, CVE-2026-116193, CVE-2026-116194

CWE

CWE-190, CWE-125, CWE-347, CWE-22, CWE-400, CWE-674, CWE-200

Affected Surface

  • Go `github.com/klauspost/compress` versions `< v1.20.2` (`CVE-2026-116591` / `GHSA-fpmh-frq8-7rj8`)
  • Go `github.com/go-jose/go-jose/v4` versions `< v4.1.6` for `CVE-2026-116587` (`GHSA-mgcc-cww5-fp2q`) and `< v4.1.5` for `CVE-2026-116586` (`GHSA-vvm8-gf78-28g4`) and `CVE-2026-116585` (`GHSA-4w3g-jfj2-cw2q`)
  • Go `github.com/rclone/rclone` versions `< v1.75.2` (`1.55.0` to `< 1.75.2` for `CVE-2026-116189` `selfupdate` signature bypass; `< 1.75.2` for `CVE-2026-116191` `serve webdav` `MKCOL` path traversal and `CVE-2026-116195` `.rclonelink` traversal)

TL;DR

Between 25 and 26 October 2026, 14 vulnerabilities were published across three foundational Go packages and tools: github.com/klauspost/compress, github.com/go-jose/go-jose/v4, and github.com/rclone/rclone:

  1. klauspost/compress (CVE-2026-116591 / GHSA-fpmh-frq8-7rj8, CVSS 8.7 High, fixed in v1.20.2): In both zstd.Decoder.DecodeAll and streaming decompression, a crafted two-block zstd frame that reaches huff0.ReadTable with a Finite State Entropy (FSE) normalized count of 32768 causes readNCount() to truncate int16(32768) to -32768. That wrapped negative value leaves stale fse.Scratch decode-table entries from the first block in place, causing nextFast() in the second block to derive an out-of-range state (32768) and panic with a slice bounds error. Because klauspost/compress powers HTTP, gRPC, object-storage, and container image decompression across the Go ecosystem, any service that does not wrap decompression in recover() can be crashed by a single request.
  2. go-jose/go-jose (CVE-2026-116587, CVSS 7.5 High; CVE-2026-116586, CVSS 6.9; CVE-2026-116585, CVSS 6.9, fixed in v4.1.5 and v4.1.6): Prior to v4.1.6, go-jose passed attacker-supplied RSA modulus and prime parameters from untrusted JWKs directly to crypto/rsa.PrivateKey.Validate without size or consistency bounds (triggering cubic CPU exhaustion on Go 1.24+), and parsed embedded jwk headers in JWE messages before checking whether the alg header was allowed. Prior to v4.1.5, deeply nested JSON inputs caused an unrecoverable goroutine stack overflow (CVE-2026-116586), and an empty JWE ciphertext with a valid HMAC tag under A128CBC-HS256, A192CBC-HS384, or A256CBC-HS512 panicked inside unpadBuffer() (CVE-2026-116585).
  3. rclone (CVE-2026-116189 and CVE-2026-116191, both CVSS 7.5 High, plus eight companion CVEs fixed in v1.75.2): In rclone selfupdate (1.55.0 to < 1.75.2), verifyHashsumDownloaded() verified the PGP clearsignature on SHA256SUMS with clearsign.Decode(sumsBuf), but then searched the entire raw sumsBuf rather than the signed block.Bytes for the archive’s SHA-256 hash. An attacker on the download path could prepend an unsigned checksum line above -----BEGIN PGP SIGNED MESSAGE----- and install a trojanized rclone binary (CVE-2026-116189). In rclone serve webdav, sending MKCOL /.. planted a VFS node above the served root (CVE-2026-116191), and in --links mode, translateLink() stripped the .rclonelink suffix after the root-containment check so a directory named ...rclonelink resolved to .. (CVE-2026-116195).

What to do now: Upgrade github.com/klauspost/compress to v1.20.2, github.com/go-jose/go-jose/v4 to v4.1.6, and rclone to v1.75.2 (do not use rclone selfupdate over an untrusted network to perform the upgrade from < v1.75.2).

Affected packages and projects

EcosystemModule / PackageCVE / AdvisorySeverityAffected versionsFixed versionVulnerable component
Gogithub.com/klauspost/compressCVE-2026-116591 (GHSA-fpmh-frq8-7rj8)CVSS 8.7 High< v1.20.2v1.20.2fse/decompress.go (readNCount), fse/compress.go (validateNorm)
Gogithub.com/go-jose/go-jose/v4CVE-2026-116587 (GHSA-mgcc-cww5-fp2q)CVSS 7.5 High< v4.1.6v4.1.6jwk.go (UnmarshalJSON RSA bounds), jwe.go (sanitized header order)
Gogithub.com/go-jose/go-jose/v4CVE-2026-116586 (GHSA-vvm8-gf78-28g4)CVSS 6.9 Medium< v4.1.5v4.1.5json/scanner.go (pushParseState unbounded nesting)
Gogithub.com/go-jose/go-jose/v4CVE-2026-116585 (GHSA-4w3g-jfj2-cw2q)CVSS 6.9 Medium< v4.1.5v4.1.5cipher/cbc_hmac.go (unpadBuffer empty slice index)
Go / CLIgithub.com/rclone/rcloneCVE-2026-116189 (GHSA-w33h-3qgq-8mv8)CVSS 7.5 High>= v1.55.0, < v1.75.2v1.75.2cmd/selfupdate/verify.go (verifyHashsumDownloaded)
Go / CLIgithub.com/rclone/rcloneCVE-2026-116191 (GHSA-44pm-2q5p-fm63)CVSS 7.5 High< v1.75.2v1.75.2cmd/serve/webdav/webdav.go (ServeHTTP MKCOL / Destination)
Go / CLIgithub.com/rclone/rcloneCVE-2026-116195 (GHSA-55qp-jrwr-x827)CVSS 6.1 Medium< v1.75.2v1.75.2backend/local/local.go (translateLink .rclonelink trim)
Go / CLIgithub.com/rclone/rcloneCVE-2026-116196 (GHSA-gpw7-77cq-9f72)CVSS 5.3 Medium< v1.75.2v1.75.2backend/b2/b2.go (--b2-download-url redirect secret headers)
Go / CLIgithub.com/rclone/rcloneCVE-2026-116187, 116188, 116190, 116192..116194CVSS 3.7 to 6.8< v1.75.2 (< v1.74.2 for 116192)v1.75.2cmd/serve/s3, backend/webdav, cmd/serve/webdav (OPTIONS), backend/pcloud

Technical analysis

1. CVE-2026-116591: int16(32768) wraparound and stale fse.Scratch table panic in klauspost/compress

When decompressing a zstd block that uses Huffman-compressed literals (huff0.ReadTable), klauspost/compress/fse decodes the Finite State Entropy (FSE) normalized symbol distribution in readNCount() and stores each symbol’s count into s.norm[charnum&0xff], which is an int16 array.

In FSE, the table size is 1 << tableLog, and maxTableLog is 15 (32768 states). If a malformed block sets tableLog = 15 and assigns the entire 32768 probability mass to a single symbol (count = 32768), casting int16(count) wraps 32768 to -32768. Because buildDtable() only populates table cells for positive counts (v > 0) and special-cases v == -1 (“less than 1” probability), a wrapped -32768 entry wrote zero cells into the decoding table while remaining reached 0.

In a two-block zstd frame, the first block populates fse.Scratch’s decoding table with valid states, and the second block triggers the count = 32768 wraparound so buildDtable() leaves the first block’s stale states in s.decTable. When nextFast() steps through that corrupted table, it computes newState = 32768 and panics indexing s.decTable[32768]. Commit 7f5d852872 fixes both readNCount() and validateNorm():

--- a/fse/decompress.go
+++ b/fse/decompress.go
@@ -123,6 +124,11 @@ func (s *Scratch) readNCount() error {
 			remaining -= count
 			gotTotal += count
 		}
+		if count > math.MaxInt16 {
+			// Only one symbol filling a tableLog 15 table, which cannot be decoded.
+			// Truncated, it would leave the decoding table unwritten.
+			return fmt.Errorf("corruption detected (count %d > %d)", count, math.MaxInt16)
+		}
 		s.norm[charnum&0xff] = int16(count)
--- a/fse/compress.go
+++ b/fse/compress.go
@@ -659,7 +659,8 @@ func (s *Scratch) validateNorm() (err error) {
 		if v >= 0 {
 			total += int(v)
 		} else {
-			total -= int(v)
+			// -1 takes one cell. Adding -v would let a wrapped -32768 pass.
+			total++
 		}
 	}

2. CVE-2026-116587, CVE-2026-116586, and CVE-2026-116585 in go-jose/go-jose

The three go-jose advisories hit JWK parsing, JSON unmarshaling, and JWE decryption:

  • Unbounded RSA JWK validation (CVE-2026-116587, commit a0111f8274): When JSONWebKey.UnmarshalJSON parsed an RSA key, it did not cap the bit length of the modulus n or check the consistency of private parameters (d, p, q, dp, dq, qi) before calling crypto/rsa.PrivateKey.Validate(). On Go 1.24+, Validate() performs primality and modulus-reconstruction checks whose CPU cost scales cubically with key size, allowing a single JWK with a huge modulus to stall a server. In jwe.go, rawJSONWebEncryption.sanitized() also called mergedHeaders.sanitized() (which parses any embedded jwk header) before checking whether the JWE’s alg header matched the caller’s expectedKeyAlgorithms slice. v4.1.6 adds MaxRSAModulusBits, rejects private JWK fields when unmarshaling untrusted headers (allowPrivate = false), and moves mergedHeaders.sanitized() after the algorithm allowlist check.
  • Unbounded JSON nesting stack overflow (CVE-2026-116586, commit a31af25836): go-jose bundles a custom case-sensitive JSON fork in json/scanner.go. Because pushParseState() appended to s.parseState without a depth cap, a token containing deeply nested [ or { characters overflowed the goroutine call stack and terminated the Go runtime. v4.1.5 enforces const maxNestingDepth = 10000.
  • Empty CBC-HMAC ciphertext panic (CVE-2026-116585, commit 35883f7999): In cipher/cbc_hmac.go, unpadBuffer(buffer []byte, blockSize int) checked if len(buffer)%blockSize != 0, which evaluates to 0 != 0 (false) when len(buffer) == 0, and then indexed buffer[len(buffer)-1], panicking with index out of range [-1]:
--- a/cipher/cbc_hmac.go
+++ b/cipher/cbc_hmac.go
@@ -176,7 +176,9 @@ func padBuffer(buffer []byte, blockSize int) []byte {
 // Remove padding
 func unpadBuffer(buffer []byte, blockSize int) ([]byte, error) {
-	if len(buffer)%blockSize != 0 {
+	// A padded buffer can't be empty because an empty input is padded with
+	// `blockSize` bytes, resulting in a non-empty ciphertext.
+	if len(buffer) == 0 || len(buffer)%blockSize != 0 {
 		return nil, errors.New("go-jose/go-jose: invalid padding")
 	}

3. CVE-2026-116189, CVE-2026-116191, and CVE-2026-116195 in rclone v1.75.2

In rclone before v1.75.2, cmd/selfupdate/verify.go downloaded the PGP-clearsigned SHA256SUMS file into sumsBuf, decoded the clearsigned block with block, _ := clearsign.Decode(sumsBuf), verified the PGP signature on block.Bytes, and then passed the raw sumsBuf (instead of block.Bytes) to findFileHash():

--- a/cmd/selfupdate/verify.go
+++ b/cmd/selfupdate/verify.go
@@ -86,7 +86,8 @@ func verifyHashsumDownloaded(ctx context.Context, sumsBuf []byte, archive string
 		return fmt.Errorf("invalid hashsum signature: %w", err)
 	}
 
-	wantHash, err := findFileHash(sumsBuf, archive)
+	// Only read hashes from the signed text
+	wantHash, err := findFileHash(block.Bytes, archive)
 	if err != nil {
 		return err
 	}

As demonstrated by the regression tests UnsignedPrefix and UnsignedInArmor in commit 3a14789eb4, clearsign.Decode ignores any bytes before -----BEGIN PGP SIGNED MESSAGE----- and any lines injected after the armor CRC checksum (or hidden via OpenPGP - dash-escaping). A man-in-the-middle or mirror attacker could prepend <attacker_sha256> rclone-v1.75.1-linux-amd64.zip\n ahead of the genuine signed block, pass signature verification, and make rclone selfupdate install a malicious binary.

The same v1.75.2 release also fixes:

  • WebDAV MKCOL /.. path traversal (CVE-2026-116191, commit 133ced103a): cmd/serve/webdav/webdav.go did not reject . or .. segments in r.URL.Path or the Destination header on COPY and MOVE before handing the path to golang.org/x/net/webdav and the rclone VFS. Sending MKCOL /.. created a VFS directory entry for the parent of the served root, allowing subsequent PUT, MOVE, or COPY requests to write outside the served directory.
  • .rclonelink suffix-trim escape (CVE-2026-116195, commit 1b500594d3): When syncing with -l / --links, backend/local/local.go checked that the destination path stayed inside the local root while the filename still carried the .rclonelink suffix, and then called strings.TrimSuffix(localPath, ".rclonelink"). A directory named ...rclonelink passed the containment check as a normal child entry and then became .. once .rclonelink was stripped, allowing metadata syncs (--metadata) to alter ownership, permissions, timestamps, and xattrs on the destination’s parent directory.

Detection and remediation

# 1. Check Go module lockfiles for vulnerable klauspost/compress, go-jose, and rclone versions
rg -n 'github\.com/(klauspost/compress|go-jose/go-jose|rclone/rclone)\b' go.mod go.sum 2>/dev/null

# 2. Check compiled Go binaries on servers or in container images for embedded module versions
for bin in $(which rclone 2>/dev/null) ./bin/*; do
  [ -f "$bin" ] && go version -m "$bin" 2>/dev/null | grep -E 'klauspost/compress|go-jose/go-jose|rclone/rclone'
done
  1. Upgrade Go dependencies: Run go get github.com/klauspost/compress@v1.20.2 and go get github.com/go-jose/go-jose/v4@v4.1.6, then rebuild and redeploy affected services.
  2. Upgrade rclone via package manager or verified release download: Upgrade rclone to v1.75.2 or later by downloading the release from the official site and verifying gpg --verify SHA256SUMS manually (or using your OS package manager), rather than running rclone selfupdate from an older binary over an untrusted network.

Timeline

  • 2026-09-02 to 2026-09-03: go-jose/go-jose merges fixes for CVE-2026-116585 (35883f7999) and CVE-2026-116586 (a31af25836) and releases v4.1.5.
  • 2026-09-09 to 2026-09-23: rclone merges fixes for CVE-2026-116196 (ed9f1d836e), CVE-2026-116195 (1b500594d3), CVE-2026-116191 (133ced103a / 2f43b99abe), CVE-2026-116189 (3a14789eb4), and CVE-2026-116187 / 116188 (8d97a50c4a, 4df376e2db).
  • 2026-10-09: rclone releases v1.75.2.
  • 2026-10-12 to 2026-10-14: klauspost/compress merges 7f5d852872 and releases v1.20.2; go-jose/go-jose merges a0111f8274 (CVE-2026-116587) and releases v4.1.6.
  • 2026-10-25 to 2026-10-26: NVD and the GitHub Advisory Database publish CVE-2026-116187 through CVE-2026-116196, CVE-2026-116585 through CVE-2026-116587, and CVE-2026-116591.

From research to remediation

Check whether this pattern exists in your codebase

Turn this research into a remediation workflow. Use AI-native static analysis to find similar application vulnerabilities and generate review-ready fixes.

References