projectdiscovery/nuclei · warning
packet length mismatch: header=%d body=%d
Error message
packet length mismatch: header=%d body=%d
What it means
Thrown while parsing a TDS pre-login response in nuclei' mssql JS library. The 16-bit big-endian packet length at bytes 2:4 of the reply must equal the total number of bytes buffered for the response; when they differ, the packet is self-inconsistent and cannot be trusted. In the current wiring (fingerprintMssql reads exactly packetLen bytes), the check is defensive and fires on replies from proxies/non-standard TDS peers or future multi-packet handling. When it escapes, FingerprintMssql wraps it as 'not a mssql service: ...' (fingerprint.go:147-149).
Source
Thrown at pkg/js/libs/mssql/fingerprint.go:191
EncryptionMode string
Mars bool
InstanceMatches bool
}
func parsePreloginResponse(response []byte) (preloginData, error) {
var out preloginData
if len(response) < 8 {
return out, fmt.Errorf("response too short for TDS header")
}
if response[0] != tdsTypeTabularResult {
return out, fmt.Errorf("unexpected TDS type 0x%02x", response[0])
}
if response[1] != tdsStatusEOM {
return out, fmt.Errorf("unexpected TDS status 0x%02x", response[1])
}
packetLength := int(binary.BigEndian.Uint16(response[2:4]))
if len(response) != packetLength {
return out, fmt.Errorf("packet length mismatch: header=%d body=%d", packetLength, len(response))
}
type optionToken struct {
token byte
offset uint16
length uint16
data []byte
}
position := 8
var tokens []optionToken
for position < len(response) {
if response[position] == tdsTerminator {
break
}
if position+5 > len(response) {
return out, fmt.Errorf("truncated PL option token")
}View on GitHub (pinned to 265b3a3dec)
Solutions
- Verify the port really speaks TDS: nmap -sV -p 1433 or mssql.IsMssql(host, port) — a false result means 'not MSSQL', not a bug
- If the target is genuinely SQL Server, capture the raw reply (info.Raw on success, or tcpdump) and compare the length field at offset 2:4 with the captured packet size
- Treat it as a fingerprint mismatch: rely on other service detection (banner, SSL, network probes) instead of the mssql fingerprint
- If writing Go code that calls parsePreloginResponse directly, ensure you buffer exactly the declared length before parsing
Defensive patterns
Strategy: try-catch
Validate before calling
const isMssql = mssql.IsMssql(host, port);
if (!isMssql) { log(host + ':' + port + ' is not mssql'); return; } Try / catch
try {
const info = mssql.FingerprintMssql(host, port);
} catch (e) {
// parse failures surface as 'not a mssql service: <detail>'
if (String(e).includes('not a mssql service')) { log('non-mssql target: ' + host); }
else { throw e; }
} Prevention
- Call mssql.IsMssql before FingerprintMssql — parse failures map to a clean false
- Restrict mssql templates to ports already identified as SQL Server
- Keep a try/catch around fingerprint calls in templates so one bad target does not abort the run
When it happens
Trigger: Calling mssql.FingerprintMssql(host, port) (or IsMssql, which maps it to false) against a TCP service whose reply's declared TDS length field disagrees with the bytes actually delivered — e.g. a load balancer, an RDP/other service on 1433, or a TDS server splitting the pre-login reply across packets.
Common situations: Scanning a host where port 1433 is actually fronted by a proxy or runs another protocol; hardened/patched SQL Server appliances with non-standard TDS framing; test harnesses feeding hand-crafted pre-login buffers.
Related errors
- truncated PL option token
- invalid PL option data range
- missing PL option terminator
- no PL option tokens
- first PL option must be VERSION
AI-assisted analysis of projectdiscovery/nuclei@265b3a3dec (2026-08-15).
Data as JSON: /api/errors/68774482dc79618c.
Report an issue: GitHub.