projectdiscovery/nuclei · error

ntlm: challenge too short

Error message

ntlm: challenge too short

What it means

The message was identified as Type-2 (challenge) but is shorter than 48 bytes. A Type-2 message has a 48-byte fixed part (signature, type, target name/offset, negotiate flags, context handle, and target-info length/offset at bytes 40-48); with fewer bytes the targetInfoOffset read at data[44:48] would go out of bounds, so parsing aborts.

Source

Thrown at pkg/js/libs/http/ntlm.go:102

	}
	return raw, nil
}

func parseNTLMMessage(data []byte) (*NTLMInfo, error) {
	if len(data) < 12 {
		return nil, fmt.Errorf("ntlm: message too short")
	}
	if !bytes.HasPrefix(data, []byte("NTLMSSP\x00")) {
		return nil, fmt.Errorf("ntlm: missing NTLMSSP signature")
	}
	msgType := binary.LittleEndian.Uint32(data[8:12])
	info := &NTLMInfo{MessageType: int(msgType)}
	if msgType != 2 {
		// Type 1/3: return type only; TargetInfo is Type-2 specific.
		return info, nil
	}
	if len(data) < 48 {
		return nil, fmt.Errorf("ntlm: challenge too short")
	}

	targetNameLen := binary.LittleEndian.Uint16(data[12:14])
	targetNameOffset := binary.LittleEndian.Uint32(data[16:20])
	if targetNameLen > 0 && int(targetNameOffset)+int(targetNameLen) <= len(data) {
		info.TargetName = decodeUTF16LE(data[targetNameOffset : targetNameOffset+uint32(targetNameLen)])
	}

	negotiateFlags := binary.LittleEndian.Uint32(data[20:24])

	targetInfoLen := binary.LittleEndian.Uint16(data[40:42])
	targetInfoOffset := binary.LittleEndian.Uint32(data[44:48])
	start := uint64(targetInfoOffset)
	end := start + uint64(targetInfoLen)
	if targetInfoLen > 0 && end <= uint64(len(data)) {
		parseAVPairs(data[int(start):int(end)], info)
	}

View on GitHub (pinned to 265b3a3dec)

Solutions

  1. Re-fetch the challenge directly (bypass any proxy) since the header value may have been clipped in transit
  2. Treat endpoints that consistently produce short challenges as non-NTLM and skip the decode
  3. When expecting a challenge, verify the token decodes to at least 48 bytes (64 base64 characters) before parsing
Defensive patterns

Strategy: try-catch

Validate before calling

function isChallengeSized(token) {
  // 48-byte Type-2 fixed part needs at least 64 base64 characters
  return token.replace(/=+$/, '').length >= 64;
}

Try / catch

try {
  const info = http.DecodeNTLM(challengeToken);
} catch (e) {
  // Malformed/truncated Type-2 challenge; treat endpoint as non-NTLM
}

Prevention

When it happens

Trigger: A truncated challenge token that still decodes to between 12 and 47 bytes; a non-compliant server emitting an abbreviated challenge; middleware rewriting or clipping the WWW-Authenticate value in transit.

Common situations: Reverse proxies or WAFs shortening long header values; embedded devices with quirky SMB/HTTP stacks; templates run against honeypots that emit synthetic NTLM-looking payloads.

Related errors


AI-assisted analysis of projectdiscovery/nuclei@265b3a3dec (2026-08-15). Data as JSON: /api/errors/2fa836cb9c46b4bc. Report an issue: GitHub.