{"record":{"id":"2fa836cb9c46b4bc","repo":"projectdiscovery/nuclei","slug":"ntlm-challenge-too-short","errorCode":null,"errorMessage":"ntlm: challenge too short","messagePattern":"ntlm: challenge too short","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/js/libs/http/ntlm.go","lineNumber":102,"sourceCode":"\t}\n\treturn raw, nil\n}\n\nfunc parseNTLMMessage(data []byte) (*NTLMInfo, error) {\n\tif len(data) < 12 {\n\t\treturn nil, fmt.Errorf(\"ntlm: message too short\")\n\t}\n\tif !bytes.HasPrefix(data, []byte(\"NTLMSSP\\x00\")) {\n\t\treturn nil, fmt.Errorf(\"ntlm: missing NTLMSSP signature\")\n\t}\n\tmsgType := binary.LittleEndian.Uint32(data[8:12])\n\tinfo := &NTLMInfo{MessageType: int(msgType)}\n\tif msgType != 2 {\n\t\t// Type 1/3: return type only; TargetInfo is Type-2 specific.\n\t\treturn info, nil\n\t}\n\tif len(data) < 48 {\n\t\treturn nil, fmt.Errorf(\"ntlm: challenge too short\")\n\t}\n\n\ttargetNameLen := binary.LittleEndian.Uint16(data[12:14])\n\ttargetNameOffset := binary.LittleEndian.Uint32(data[16:20])\n\tif targetNameLen > 0 && int(targetNameOffset)+int(targetNameLen) <= len(data) {\n\t\tinfo.TargetName = decodeUTF16LE(data[targetNameOffset : targetNameOffset+uint32(targetNameLen)])\n\t}\n\n\tnegotiateFlags := binary.LittleEndian.Uint32(data[20:24])\n\n\ttargetInfoLen := binary.LittleEndian.Uint16(data[40:42])\n\ttargetInfoOffset := binary.LittleEndian.Uint32(data[44:48])\n\tstart := uint64(targetInfoOffset)\n\tend := start + uint64(targetInfoLen)\n\tif targetInfoLen > 0 && end <= uint64(len(data)) {\n\t\tparseAVPairs(data[int(start):int(end)], info)\n\t}\n","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/projectdiscovery/nuclei/blob/265b3a3dec374741614e342f813c10f8b38d2bb7/pkg/js/libs/http/ntlm.go#L84-L120","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Re-fetch the challenge directly (bypass any proxy) since the header value may have been clipped in transit","Treat endpoints that consistently produce short challenges as non-NTLM and skip the decode","When expecting a challenge, verify the token decodes to at least 48 bytes (64 base64 characters) before parsing"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"function isChallengeSized(token) {\n  // 48-byte Type-2 fixed part needs at least 64 base64 characters\n  return token.replace(/=+$/, '').length >= 64;\n}","typeGuard":null,"tryCatchPattern":"try {\n  const info = http.DecodeNTLM(challengeToken);\n} catch (e) {\n  // Malformed/truncated Type-2 challenge; treat endpoint as non-NTLM\n}","preventionTips":["Fetch challenges directly without proxy rewrites when possible","Validate the token decodes to at least 48 bytes before asserting Type-2 fields"],"tags":["ntlm","parsing","malformed-response"],"backgroundTag":null,"analyzedSha":"265b3a3dec374741614e342f813c10f8b38d2bb7","analyzedAt":"2026-08-15T20:05:51.855Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}