projectdiscovery/nuclei · warning · errNotMssql

%w: %v

Error message

%w: %v

What it means

Returned by mssql.FingerprintMssql when parsePreloginResponse rejects the assembled packet, wrapping the specific parse failure (bad type byte, bad status byte, length mismatch, malformed option tokens) with the errNotMssql sentinel. Semantically identical to the raw length check: the service answered but the reply is not a valid MSSQL pre-login response, so the target is presumed not MSSQL.

Source

Thrown at pkg/js/libs/mssql/fingerprint.go:149

	header := make([]byte, 8)
	if _, err := io.ReadFull(conn, header); err != nil {
		return info, err
	}
	packetLen := int(binary.BigEndian.Uint16(header[2:4]))
	if packetLen < 8 {
		return info, fmt.Errorf("%w: invalid TDS packet length %d", errNotMssql, packetLen)
	}
	body := make([]byte, packetLen-8)
	if packetLen > 8 {
		if _, err := io.ReadFull(conn, body); err != nil {
			return info, err
		}
	}
	response := append(header, body...)

	parsed, err := parsePreloginResponse(response)
	if err != nil {
		return info, fmt.Errorf("%w: %v", errNotMssql, err)
	}
	info.Version = parsed.Version
	info.MajorVersion = parsed.MajorVersion
	info.MinorVersion = parsed.MinorVersion
	info.BuildNumber = parsed.BuildNumber
	info.Encryption = parsed.Encryption
	info.EncryptionMode = parsed.EncryptionMode
	info.Mars = parsed.Mars
	info.InstanceMatches = parsed.InstanceMatches
	info.TLS = parsed.Encryption == encryptOn || parsed.Encryption == encryptReq
	info.Raw = hex.EncodeToString(response)
	if ip := net.ParseIP(host); ip != nil {
		info.IP = ip.String()
	}
	return info, nil
}

type preloginData struct {

View on GitHub (pinned to 265b3a3dec)

Solutions

  1. Handle it as 'not MSSQL' and move on, or switch to mssql.IsMssql for a boolean result
  2. Confirm you are hitting the real SQL TCP port, not a TLS frontend (try the TLS-port variant or check for a 0x16 first byte)
  3. Log the raw hex (info.Raw on success paths) while debugging to see what the service actually sent
Defensive patterns

Strategy: fallback

Try / catch

try {
  const info = mssql.FingerprintMssql(host, port);
} catch (e) {
  if (String(e).includes('not a mssql service')) return; // classify as non-MSSQL
  throw e; // real network errors still propagate
}

Prevention

When it happens

Trigger: The reply's first bytes are a TLS ServerHello / alert (byte 0x16/0x15) instead of a TDS tabular-result packet; an HTTP error page on the port; a half-broken proxy answer that passes the >=8 length check but fails deeper structure validation.

Common situations: Probing ports behind load balancers or TLS-terminating proxies; servers that force encryption from the first byte; any non-MSSQL service that happens to send 8+ bytes whose length field looks plausible.

Related errors


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