← Back to Feed CACHED · 2026-11-02 04:59:17 · CACHE_KEY CVE-2026-63209
CVE-2026-63209 · CWE-190 · Disclosed 2026-09-29

compress s2.NewDict signed integer overflow via oversized uvarint repeat value

ASSESSED — NOISGATE
Vendor
—
—
—
Reassessed
—
—
—
Verdict: —
Do you agree?
01 · The Real Story

A dictionary with a negative page number makes the reader walk off the book

CVE-2026-63209 affects the compress Go library's s2 package before v1.18.7. When an application calls s2.NewDict() with a malicious dictionary containing a uvarint-encoded repeat value larger than MaxInt64, the signed integer overflows to a negative number. Later, Dict.Encode() uses that negative value in unsafe.Pointer arithmetic and faults with SIGSEGV. It is a crash-only failure — no evidence of code execution, data corruption, or confidentiality impact.

The vendor severity of HIGH 7.5 is inflated by the CVSS vector AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H. That vector assumes the application accepts remote attacker-controlled bytes and feeds them directly into s2.NewDict. In most real deployments, dictionaries are static, built-in, or generated from trusted content. The practical exposure is much narrower, so the vendor score does not match reality.

"Crash-only library bug that needs attacker-controlled dictionary input — patch low-priority unless you expose s2.NewDict on untrusted data."
02 · The Attack Path

5 steps from start to impact.

STEP 01

Attacker reaches an endpoint that feeds attacker-controlled bytes to s2.NewDict

The vulnerable application must expose a path where an unauthenticated or low-privilege user can supply a byte slice that becomes the dictionary argument to s2.NewDict. This is not a default behavior of the library; it requires application-specific plumbing such as accepting compression dictionaries from API headers, file uploads, or client parameters.
Conditions required:
  • Application uses github.com/klauspost/compress/s2 version < 1.18.7
  • Application accepts untrusted input and passes it as a dictionary to s2.NewDict
  • No validation/sanitization on the dictionary content
Where this breaks in practice:
  • Most uses of s2 never expose dictionary input from the network
  • Dictionary content is typically fixed at compile time or derived from trusted data
  • Typical compression endpoints accept the data to compress, not the dictionary
Detection/coverage: No network scanner or WAF signature reliably identifies malicious s2 dictionary bytes; SBOM or source review is needed to confirm the library version and call sites.
STEP 02

Craft a dictionary with an oversized uvarint repeat value

The attacker constructs a dictionary that includes a uvarint-encoded repeat value exceeding MaxInt64. When s2.NewDict parses it, the signed integer overflows and produces a negative repeat index instead of rejecting the input.
Conditions required:
  • Attacker understands the s2 dictionary binary format
  • Ability to send arbitrary bytes to the vulnerable API
Where this breaks in practice:
  • Requires knowledge of the internal dictionary format; not a simple malformed input
  • No public exploit tooling has lowered attacker skill requirements
Detection/coverage: Generic fuzzing or custom static analysis can find the overflow, but commercial scanners do not currently flag this specific pattern.
STEP 03

Trigger Dict.Encode with the poisoned dictionary

The attacker causes the application to call Dict.Encode() using the previously created malicious dictionary. The negative repeat index flows into unsafe.Pointer arithmetic.
Conditions required:
  • Application automatically encodes data after creating the dictionary, or attacker can invoke the encode path
Where this breaks in practice:
  • If the application only creates the dictionary and never calls Encode, the crash does not occur
  • Many code paths validate or discard malformed dictionaries before encoding
Detection/coverage: Runtime crash analytics (e.g., SIGSEGV telemetry, core dumps) may reveal the fault after the fact.
STEP 04

Process crashes with SIGSEGV

The out-of-bounds memory access via unsafe.Pointer arithmetic causes a segmentation fault, terminating the process. Because the impact is availability-only, the attacker gains no code execution or data access.
Conditions required:
  • Compiled Go binary uses the vulnerable s2 version
  • Go runtime does not recover from the unsafe memory fault
Where this breaks in practice:
  • Only the current process crashes; unrelated services on the same host typically survive
  • Automatic restart or process supervision can quickly resume service
Detection/coverage: Container orchestration or systemd can log repeated restarts; APM tools may alert on crash loops.
STEP 05

Repeat crash requests to sustain denial of service

By sending multiple malformed dictionaries, the attacker can repeatedly crash the process and degrade availability. This is brute-force DoS, not a persistent compromise.
Conditions required:
  • Attacker can reach the vulnerable endpoint repeatedly
  • Service automatically restarts or is otherwise reachable after each crash
Where this breaks in practice:
  • Rate limiting, connection limits, and load balancer health checks reduce the blast radius
  • Each crash generates noise that security operations can observe
Detection/coverage: SIEM alarms on repeated SIGSEGV crashes or process restart storms would flag the activity.
03 · Compensating Control

