{"id":"GHSA-2mjx-qc3c-rqvc","revision":null,"records":[{"revision":"1d0e044b30c1493f8dd7008a732fe45e","observedAt":"2026-10-27T15:46:16.241+00:00","statement":{"source":"osv","id":"GHSA-2mjx-qc3c-rqvc","aliases":["RUSTSEC-2026-0285"],"title":"Rustls: TLS 1.3 handshake messages incorrectly accepted across encryption level boundaries","description":"Rustls accepted TLS 1.3 handshake messages sent at the wrong encryption level when they followed a key-changing message in the same record. The handshake transcript is still authenticated, so a network-position attacker cannot use this to alter or complete a handshake; the practical effect is that a peer could send handshake messages that should be encrypted in plaintext without rustls rejecting the connection.\n\nThis issue affects rustls versions 0.23.13 through 0.23.44 inclusive.\n\n# Original report\n### Summary\nRustls (tested version 0.23.44, and it appears still an issue on latest master though I have not tested this) accepts a TLS 1.3 server flight where a plaintext EncryptedExtensions is packed into the same record as the ServerHello.\n\nThis is very similar to Go's CVE-2025-61730 fixed in https://github.com/golang/go/commit/5046bdf8a612b35a2c1a9e168054c1d5c65e7dd7\n\n### Details\nIt appears `Deframer::aligned` considers itself aligned as long as all messages remaining in the buffer are complete. Rustls processes the ServerHello, installs the handshake keys, then pulls the complete (plaintext) EncryptedExtensions out of the buffer.\n\nThis is insufficient per RFC 8446 section 5.1's\n\n> Handshake messages MUST NOT span key changes.  Implementations MUST verify that all messages immediately preceding a key change align with a record boundary; if not, then they MUST terminate the connection with an \"unexpected_message\" alert.  Because the ClientHello, EndOfEarlyData, ServerHello, Finished, and KeyUpdate messages can immediately precede a key change, implementations MUST send these messages in alignment with a record boundary.\n\n### Impact\nAn on path attacker can inject plaintext messages that are accepted.\n\n### Tool Use Disclosure\nThis was discovered by a new TLS/DTLS test suite currently under construction. The specific testcase was inspired by the Go CVE. Other tested implementations (Botan, OpenSSL, BoringSSL, Go, wolfSSL) reject this protocol flow. Daybreak Blue reviewed the rustls code to identify probable root cause.","state":0,"publishedAt":"2026-10-05T23:30:17+00:00","modifiedAt":"2026-10-27T15:30:05.5093055+00:00","affected":[{"ecosystem":"crates.io","name":"rustls","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"0.23.13"},{"kind":"fixed","version":"0.23.45"}]}],"versions":[],"rawVersionEvidence":null}],"metrics":[{"system":"CVSS_V3","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N","score":null,"severity":null},{"system":"Publisher rating","vector":null,"score":null,"severity":"MODERATE"}],"references":["https://github.com/rustls/rustls/security/advisories/GHSA-2mjx-qc3c-rqvc","https://github.com/rustls/rustls/pull/3265","https://github.com/golang/go/commit/5046bdf8a612b35a2c1a9e168054c1d5c65e7dd7","https://github.com/rustls/rustls/commit/98456aea708a7e3c6151e00ca2d4428e7a58257a","https://github.com/rustls/rustls","https://github.com/rustls/rustls/releases/tag/v/0.23.45","https://rustsec.org/advisories/RUSTSEC-2026-0285.html"],"sourceUrl":"https://github.com/advisories/GHSA-2mjx-qc3c-rqvc","license":"GitHub Advisory Database · CC-BY-4.0","key":"osv:GHSA-2mjx-qc3c-rqvc","identifiers":["GHSA-2mjx-qc3c-rqvc","RUSTSEC-2026-0285"]},"retained":false,"historicalAffected":[]},{"revision":"9534a14f85dc4fa399629e190e00dde2","observedAt":"2026-10-24T13:19:54.901+00:00","statement":{"source":"osv","id":"RUSTSEC-2026-0285","aliases":["GHSA-2mjx-qc3c-rqvc"],"title":"TLS 1.3 handshake messages incorrectly accepted across encryption level boundaries","description":"Rustls accepted TLS 1.3 handshake messages sent at the wrong encryption level\nwhen they followed a key-changing message in the same record. For example,\na plaintext `EncryptedExtensions` message packed into the same record as the\n`ServerHello` was accepted.\n\nRFC 8446 section 5.1 requires that handshake messages do not span key changes,\nand that implementations terminate the connection with an \"unexpected_message\"\nalert if they do.\n\nThe handshake transcript is still authenticated, so a network-position attacker\ncannot use this to alter or complete a handshake; the practical effect is that\na peer could send handshake messages that should be encrypted in plaintext\nwithout rustls rejecting the connection.\n\nThis is functionally the same bug as Go's\n[GO-2026-4340](https://pkg.go.dev/vuln/GO-2026-4340) (CVE-2025-61730).","state":0,"publishedAt":"2026-09-14T12:00:00+00:00","modifiedAt":"2026-10-12T18:00:10.9449583+00:00","affected":[{"ecosystem":"crates.io","name":"rustls","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"0.23.13"},{"kind":"fixed","version":"0.23.45"}]}],"versions":[],"rawVersionEvidence":null}],"metrics":[{"system":"CVSS_V3","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N","score":null,"severity":null}],"references":["https://crates.io/crates/rustls","https://rustsec.org/advisories/RUSTSEC-2026-0285.html","https://github.com/rustls/rustls/pull/3265"],"sourceUrl":"https://osv.dev/vulnerability/RUSTSEC-2026-0285","license":"OSV · upstream source license applies","key":"osv:RUSTSEC-2026-0285","identifiers":["RUSTSEC-2026-0285","GHSA-2mjx-qc3c-rqvc"]},"retained":false,"historicalAffected":[]}],"coverage":[{"source":"cisa-kev:global","scope":"Complete CISA KEV catalog; all vendors. Missing entries do not establish absence of exploitation.","generation":"2026-10-30T14:45:26.6987549+00:00","complete":true,"records":1764,"lastAttemptAt":"2026-10-30T14:45:26.6987549+00:00","lastSuccessAt":"2026-10-30T14:45:26.9497648+00:00","error":null,"lastVerifiedAt":"2026-10-30T14:45:26.9497653+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"cve-program","scope":"Official CVE Program baseline and cumulative hourly delta; all vendors, published and rejected records","generation":"cve-7e2c4e7288f2c464ad8c61f3bb6017374714faedcc781283ac06a706ee1a820b-9ae73af7991357f8171c14345365990a8a2ca2ac30d2f5c0345295ca47cd8b59","complete":true,"records":417062,"lastAttemptAt":"2026-10-30T14:45:26.2761545+00:00","lastSuccessAt":"2026-10-30T13:45:42.363036+00:00","error":null,"lastVerifiedAt":"2026-10-30T14:45:26.2761545+00:00","snapshotPublishedAt":"2026-10-30T13:19:40+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"euvd","scope":"Rolling EUVD lookups of CVE aliases in current public OSV archives; 500 identifiers per refresh, rechecked after 48 hours. Not a global EUVD catalog. Successful not-found lookups count as checked; they do not imply withdrawal or safety. No reader inventory is sent.","generation":"enrichment-2061c7564831481480eca7336a6a2d59","complete":false,"records":13525,"lastAttemptAt":"2026-10-30T14:57:22.1548673+00:00","lastSuccessAt":"2026-10-30T14:57:22.151+00:00","error":"74 identifier lookups failed; latest failures include HTTP 403. Other identifiers were checked independently.","lastVerifiedAt":"2026-10-30T14:57:22.151+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":12100,"expectedIdentifiers":13603,"failedIdentifiers":74},{"source":"first-epss:nuget","scope":"FIRST EPSS for explicit CVE aliases in the collected public NuGet archive. Not a global EPSS backfill.","generation":"2026-10-30T14:45:26.6987549+00:00","complete":true,"records":1094,"lastAttemptAt":"2026-10-30T14:45:26.6987549+00:00","lastSuccessAt":"2026-10-30T14:45:26.9516817+00:00","error":null,"lastVerifiedAt":"2026-10-30T14:45:26.951682+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"nvd","scope":"Rolling NVD lookups of CVE aliases in current public OSV archives; 500 identifiers per refresh, rechecked after 48 hours. Not a global NVD catalog. Successful not-found lookups count as checked; they do not imply withdrawal or safety. No reader inventory is sent.","generation":"enrichment-6a13c6f8f39a448a8b96c895e97b0fc8","complete":true,"records":13543,"lastAttemptAt":"2026-10-30T14:45:34.6994115+00:00","lastSuccessAt":"2026-10-30T14:45:34.696+00:00","error":null,"lastVerifiedAt":"2026-10-30T14:45:34.696+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":13603,"expectedIdentifiers":13603,"failedIdentifiers":0},{"source":"osv:Go","scope":"Complete OSV Go ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"go-b597efeb8fc540d31a792e2148f8b153f027cb0902f6eec1f988f717bba80dd6","complete":true,"records":9806,"lastAttemptAt":"2026-10-30T14:45:26.6211704+00:00","lastSuccessAt":"2026-10-30T11:49:32.1566+00:00","error":null,"lastVerifiedAt":"2026-10-30T14:45:26.6211704+00:00","snapshotPublishedAt":"2026-10-30T11:03:04+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"osv:NuGet","scope":"Complete OSV NuGet ecosystem archive, including GitHub Advisory Database records; NuGet version matching only","generation":"nuget-2de9ccc5290f060c7aa63f89c25dd76f655a64ba1aba7c05c97fa3bee4f09899","complete":true,"records":1967,"lastAttemptAt":"2026-10-30T14:45:26.3367706+00:00","lastSuccessAt":"2026-10-28T20:55:34.2982937+00:00","error":null,"lastVerifiedAt":"2026-10-30T14:45:26.3367706+00:00","snapshotPublishedAt":"2026-10-28T20:03:08+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"osv:crates.io","scope":"Complete OSV crates.io ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"crates.io-f63fa91e750071ae88c9f82019ecd6c982fa4fcc1d3dc5ceb5d9c642fb6bf05c","complete":true,"records":3023,"lastAttemptAt":"2026-10-30T14:45:26.6363468+00:00","lastSuccessAt":"2026-10-30T11:49:36.4759887+00:00","error":null,"lastVerifiedAt":"2026-10-30T14:45:26.6363468+00:00","snapshotPublishedAt":"2026-10-30T11:18:14+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"osv:npm","scope":"Complete OSV npm ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"npm-38769c8a86ea1c9a6224e5523e119bd23337098bd8f535cc5952f8ec88cdd622","complete":true,"records":230950,"lastAttemptAt":"2026-10-30T14:45:26.5064351+00:00","lastSuccessAt":"2026-10-30T13:47:22.3495471+00:00","error":null,"lastVerifiedAt":"2026-10-30T14:45:26.5064351+00:00","snapshotPublishedAt":"2026-10-30T13:33:12+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null}]}