← Back to Feed CACHED · 2026-05-17 09:42:19 · cache_key CVE-2025-29912
CVE-2026-42507 · Disclosed 2026-06-02

When returning errors

ASSESSED — NOISGATE V0.5
Vendor
Reassessed
Verdict:
01 · The Real Story

This is a forged baggage tag on a broken suitcase, not a master key to the airport

net/textproto in Go would echo attacker-controlled protocol input back inside returned errors, affecting Error.Error, Reader.ReadCodeLine, Reader.ReadMIMEHeader, and Reader.ReadResponse. The Go vuln database marks affected versions as all standard-library releases before go1.25.11, plus go1.26.0 through go1.26.3; fixed releases are go1.25.11 and go1.26.4 on 2026-06-02.

There is no vendor CVSS baseline, but in enterprise reality this is not a classic remote exploit. The attacker needs to be the protocol peer or otherwise control upstream text being parsed, then must drive an error path, then rely on your application to print or log that raw error in a way humans or tooling will trust. That is a genuine integrity problem for logs and terminals, but the blast radius is mostly confusion, poisoned telemetry, and operator misdirection rather than code execution, privilege gain, or service loss.

"ASSESSED AT LOW: real log/terminal injection risk, but only on error paths and without direct system compromise"
02 · The Attack Path

4 steps from start to impact.

STEP 01

Stand up a malicious text-protocol peer

The attacker uses a simple server tool such as nc, socat, or a custom HTTP/SMTP/POP3/IMAP responder to send crafted header lines or status lines to a Go client. Go explicitly notes a natural path here: a net/http client reaches ReadMIMEHeader while parsing headers received from a server.
Conditions required:
  • Attacker can act as the remote server, upstream proxy, or otherwise control protocol responses
  • Victim application uses a Go binary linked against a vulnerable standard library
Where this breaks in practice:
  • This is not broad internet pre-auth reach into arbitrary servers; it usually requires the victim to initiate a connection to the attacker-controlled endpoint
  • If the application never uses the vulnerable parsing paths, the chain stops here
Detection/coverage: External vulnerability scanners have poor coverage because this is a library behavior issue, not a remotely bannerable product flaw.
STEP 02

Force the parser onto an error path

The attacker sends malformed input so ReadMIMEHeader, ReadCodeLine, or ReadResponse returns an error containing the original input. Pre-fix behavior included raw protocol content in the error, enabling injected fake log lines, control characters, or misleading status text.
Conditions required:
  • The malformed response must trigger parsing failure rather than be accepted as valid protocol data
Where this breaks in practice:
  • The bug only matters when parsing fails; successful parsing does not surface the dangerous error string
  • Many production integrations do not expose upstream parse errors to end users at all
Detection/coverage: Application debug logs and exception traces may show protocol parse failures; SAST/SCA will usually find vulnerable Go versions faster than DAST.
STEP 03

Land the payload in logs or operator output

The vulnerable application must pass err.Error() into a logger, terminal, alert, or support bundle without sufficient quoting or neutralization. The attacker wins only if that output channel preserves the misleading content closely enough to affect humans or downstream tooling.
Conditions required:
  • Application logs raw error strings from upstream parsing
  • Log pipeline or terminal preserves special characters, newlines, or deceptive text
Where this breaks in practice:
  • Structured logging, JSON encoding, or explicit quoting reduces the practical impact
  • Some collectors normalize control characters or escape newlines before storage
Detection/coverage: Look for parse-error entries containing unexpected header fragments, embedded line breaks, ANSI escapes, or protocol text copied into error fields.
STEP 04

Exploit trust in the polluted output

The end impact is operational: false breadcrumbs in SIEM, confusing terminal output, or misleading incident notes that can waste analyst time or hide the real failure cause. This is an integrity problem for observability, not a path to memory corruption, RCE, or privilege escalation.
Conditions required:
  • Humans or automation make decisions from the polluted logs or console output
Where this breaks in practice:
  • No direct compromise primitive exists after the error is emitted
  • Blast radius is usually limited to the specific transaction, service logs, or analyst workflow
Detection/coverage: Detection is mostly post-event review: log quality checks, ANSI/control-character scrubbing, and anomaly rules for malformed upstream error content.
03 · Intelligence Metadata

The supporting signals.

