{"record":{"id":"0c9ff37eb078ea1f","repo":"jstedfast/MailKit","slug":"digest-md5-does-not-support-sasl-ir","errorCode":null,"errorMessage":"DIGEST-MD5 does not support SASL-IR.","messagePattern":"DIGEST-MD5 does not support SASL-IR\\.","errorType":"exception","errorClass":"NotSupportedException","httpStatus":null,"severity":"error","filePath":"MailKit/Security/SaslMechanismDigestMd5.cs","lineNumber":145,"sourceCode":"\t\t/// </exception>\n\t\t/// <exception cref=\"System.OperationCanceledException\">\n\t\t/// The operation was canceled via the cancellation token.\n\t\t/// </exception>\n\t\t/// <exception cref=\"SaslException\">\n\t\t/// An error has occurred while parsing the server's challenge token.\n\t\t/// </exception>\n\t\tprotected override byte[]? Challenge (byte[]? token, int startIndex, int length, CancellationToken cancellationToken)\n\t\t{\n\t\t\tif (IsAuthenticated)\n\t\t\t\treturn null;\n\n\t\t\tif (Uri is null)\n\t\t\t\tthrow new InvalidOperationException ();\n\n\t\t\tswitch (state) {\n\t\t\tcase LoginState.Auth:\n\t\t\t\tif (token == null)\n\t\t\t\t\tthrow new NotSupportedException (\"DIGEST-MD5 does not support SASL-IR.\");\n\n\t\t\t\tif (token.Length > 2048)\n\t\t\t\t\tthrow new SaslException (MechanismName, SaslErrorCode.ChallengeTooLong, \"Server challenge too long.\");\n\n\t\t\t\tchallenge = DigestChallenge.Parse (Encoding.UTF8.GetString (token, startIndex, length));\n\t\t\t\tencoding = challenge.Charset != null ? Encoding.UTF8 : TextEncodings.Latin1;\n\t\t\t\tcnonce ??= GenerateEntropy (15);\n\n\t\t\t\tresponse = new DigestResponse (challenge, encoding, Uri.Scheme, Uri.DnsSafeHost, AuthorizationId, Credentials.UserName, Credentials.Password, cnonce);\n\t\t\t\tstate = LoginState.Final;\n\n\t\t\t\treturn response.Encode (encoding);\n\t\t\tcase LoginState.Final:\n\t\t\t\tif (token == null || token.Length == 0)\n\t\t\t\t\tthrow new SaslException (MechanismName, SaslErrorCode.MissingChallenge, \"Server response did not contain any authentication data.\");\n\n\t\t\t\tvar text = encoding!.GetString (token, startIndex, length);\n\t\t\t\tstring? key, value;","sourceCodeStart":127,"sourceCodeEnd":163,"githubUrl":"https://github.com/jstedfast/MailKit/blob/9d3859a7855e3e17582c07fd01972b8e262bf176/MailKit/Security/SaslMechanismDigestMd5.cs#L127-L163","documentation":"DIGEST-MD5 is a challenge/response mechanism that cannot send an initial response. SaslMechanismDigestMd5.Challenge throws NotSupportedException ('DIGEST-MD5 does not support SASL-IR.') when invoked with a null token, i.e. when asked to produce credentials before the server has issued its challenge.","triggerScenarios":"Authenticating with SaslMechanismDigestMd5 over a protocol path that uses SASL Initial Client Response, or calling Challenge(null, ...) directly.","commonSituations":"Client libraries with 'send initial response' optimization enabled negotiating DIGEST-MD5; custom SASL engine that treats all mechanisms uniformly with IR.","solutions":["Let the server issue the challenge first: do not use SASL-IR when the negotiated mechanism is DIGEST-MD5.","Choose an IR-capable mechanism (PLAIN, SCRAM-SHA-1/256/512) if initial response is required.","In custom protocol code, only pass the server's challenge bytes to Challenge(); treat null as invalid for this mechanism."],"exampleFix":"// before\nvar mech = new SaslMechanismDigestMd5(uri, user, pass);\nsendAuthCommand(mech.Challenge(null, 0, 0, ct)); // SASL-IR attempt\n// after\nvar mech = new SaslMechanismDigestMd5(uri, user, pass);\nvar challenge = readServerChallenge();\nsendAuthCommand(mech.Challenge(challenge, 0, challenge.Length, ct));","handlingStrategy":"try-catch","validationCode":"// ensure the transport does not use SASL-IR for DIGEST-MD5\nbool useInitialResponse = mech is not SaslMechanismDigestMd5;","typeGuard":null,"tryCatchPattern":"try {\n    client.Authenticate(uri, new SaslMechanismDigestMd5(uri, user, pass));\n} catch (NotSupportedException) {\n    client.Authenticate(uri, new SaslMechanismPlain(user, pass)); // over TLS\n}","preventionTips":["Wait for the server challenge before invoking Challenge for DIGEST-MD5","Configure clients to skip initial-response for non-IR mechanisms","Prefer SCRAM/PLAIN when SASL-IR is required by the transport"],"tags":["sasl","digest-md5","unsupported-feature"],"backgroundTag":"unsupported-operation","analyzedSha":"9d3859a7855e3e17582c07fd01972b8e262bf176","analyzedAt":"2026-09-15T15:46:11.592Z","contentChangedAt":"2026-09-15T15:46:11.592Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}