{"record":{"id":"060422a6cfe09ca7","repo":"projectdiscovery/nuclei","slug":"ntlm-message-too-short","errorCode":null,"errorMessage":"ntlm: message too short","messagePattern":"ntlm: message too short","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/js/libs/http/ntlm.go","lineNumber":90,"sourceCode":"\tcase strings.HasPrefix(lower, \"ntlm \"):\n\t\ts = strings.TrimSpace(s[5:])\n\tcase strings.HasPrefix(lower, \"negotiate \"):\n\t\ts = strings.TrimSpace(s[10:])\n\t}\n\t// Some servers return \"Negotiate <spnego>\" - still try base64 of remainder.\n\traw, err := base64.StdEncoding.DecodeString(s)\n\tif err != nil {\n\t\traw, err = base64.RawStdEncoding.DecodeString(s)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"ntlm: base64 decode: %w\", err)\n\t\t}\n\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)])","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/projectdiscovery/nuclei/blob/265b3a3dec374741614e342f813c10f8b38d2bb7/pkg/js/libs/http/ntlm.go#L72-L108","documentation":"parseNTLMMessage rejects any decoded blob shorter than 12 bytes, the minimum NTLMSSP fixed header: the 8-byte 'NTLMSSP\\x00' signature plus the 4-byte little-endian message type. The input base64-decoded successfully but the result is too small to be any valid NTLM message, so offsets like data[8:12] would be out of bounds.","triggerScenarios":"DecodeNTLM('NTLM QQ==') (decodes to a single byte); a challenge token truncated mid-base64 that still decodes to a few bytes; passing base64 of short unrelated strings; proxy or middleware trimming the header value.","commonSituations":"Copy-pasting partial tokens from documentation or Burp; test fixtures with placeholder tokens like 'AAAA'; responses passed through gateways that shorten header values; probing hosts that are not AD members.","solutions":["Re-fetch the challenge and pass the complete token from the 401 response that follows a Type-1 negotiate (http.NegotiateNTLM())","Check the base64 token length: 16 base64 characters are needed to represent the 12-byte minimum, so shorter tokens can never be valid","If the endpoint is not NTLM-capable, skip the decode step entirely"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"function isPlausibleNTLMLength(token) {\n  // 12-byte minimum NTLMSSP header needs at least 16 base64 characters\n  return /^[A-Za-z0-9+/]+={0,2}$/.test(token) && token.length >= 16;\n}","typeGuard":null,"tryCatchPattern":"try {\n  const info = http.DecodeNTLM(token);\n} catch (e) {\n  // Blob too short to be NTLM; ignore endpoint\n}","preventionTips":["Always decode the untouched challenge from the server response, never a hand-copied fragment","Prefer obtaining the challenge by sending a Type-1 negotiate so the token is complete"],"tags":["ntlm","parsing","validation"],"backgroundTag":null,"analyzedSha":"265b3a3dec374741614e342f813c10f8b38d2bb7","analyzedAt":"2026-08-15T20:05:51.855Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}