shadow1ng/fscan · error

truncated

Error message

truncated

What it means

After the 12-byte reply header, the reply carries an auth verifier (flavor + length, 8 bytes). getExports requires offset+8 <= len(reply); if the record ends before those 8 bytes exist, it reports "truncated". The server's response was cut off mid-header.

Source

Thrown at plugins/services/nfs.go:145

	}

	replyXID := binary.BigEndian.Uint32(reply[0:4])
	if replyXID != xid {
		return nil, fmt.Errorf("xid mismatch")
	}
	msgType := binary.BigEndian.Uint32(reply[4:8])
	if msgType != 1 { // REPLY
		return nil, fmt.Errorf("not a reply")
	}
	replyStatus := binary.BigEndian.Uint32(reply[8:12])
	if replyStatus != 0 { // MSG_ACCEPTED
		return nil, fmt.Errorf("reply rejected")
	}

	// Skip auth verifier
	offset := 12
	if offset+8 > len(reply) {
		return nil, fmt.Errorf("truncated")
	}
	// verifier flavor + length
	verifierLen := binary.BigEndian.Uint32(reply[offset+4 : offset+8])
	if verifierLen > uint32(len(reply)-offset-8) {
		return nil, fmt.Errorf("truncated verifier")
	}
	offset += 8 + int(verifierLen)
	if pad := (4 - verifierLen%4) % 4; pad > 0 {
		if int(pad) > len(reply)-offset {
			return nil, fmt.Errorf("truncated verifier padding")
		}
		offset += int(pad)
	}

	// Accept status
	if offset+4 > len(reply) {
		return nil, fmt.Errorf("truncated")
	}

View on GitHub (pinned to 95cc12e753)

Solutions

  1. Retry the scan — partial reads are often transient
  2. Check network equipment (proxy, firewall) for TCP truncation of small frames
  3. Verify the server writes the complete reply before closing (tcpdump/wireshark)
  4. Increase read timeout so readRPCFragment can read the full fragment

Example fix

// before
conn.SetReadDeadline(time.Now().Add(1 * time.Second)) // too short, partial reads
// after
conn.SetReadDeadline(time.Now().Add(10 * time.Second))
Defensive patterns

Strategy: retry

Validate before calling

null

Type guard

func hasVerifierFields(reply []byte) bool { return len(reply) >= 20 }

Try / catch

exports, err := getExports(conn, xid)
if err != nil && strings.Contains(err.Error(), "truncated") {
    conn.Close()
    return retryGetExports(host, 2) // bounded retries
}

Prevention

When it happens

Trigger: Calling Scan or TestNFSGetExportsHandlesVerifierPadding when the reply fragment is exactly 12-19 bytes long — the reply header parsed fine but the verifier fields are missing.

Common situations: A proxy or middlebox truncating large-ish frames; a malformed server implementation; MTU/fragmentation issues dropping tail bytes; a half-closed connection after partial write.

Related errors


AI-assisted analysis of shadow1ng/fscan@95cc12e753 (2026-09-06). Data as JSON: /api/errors/91a02adcaa2c5ce4. Report an issue: GitHub.