← Back to Feed CACHED · 2026-06-29 20:22:59 · CACHE_KEY CVE-2026-46604
CVE-2026-46604 · CWE-125 · Disclosed 2026-06-26

The TIFF decoder can panic when decoding an invalid image with an out-of-bounds strip offset

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

A crash bug in a niche image decoder that vendors love to label HIGH because the input is network-reachable

CVE-2026-46604 is a panic in the TIFF decoder of golang.org/x/image — a supplementary Go imaging package, not the standard library. A crafted TIFF with an out-of-bounds strip offset trips an unchecked slice index inside tiff.Decode, and the goroutine panics with runtime error: slice bounds out of range. The bug affects every release of golang.org/x/image prior to 0.43.0; the fix landed in CL 788421 and ships as GO-2026-5066. Reporter credit: *sorte*.

Vendor severity here is the Go security team's standard CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H — which is mechanically correct (the panic is unauthenticated, network-triggerable in some apps, and is *availability* impact) but practitionally misleading. There is no memory disclosure, no code execution, no integrity impact. The damage ceiling is whatever the panicking process was doing — and in Go, a panic on a per-request goroutine inside an http.Handler is recovered by net/http's default serverHandler. Real-world blast radius is much narrower than 7.5 implies.

"A Go TIFF library panic that crashes goroutines on malformed input — vendor HIGH overstates the impact for almost every real deployment."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Identify a service that decodes untrusted TIFFs via golang.org/x/image

The attacker enumerates services that ingest user-supplied images and route TIFF MIME types (or content-sniffed TIFF magic II*\0 / MM\0*) into tiff.Decode. Typical targets: avatar/upload pipelines, OCR/scan-ingestion microservices, thumbnailing workers, document-conversion APIs. Tools: ffuf, gobuster, and content-type fuzzers like tiffuzz.
Conditions required:
  • Target accepts user-uploaded images or fetches remote images
  • TIFF format is in the accepted/auto-detected set
  • Server uses golang.org/x/image/tiff < 0.43.0
Where this breaks in practice:
  • Most Go web apps only accept JPEG/PNG/WebP and explicitly reject TIFF
  • Many pipelines pre-validate via libvips or ImageMagick (different code path entirely)
  • Cloud image CDNs (Cloudflare Images, imgix, Cloudinary) handle decode outside the customer's Go process
Detection/coverage: Snyk, GitHub Dependabot, govulncheck, Trivy, and OSV-Scanner all flag this advisory by module path. govulncheck is the highest-fidelity check because it verifies the *vulnerable symbol* tiff.Decode is actually reached in your binary.
STEP 02

Craft a TIFF with an out-of-bounds StripOffsets tag

Using a TIFF builder (tiffcp, exiftool, or a 20-line Go script), the attacker forges a TIFF whose StripOffsets (tag 273) points past the file size, or whose StripByteCounts (tag 279) exceeds the remaining strip buffer. Public PoC pattern is trivial — set StripOffsets = 0xFFFFFFFF.
Conditions required:
  • Knowledge of TIFF tag layout — well documented in the TIFF 6.0 spec
Where this breaks in practice:
  • None — this is a one-liner. Expect public PoCs within days of disclosure.
Detection/coverage: WAFs do not parse TIFF tag structures; rely on egress sandboxing or pre-decode validation instead.
STEP 03

Submit the TIFF to the decoding endpoint

The malformed file is POSTed to the upload/ingest endpoint, or hosted at a URL the target server fetches (SSRF-adjacent flows: webhook image previews, OpenGraph scrapers, RSS image hydration). tiff.Decode is called and panics.
Conditions required:
  • Reachable HTTP endpoint that consumes user-supplied bytes
  • No size/type pre-validation that blocks TIFF
