{"record":{"id":"91a02adcaa2c5ce4","repo":"shadow1ng/fscan","slug":"truncated","errorCode":null,"errorMessage":"truncated","messagePattern":"truncated","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugins/services/nfs.go","lineNumber":145,"sourceCode":"\t}\n\n\treplyXID := binary.BigEndian.Uint32(reply[0:4])\n\tif replyXID != xid {\n\t\treturn nil, fmt.Errorf(\"xid mismatch\")\n\t}\n\tmsgType := binary.BigEndian.Uint32(reply[4:8])\n\tif msgType != 1 { // REPLY\n\t\treturn nil, fmt.Errorf(\"not a reply\")\n\t}\n\treplyStatus := binary.BigEndian.Uint32(reply[8:12])\n\tif replyStatus != 0 { // MSG_ACCEPTED\n\t\treturn nil, fmt.Errorf(\"reply rejected\")\n\t}\n\n\t// Skip auth verifier\n\toffset := 12\n\tif offset+8 > len(reply) {\n\t\treturn nil, fmt.Errorf(\"truncated\")\n\t}\n\t// verifier flavor + length\n\tverifierLen := binary.BigEndian.Uint32(reply[offset+4 : offset+8])\n\tif verifierLen > uint32(len(reply)-offset-8) {\n\t\treturn nil, fmt.Errorf(\"truncated verifier\")\n\t}\n\toffset += 8 + int(verifierLen)\n\tif pad := (4 - verifierLen%4) % 4; pad > 0 {\n\t\tif int(pad) > len(reply)-offset {\n\t\t\treturn nil, fmt.Errorf(\"truncated verifier padding\")\n\t\t}\n\t\toffset += int(pad)\n\t}\n\n\t// Accept status\n\tif offset+4 > len(reply) {\n\t\treturn nil, fmt.Errorf(\"truncated\")\n\t}","sourceCodeStart":127,"sourceCodeEnd":163,"githubUrl":"https://github.com/shadow1ng/fscan/blob/95cc12e753bf43de7004e5aef42a9ffba3934303/plugins/services/nfs.go#L127-L163","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Retry the scan — partial reads are often transient","Check network equipment (proxy, firewall) for TCP truncation of small frames","Verify the server writes the complete reply before closing (tcpdump/wireshark)","Increase read timeout so readRPCFragment can read the full fragment"],"exampleFix":"// before\nconn.SetReadDeadline(time.Now().Add(1 * time.Second)) // too short, partial reads\n// after\nconn.SetReadDeadline(time.Now().Add(10 * time.Second))","handlingStrategy":"retry","validationCode":"null","typeGuard":"func hasVerifierFields(reply []byte) bool { return len(reply) >= 20 }","tryCatchPattern":"exports, err := getExports(conn, xid)\nif err != nil && strings.Contains(err.Error(), \"truncated\") {\n    conn.Close()\n    return retryGetExports(host, 2) // bounded retries\n}","preventionTips":["Set generous read deadlines so full fragments arrive","Retry truncated replies once before giving up on the host","Exclude middleboxes/proxies from the scan path"],"tags":["network","rpc","truncated","nfs"],"backgroundTag":"empty-response-body","analyzedSha":"95cc12e753bf43de7004e5aef42a9ffba3934303","analyzedAt":"2026-09-06T17:07:30.094Z","contentChangedAt":"2026-09-06T17:07:30.094Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}