{"id":"a1e755c05639181f","repo":"jackc/pgx","slug":"bad-auth-type","errorCode":null,"errorMessage":"bad auth type","messagePattern":"bad auth type","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pgproto3/authentication_cleartext_password.go","lineNumber":30,"sourceCode":"type AuthenticationCleartextPassword struct{}\n\n// Backend identifies this message as sendable by the PostgreSQL backend.\nfunc (*AuthenticationCleartextPassword) Backend() {}\n\n// Backend identifies this message as an authentication response.\nfunc (*AuthenticationCleartextPassword) AuthenticationResponse() {}\n\n// Decode decodes src into dst. src must contain the complete message with the exception of the initial 1 byte message\n// type identifier and 4 byte message length.\nfunc (dst *AuthenticationCleartextPassword) Decode(src []byte) error {\n\tif len(src) != 4 {\n\t\treturn errors.New(\"bad authentication message size\")\n\t}\n\n\tauthType := binary.BigEndian.Uint32(src)\n\n\tif authType != AuthTypeCleartextPassword {\n\t\treturn errors.New(\"bad auth type\")\n\t}\n\n\treturn nil\n}\n\n// Encode encodes src into dst. dst will include the 1 byte message type identifier and the 4 byte message length.\nfunc (src *AuthenticationCleartextPassword) Encode(dst []byte) ([]byte, error) {\n\tdst, sp := beginMessage(dst, 'R')\n\tdst = pgio.AppendUint32(dst, AuthTypeCleartextPassword)\n\treturn finishMessage(dst, sp)\n}\n\n// MarshalJSON implements encoding/json.Marshaler.\nfunc (src AuthenticationCleartextPassword) MarshalJSON() ([]byte, error) {\n\treturn json.Marshal(struct {\n\t\tType string\n\t}{\n\t\tType: \"AuthenticationCleartextPassword\",","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/jackc/pgx/blob/ec1a0befd22592cffffdeeb0a50311b506372f4c/pgproto3/authentication_cleartext_password.go#L12-L48","documentation":"Returned by AuthenticationCleartextPassword.Decode in pgproto3/authentication_cleartext_password.go:30 when the first 4 bytes of the message body do not equal AuthTypeCleartextPassword (3). It is a defensive re-check: the frontend's findAuthenticationMessageType already selected this struct from that same code, so in the standard pgconn path it cannot fire. It indicates either byte corruption between dispatch and decode or direct misuse of Decode on bytes whose auth-type code is not 3.","triggerScenarios":"Calling Decode on a byte slice whose leading uint32 is not 3 (e.g. feeding MD5/SASL/GSS bytes into a cleartext struct), or memory/stream corruption that mutates the code after dispatch. Most realistic in custom protocol tools, proxies, fuzzers, or tests rather than normal pgx connections.","commonSituations":"Test or proxy code that hard-codes the wrong Authentication* struct for a given frame; a corrupted buffer; a hand-crafted fuzz input.","solutions":["Route 'R' messages through Frontend.Receive / findAuthenticationMessageType instead of picking the Decode struct manually.","If decoding manually, read the 4-byte auth code first and select the matching struct (3 => cleartext).","Check for memory/buffer aliasing if the same buffer is reused across decode attempts."],"exampleFix":"// before: wrong struct for the frame\nvar m pgproto3.AuthenticationCleartextPassword\nm.Decode(md5Bytes) // -> \"bad auth type\"\n\n// after: dispatch on the auth code like the frontend does\nswitch binary.BigEndian.Uint32(body) {\ncase pgproto3.AuthTypeCleartextPassword:\n    var m pgproto3.AuthenticationCleartextPassword\n    return m.Decode(body)\ncase pgproto3.AuthTypeMD5Password:\n    var m pgproto3.AuthenticationMD5Password\n    return m.Decode(body)\n}","handlingStrategy":"validation","validationCode":"// When decoding 'R' frames manually, dispatch on the auth code first.\nif len(body) >= 4 {\n    switch binary.BigEndian.Uint32(body) {\n    case pgproto3.AuthTypeCleartextPassword:\n        var m pgproto3.AuthenticationCleartextPassword\n        return m.Decode(body)\n    }\n}","typeGuard":"func isCleartextAuthFrame(body []byte) bool {\n    return len(body) == 4 && binary.BigEndian.Uint32(body) == pgproto3.AuthTypeCleartextPassword\n}","tryCatchPattern":null,"preventionTips":["Use Frontend.Receive (which dispatches via findAuthenticationMessageType) instead of hand-picking the Decode struct.","Switch on the 4-byte auth code before calling any Authentication*.Decode.","Never reuse the underlying byte buffer across decode calls."],"tags":["authentication","protocol","cleartext-password","pgproto3","validation"],"analyzedSha":"ec1a0befd22592cffffdeeb0a50311b506372f4c","analyzedAt":"2026-08-04T22:52:11.263Z","schemaVersion":2}