Where this breaks in practice:
  • Upload size limits, content-type allowlists, and pre-decode image.DecodeConfig checks (which also panic, so this doesn't always help) all narrow exposure
  • API gateways (Kong, Envoy) frequently reject unknown MIME types
Detection/coverage: Application logs will show runtime error: slice bounds out of range followed by a Go stack trace through tiff.Decode — very high-signal IOC.
STEP 04

Realize the impact: goroutine panic, process crash, or denial-of-service

If the call is inside net/http's default serve loop, the panic is recovered and only that one request fails — effectively a logged error, not an outage. If the call sits in a background worker, a go func() without recover(), or a non-HTTP service (gRPC streaming, queue consumer, CLI batch job), the panic terminates the entire process. Repeated submissions become a sustained DoS against the worker pool.
Conditions required:
  • Decode call runs without defer recover()
  • Worker is not isolated per-message (e.g., shared goroutine pool)
Where this breaks in practice:
  • net/http recovers panics by default — the most common Go web deployment is largely insulated
  • Kubernetes restarts crashed pods within seconds
  • No persistence, no privilege escalation, no data exposure
Detection/coverage: OOM/crash loop alerts in Prometheus, k8s BackOff events, and panic stack traces in stdout aggregators (Loki, Datadog Logs).
03 · Intelligence Metadata

The supporting signals.

In-the-wild exploitationNone observed. No KEV listing, no GreyNoise tags, no incident-response chatter at disclosure +4 days.
Proof-of-conceptTrivial to write from the Go CL 788421 test fixture; expect public PoCs in osv-scanner regression suites and security blogs within days.
EPSS0.00169 (~0.17%) — bottom-quartile percentile, consistent with availability-only Go library bugs.
KEV statusNot listed by CISA as of 2026-06-30.
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H — availability-only; no confidentiality or integrity impact. Vendor score 7.5 (HIGH).
Affected versionsAll golang.org/x/image releases before 0.43.0 (module path: golang.org/x/image/tiff).
Fixed version0.43.0 — see GO-2026-5066 and CL 788421.
Exposure populationLimited. golang.org/x/image is a supplementary package; most Go HTTP services use image/jpeg + image/png from stdlib or shell out to libvips/ImageMagick. govulncheck data suggests <5% of indexed Go binaries import the tiff subpackage.
Disclosure date2026-06-26 (reserved 2026-05-15).
Reporter*sorte* via the Go security team.
04 · The Call

noisgate verdict.

Final Verdict
DOWNGRADED to MEDIUM (5.3/10)

Downgraded from vendor HIGH (7.5) to MEDIUM (5.3) because the single decisive factor is availability-only impact with no code execution path — the CVSS A:H reflects a goroutine panic, not RCE or data exposure. The blast radius is bounded by the panic-recovery behavior of net/http and the narrow population of Go services that actually parse TIFFs.

HIGH Technical impact ceiling (DoS only, no memory safety violation)
HIGH Patch availability and version identification
MEDIUM Exposure population — depends on whether your Go services accept TIFF uploads

Why this verdict

  • Availability-only impact: vector explicitly says C:N/I:N/A:H. There is no RCE, no information leak, no privilege escalation — the worst case is a panic.
  • net/http panic recovery: the default Go HTTP server recovers per-request panics, so the most common deployment shape (an HTTP handler that decodes uploads) degrades to a logged 500 rather than a process crash.
  • Narrow library footprint: golang.org/x/image/tiff is opt-in. Stdlib JPEG/PNG/GIF/WebP decoders are unaffected. Most image-handling Go services never import this package.
  • Role multiplier (workstation/dev sandbox): non-applicable — this is a library, not a deployment role. No fleet-scale identity, hypervisor, CI/CD, or kernel-mode amplifier exists.
  • Role multiplier (typical app server): panic is contained per-request by net/http recovery; outcome is a single failed request. Floor stays MEDIUM at worst.
  • Role multiplier (background worker / gRPC streaming server / queue consumer): chain succeeds — these contexts often lack recover() and a sustained malformed-TIFF stream can crash-loop the worker. Blast radius is host-level service outage, not fleet compromise. Floor remains MEDIUM; does not lift to HIGH because remediation is a single go get and there is no privilege escalation.
  • EPSS 0.17% and no KEV listing confirm the realistic-exploit picture: low priority by external telemetry.

Why not higher?

HIGH (7.0+) would require either a real path to RCE, information disclosure, or a deployment role with fleet-scale blast radius. None apply: the bug is a slice-bounds panic, the panic is recoverable, and the affected library is not canonically deployed in identity, hypervisor, CI/CD, backup, or kernel-mode roles. A process crash is real, but it is recoverable in seconds and does not pivot to other assets.

Why not lower?

LOW (≤3.9) would require either no realistic reachability or trivial built-in mitigation. The bug is reachable from unauthenticated network requests on services that accept TIFFs, and not every Go process is wrapped in net/http panic recovery — gRPC servers, queue workers, and CLI batch jobs can be crashed outright. Sustained DoS against a critical ingest pipeline is a real operational risk, so MEDIUM is the honest floor.

05 · Compensating Control

What to do — in priority order.

  1. Run govulncheck across your Go fleet to find binaries that reach tiff.Decodegovulncheck ./... does symbol-level reachability analysis — it tells you which of your services actually import and call the vulnerable function, not just which ones import the module. Prioritize the reachable set. Per noisgate MEDIUM SLA there is no mitigation deadline; complete this inventory within the 365-day remediation window, but front-load it in the first 30 days while triage attention is still on this CVE.
  2. Add a TIFF MIME-type denylist at the upload gateway — If your application has no business reason to accept TIFFs (most don't), reject image/tiff, image/tif, and content-sniff for the II*\0 / MM\0* magic bytes at the WAF/API gateway. This is a one-line change in Envoy/Kong/Cloudflare and neutralizes the bug regardless of whether the underlying library is patched. Apply within 30 days as a defensive hygiene step.
  3. Wrap decode calls in defer recover() for non-HTTP contexts — gRPC streaming handlers, queue consumers (NATS, Kafka, SQS workers), and CLI batch jobs do not get net/http's automatic panic recovery. Audit every tiff.Decode call site in a non-HTTP context and add a defer func() { if r := recover(); r != nil { ... } }() block. Apply within 30 days as defense-in-depth.
  4. Pin and bump golang.org/x/image to ≥ 0.43.0 — The fix is in version 0.43.0. Use go get golang.org/x/[email protected] && go mod tidy, rebuild, and ship. Stage through your normal release pipeline within the noisgate remediation SLA of 365 days for MEDIUM — but most shops will roll this with the next routine dependency bump.
What doesn't work
  • WAF signatures on TIFF content — generic WAFs do not parse TIFF tag structures and cannot distinguish a malformed StripOffsets from a legitimate one.
  • Pre-decode image.DecodeConfig checksDecodeConfig for TIFF in the affected versions traverses the same IFD parsing path and can panic on similar inputs; it is not a safe guard.
  • File-size limits — the malicious TIFF can be under 1 KB. Size caps don't help.
  • Sandboxing the Go process — does not prevent the DoS; the process still crashes inside the sandbox.
06 · Verification

Crowdsourced verification payload.

Run on a CI worker or developer workstation with the Go toolchain installed and your project checked out. Invoke from the repo root: bash check-cve-2026-46604.sh ./.... No elevated privileges required. The script uses govulncheck for symbol-level reachability and falls back to go list -m for dependency-graph detection.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# check-cve-2026-46604.sh — detect vulnerable golang.org/x/image TIFF decoder
# Usage: bash check-cve-2026-46604.sh [go-package-spec, default ./...]
set -u

TARGET="${1:-./...}"
FIXED_VERSION="v0.43.0"
MODULE="golang.org/x/image"

if ! command -v go >/dev/null 2>&1; then
  echo "UNKNOWN: go toolchain not found" >&2
  exit 2
fi

if ! [ -f go.mod ]; then
  echo "UNKNOWN: no go.mod in current directory" >&2
  exit 2
fi

# 1. Check resolved dependency version
VERSION=$(go list -m -f '{{.Version}}' "$MODULE" 2>/dev/null || true)
if [ -z "$VERSION" ]; then
  echo "PATCHED: module $MODULE is not in the dependency graph"
  exit 0
fi

# 2. Numeric compare against fixed version
LOWEST=$(printf '%s\n%s\n' "$VERSION" "$FIXED_VERSION" | sort -V | head -n1)
if [ "$LOWEST" = "$FIXED_VERSION" ] && [ "$VERSION" != "$FIXED_VERSION" ]; then
  STATE="PATCHED"  # version is >= fixed
elif [ "$VERSION" = "$FIXED_VERSION" ]; then
  STATE="PATCHED"
else
  STATE="VULNERABLE"
fi

# 3. Symbol-level reachability via govulncheck (if installed)
if command -v govulncheck >/dev/null 2>&1; then
  if govulncheck "$TARGET" 2>/dev/null | grep -q "GO-2026-5066\|CVE-2026-46604"; then
    echo "VULNERABLE: $MODULE@$VERSION — tiff.Decode is reachable (govulncheck)"
    exit 1
  fi
fi

if [ "$STATE" = "VULNERABLE" ]; then
  echo "VULNERABLE: $MODULE@$VERSION < $FIXED_VERSION (reachability not confirmed; install govulncheck for symbol check)"
  exit 1
fi

echo "PATCHED: $MODULE@$VERSION >= $FIXED_VERSION"
exit 0
07 · Bottom Line

If you remember one thing.

TL;DR
Treat this as a routine dependency bump. Monday morning: run govulncheck ./... across your Go services to find binaries that actually call tiff.Decode, and check whether any of those run as non-HTTP workers (queue consumers, gRPC streamers, batch jobs) where panics are not auto-recovered. Per noisgate mitigation SLA for MEDIUM, there is no mitigation SLA — go straight to the noisgate remediation SLA of 365 days to ship golang.org/x/[email protected] through normal release trains. The two free wins to take this week regardless: (1) deny image/tiff at the upload gateway for any app that has no business reason to accept it, and (2) confirm any non-HTTP TIFF-decoding worker has defer recover(). Do NOT page anyone over this CVE — vendor HIGH is overstated.

Sources

  1. Go vulnerability database — GO-2026-5066
  2. Go fix commit — CL 788421
  3. Go issue tracker — go.dev/issue/80122
  4. NVD — CVE-2026-46604
  5. CVE record — cve.org
  6. ThreatINT CVE summary
  7. govulncheck reference
  8. golang.org/x/image module
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.