{"containers":{"cna":{"affected":[{"cpes":["cpe:2.3:a:erlang:erlang\\/otp:*:*:*:*:*:*:*:*"],"defaultStatus":"unaffected","modules":["ssl_handshake","tls_handshake_1_3","tls_client_ticket_store"],"packageName":"otp","packageURL":"pkg:software-id/erlang.org/otp","product":"OTP","programFiles":["lib/ssl/src/ssl_handshake.erl","lib/ssl/src/tls_handshake_1_3.erl","lib/ssl/src/tls_client_ticket_store.erl"],"programRoutines":[{"name":"ssl_handshake:decode_extensions/4"},{"name":"tls_handshake_1_3:decode_handshake/2"},{"name":"tls_handshake_1_3:get_max_early_data/1"},{"name":"tls_client_ticket_store:find_ticket/5"},{"name":"tls_client_ticket_store:get_tickets/2"}],"vendor":"Erlang","versions":[{"changes":[{"at":"27.3.4.19","status":"unaffected"},{"at":"28.5.0.8","status":"unaffected"},{"at":"29.1.2","status":"unaffected"}],"lessThan":"*","status":"affected","version":"23.3","versionType":"otp"}]},{"cpes":["cpe:2.3:a:erlang:erlang\\/otp:*:*:*:*:*:*:*:*"],"defaultStatus":"unaffected","modules":["ssl_handshake","tls_handshake_1_3","tls_client_ticket_store"],"packageName":"ssl","packageURL":"pkg:otp/ssl?repository_url=https:%2F%2Fgithub.com%2Ferlang%2Fotp&vcs_url=git%2Bhttps:%2F%2Fgithub.com%2Ferlang%2Fotp.git","product":"OTP","programFiles":["src/ssl_handshake.erl","src/tls_handshake_1_3.erl","src/tls_client_ticket_store.erl"],"programRoutines":[{"name":"ssl_handshake:decode_extensions/4"},{"name":"tls_handshake_1_3:decode_handshake/2"},{"name":"tls_handshake_1_3:get_max_early_data/1"},{"name":"tls_client_ticket_store:find_ticket/5"},{"name":"tls_client_ticket_store:get_tickets/2"}],"repo":"https://github.com/erlang/otp","vendor":"Erlang","versions":[{"changes":[{"at":"11.2.12.14","status":"unaffected"},{"at":"11.6.0.7","status":"unaffected"},{"at":"11.7.8","status":"unaffected"}],"lessThan":"*","status":"affected","version":"10.3","versionType":"otp"}]},{"collectionURL":"https://github.com","cpes":["cpe:2.3:a:erlang:erlang\\/otp:*:*:*:*:*:*:*:*"],"defaultStatus":"unaffected","modules":["ssl_handshake","tls_handshake_1_3","tls_client_ticket_store"],"packageName":"erlang/otp","packageURL":"pkg:github/erlang/otp","product":"OTP","programFiles":["lib/ssl/src/ssl_handshake.erl","lib/ssl/src/tls_handshake_1_3.erl","lib/ssl/src/tls_client_ticket_store.erl"],"programRoutines":[{"name":"ssl_handshake:decode_extensions/4"},{"name":"tls_handshake_1_3:decode_handshake/2"},{"name":"tls_handshake_1_3:get_max_early_data/1"},{"name":"tls_client_ticket_store:find_ticket/5"},{"name":"tls_client_ticket_store:get_tickets/2"}],"repo":"https://github.com/erlang/otp","vendor":"Erlang","versions":[{"changes":[{"at":"66febc190e6dc42a5c4aedbfe250bf9a2edc2d5e","status":"unaffected"},{"at":"00a333bcf2800b69f540369b54167e897dae7219","status":"unaffected"},{"at":"cd0334854bf3ef56dc16f9fb728efe88fb05c4ac","status":"unaffected"}],"lessThan":"*","status":"affected","version":"0abe6f66db0d295cd06b0efab3bdb3caa2803930","versionType":"git"}]}],"configurations":[{"lang":"en","supportingMedia":[{"base64":false,"type":"text/html","value":"<p>Only TLS 1.3 clients that set the <code>ssl</code> option <code>{session_tickets, auto}</code> are affected. The default value of <code>session_tickets</code> is <code>disabled</code>, and clients that use <code>manual</code> ticket handling do not store tickets in the node-global ticket store. The client must also connect to a server that the attacker controls, or that the attacker can impersonate.</p>"},{"base64":false,"type":"text/markdown","value":"Only TLS 1.3 clients that set the `ssl` option `{session_tickets, auto}` are affected. The default value of `session_tickets` is `disabled`, and clients that use `manual` ticket handling do not store tickets in the node-global ticket store. The client must also connect to a server that the attacker controls, or that the attacker can impersonate."}],"value":"Only TLS 1.3 clients that set the ssl option {session_tickets, auto} are affected. The default value of session_tickets is disabled, and clients that use manual ticket handling do not store tickets in the node-global ticket store. The client must also connect to a server that the attacker controls, or that the attacker can impersonate."}],"cpeApplicability":[{"nodes":[{"cpeMatch":[{"criteria":"cpe:2.3:a:erlang:erlang\\/otp:*:*:*:*:*:*:*:*","versionEndExcluding":"27.3.4.19","versionStartIncluding":"23.3","vulnerable":true},{"criteria":"cpe:2.3:a:erlang:erlang\\/otp:*:*:*:*:*:*:*:*","versionEndExcluding":"28.5.0.8","versionStartIncluding":"28.0","vulnerable":true},{"criteria":"cpe:2.3:a:erlang:erlang\\/otp:*:*:*:*:*:*:*:*","versionEndExcluding":"29.1.2","versionStartIncluding":"29.0","vulnerable":true}],"negate":false,"operator":"OR"}],"operator":"AND"}],"credits":[{"lang":"en","type":"reporter","value":"Lukas Backström / Erlang Solutions"},{"lang":"en","type":"remediation developer","value":"Ingela Anderton Andin"},{"lang":"en","type":"coordinator","value":"Jonatan Männchen / EEF"},{"lang":"en","type":"analyst","value":"Jonatan Männchen / EEF"}],"dateAssigned":"2026-10-01T08:50:00.000Z","descriptions":[{"lang":"en","supportingMedia":[{"base64":false,"type":"text/html","value":"<p>Improper Validation of Consistency within Input vulnerability in Erlang OTP ssl (<code>tls_handshake_1_3</code>, <code>ssl_handshake</code> and <code>tls_client_ticket_store</code> modules) allows a malicious TLS 1.3 server to cause a denial of service of the <code>ssl</code> application on the client node.</p>\n<p>The TLS 1.3 client decodes the extensions of a <code>NewSessionTicket</code> message as if they came from <code>EncryptedExtensions</code>. It therefore accepts a 0-length <code>early_data</code> extension, a form that is only valid in <code>ClientHello</code> and <code>EncryptedExtensions</code>. With <code>{session_tickets, auto}</code>, the client stores the ticket in the node-global <code>tls_client_ticket_store</code>. On the next automatic resumption, <code>tls_handshake_1_3:get_max_early_data/1</code> crashes the store with a <code>case_clause</code>. Repeated crashes can exceed the restart intensity of the <code>ssl</code> supervisors, which use the <code>rest_for_one</code> strategy, and take down <code>ssl</code> for all connections on the node.</p>\n<p>This issue affects OTP from OTP&nbsp;23.3 before OTP&nbsp;27.3.4.19, OTP&nbsp;28.5.0.8, and OTP&nbsp;29.1.2, corresponding to ssl from 10.3 before 11.2.12.14, 11.6.0.7, and 11.7.8.</p>"},{"base64":false,"type":"text/markdown","value":"Improper Validation of Consistency within Input vulnerability in Erlang OTP ssl (`tls_handshake_1_3`, `ssl_handshake` and `tls_client_ticket_store` modules) allows a malicious TLS 1.3 server to cause a denial of service of the `ssl` application on the client node.\n\nThe TLS 1.3 client decodes the extensions of a `NewSessionTicket` message as if they came from `EncryptedExtensions`. It therefore accepts a 0-length `early_data` extension, a form that is only valid in `ClientHello` and `EncryptedExtensions`. With `{session_tickets, auto}`, the client stores the ticket in the node-global `tls_client_ticket_store`. On the next automatic resumption, `tls_handshake_1_3:get_max_early_data/1` crashes the store with a `case_clause`. Repeated crashes can exceed the restart intensity of the `ssl` supervisors, which use the `rest_for_one` strategy, and take down `ssl` for all connections on the node.\n\nThis issue affects OTP from OTP 23.3 before OTP 27.3.4.19, OTP 28.5.0.8, and OTP 29.1.2, corresponding to ssl from 10.3 before 11.2.12.14, 11.6.0.7, and 11.7.8."}],"value":"Improper Validation of Consistency within Input vulnerability in Erlang OTP ssl (tls_handshake_1_3, ssl_handshake and tls_client_ticket_store modules) allows a malicious TLS 1.3 server to cause a denial of service of the ssl application on the client node.\n\nThe TLS 1.3 client decodes the extensions of a NewSessionTicket message as if they came from EncryptedExtensions. It therefore accepts a 0-length early_data extension, a form that is only valid in ClientHello and EncryptedExtensions. With {session_tickets, auto}, the client stores the ticket in the node-global tls_client_ticket_store. On the next automatic resumption, tls_handshake_1_3:get_max_early_data/1 crashes the store with a case_clause. Repeated crashes can exceed the restart intensity of the ssl supervisors, which use the rest_for_one strategy, and take down ssl for all connections on the node.\n\nThis issue affects OTP from OTP 23.3 before OTP 27.3.4.19, OTP 28.5.0.8, and OTP 29.1.2, corresponding to ssl from 10.3 before 11.2.12.14, 11.6.0.7, and 11.7.8."}],"impacts":[{"capecId":"CAPEC-153","descriptions":[{"lang":"en","supportingMedia":[{"base64":false,"type":"text/html","value":"<p>A malicious TLS 1.3 server can crash the client node's session ticket store, and by repeating the attack it can stop the <code>ssl</code> application for all TLS connections on that node. Only clients that use <code>{session_tickets, auto}</code> are affected.</p>"},{"base64":false,"type":"text/markdown","value":"A malicious TLS 1.3 server can crash the client node's session ticket store, and by repeating the attack it can stop the `ssl` application for all TLS connections on that node. Only clients that use `{session_tickets, auto}` are affected."}],"value":"A malicious TLS 1.3 server can crash the client node's session ticket store, and by repeating the attack it can stop the ssl application for all TLS connections on that node. Only clients that use {session_tickets, auto} are affected."}]}],"metrics":[{"cvssV4_0":{"Automatable":"NOT_DEFINED","Recovery":"NOT_DEFINED","Safety":"NOT_DEFINED","attackComplexity":"LOW","attackRequirements":"PRESENT","attackVector":"NETWORK","baseScore":8.2,"baseSeverity":"HIGH","privilegesRequired":"NONE","providerUrgency":"NOT_DEFINED","subAvailabilityImpact":"NONE","subConfidentialityImpact":"NONE","subIntegrityImpact":"NONE","userInteraction":"NONE","valueDensity":"NOT_DEFINED","vectorString":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N","version":"4.0","vulnAvailabilityImpact":"HIGH","vulnConfidentialityImpact":"NONE","vulnIntegrityImpact":"NONE","vulnerabilityResponseEffort":"NOT_DEFINED"},"format":"CVSS","scenarios":[{"lang":"en","value":"GENERAL"}]}],"problemTypes":[{"descriptions":[{"cweId":"CWE-1288","description":"CWE-1288 Improper Validation of Consistency within Input","lang":"en","type":"CWE"}]}],"providerMetadata":{"dateUpdated":"2026-10-14T16:55:23.328Z","orgId":"6b3ad84c-e1a6-4bf7-a703-f496b71e49db","shortName":"EEF"},"references":[{"name":"GitHub Advisory","tags":["related","vendor-advisory"],"url":"https://github.com/erlang/otp/security/advisories/GHSA-m5mh-q53w-67jq"},{"name":"EEF CNA record for CVE-2026-94200","tags":["related"],"url":"https://cna.erlef.org/cves/CVE-2026-94200.html"},{"name":"OSV record EEF-CVE-2026-94200","tags":["related"],"url":"https://osv.dev/vulnerability/EEF-CVE-2026-94200"},{"name":"Erlang/OTP version ordering","tags":["x_version-scheme"],"url":"https://www.erlang.org/doc/system/versions.html#order-of-versions"},{"name":"Introducing commit 0abe6f6 in erlang/otp","tags":["related"],"url":"https://github.com/erlang/otp/commit/0abe6f66db0d295cd06b0efab3bdb3caa2803930"},{"name":"Fix commit 66febc1 in erlang/otp","tags":["patch"],"url":"https://github.com/erlang/otp/commit/66febc190e6dc42a5c4aedbfe250bf9a2edc2d5e"},{"name":"Fix commit 00a333b in erlang/otp","tags":["patch"],"url":"https://github.com/erlang/otp/commit/00a333bcf2800b69f540369b54167e897dae7219"},{"name":"Fix commit cd03348 in erlang/otp","tags":["patch"],"url":"https://github.com/erlang/otp/commit/cd0334854bf3ef56dc16f9fb728efe88fb05c4ac"}],"source":{"discovery":"INTERNAL"},"title":"TLS 1.3 client ticket store crashed by NewSessionTicket with empty early_data extension in ssl","workarounds":[{"lang":"en","supportingMedia":[{"base64":false,"type":"text/html","value":"<p>Do not set <code>{session_tickets, auto}</code> on TLS 1.3 clients. Use <code>manual</code> ticket handling, or keep the default value <code>disabled</code>.</p>"},{"base64":false,"type":"text/markdown","value":"Do not set `{session_tickets, auto}` on TLS 1.3 clients. Use `manual` ticket handling, or keep the default value `disabled`."}],"value":"Do not set {session_tickets, auto} on TLS 1.3 clients. Use manual ticket handling, or keep the default value disabled."}],"x_technicalAnalysis":[{"lang":"en","supportingMedia":[{"base64":false,"type":"text/html","value":"<p><strong>1. Decoding.</strong> <code>tls_handshake_1_3:decode_handshake/2</code> decodes the extensions of a <code>NewSessionTicket</code> with the message type <code>encrypted_extensions</code>. <code>ssl_handshake:decode_extensions/4</code> does not check the message type for most extensions. A 0-length <code>early_data</code> extension therefore decodes to <code>#early_data_indication{}</code>, the <code>ClientHello</code> and <code>EncryptedExtensions</code> form, and not to <code>#early_data_indication_nst{}</code>, the 4-byte <code>max_early_data_size</code> form that RFC 8446 requires in a <code>NewSessionTicket</code>.</p>\n<p><strong>2. Storage.</strong> In <code>auto</code> mode the client sends the ticket to the node-global <code>tls_client_ticket_store</code> gen_server, which keeps it for later resumption.</p>\n<p><strong>3. Crash.</strong> When a later connection resumes automatically, the store calls <code>tls_handshake_1_3:get_max_early_data/1</code> on the stored extensions, from <code>maybe_use_ticket</code> and <code>get_tickets</code>. That function only handles <code>undefined</code> and <code>#early_data_indication_nst{}</code>, so the store process crashes with a <code>case_clause</code>.</p>\n<p><strong>4. Escalation.</strong> The store is a <code>permanent</code> child of <code>ssl_admin_sup</code>. Each restart of the store also restarts the children after it, because the supervisor uses <code>rest_for_one</code>. A server that keeps sending the malformed ticket makes the crashes repeat. When the crashes exceed the supervisor restart intensity, the failure goes up through <code>ssl_sup</code> and stops the <code>ssl</code> application for the whole node.</p>\n<p>The fix makes <code>ssl_handshake:decode_extensions/4</code> accept each extension form only in the handshake messages where it is permitted, and decodes <code>NewSessionTicket</code> extensions with the message type <code>new_session_ticket</code>.</p>"},{"base64":false,"type":"text/markdown","value":"**1. Decoding.** `tls_handshake_1_3:decode_handshake/2` decodes the extensions of a `NewSessionTicket` with the message type `encrypted_extensions`. `ssl_handshake:decode_extensions/4` does not check the message type for most extensions. A 0-length `early_data` extension therefore decodes to `#early_data_indication{}`, the `ClientHello` and `EncryptedExtensions` form, and not to `#early_data_indication_nst{}`, the 4-byte `max_early_data_size` form that RFC 8446 requires in a `NewSessionTicket`.\n\n**2. Storage.** In `auto` mode the client sends the ticket to the node-global `tls_client_ticket_store` gen_server, which keeps it for later resumption.\n\n**3. Crash.** When a later connection resumes automatically, the store calls `tls_handshake_1_3:get_max_early_data/1` on the stored extensions, from `maybe_use_ticket` and `get_tickets`. That function only handles `undefined` and `#early_data_indication_nst{}`, so the store process crashes with a `case_clause`.\n\n**4. Escalation.** The store is a `permanent` child of `ssl_admin_sup`. Each restart of the store also restarts the children after it, because the supervisor uses `rest_for_one`. A server that keeps sending the malformed ticket makes the crashes repeat. When the crashes exceed the supervisor restart intensity, the failure goes up through `ssl_sup` and stops the `ssl` application for the whole node.\n\nThe fix makes `ssl_handshake:decode_extensions/4` accept each extension form only in the handshake messages where it is permitted, and decodes `NewSessionTicket` extensions with the message type `new_session_ticket`."}],"value":"1. Decoding. tls_handshake_1_3:decode_handshake/2 decodes the extensions of a NewSessionTicket with the message type encrypted_extensions. ssl_handshake:decode_extensions/4 does not check the message type for most extensions. A 0-length early_data extension therefore decodes to #early_data_indication{}, the ClientHello and EncryptedExtensions form, and not to #early_data_indication_nst{}, the 4-byte max_early_data_size form that RFC 8446 requires in a NewSessionTicket.\n\n2. Storage. In auto mode the client sends the ticket to the node-global tls_client_ticket_store gen_server, which keeps it for later resumption.\n\n3. Crash. When a later connection resumes automatically, the store calls tls_handshake_1_3:get_max_early_data/1 on the stored extensions, from maybe_use_ticket and get_tickets. That function only handles undefined and #early_data_indication_nst{}, so the store process crashes with a case_clause.\n\n4. Escalation. The store is a permanent child of ssl_admin_sup. Each restart of the store also restarts the children after it, because the supervisor uses rest_for_one. A server that keeps sending the malformed ticket makes the crashes repeat. When the crashes exceed the supervisor restart intensity, the failure goes up through ssl_sup and stops the ssl application for the whole node.\n\nThe fix makes ssl_handshake:decode_extensions/4 accept each extension form only in the handshake messages where it is permitted, and decodes NewSessionTicket extensions with the message type new_session_ticket."}]}},"cveMetadata":{"assignerOrgId":"6b3ad84c-e1a6-4bf7-a703-f496b71e49db","assignerShortName":"EEF","cveId":"CVE-2026-94200","datePublished":"2026-10-14T16:55:23.328Z","dateReserved":"2026-09-21T12:15:01.330Z","dateUpdated":"2026-10-14T16:55:23.328Z","state":"PUBLISHED"},"dataType":"CVE_RECORD","dataVersion":"5.2"}