In-the-wild statusNo active exploitation evidence found in the authoritative sources reviewed, and not KEV-listed as of 2026-06-03.
Public PoC statusNo public exploit repo located for CVE-2026-42507; practical reproduction is trivial with a malicious protocol peer sending malformed status/header lines.
EPSSNo public EPSS record surfaced yet in the sources reviewed, likely because the CVE was published on 2026-06-02 and is very new.
KEV statusAbsent from CISA KEV; no KEV due date applies.
Affected versionsGo standard library before go1.25.11, and go1.26.0 through go1.26.3 in net/textproto.
Affected symbolsError.Error, Reader.ReadCodeLine, Reader.ReadMIMEHeader, Reader.ReadResponse.
Fixed versionsUpgrade or rebuild with go1.25.11 or go1.26.4 or later. I did not locate authoritative distro backport advisories yet.
Exposure/scanning realityNo meaningful Shodan/Censys/FOFA census exists for this flaw because it is a standard-library issue embedded inside arbitrary Go binaries, not a directly fingerprintable network appliance. *Inference based on component type and vendor advisory.*
Disclosure datePublicly disclosed on 2026-06-02 in the Go security release announcement.
ReporterReporter not publicly named in the Go advisory or vulnerability record reviewed.
CVSS reality checkThere is no vendor/NVD CVSS yet. *noisgate inference:* this behaves closest to network-reachable, low-complexity, integrity-only output injection rather than a system-compromise bug.
04 · The Call

noisgate verdict.

Final Verdict
= UNCHANGED to LOW (3.3/10)

The decisive downward pressure is that the attacker only gets value if they already control the upstream protocol conversation and can force an error that your application then logs or prints raw. That makes this an observability-integrity bug on a narrow error path, not a broad compromise primitive.

HIGH Affected version and fixed-version boundaries
MEDIUM Practical exploitation path through logging and terminal output
MEDIUM Severity bucket assignment without a vendor CVSS baseline

Why this verdict

  • Narrow impact surface: the vulnerability contaminates returned error text, so the core impact is misleading logs, terminal control sequences, and analyst confusion rather than host takeover.
  • Multiple chained prerequisites push severity down: attacker-controlled upstream input, parse failure, raw error emission, and a trusted consumer of that output are all required before there is meaningful impact.
  • Wide codebase presence but weak exploit payoff: Go's standard library is everywhere, but most deployments will see at most noisy or deceptive telemetry, not confidentiality loss, privilege gain, or service interruption.

Why not higher?

This is not unauthenticated remote code execution, authentication bypass, or memory corruption. Even though attacker-controlled input may arrive over the network, the chain terminates in output integrity unless the application makes unusually unsafe decisions from raw parser errors.

Why not lower?

It is still a real security defect, not mere cosmetics. In environments where parse errors are surfaced into analyst consoles, support logs, or SIEM pipelines, an attacker can deliberately plant deceptive content that slows triage and muddies evidence.

05 · Compensating Control

What to do — in priority order.

  1. Quote or sanitize upstream parse errors — Wrap err.Error() output with structured logging or explicit escaping so embedded newlines, tabs, and control bytes cannot masquerade as trusted log content. For a LOW verdict there is no SLA; do this as backlog hygiene where these errors reach operators or shared logging.
  2. Strip ANSI and control characters in the log pipeline — Normalize or reject non-printable bytes before terminal display, alert rendering, or ticket creation so malformed protocol text cannot manipulate consoles. For a LOW verdict there is no SLA; prioritize admin consoles, jump boxes, and SOC-facing views first.
  3. Reduce raw error exposure — Avoid sending full upstream protocol parser errors into customer-visible responses, chat alerts, or pager text. For a LOW verdict there is no SLA; fold this into the next application logging hardening sprint.
  4. Rebuild with fixed Go toolchains — Move builders and base images to go1.25.11 / go1.26.4 or later, then rebuild and redeploy affected binaries so the vulnerable standard library is no longer embedded. For a LOW verdict there is no SLA; treat this as routine patch hygiene.
What doesn't work
  • WAF rules alone do not solve this, because the vulnerable side may be an outbound client parsing a malicious server response rather than an inbound HTTP service.
  • EDR alone will not prevent deceptive log strings; there is no process injection or payload execution to catch.
  • Upgrading the build host without rebuilding applications does not fix already-deployed statically linked Go binaries.
06 · Verification

Crowdsourced verification payload.

Run this on a developer workstation, build runner, or target host that has either the Go toolchain or a compiled Go binary you want to inspect. Invoke it as python3 check_cve_2026_42507.py --go-bin /usr/local/go/bin/go to assess an installed toolchain, or python3 check_cve_2026_42507.py --go-bin /usr/local/go/bin/go --target-bin /opt/app/myservice to inspect a built executable with go version -m; no admin rights are required.

noisgate-verify.py
PYTHONREAD-ONLYSAFE
#!/usr/bin/env python3
# CVE-2026-42507 verifier for Go stdlib net/textproto
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN, 3=usage/runtime error

import argparse
import os
import re
import subprocess
import sys

VERSION_RE = re.compile(r'go(\d+)\.(\d+)(?:\.(\d+))?')


def parse_go_version(text):
    m = VERSION_RE.search(text or "")
    if not m:
        return None
    major = int(m.group(1))
    minor = int(m.group(2))
    patch = int(m.group(3) or 0)
    return (major, minor, patch)