1
MEDIUM 4.5→IGNORE 0.0
SEVERITY REDUCED
Upgrade github.com/klauspost/compress to v1.18.7 or later — This is the only permanent fix. Deploy within the noisgate remediation SLA of 365 days for MEDIUM severity. Update the Go module dependency, rebuild, and deploy the patched binaries.
2
MEDIUM 4.5→LOW 2.5
SEVERITY REDUCED
Validate or sanitize all dictionary inputs before passing to s2.NewDict — Reject dictionaries with uvarint repeat values greater than MaxInt64 or restrict dictionaries to an allow-list of static values. Deploy immediately, before the patch if needed.
3
MEDIUM 4.5→MEDIUM 3.5
Apply rate limits and input size caps on endpoints that accept compression dictionaries — Limits reduce the ability to repeatedly trigger crashes. Deploy within 30 days for HIGH-rated components or immediately for exposed services.
4
MEDIUM 4.5→MEDIUM 4.0
Enable process supervision and crash-loop alerting — Automatic restarts keep service available, and SIEM alerts on repeated SIGSEGV give defenders a detection signal. Deploy within 30 days.
What doesn't work
  • Network WAF rules generally cannot identify malicious s2 dictionary bytes because they look like ordinary compressed data.
  • Relying on Go memory safety does not help because the vulnerable code uses unsafe.Pointer, bypassing Go's bounds checks.
  • DEP/ASLR and similar OS-level memory protections do not prevent the SIGSEGV crash.
04 · Intelligence Metadata

The supporting signals.

Affected componentgithub.com/klauspost/compress/s2 prior to v1.18.7
Fixed versionv1.18.7
CWECWE-190 Integer Overflow
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H (HIGH 7.5)
EPSS score0.00572 (0.572% probability of exploitation in the next 30 days)
KEV statusNot listed by CISA Known Exploited Vulnerabilities
In-the-wild statusNo active exploitation, public campaigns, or ransomware activity observed as of this assessment
Proof of conceptNo public PoC located; exploitation requires custom-crafted dictionary bytes and an application-specific input path
Disclosure date2026-09-29
Reporter/OrgNot disclosed in the NVD record

Sources.

  1. NVD - CVE-2026-63209
  2. CVE.org - CVE-2026-63209
  3. GitHub - klauspost/compress releases
  4. OSV - CVE-2026-63209
  5. PoC Index - CVE-2026-63209
  6. FIRST - EPSS API
  7. MITRE - CWE-190
05 · The Call

Final Verdict
↓ DOWNGRADED to MEDIUM (4.5/10)

Why this verdict

  • Remote exposure is rare: AV:N assumes network reachability, but the vulnerable path requires the app to accept untrusted bytes as an s2.NewDict dictionary — not the normal compression use case.
  • Impact is availability-only: CVSS shows C:N/I:N; the worst confirmed outcome is SIGSEGV, not code execution, privilege escalation, or data exfiltration.
  • Friction is high: Most applications initialize s2 dictionaries from trusted constants, and many never expose Dict.Encode on attacker-influenced content.
  • Role multiplier: The bug is in a compression library, not in a domain controller, hypervisor, IdP, CA, PAM, backup, CI/CD registry, or network edge. A successful crash affects one process, not a domain, fleet, or supply chain.

Why not higher?

There is no evidence of active exploitation, no KEV listing, and EPSS is very low. The vulnerability does not provide integrity or confidentiality impact and does not map to a high-value-role outcome such as domain takeover or supply-chain pivot. The vendor score of 7.5 assumes the worst-case remote entry point that most deployments simply do not have.

Why not lower?

If an application does expose attacker-controlled dictionaries, repeated SIGSEGV can take down a critical service. The library is widely embedded across Go projects, and the fix is a simple version update, so it deserves a MEDIUM severity rather than LOW or IGNORE.

06 · Verification

Crowdsourced verification payload.

Run this on a Linux/macOS build or CI host where the Go application source tree or module cache is available. No elevated privileges are required. Invoke with the path to the application's go.mod file: bash check_cve-2026-63209.sh /path/to/go.mod. The script parses the module version and outputs VULNERABLE, PATCHED, or UNKNOWN.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
set -euo pipefail

TARGET="github.com/klauspost/compress"
FIXED="1.18.7"
INPUT="${1:-}"

if [[ -z "$INPUT" ]]; then
  echo "Usage: $0 /path/to/go.mod" >&2
  exit 3
fi

if [[ ! -f "$INPUT" ]]; then
  echo "UNKNOWN: file not found: $INPUT" >&2
  exit 2
fi

# Extract module version from go.mod or go.sum
VERSION=$(awk -v mod="$TARGET" '
  $1 == "require" && $2 == mod {print $3; exit}
  $1 == mod {print $2; exit}
' "$INPUT" | sed 's/^v//')

if [[ -z "$VERSION" ]]; then
  # Try go.sum
  VERSION=$(grep "^${TARGET} " "$INPUT" 2>/dev/null | awk '{print $2}' | sed 's/^v//' | head -n1 || true)
fi

if [[ -z "$VERSION" ]]; then
  echo "UNKNOWN: $TARGET not found in $INPUT"
  exit 2
fi

# Handle pseudo-versions like v1.18.6-0.2026...
VERSION_CLEAN=$(echo "$VERSION" | awk -F- '{print $1}')

compare_versions() {
  local a="$1" b="$2"
  if [[ "$a" == "$b" ]]; then echo 0; return; fi
  local IFS=.
  local i a_parts b_parts
  read -r -a a_parts <<< "$a"
  read -r -a b_parts <<< "$b"
  for i in 0 1 2; do
    local av="${a_parts[$i]:-0}"
    local bv="${b_parts[$i]:-0}"
    if (( av > bv )); then echo 1; return; fi
    if (( av < bv )); then echo -1; return; fi
  done
  echo 0
}

CMP=$(compare_versions "$VERSION_CLEAN" "$FIXED")
if [[ "$CMP" -lt 0 ]]; then
  echo "VULNERABLE: $TARGET version $VERSION_CLEAN < $FIXED"
  exit 1
else
  echo "PATCHED: $TARGET version $VERSION_CLEAN >= $FIXED"
  exit 0
fi