Apr 24, 2026·6 min read·5 visits
A missing bounds check in the NTLM Type 2 message parser of Azure go-ntlmssp allows malicious servers to crash the client application via an out-of-bounds slice panic.
The Azure go-ntlmssp package prior to version 0.1.1 contains a denial-of-service vulnerability stemming from improper input validation. Malicious servers can trigger an unrecoverable Go panic by supplying a crafted NTLM Challenge message, terminating the client application process.
The go-ntlmssp package provides NTLM/Negotiate authentication capabilities over HTTP for Go applications. Developers typically use it as a wrapper for http.RoundTripper to authenticate outgoing requests seamlessly. The vulnerability exists in how the library parses NTLM Challenge (Type 2) messages returned by the server during the negotiation phase.
NTLM authentication involves a multi-step handshake. When a client attempts to access a protected resource, the server responds with an HTTP 401 Unauthorized status and an NTLM Type 2 Challenge message. This message contains various data structures, including the Target Name and Target Info fields, which are located via offsets and lengths specified in the message header.
The parser in vulnerable versions of go-ntlmssp extracts these offset and length values directly from the server's response and uses them to slice a byte array containing the payload. The lack of validation on these extracted values constitutes a CWE-190 (Integer Overflow or Wraparound) condition, leading directly to a slice bounds out-of-range operation.
The root cause of CVE-2026-32952 is the absence of bounds checking prior to executing Go slice operations on network-provided data. NTLM messages utilize a specific header structure to define variable-length fields. Each descriptor consists of an 8-byte block containing a 2-byte Length, a 2-byte Max Length, and a 4-byte Offset.
When the ntlmssp.Negotiator receives the Type 2 message, it decodes the Base64 payload and reads these descriptors. It converts the Little-Endian byte sequences into Go integer types (uint16 and uint32). The code then retrieves the field data by slicing the payload byte array using the extracted variables.
If a server provides a maliciously crafted descriptor, it can specify an Offset or Length combination that exceeds the total size of the received payload byte slice. In Go, attempting to access a slice index outside its capacity triggers an immediate runtime panic. Because this parsing occurs within the RoundTrip execution path of an HTTP client, the unhandled panic unwinds the stack and crashes the entire application.
To understand the mechanics of the panic, it is necessary to examine the interaction between the parsed NTLM headers and Go's slice syntax. The vulnerability materializes when the code attempts to extract variable-length data based on untrusted inputs.
The vulnerable implementation directly applies the parsed offset and length variables to the byte slice. The logic resembles the following sequence:
// Vulnerable pattern
length := binary.LittleEndian.Uint16(payload[descriptorOffset : descriptorOffset+2])
offset := binary.LittleEndian.Uint32(payload[descriptorOffset+4 : descriptorOffset+8])
// The following line panics if offset+uint32(length) > uint32(len(payload))
fieldData := payload[offset : offset+uint32(length)]The fix introduces strict validation logic to ensure that neither the offset nor the computed end boundary exceeds the actual length of the payload. The patched implementation verifies these constraints before attempting the slice operation.
// Patched pattern
length := uint32(binary.LittleEndian.Uint16(payload[descriptorOffset : descriptorOffset+2]))
offset := binary.LittleEndian.Uint32(payload[descriptorOffset+4 : descriptorOffset+8])
// Bounds validation added to prevent slice panic
if offset > uint32(len(payload)) || offset+length > uint32(len(payload)) {
return nil, errors.New("invalid NTLM descriptor bounds")
}
fieldData := payload[offset : offset+length]By returning an error instead of executing the invalid slice operation, the application correctly handles the malformed HTTP response without crashing.
Exploitation requires the attacker to control the HTTP server responding to the client's requests, or to operate in a Man-in-the-Middle (MitM) position capable of intercepting and modifying the HTTP traffic. The target application must be configured to use go-ntlmssp to authenticate against the attacker-controlled endpoint.
When the client initiates the connection, the attacker responds with an HTTP 401 Unauthorized status code. The response includes a WWW-Authenticate: NTLM <base64_payload> header. The base64 payload encodes a structurally valid NTLM Type 2 message, but with manipulated descriptor fields. The attacker sets the Target Name offset to 0xFFFFFFFF or specifies a length that guarantees the addition overflows or exceeds the actual payload size.
Upon receiving the 401 response, the go-ntlmssp RoundTripper intercepts the response and attempts to parse the challenge to formulate a Type 3 Authenticate message. The parser extracts the malformed descriptors, executes the out-of-bounds slice operation, and triggers the panic.
The direct impact of CVE-2026-32952 is a Denial of Service (DoS) against the client application utilizing the go-ntlmssp package. While often viewed as less critical than Remote Code Execution, DoS via unhandled panics in Go applications carries significant operational consequences.
In Go, a panic triggered in a goroutine that is not subsequently caught by a deferred recover() function will terminate the entire process. If the application acts as an API gateway, a backend microservice, or an orchestration tool, a single malicious NTLM challenge can halt all operations, affecting all users and requests currently being processed by the binary.
The CVSS v3.1 score of 5.3 (Medium) reflects the strict constraints of the attack vector. The availability impact is categorized as Low (A:L) under CVSS methodologies because the vulnerability primarily affects the individual client instance rather than a centralized, shared resource. However, in modern microservice architectures where clients perform critical backend polling or webhook delivery, the practical impact on service availability can be severe.
The primary remediation for CVE-2026-32952 is upgrading the go-ntlmssp dependency to version 0.1.1 or later. This version implements the necessary bounds checking required to safely parse NTLM message headers. Developers should update their go.mod files and verify the dependency tree.
If immediate patching is not feasible due to deployment freezes or complex dependency conflicts, developers must implement structural mitigations within their own application code. The most effective workaround involves utilizing Go's recover() mechanism.
By wrapping the HTTP client invocation or the execution of the RoundTripper in a goroutine with a deferred recovery function, developers can catch the panic before it crashes the parent process. While this prevents the complete termination of the service, the specific HTTP request will still fail, and resource cleanup must be handled manually to prevent memory leaks.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L| Product | Affected Versions | Fixed Version |
|---|---|---|
go-ntlmssp Azure | < 0.1.1 | 0.1.1 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-190 |
| Attack Vector | Network |
| CVSS v3.1 Score | 5.3 |
| Impact | Denial of Service (Process Crash) |
| Exploit Status | Proof of Concept available |
| CISA KEV | Not Listed |
The software performs a calculation that can produce an integer overflow or wraparound, which results in out-of-bounds memory access.