def classify(v):
    if v is None:
        return ("UNKNOWN", "Could not parse Go version")

    major, minor, patch = v

    # CVE-2026-42507 fixed in go1.25.11 and go1.26.4.
    # Go vuln range indicates versions before 1.25.11 are vulnerable,
    # and 1.26.0 through 1.26.3 are vulnerable.
    if major != 1:
        return ("UNKNOWN", f"Unexpected Go major version: go{major}.{minor}.{patch}")

    if minor < 25:
        return ("VULNERABLE", f"go{major}.{minor}.{patch} is older than go1.25.11")
    if minor == 25:
        if patch >= 11:
            return ("PATCHED", f"go{major}.{minor}.{patch} includes the fix threshold go1.25.11")
        return ("VULNERABLE", f"go{major}.{minor}.{patch} is below go1.25.11")
    if minor == 26:
        if patch >= 4:
            return ("PATCHED", f"go{major}.{minor}.{patch} includes the fix threshold go1.26.4")
        return ("VULNERABLE", f"go{major}.{minor}.{patch} is below go1.26.4")
    if minor > 26:
        return ("PATCHED", f"go{major}.{minor}.{patch} is newer than the fixed branches")

    return ("UNKNOWN", f"Unhandled version logic for go{major}.{minor}.{patch}")


def run_cmd(cmd):
    try:
        p = subprocess.run(cmd, capture_output=True, text=True, check=False)
        return p.returncode, (p.stdout or "") + (p.stderr or "")
    except FileNotFoundError:
        return 127, "command not found"
    except Exception as e:
        return 126, str(e)


def get_toolchain_version(go_bin):
    rc, out = run_cmd([go_bin, "version"])
    if rc != 0:
        return None, f"failed to run {' '.join([go_bin, 'version'])}: {out.strip()}"
    v = parse_go_version(out)
    if v is None:
        return None, f"unable to parse toolchain version from: {out.strip()}"
    return v, out.strip()


def get_binary_build_version(go_bin, target_bin):
    rc, out = run_cmd([go_bin, "version", "-m", target_bin])
    if rc != 0:
        return None, f"failed to inspect binary with {' '.join([go_bin, 'version', '-m', target_bin])}: {out.strip()}"
    # The first line usually contains: /path/bin: go1.X.Y
    first_line = out.splitlines()[0] if out.splitlines() else out
    v = parse_go_version(first_line)
    if v is None:
        # Fallback: search anywhere in output.
        v = parse_go_version(out)
    if v is None:
        return None, f"unable to parse embedded Go version from binary metadata: {first_line.strip()}"
    return v, first_line.strip()


def main():
    ap = argparse.ArgumentParser(description="Check exposure to CVE-2026-42507 in Go net/textproto")
    ap.add_argument("--go-bin", help="Path to go executable (default: go from PATH)", default="go")
    ap.add_argument("--target-bin", help="Optional path to a compiled Go binary to inspect with 'go version -m'")
    ap.add_argument("--version", help="Optional literal version string to classify, e.g. 'go1.26.3'")
    args = ap.parse_args()

    if args.version:
        v = parse_go_version(args.version)
        state, reason = classify(v)
        print(f"{state}: {reason}")
        sys.exit(0 if state == "PATCHED" else 1 if state == "VULNERABLE" else 2)

    if args.target_bin:
        if not os.path.exists(args.target_bin):
            print(f"UNKNOWN: target binary not found: {args.target_bin}")
            sys.exit(2)
        v, detail = get_binary_build_version(args.go_bin, args.target_bin)
        if v is None:
            print(f"UNKNOWN: {detail}")
            sys.exit(2)
        state, reason = classify(v)
        print(f"{state}: binary {args.target_bin} built with {detail} -> {reason}")
        sys.exit(0 if state == "PATCHED" else 1 if state == "VULNERABLE" else 2)

    v, detail = get_toolchain_version(args.go_bin)
    if v is None:
        print(f"UNKNOWN: {detail}")
        sys.exit(2)
    state, reason = classify(v)
    print(f"{state}: toolchain {detail} -> {reason}")
    sys.exit(0 if state == "PATCHED" else 1 if state == "VULNERABLE" else 2)


if __name__ == "__main__":
    main()
07 · Bottom Line

If you remember one thing.

TL;DR
Monday morning: inventory Go builders, base images, and any binaries that ingest untrusted HTTP/SMTP/other text-protocol responses, then verify whether they were built with versions older than go1.25.11 or go1.26.4. For this LOW finding there is no noisgate mitigation SLA and no noisgate remediation SLA—treat it as backlog hygiene: sanitize raw parser errors where they hit operator-facing logs, move builders to fixed Go releases in the next routine toolchain refresh, and rebuild/redeploy affected binaries as part of normal maintenance rather than emergency patching.

Sources

  1. NVD CVE record
  2. Go vulnerability report GO-2026-5039
  3. Go vuln JSON record
  4. Go security announcement for 1.26.4 / 1.25.11
  5. Go release history
  6. Go issue #79346
  7. Pre-fix net/textproto source showing raw input in errors
  8. Current net/textproto source
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.