{"record":{"id":"9c94b744c09dda33","repo":"shadow1ng/fscan","slug":"invalid-oracle-packet-length-d","errorCode":null,"errorMessage":"invalid oracle packet length %d","messagePattern":"invalid oracle packet length (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugins/services/oracle_raw.go","lineNumber":245,"sourceCode":"\ttyp  uint8\n\tflag uint8\n\traw  []byte\n\tdata []byte\n}\n\nfunc (s *oracleSession) readPacket() (*oraclePacket, error) {\n\theader := make([]byte, 8)\n\tif err := s.readFull(header); err != nil {\n\t\treturn nil, err\n\t}\n\tvar length uint32\n\tif s.handshakeComplete && s.version >= 315 {\n\t\tlength = binary.BigEndian.Uint32(header[0:4])\n\t} else {\n\t\tlength = uint32(binary.BigEndian.Uint16(header[0:2]))\n\t}\n\tif length < 8 || length > 16*1024*1024 {\n\t\treturn nil, fmt.Errorf(\"invalid oracle packet length %d\", length)\n\t}\n\traw := make([]byte, length)\n\tcopy(raw, header)\n\tif err := s.readFull(raw[8:]); err != nil {\n\t\treturn nil, err\n\t}\n\tp := &oraclePacket{typ: raw[4], flag: raw[5], raw: raw}\n\tif p.typ == oraclePacketData {\n\t\tif len(raw) < 10 {\n\t\t\treturn nil, errors.New(\"short oracle data packet\")\n\t\t}\n\t\tp.data = raw[10:]\n\t\ts.in = append(s.in, p.data...)\n\t}\n\treturn p, nil\n}\n\nfunc (s *oracleSession) readFull(buf []byte) error {","sourceCodeStart":227,"sourceCodeEnd":263,"githubUrl":"https://github.com/shadow1ng/fscan/blob/95cc12e753bf43de7004e5aef42a9ffba3934303/plugins/services/oracle_raw.go#L227-L263","documentation":"readPacket first reads an 8-byte header, then derives the packet length: 4 bytes big-endian for post-handshake sessions with version >= 315, otherwise 2 bytes. This error is thrown when the derived length is below the minimum viable packet (8) or exceeds the 16MB cap — a framing desync or malicious/garbage stream.","triggerScenarios":"connect or read calls readPacket on a stream where the header bytes are not a real TNS packet header — e.g. after protocol desync or from a non-Oracle peer.","commonSituations":"Parsing a stream offset by a few bytes after a misread packet; target service is not Oracle; corrupted TCP stream from a flaky link; attacker-supplied oversized length field.","solutions":["Check whether a prior parse error desynchronized the stream; re-establish the connection rather than continuing to read","Confirm the peer is an Oracle TNS listener","Verify the version-based length field selection matches the negotiated packet version","If legitimate packets exceed 16MB, revisit the cap (unlikely for TNS control packets)"],"exampleFix":"// before\nif length < 8 || length > 16*1024*1024 {\n    return nil, fmt.Errorf(\"invalid oracle packet length %d\", length)\n}\n// after\nif length < 8 || length > 16*1024*1024 {\n    return nil, fmt.Errorf(\"invalid oracle packet length %d (header % x)\", length, header)\n}","handlingStrategy":"validation","validationCode":"func validPacketLength(length uint32) bool {\n    return length >= 8 && length <= 16*1024*1024\n}","typeGuard":"func isValidTNSSession(s *Session) bool { return s != nil && s.version >= 0 } // ensure version negotiated before length parsing","tryCatchPattern":"pkt, err := s.readPacket()\nif err != nil {\n    if strings.Contains(err.Error(), \"invalid oracle packet length\") {\n        return reconnectAndRestart() // framing desynced; session is unrecoverable\n    }\n    return err\n}","preventionTips":["After any parse error, discard the session instead of continuing reads","Match length-field width (2 vs 4 bytes) to the negotiated packet version","Treat lengths near the 16MB cap as suspicious — TNS control packets are small"],"tags":["oracle","tns","protocol-violation","framing"],"backgroundTag":"value-out-of-range","analyzedSha":"95cc12e753bf43de7004e5aef42a9ffba3934303","analyzedAt":"2026-09-06T17:07:30.094Z","contentChangedAt":"2026-09-06T17:07:30.094Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}