{"record":{"id":"667136dede89ba89","repo":"shadow1ng/fscan","slug":"short-oracle-ncharset-negotiation","errorCode":null,"errorMessage":"short oracle ncharset negotiation","messagePattern":"short oracle ncharset negotiation","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugins/services/oracle_raw.go","lineNumber":1014,"sourceCode":"\tif charsetElem > 0 {\n\t\tif _, err = s.getBytes(charsetElem * 5); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\tlen1, err := s.getInt(2, false, true)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tnumArray, err := s.getBytes(len1)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif len(numArray) < 11 {\n\t\treturn nil, errors.New(\"short oracle charset negotiation\")\n\t}\n\toffset := int(6 + numArray[5] + numArray[6])\n\tif len(numArray) < offset+5 {\n\t\treturn nil, errors.New(\"short oracle ncharset negotiation\")\n\t}\n\tserverNCharset := int(binary.BigEndian.Uint16(numArray[offset+3 : offset+5]))\n\tlen2, err := s.getByte()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tcompileCaps, err := s.getBytes(int(len2))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tlen3, err := s.getByte()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\truntimeCaps, err := s.getBytes(int(len3))\n\tif err != nil {\n\t\treturn nil, err\n\t}","sourceCodeStart":996,"sourceCodeEnd":1032,"githubUrl":"https://github.com/shadow1ng/fscan/blob/95cc12e753bf43de7004e5aef42a9ffba3934303/plugins/services/oracle_raw.go#L996-L1032","documentation":"Immediately after parsing the server charset, protocolNegotiation computes an offset (6 + numArray[5] + numArray[6]) to locate the server NCHARSET field, which needs 5 readable bytes at that offset. If numArray is shorter than offset+5, the NCHARSET cannot be extracted and the library aborts the handshake.","triggerScenarios":"protocolNegotiation() during oracleRawAuth: len(numArray) < (6 + numArray[5] + numArray[6] + 5), i.e. the variable-length sections claimed by the accept-data array extend past its actual size.","commonSituations":"Server accept packet with unusually large substructure fields (bytes 5/6) relative to actual data — often a protocol-version mismatch; truncated transport frame; desynchronized parsing from a previous step.","solutions":["Check server Oracle version/patch level for known accept-packet layout differences and update the plugin accordingly","Capture the accept packet (tcpdump) and compare byte layout with a known-good client session","Rule out transport truncation (retry, test direct connection without proxy)","If reproducible against a specific server version, file an upstream issue with the packet dump"],"exampleFix":"// before\noffset := int(6 + numArray[5] + numArray[6])\nif len(numArray) < offset+5 {\n\treturn nil, errors.New(\"short oracle ncharset negotiation\")\n}\n// after\noffset := int(6 + numArray[5] + numArray[6])\nif len(numArray) < offset+5 {\n\treturn nil, fmt.Errorf(\"short oracle ncharset negotiation: need %d bytes, got %d\", offset+5, len(numArray))\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"short oracle ncharset negotiation\") {\n\treturn fmt.Errorf(\"server accept-data shorter than its own offsets; check server version/patch and proxy handling: %w\", err)\n}","preventionTips":["Test a direct connection (no proxy) to rule out frame truncation","Compare against a known-good client (sqlplus) from the same host","Report server-version-specific layout differences upstream with a packet dump"],"tags":["oracle","protocol","charset","negotiation"],"backgroundTag":"unexpected-response-shape","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"}