{"id":22332,"name":"com.squareup.okhttp3:mockwebserver","ecosystem":"maven","repository_url":"https://github.com/square/okhttp","issues_count":331,"created_at":"2025-06-07T02:52:13.183Z","updated_at":"2025-06-07T02:52:13.183Z","purl":"pkg:maven/com.squareup.okhttp3:mockwebserver","metadata":{"id":4772657,"name":"com.squareup.okhttp3:mockwebserver","ecosystem":"maven","description":"Square’s meticulous HTTP client for Java and Kotlin.","homepage":"https://square.github.io/okhttp/","licenses":"The Apache Software License, Version 2.0","normalized_licenses":["Apache-2.0"],"repository_url":"https://github.com/square/okhttp","keywords_array":[],"namespace":"com.squareup.okhttp3","versions_count":96,"first_release_published_at":"2016-01-02T07:34:50.000Z","latest_release_published_at":"2023-10-17T02:23:47.000Z","latest_release_number":"4.12.0","last_synced_at":"2025-06-07T02:01:26.505Z","created_at":"2022-07-26T07:26:46.006Z","updated_at":"2025-06-07T02:01:26.505Z","registry_url":"https://central.sonatype.com/artifact/com.squareup.okhttp3/mockwebserver/","install_command":null,"documentation_url":"https://appdoc.app/artifact/com.squareup.okhttp3/mockwebserver/","metadata":{},"repo_metadata":{"uuid":"5152285","full_name":"square/okhttp","owner":"square","description":"Square’s meticulous HTTP client for the JVM, Android, and GraalVM.","archived":false,"fork":false,"pushed_at":"2023-03-20T01:11:27.000Z","size":48715,"stargazers_count":43706,"open_issues_count":169,"forks_count":9054,"subscribers_count":1644,"default_branch":"master","last_synced_at":"2023-03-21T12:54:49.778Z","etag":null,"topics":["android","graalvm","java","kotlin"],"latest_commit_sha":null,"homepage":"https://square.github.io/okhttp/","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"logo_url":null,"metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":".github/CONTRIBUTING.md","funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"docs/security/security.md","support":null}},"created_at":"2012-07-23T13:42:55.000Z","updated_at":"2023-03-21T12:52:06.000Z","dependencies_parsed_at":"2023-02-18T04:16:13.589Z","dependency_job_id":null,"html_url":"https://github.com/square/okhttp","commit_stats":null,"repository_url":"http://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/square%2Fokhttp","tags_url":"http://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/square%2Fokhttp/tags","manifests_url":"http://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/square%2Fokhttp/manifests","owner_url":"http://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/square","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":108921946,"host_url":"http://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"http://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"http://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names"},"owner_record":{"login":"square","name":"Square","uuid":"82592","kind":"organization","description":"","email":null,"website":"https://square.github.io","location":null,"twitter":"SquareDev","company":null,"avatar_url":"https://avatars.githubusercontent.com/u/82592?v=4","repositories_count":266,"last_synced_at":"2023-02-19T21:47:56.162Z","metadata":{"has_sponsors_listing":false},"owner_url":"http://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/square"},"tags":[{"name":"parent-4.7.1","sha":"186ec88aff706f31724210f0b73f88e942e7fb11","kind":"tag","published_at":"2020-05-18T21:46:52.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-4.7.1","html_url":"https://github.com/square/okhttp/releases/tag/parent-4.7.1"},{"name":"parent-4.7.0","sha":"ef7c5f358e2ac8dad806952c70c7af9061a6f7af","kind":"tag","published_at":"2020-05-17T17:52:56.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-4.7.0","html_url":"https://github.com/square/okhttp/releases/tag/parent-4.7.0"},{"name":"parent-3.14.9","sha":"ad97bd3df34376eec85aa187dc8f45cfde8a2c01","kind":"tag","published_at":"2020-05-17T16:50:58.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.14.9","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.14.9"},{"name":"parent-3.12.12","sha":"06d38cb795d82d086f13c595a62ce0cbe60904ac","kind":"tag","published_at":"2020-05-17T16:28:08.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.12.12","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.12.12"},{"name":"parent-4.6.0","sha":"0deadd5611c4bc793a776aaaa68710012e456b9f","kind":"tag","published_at":"2020-04-29T04:52:51.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-4.6.0","html_url":"https://github.com/square/okhttp/releases/tag/parent-4.6.0"},{"name":"parent-3.14.8","sha":"7a0d6b22160aeabfc4b64508dbd10ea9726d020f","kind":"tag","published_at":"2020-04-29T04:35:43.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.14.8","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.14.8"},{"name":"parent-3.12.11","sha":"3e749792236637f07834be633a4157decaa70a11","kind":"tag","published_at":"2020-04-29T02:53:19.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.12.11","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.12.11"},{"name":"parent-4.5.0","sha":"ca0c8d6a1a9c24ebef74554527dd13d9d6234381","kind":"tag","published_at":"2020-04-06T14:54:15.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-4.5.0","html_url":"https://github.com/square/okhttp/releases/tag/parent-4.5.0"},{"name":"parent-4.5.0-RC1","sha":"7334150d1da63f4fe7e256de173bdc5837022ff9","kind":"tag","published_at":"2020-03-18T03:51:12.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-4.5.0-RC1","html_url":"https://github.com/square/okhttp/releases/tag/parent-4.5.0-RC1"},{"name":"parent-4.4.1","sha":"046f7f2450f9c913d759e7c8bdb52fda528fb631","kind":"tag","published_at":"2020-03-08T13:36:36.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-4.4.1","html_url":"https://github.com/square/okhttp/releases/tag/parent-4.4.1"},{"name":"parent-3.12.10","sha":"3840c217aa54444e13c7b23e965c87b1cfc97dbe","kind":"tag","published_at":"2020-02-29T14:40:36.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.12.10","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.12.10"},{"name":"parent-3.14.7","sha":"25186b401fef60ae48c47716d3db3f2a6bf6521b","kind":"tag","published_at":"2020-02-25T02:46:06.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.14.7","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.14.7"},{"name":"parent-3.12.9","sha":"57e0da93169b1b24e1edb8996ecaf3492cd60aa8","kind":"tag","published_at":"2020-02-24T22:28:53.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.12.9","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.12.9"},{"name":"parent-4.4.0","sha":"44124ba2a36de31ea5e6e8b4c0dc7d3b7f350df5","kind":"tag","published_at":"2020-02-17T22:51:22.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-4.4.0","html_url":"https://github.com/square/okhttp/releases/tag/parent-4.4.0"},{"name":"parent-3.12.8","sha":"95ef698c3cce78f6c0848256325fdf18775ff0e3","kind":"tag","published_at":"2020-01-12T02:14:13.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.12.8","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.12.8"},{"name":"parent-3.14.6","sha":"ddd8c7f88e50d426e16833a5931ec1d7e59fce8c","kind":"tag","published_at":"2020-01-12T01:49:58.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.14.6","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.14.6"},{"name":"parent-4.3.1","sha":"a56a1b9544171add7730fa025c0cb46125e0356e","kind":"tag","published_at":"2020-01-07T18:32:01.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-4.3.1","html_url":"https://github.com/square/okhttp/releases/tag/parent-4.3.1"},{"name":"parent-3.14.5","sha":"5fe92352ab0e23214c8b1f629a56417e7f12e52b","kind":"tag","published_at":"2020-01-03T23:12:15.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.14.5","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.14.5"},{"name":"parent-3.12.7","sha":"c7e3bc33b4d7bc582803c5dac1934be1f8659d98","kind":"tag","published_at":"2020-01-03T22:57:18.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.12.7","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.12.7"},{"name":"parent-4.3.0","sha":"b63debd827dc6b2e23f4e01d9a58d9671fc80804","kind":"tag","published_at":"2019-12-31T21:39:08.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-4.3.0","html_url":"https://github.com/square/okhttp/releases/tag/parent-4.3.0"},{"name":"parent-4.2.2","sha":"d02340f9dfac4ead42befc1a4d477b45401956cf","kind":"tag","published_at":"2019-10-06T20:18:49.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-4.2.2","html_url":"https://github.com/square/okhttp/releases/tag/parent-4.2.2"},{"name":"parent-4.2.1","sha":"57a165b69c6551c1caec8a557e0e9c9abf54b536","kind":"tag","published_at":"2019-10-02T12:53:31.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-4.2.1","html_url":"https://github.com/square/okhttp/releases/tag/parent-4.2.1"},{"name":"parent-3.12.6","sha":"b2c5000535c7764d42f25b0e6b0026208a277ad2","kind":"tag","published_at":"2019-09-29T19:34:20.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.12.6","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.12.6"},{"name":"parent-3.14.4","sha":"488b8f403982a0db4d9bb0d3a2d4b386a2d7422b","kind":"tag","published_at":"2019-09-29T18:45:22.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.14.4","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.14.4"},{"name":"parent-3.14.3","sha":"966914967317393f2677b922f3c07d534b38d4bd","kind":"tag","published_at":"2019-09-10T21:47:39.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.14.3","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.14.3"},{"name":"parent-3.12.5","sha":"f101f9d9d35660d5394d8b32d9c026e0e748cba4","kind":"tag","published_at":"2019-09-10T20:55:44.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.12.5","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.12.5"},{"name":"parent-4.2.0","sha":"582f8ef2f78cf001d479cb65831674289fd83af0","kind":"tag","published_at":"2019-09-10T17:04:12.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-4.2.0","html_url":"https://github.com/square/okhttp/releases/tag/parent-4.2.0"},{"name":"parent-4.1.1","sha":"cf93aca33cc30a44724a8fb9e7042ccd17a37f07","kind":"tag","published_at":"2019-09-05T04:24:05.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-4.1.1","html_url":"https://github.com/square/okhttp/releases/tag/parent-4.1.1"},{"name":"parent-3.12.4","sha":"197ca277653a1071075b4b79833e319e991045a8","kind":"tag","published_at":"2019-09-04T14:28:06.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.12.4","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.12.4"},{"name":"parent-4.1.0","sha":"4739b278066c25de7d1fcada943e0aaddda7e7a7","kind":"tag","published_at":"2019-08-12T17:00:04.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-4.1.0","html_url":"https://github.com/square/okhttp/releases/tag/parent-4.1.0"},{"name":"parent-4.0.1","sha":"1854a7b82d1d23309ff9e2aa38064e7fce3b6b2c","kind":"tag","published_at":"2019-07-10T15:31:59.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-4.0.1","html_url":"https://github.com/square/okhttp/releases/tag/parent-4.0.1"},{"name":"parent-4.0.0","sha":"911c5bf5b27e8378f209861a16a9da4cc54cfff7","kind":"tag","published_at":"2019-06-27T02:30:34.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-4.0.0","html_url":"https://github.com/square/okhttp/releases/tag/parent-4.0.0"},{"name":"parent-4.0.0-RC3","sha":"bad333c0a31904ff76b0d67ab8c46d085cc99461","kind":"tag","published_at":"2019-06-24T23:44:26.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-4.0.0-RC3","html_url":"https://github.com/square/okhttp/releases/tag/parent-4.0.0-RC3"},{"name":"parent-4.0.0-RC2","sha":"8603e2d20e4335a7a530f90a2f6439d16b8767de","kind":"tag","published_at":"2019-06-21T14:01:40.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-4.0.0-RC2","html_url":"https://github.com/square/okhttp/releases/tag/parent-4.0.0-RC2"},{"name":"parent-4.0.0-RC1","sha":"148938a17895ec72ee09b6bb4d23fb2bd7e464f4","kind":"tag","published_at":"2019-06-04T04:28:50.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-4.0.0-RC1","html_url":"https://github.com/square/okhttp/releases/tag/parent-4.0.0-RC1"},{"name":"parent-4.0.0-alpha02","sha":"7925bfc5c5da1605486e37a9360ab03f1e417050","kind":"tag","published_at":"2019-05-26T00:54:04.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-4.0.0-alpha02","html_url":"https://github.com/square/okhttp/releases/tag/parent-4.0.0-alpha02"},{"name":"parent-3.14.2","sha":"b8b6ee831c65208940c741f8e091ff02425566d5","kind":"tag","published_at":"2019-05-19T17:34:31.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.14.2","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.14.2"},{"name":"parent-4.0.0-ALPHA01","sha":"8f21b934f928986bba7e50114911c3c494e1d5c5","kind":"tag","published_at":"2019-05-09T01:41:25.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-4.0.0-ALPHA01","html_url":"https://github.com/square/okhttp/releases/tag/parent-4.0.0-ALPHA01"},{"name":"parent-3.12.3","sha":"44b00791f62938497597d7fc767c9b23bba03955","kind":"tag","published_at":"2019-05-07T17:18:40.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.12.3","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.12.3"},{"name":"parent-3.14.1","sha":"a5c4668abf1c68545e2a3a6ea365cae27d5958c1","kind":"tag","published_at":"2019-04-10T16:07:36.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.14.1","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.14.1"},{"name":"parent-3.12.2","sha":"3637fc56f70f87da696847defd311dbfb28e87b5","kind":"tag","published_at":"2019-03-14T16:07:30.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.12.2","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.12.2"},{"name":"parent-3.14.0","sha":"44d51d0cebea7d2c69f293e2fb2a7e97e7984bcc","kind":"tag","published_at":"2019-03-14T03:42:36.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.14.0","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.14.0"},{"name":"parent-3.13.1","sha":"d28d2cec21641b61f3d34e05dd52f43a717c2d32","kind":"tag","published_at":"2019-02-05T17:15:43.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.13.1","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.13.1"},{"name":"parent-3.13.0","sha":"d55661544bc95d5850f393809d26c3c8b5ee670f","kind":"tag","published_at":"2019-02-05T04:32:48.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.13.0","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.13.0"},{"name":"parent-3.12.1","sha":"875bfa3eef611237111fdc3560caec00c52c66ca","kind":"tag","published_at":"2018-12-23T17:41:46.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.12.1","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.12.1"},{"name":"parent-3.12.0","sha":"7f63a35ab1a8344279d2e84e07884a45f45f0690","kind":"tag","published_at":"2018-11-17T04:44:15.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.12.0","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.12.0"},{"name":"parent-3.11.0","sha":"95ae0cf421c0f9c5521578781952108d1a1e1bdd","kind":"tag","published_at":"2018-07-13T03:41:06.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.11.0","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.11.0"},{"name":"parent-3.10.0","sha":"c0739a419949a24d0c34cf38a25953c60871268b","kind":"tag","published_at":"2018-02-24T18:33:55.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.10.0","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.10.0"},{"name":"parent-3.9.1","sha":"23b6f7556d7df15ac3e832bdf85d940b6e50989e","kind":"tag","published_at":"2017-11-18T19:37:56.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.9.1","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.9.1"},{"name":"list","sha":"a4878313c5d1b3671b0c9c050d6724b781091299","kind":"commit","published_at":"2017-11-18T00:32:59.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/list","html_url":"https://github.com/square/okhttp/releases/tag/list"},{"name":"parent-3.9.0","sha":"51663fd08f1670c5d55fdc5b8b0bd5e326054a4e","kind":"tag","published_at":"2017-09-04T21:00:19.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.9.0","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.9.0"},{"name":"parent-3.8.1","sha":"ea582e6c1bd81c6d10c1ae89a644b94313f0de18","kind":"tag","published_at":"2017-06-18T17:08:23.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.8.1","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.8.1"},{"name":"parent-3.8.0","sha":"cb981daecfe065c3a9afd3cbf4560de6d2f8b291","kind":"tag","published_at":"2017-05-13T14:58:10.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.8.0","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.8.0"},{"name":"parent-3.7.0","sha":"e56f561e9351fac12035ea4a387b5eb3e30d9a2a","kind":"tag","published_at":"2017-04-16T01:53:05.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.7.0","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.7.0"},{"name":"parent-3.6.0","sha":"9dc1bbad245a325ffb0cd1bd88d2c439a1c2a5bd","kind":"tag","published_at":"2017-01-29T19:14:35.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.6.0","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.6.0"},{"name":"parent-3.5.0","sha":"366bc4752be25b274bb32d156a81c700bd359fa1","kind":"tag","published_at":"2016-12-01T17:53:47.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.5.0","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.5.0"},{"name":"parent-3.4.2","sha":"4fa181b3fe43795b3aaac28b97e0c1ecde9f6d42","kind":"tag","published_at":"2016-11-04T03:21:52.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.4.2","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.4.2"},{"name":"parent-3.4.1","sha":"aa69328e677e8d6ea8b3f1b0c1c2483cff11aa20","kind":"tag","published_at":"2016-07-10T15:10:02.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.4.1","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.4.1"},{"name":"parent-3.4.0","sha":"ee2b9a2917423ceb9e9908636982dd492628f402","kind":"tag","published_at":"2016-07-09T02:39:30.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.4.0","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.4.0"},{"name":"parent-3.4.0-RC1","sha":"9db491924acdac431fe51d274deed270003a1633","kind":"tag","published_at":"2016-07-03T03:18:31.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.4.0-RC1","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.4.0-RC1"},{"name":"parent-3.3.1","sha":"358d96c5fbd45a611f7af7846a9dd99847104406","kind":"tag","published_at":"2016-05-28T18:11:53.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.3.1","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.3.1"},{"name":"parent-3.3.0","sha":"b031042e671f15146dc6f4b5af25a0b31069b30c","kind":"tag","published_at":"2016-05-25T02:12:29.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.3.0","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.3.0"},{"name":"parent-2.7.5","sha":"6e236ce3b80f21369dc544f0e1053ff71be8689b","kind":"tag","published_at":"2016-02-26T15:22:35.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-2.7.5","html_url":"https://github.com/square/okhttp/releases/tag/parent-2.7.5"},{"name":"parent-3.2.0","sha":"14eb077351a8f24e83cdac92930eff84d05e8787","kind":"tag","published_at":"2016-02-26T01:54:09.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.2.0","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.2.0"},{"name":"parent-3.1.2","sha":"9aa5e87a2c90b90ad83866af1762d4e40d44dab0","kind":"tag","published_at":"2016-02-10T13:37:53.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.1.2","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.1.2"},{"name":"parent-2.7.4","sha":"edaa258106aa77f536a7357a2817e98e7669d737","kind":"tag","published_at":"2016-02-08T03:21:12.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-2.7.4","html_url":"https://github.com/square/okhttp/releases/tag/parent-2.7.4"},{"name":"parent-3.1.1","sha":"0cd6b186b1789cbdb81d22768425ec149d395766","kind":"tag","published_at":"2016-02-08T03:10:21.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.1.1","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.1.1"},{"name":"parent-2.7.3","sha":"2df2565bba8edac14070460bd9034aa281a94afc","kind":"tag","published_at":"2016-02-07T03:13:30.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-2.7.3","html_url":"https://github.com/square/okhttp/releases/tag/parent-2.7.3"},{"name":"parent-3.1.0","sha":"519ec8adcac12359841cbdb0cb6666070b714776","kind":"tag","published_at":"2016-02-06T17:59:25.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.1.0","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.1.0"},{"name":"parent-3.0.1","sha":"bdbb3ad03ca7026a8a2d11690d4174412fa79685","kind":"tag","published_at":"2016-01-15T00:03:10.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.0.1","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.0.1"},{"name":"parent-3.0.0","sha":"c9b812a4ab75bfbf1e1de439ee719fa700a592f1","kind":"tag","published_at":"2016-01-13T22:12:14.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.0.0","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.0.0"},{"name":"parent-2.7.2","sha":"abf0341402429deb097cd40460766aa16b7142a6","kind":"tag","published_at":"2016-01-08T05:27:49.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-2.7.2","html_url":"https://github.com/square/okhttp/releases/tag/parent-2.7.2"},{"name":"parent-3.0.0-RC1","sha":"ffc35dbd02822bf6584c6144266cbbca6b348b17","kind":"tag","published_at":"2016-01-02T07:31:15.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-3.0.0-RC1","html_url":"https://github.com/square/okhttp/releases/tag/parent-3.0.0-RC1"},{"name":"parent-2.7.1","sha":"e871c6068a2c9289638fde69fe311f2e8165f898","kind":"tag","published_at":"2016-01-01T16:13:38.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-2.7.1","html_url":"https://github.com/square/okhttp/releases/tag/parent-2.7.1"},{"name":"parent-2.7.0","sha":"a36b1fb73c1b37a1e0f4bff0b5627d7b1198ce1c","kind":"tag","published_at":"2015-12-14T01:35:29.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-2.7.0","html_url":"https://github.com/square/okhttp/releases/tag/parent-2.7.0"},{"name":"parent-2.6.0","sha":"d0a381edc1a20d8d3e17bde0a6eda598334162cc","kind":"tag","published_at":"2015-11-22T17:30:33.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-2.6.0","html_url":"https://github.com/square/okhttp/releases/tag/parent-2.6.0"},{"name":"parent-2.5.0","sha":"f36bed41a87296d8cd641b5c0602fcb860fe7043","kind":"tag","published_at":"2015-08-26T01:11:24.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-2.5.0","html_url":"https://github.com/square/okhttp/releases/tag/parent-2.5.0"},{"name":"parent-2.4.0","sha":"7298bee253df7a9b8bf3cf4438aa077a28502c01","kind":"tag","published_at":"2015-05-22T23:47:48.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-2.4.0","html_url":"https://github.com/square/okhttp/releases/tag/parent-2.4.0"},{"name":"parent-2.4.0-RC1","sha":"5cc7dba3ad1597f5ca7f5380a4845d0385fa497f","kind":"tag","published_at":"2015-05-16T21:03:18.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-2.4.0-RC1","html_url":"https://github.com/square/okhttp/releases/tag/parent-2.4.0-RC1"},{"name":"parent-2.3.0","sha":"c49eedeba374e06bc82f5aed7c67506f65dd2482","kind":"tag","published_at":"2015-03-17T02:28:11.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-2.3.0","html_url":"https://github.com/square/okhttp/releases/tag/parent-2.3.0"},{"name":"parent-2.2.0","sha":"6aef5ab3c5dd964156be8e3a2501ff740dda1516","kind":"tag","published_at":"2014-12-31T02:52:34.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-2.2.0","html_url":"https://github.com/square/okhttp/releases/tag/parent-2.2.0"},{"name":"parent-2.1.0","sha":"86d4716b58ad3652e5e768bc52f807817a97c61c","kind":"tag","published_at":"2014-11-12T05:34:32.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-2.1.0","html_url":"https://github.com/square/okhttp/releases/tag/parent-2.1.0"},{"name":"parent-2.1.0-RC1","sha":"7b6771bb2939da2e7d42ca359a7cfc0a6e86272b","kind":"tag","published_at":"2014-11-05T07:12:02.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-2.1.0-RC1","html_url":"https://github.com/square/okhttp/releases/tag/parent-2.1.0-RC1"},{"name":"parent-2.0.0","sha":"a3c18f69c9a903b9078fd08dffe819f922b5833b","kind":"tag","published_at":"2014-06-21T04:02:20.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-2.0.0","html_url":"https://github.com/square/okhttp/releases/tag/parent-2.0.0"},{"name":"parent-2.0.0-RC2","sha":"f171096b1124485c538e0f65059d564ed378ab91","kind":"tag","published_at":"2014-06-11T05:36:55.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-2.0.0-RC2","html_url":"https://github.com/square/okhttp/releases/tag/parent-2.0.0-RC2"},{"name":"parent-2.0.0-RC1","sha":"8dcc74d339e0664580756063ff47c65c6f1a17ae","kind":"tag","published_at":"2014-05-24T06:03:45.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-2.0.0-RC1","html_url":"https://github.com/square/okhttp/releases/tag/parent-2.0.0-RC1"},{"name":"parent-1.6.0","sha":"bbfbfdf49e0ef1f5607243adf854252ee1236a39","kind":"tag","published_at":"2014-05-24T04:10:55.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-1.6.0","html_url":"https://github.com/square/okhttp/releases/tag/parent-1.6.0"},{"name":"parent-1.5.4","sha":"e5cb379d09a5a26f194895fed3cd8aea20a1c6c8","kind":"tag","published_at":"2014-04-15T03:37:48.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-1.5.4","html_url":"https://github.com/square/okhttp/releases/tag/parent-1.5.4"},{"name":"parent-1.5.3","sha":"fa8cb2ee264655fd553193cfe567c1df19c95e42","kind":"tag","published_at":"2014-03-29T21:27:58.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-1.5.3","html_url":"https://github.com/square/okhttp/releases/tag/parent-1.5.3"},{"name":"parent-1.5.2","sha":"b46882bdd9755c047578eb260c7875108714b7a4","kind":"tag","published_at":"2014-03-18T02:02:43.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-1.5.2","html_url":"https://github.com/square/okhttp/releases/tag/parent-1.5.2"},{"name":"parent-1.5.1","sha":"d0efad2fd421da0ddf5eabf55d6a2f725a754031","kind":"tag","published_at":"2014-03-12T03:40:05.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-1.5.1","html_url":"https://github.com/square/okhttp/releases/tag/parent-1.5.1"},{"name":"parent-1.5.0","sha":"aebb2c4afd5edc46e97a372eef74d51df7988284","kind":"tag","published_at":"2014-03-07T22:59:52.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-1.5.0","html_url":"https://github.com/square/okhttp/releases/tag/parent-1.5.0"},{"name":"1.3.0","sha":"3e14ab4438cff64e16d7ae14ceb79ed59643a280","kind":"tag","published_at":"2014-01-12T02:47:23.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/1.3.0","html_url":"https://github.com/square/okhttp/releases/tag/1.3.0"},{"name":"parent-1.2.1","sha":"4eb81fee1f807cb97bf8fb39d23652c947561bf2","kind":"tag","published_at":"2013-08-24T06:19:50.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-1.2.1","html_url":"https://github.com/square/okhttp/releases/tag/parent-1.2.1"},{"name":"parent-1.2.0","sha":"f7699d92436ccb8f240d003469b128bfdedc378a","kind":"tag","published_at":"2013-08-12T07:01:28.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-1.2.0","html_url":"https://github.com/square/okhttp/releases/tag/parent-1.2.0"},{"name":"parent-1.1.1","sha":"d439855a9d061a274730409e471310ea9291c693","kind":"tag","published_at":"2013-06-24T00:01:04.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-1.1.1","html_url":"https://github.com/square/okhttp/releases/tag/parent-1.1.1"},{"name":"parent-1.1.0","sha":"20f7eebbf58109009577e3369f68e0e241f2cd61","kind":"tag","published_at":"2013-06-16T00:28:30.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-1.1.0","html_url":"https://github.com/square/okhttp/releases/tag/parent-1.1.0"},{"name":"parent-1.0.2","sha":"34049c1c0f193e293aa4466acee774e2bdc7cb65","kind":"tag","published_at":"2013-05-12T03:56:17.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-1.0.2","html_url":"https://github.com/square/okhttp/releases/tag/parent-1.0.2"},{"name":"parent-1.0.1","sha":"66544feab64f1e53796d261c6820565a67425803","kind":"tag","published_at":"2013-05-06T16:19:49.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-1.0.1","html_url":"https://github.com/square/okhttp/releases/tag/parent-1.0.1"},{"name":"parent-1.0.0","sha":"d95ecff5423f19e019e178baddfe4211f2fe57aa","kind":"tag","published_at":"2013-05-06T14:00:53.000Z","download_url":"https://codeload.github.com/square/okhttp/tar.gz/parent-1.0.0","html_url":"https://github.com/square/okhttp/releases/tag/parent-1.0.0"}]},"repo_metadata_updated_at":"2023-03-21T21:51:56.050Z","dependent_packages_count":1136,"downloads":null,"downloads_period":null,"dependent_repos_count":9272,"rankings":{"downloads":null,"dependent_repos_count":0.08675963773342951,"dependent_packages_count":0.06952793139376452,"stargazers_count":0.45042878897170796,"forks_count":0.7605995030856776,"docker_downloads_count":3.382423659533542,"average":0.9499479041436244},"purl":"pkg:maven/com.squareup.okhttp3/mockwebserver","advisories":[],"docker_usage_url":"https://docker.ecosyste.ms/usage/maven/com.squareup.okhttp3:mockwebserver","docker_dependents_count":49,"docker_downloads_count":127114,"usage_url":"https://repos.ecosyste.ms/usage/maven/com.squareup.okhttp3:mockwebserver","dependent_repositories_url":"https://repos.ecosyste.ms/api/v1/usage/maven/com.squareup.okhttp3:mockwebserver/dependencies","status":null,"funding_links":[],"critical":true,"versions_url":"https://packages.ecosyste.ms/api/v1/registries/repo1.maven.org/packages/com.squareup.okhttp3:mockwebserver/versions","version_numbers_url":"https://packages.ecosyste.ms/api/v1/registries/repo1.maven.org/packages/com.squareup.okhttp3:mockwebserver/version_numbers","dependent_packages_url":"https://packages.ecosyste.ms/api/v1/registries/repo1.maven.org/packages/com.squareup.okhttp3:mockwebserver/dependent_packages","related_packages_url":"https://packages.ecosyste.ms/api/v1/registries/repo1.maven.org/packages/com.squareup.okhttp3:mockwebserver/related_packages","maintainers":[],"registry":{"name":"repo1.maven.org","url":"https://repo.maven.apache.org/maven2","ecosystem":"maven","default":true,"packages_count":517936,"maintainers_count":0,"namespaces_count":68848,"keywords_count":32053,"github":"maven-central","metadata":{"funded_packages_count":25044},"icon_url":"https://github.com/maven-central.png","created_at":"2022-07-21T16:40:13.074Z","updated_at":"2025-06-07T05:38:09.526Z","packages_url":"https://packages.ecosyste.ms/api/v1/registries/repo1.maven.org/packages","maintainers_url":"https://packages.ecosyste.ms/api/v1/registries/repo1.maven.org/maintainers","namespaces_url":"https://packages.ecosyste.ms/api/v1/registries/repo1.maven.org/namespaces"}},"unique_repositories_count":179,"unique_repositories_count_past_30_days":19,"recent_issues":[{"uuid":"5427351762","node_id":"PR_kwDOTHJuas8AAAABDLid1g","number":33,"state":"open","title":"chore(deps): bump the android-deps group across 1 directory with 19 updates","user":"dependabot[bot]","labels":["dependencies","java"],"assignees":[],"locked":false,"comments_count":1,"pull_request":true,"closed_at":null,"author_association":null,"state_reason":null,"created_at":"2026-09-11T17:43:45.000Z","updated_at":"2026-09-11T17:45:39.000Z","time_to_close":null,"merged_at":null,"merged_by":null,"closed_by":null,"dependency_metadata":{"prefix":"chore(deps): bump","group_name":"android-deps","update_count":19,"packages":[{"name":"gradle-wrapper","old_version":"9.5.1","new_version":"9.7.1","repository_url":"https://github.com/gradle/gradle"},{"name":"androidx.benchmark:benchmark-macro-junit4","old_version":"1.4.1","new_version":"1.5.0"},{"name":"androidx.compose:compose-bom","old_version":"2026.05.01","new_version":"2026.09.00"},{"name":"androidx.core:core-ktx","old_version":"1.18.0","new_version":"1.19.0"},{"name":"org.bouncycastle:bcprov-jdk18on","old_version":"1.84","new_version":"1.85.2","repository_url":"https://github.com/bcgit/bc-java"},{"name":"org.commonmark:commonmark","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-autolink","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-strikethrough","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-tables","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-task-list-items","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.junit.vintage:junit-vintage-engine","old_version":"6.1.0","new_version":"6.1.3","repository_url":"https://github.com/junit-team/junit-framework"},{"name":"io.kotest:kotest-assertions-core-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"io.kotest:kotest-runner-junit5-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"com.squareup.okhttp3:mockwebserver","old_version":"5.3.2","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.squareup.okhttp3:okhttp","old_version":"5.3.2","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.android.application","old_version":"9.2.1","new_version":"9.4.0"},{"name":"com.android.test","old_version":"9.2.1","new_version":"9.4.0"},{"name":"org.jetbrains.kotlin.plugin.compose","old_version":"2.4.0","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"},{"name":"org.jetbrains.kotlin.plugin.serialization","old_version":"2.4.0","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"}],"path":null,"ecosystem":"maven"},"body":"Bumps the android-deps group with 19 updates in the /apps/android directory:\n\n| Package | From | To |\n| --- | --- | --- |\n| [gradle-wrapper](https://github.com/gradle/gradle) | `9.5.1` | `9.7.1` |\n| androidx.benchmark:benchmark-macro-junit4 | `1.4.1` | `1.5.0` |\n| androidx.compose:compose-bom | `2026.05.01` | `2026.09.00` |\n| androidx.core:core-ktx | `1.18.0` | `1.19.0` |\n| [org.bouncycastle:bcprov-jdk18on](https://github.com/bcgit/bc-java) | `1.84` | `1.85.2` |\n| [org.commonmark:commonmark](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-autolink](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-strikethrough](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-tables](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-task-list-items](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.junit.vintage:junit-vintage-engine](https://github.com/junit-team/junit-framework) | `6.1.0` | `6.1.3` |\n| [io.kotest:kotest-assertions-core-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [io.kotest:kotest-runner-junit5-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [com.squareup.okhttp3:mockwebserver](https://github.com/lysine-dev/okhttp) | `5.3.2` | `5.5.0` |\n| [com.squareup.okhttp3:okhttp](https://github.com/lysine-dev/okhttp) | `5.3.2` | `5.5.0` |\n| com.android.application | `9.2.1` | `9.4.0` |\n| com.android.test | `9.2.1` | `9.4.0` |\n| [org.jetbrains.kotlin.plugin.compose](https://github.com/JetBrains/kotlin) | `2.4.0` | `2.4.20` |\n| [org.jetbrains.kotlin.plugin.serialization](https://github.com/JetBrains/kotlin) | `2.4.0` | `2.4.20` |\n\n\nUpdates `gradle-wrapper` from 9.5.1 to 9.7.1\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/gradle/gradle/releases\"\u003egradle-wrapper's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e9.7.1\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.1.\u003c/p\u003e\n\u003cp\u003eThis is a patch release for 9.7.0. We recommend using 9.7.1 instead of 9.7.0.\u003c/p\u003e\n\u003cp\u003eHere are the highlights of 9.7.0 release:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIsolated Projects graduates to incubating\u003c/li\u003e\n\u003cli\u003eBroader Configuration Cache compatibility\u003c/li\u003e\n\u003cli\u003eResilient Sync helps you fix broken builds\u003c/li\u003e\n\u003cli\u003eMore source locations in problem reports\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003ca href=\"https://docs.gradle.org/9.7.1/release-notes.html\"\u003eRead the Release Notes\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eWe would like to thank the following community members for their contributions to this release of Gradle:\n\u003ca href=\"https://github.com/aSemy\"\u003eAdam\u003c/a\u003e,\n\u003ca href=\"https://github.com/Gautam-aman\"\u003eAman Gautam\u003c/a\u003e,\n\u003ca href=\"https://github.com/YukiCodepth\"\u003eAman Kumar\u003c/a\u003e,\n\u003ca href=\"https://github.com/adubrouski\"\u003eAnton Dubrouski\u003c/a\u003e,\n\u003ca href=\"https://github.com/liutikas\"\u003eAurimas\u003c/a\u003e,\n\u003ca href=\"https://github.com/gbhavya07\"\u003egbhavya07\u003c/a\u003e,\n\u003ca href=\"https://github.com/joshfriend\"\u003eJosh Friend\u003c/a\u003e,\n\u003ca href=\"https://github.com/nicklauslittle-gov\"\u003enicklauslittle-gov\u003c/a\u003e,\n\u003ca href=\"https://github.com/psoni674\"\u003ePragati\u003c/a\u003e,\n\u003ca href=\"https://github.com/Project516\"\u003eproject516\u003c/a\u003e,\n\u003ca href=\"https://github.com/Uomocapra\"\u003eQin Mi\u003c/a\u003e,\n\u003ca href=\"https://github.com/rkdfx\"\u003eRavi\u003c/a\u003e,\n\u003ca href=\"https://github.com/sk-reddy17\"\u003esk-reddy17\u003c/a\u003e,\n\u003ca href=\"https://github.com/Suvrat1629\"\u003eSuvrat Acharya\u003c/a\u003e,\n\u003ca href=\"https://github.com/ShreckYe\"\u003eYongshun Ye\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eUpgrade instructions\u003c/h2\u003e\n\u003cp\u003eSwitch your build to use Gradle 9.7.1 by updating your wrapper:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e./gradlew :wrapper --gradle-version=9.7.1 \u0026amp;\u0026amp; ./gradlew :wrapper\r\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eSee the Gradle \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/upgrading_version_9.html\"\u003e9.x upgrade guide\u003c/a\u003e to learn about deprecations, breaking changes and other considerations when upgrading.\u003c/p\u003e\n\u003cp\u003eFor Java, Groovy, Kotlin and Android compatibility, see the \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/compatibility.html\"\u003efull compatibility notes\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eReporting problems\u003c/h2\u003e\n\u003cp\u003eIf you find a problem with this release, please file a bug on \u003ca href=\"https://github.com/gradle/gradle/issues\"\u003eGitHub Issues\u003c/a\u003e adhering to our issue guidelines.\nIf you're not sure you're encountering a bug, please use the \u003ca href=\"https://discuss.gradle.org/c/help-discuss\"\u003eforum\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eWe hope you will build happiness with Gradle, and we look forward to your feedback via \u003ca href=\"https://twitter.com/gradle\"\u003eTwitter\u003c/a\u003e or on \u003ca href=\"https://github.com/gradle\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003e9.7.0\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.0.\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/92f0512e7f06d84621afba191f75e265363890cf\"\u003e\u003ccode\u003e92f0512\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38892\"\u003e#38892\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/820ee75a99a179bbffa41bcedc6477b685fabb9f\"\u003e\u003ccode\u003e820ee75\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/82c23f9bd2a89b4cc644e1f90a28a8668feb3dee\"\u003e\u003ccode\u003e82c23f9\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering problem in KTS (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38878\"\u003e#38878\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/ef11a7268fe8cc8d6ab849ec911aa11220180553\"\u003e\u003ccode\u003eef11a72\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering issue\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/bb0d8a974a71b1003efea41e4046e98855cd5ff8\"\u003e\u003ccode\u003ebb0d8a9\u003c/code\u003e\u003c/a\u003e Make relevant tests polyglot (run for multiple DSLs)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/336e129d7f95c03486acafc97abf59734acfed48\"\u003e\u003ccode\u003e336e129\u003c/code\u003e\u003c/a\u003e Update signing configuration (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38874\"\u003e#38874\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/4bdf0da2dad9884d089a6062a45ea7183e7d735d\"\u003e\u003ccode\u003e4bdf0da\u003c/code\u003e\u003c/a\u003e Update signing configuration\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/cd9b92c1b82856248cf1dc58b50378238bec7b52\"\u003e\u003ccode\u003ecd9b92c\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38839\"\u003e#38839\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/5f4e381964897ad8d6b99e5a7c77f26dba3259fb\"\u003e\u003ccode\u003e5f4e381\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/1e08ab551367aeb5fb48b26e72807e1d2b27c939\"\u003e\u003ccode\u003e1e08ab5\u003c/code\u003e\u003c/a\u003e Keep type-use annotations in extracted ABI classes (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38810\"\u003e#38810\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/gradle/gradle/compare/v9.5.1...v9.7.1\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `androidx.benchmark:benchmark-macro-junit4` from 1.4.1 to 1.5.0\n\nUpdates `androidx.compose:compose-bom` from 2026.05.01 to 2026.09.00\n\nUpdates `androidx.core:core-ktx` from 1.18.0 to 1.19.0\n\nUpdates `org.bouncycastle:bcprov-jdk18on` from 1.84 to 1.85.2\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.md\"\u003eorg.bouncycastle:bcprov-jdk18on's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch1\u003eBouncy Castle Crypto Package - Release Notes\u003c/h1\u003e\n\u003ch2\u003e1.0 Introduction\u003c/h2\u003e\n\u003cp\u003eThe Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. The package is organised so that it contains a light-weight API suitable for use in any environment (including the J2ME) with the additional infrastructure to conform the algorithms to the JCE framework.\u003c/p\u003e\n\u003ch2\u003e2.0 Release History\u003c/h2\u003e\n\u003cp\u003e\u003c!-- raw HTML omitted --\u003e\u003c!-- raw HTML omitted --\u003e\u003c/p\u003e\n\u003ch3\u003e2.1.1 Version\u003c/h3\u003e\n\u003cp\u003eRelease: 1.86\u003cbr /\u003e\nDate: 2026, 11th September.\u003c/p\u003e\n\u003ch3\u003e2.1.2 Defects Fixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) let a subkey inherit the primary key's Key Flags when its own Subkey Binding signature carried no Key Flags subpacket, which made the two capability decisions taken for one subkey disagree. OpenPGPCertificate.OpenPGPComponentKey.isSigningKey() reads the effective flags, which fell back to the primary key's direct-key or primary user ID self-signature, so a subkey bound with no flags of its own counted as signing-capable; verifyEmbeddedPrimaryKeyBinding reads the binding signature's own flags, found no signing capability there, and so skipped the embedded Primary Key Binding (cross-certification) signature that RFC 9580 sec. 5.2.1.8 and sec. 10.1.3 require of a subkey that can issue signatures. A data signature made by such a subkey was therefore attributed to the certificate and reported valid by OpenPGPSignature.OpenPGPDocumentSignature.isValid() with the cross-certification requirement never applied, where GnuPG refuses the same certificate and message as not cross-certified. An attacker holding a third party's public signing subkey - which is public material - could bind it to their own primary key with a Subkey Binding signature they are able to make, carrying no Key Flags and no embedded Primary Key Binding signature, which they cannot make without the subkey's private key, and have that party's genuine signatures verify as valid under the attacker's own identity: misattribution of a real signature rather than a forgery of a new one, since the signature still has to be one the subkey actually made. Key Flags are a statement about the key the carrying signature refers to (RFC 9580 sec. 5.2.3.29), so a subkey no longer inherits them from the certificate-wide signatures of the primary key: a Subkey Binding signature that omits the subpacket now leaves the subkey with no capabilities rather than the primary's, which makes the flags the cross-certification check consults the same flags every other decision consults. Preferences and the other subpackets a direct-key signature carries are inherited as before, and the primary key itself - whose flags legitimately come from its direct-key or user ID self-signature - is unaffected. The low-level PGPSignature / PGPPublicKeyRing API performs no binding checks by design and is unchanged (CVE-2026-71887).\u003c/li\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) used a version 6 key that carried no valid Direct Key signature, falling back to the primary user ID binding as it correctly does for a version 4 key. RFC 9580 sec. 5.2.3.10 requires the opposite: \u0026quot;An implementation MUST ensure that a valid Direct Key signature is present before using a version 6 key. This prevents certain attacks where an adversary strips a self-signature specifying a Key Expiration Time or certain preferences.\u0026quot; The certificate grammar says the same structurally, the Direct Key signature being mandatory in the version 6 structure of sec. 10.1.1 and optional in the version 4 one of sec. 10.1.3. Because a version 6 certificate carries its key expiration, features and algorithm preferences on the Direct Key signature - the convention the RFC recommends and the one OpenPGPKeyGenerator follows, its user ID certification carrying no expiration at all - removing that single signature packet from a published certificate silently dropped the expiration along with the preferences and features: OpenPGPCertificate.getSignatureChainFor fell back to the user ID binding, the primary key was still reported bound, and getEncryptionKeys() and getSigningKeys() went on returning the subkeys of a key whose owner had set it to expire. The primary key fingerprint is unchanged by the removal, so a relying party pinning the key by fingerprint still treats it as the same key, and no private key or hash collision is involved; the natural moment for the strip is the key refresh that RFC 9580 names as the reason to refetch a key at all - to learn about changes in expiration, features, preferences and revocation - which is exactly the update it defeats. This is a downgrade rather than a forgery, nothing being attributed to a key that did not authorise it, and the concerning direction is encryption, to a key meant to have been retired. OpenPGPCertificate.isBoundBy now requires a valid Direct Key self-signature on a version 6 primary key before any component of the certificate - the primary key, its subkeys or its identities - is treated as bound, so a version 6 certificate stripped of it offers no keys at all rather than an unexpiring set. Version 4 certificates are unaffected: there the key expiration legitimately lives on the user ID self-signature and the fallback is correct, so it stays. The revocation-only version 6 certificate of sec. 10.1.2, which legitimately carries no Direct Key signature, is unaffected as well - its key was already refused as revoked, and reading the revocation does not go through the binding check.\u003c/li\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) ignored the OpenPGPPolicy a caller had configured when it verified the signatures on an inline message. OpenPGPMessageInputStream took the policy it sanitizes each document signature against from the implementation's own default rather than from the processor the signature is being verified by, so a policy supplied through the documented OpenPGPApi(implementation, policy) / OpenPGPMessageProcessor(implementation, policy) constructor - which is how OpenPGPApi.decryptAndOrVerifyMessage() plumbs the configured policy through - had no bearing on whether a signature was accepted, although the same processor already applied it to the decompressed-size bound. A caller who hardened the policy beyond the default therefore had a signature that policy rejects handed back from getResult().getSignatures() with isTestedCorrect() true, while OpenPGPSignature.isValid(policy) on that same signature reported the rejection. Both verify paths, the one-pass and the prefixed-signature one, now read the configured policy; the detached-signature processor already did.\u003c/li\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) went on offering the subkeys of a certificate whose primary key had expired. OpenPGPCertificate's binding check evaluated only a subkey's own Subkey Binding signature, so a primary key whose Key Expiration Time (RFC 9580 sec. 5.2.3.13) had passed still handed out a longer-lived encryption or signing subkey from getEncryptionKeys() / getSigningKeys(), leaving the certificate contradicting itself - getExpirationTime() in the past and getPrimaryKey().isBoundAt() false, while isBoundAt() on the subkey answered true. An expired primary key can no longer certify, so the subkeys it bound are not usable with it either, which is how GnuPG and Sequoia both treat such a certificate; primary key revocation already propagated, since a revocation appears in the subkey's signature chain, but expiration is not carried there. Relatedly, a subkey no longer inherits the primary key's validity period at all - sec. 5.2.3.13 counts that period from the creation time of the key the carrying self-signature is made on, so re-basing the primary key's period on a subkey created later than it gave that subkey an expiration date later than the primary key's own.\u003c/li\u003e\n\u003cli\u003eOpenPGPSignature.OpenPGPDocumentSignature.isValidAt(Date) in the high-level OpenPGP API reported a data signature as valid at an evaluation time past the signature's own Signature Expiration Time (RFC 9580 sec. 5.2.3.18, hashed subpacket type 3). The method checked that the signature was correct and that the issuing key was bound and signing-capable at that date, but never consulted the signature's own expiration, so it disagreed with isEffectiveAt(Date) on the same object and with its own javadoc, which names being effective as one of the three criteria of a valid signature. Signature expiration is a separate axis from the issuing key's Key Expiration Time that the binding checks already cover, and GnuPG, GPGME, git and Sequoia all keep the two apart and treat a signature past its expiration as not good. isValid() and isValid(policy) evaluate at the signature's creation time, where a signature is always inside its own window, and are unchanged.\u003c/li\u003e\n\u003cli\u003eThe lightweight LMSSigner and HSSSigner refused a key wrapped in ParametersWithRandom, which is how BcContentSignerBuilder passes a key whenever setSecureRandom() has been called - so BcHssLmsContentSignerBuilder built a working signer until a random was set and then failed with \u0026quot;Incorrect Key Parameters\u0026quot;, and the two signers themselves raised ClassCastException on the same input. All three now unwrap it, as the promoted ML-DSA and SLH-DSA signers already did. The random is accepted and not used: LMS derives its message randomiser C from the key's seed and the one-time index, so it is deterministic and cannot repeat while q does not. Note SP 800-208 sec. 6.1 asks for C to come from an approved random bit generator, which this implementation does not do; that is unchanged here, and a supplied random is now ignored rather than refused.\u003c/li\u003e\n\u003cli\u003eLMS signature verification did not apply two of the checks RFC 8554 sec. 5.4.2 requires before a signature is processed. Step 2g refuses a signature whose LMS typecode is not the one from the public key, and without it the path computation took its height and tree digest from the parameter set the signature named rather than the key's, so a signature claiming a height-25 parameter set drove a 25-level computation against a height-5 key. Step 2i refuses a leaf number q outside the tree, and without it an out-of-range q flowed into the node arithmetic and was left for the candidate-root comparison to catch. Neither was a forgery - the domain separation between D_LEAF and D_INTR and the final comparison saw to that - but both are attacker-chosen work the specification says to refuse up front. Both are now checked, and a signature failing either is still reported as not verifying rather than thrown out of Signature.verify(). The catch around the signature decode in LMSSigner and HSSSigner has also been narrowed to the decode itself, as the corresponding SPI was corrected to do for github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2408\"\u003e#2408\u003c/a\u003e: past the parse the engine reports an inconsistent signature by returning false rather than by throwing, so the wider catch caught nothing while standing ready to turn a future internal error into a quiet false.\u003c/li\u003e\n\u003cli\u003eThe LMS and HSS key parameter classes now apply at construction the checks their decoders apply, so a key built directly cannot be one the decoder would refuse. LMSPrivateKeyParameters accepted an identifier of any length although the decoder reads exactly 16 bytes - such a key encoded but could not be read back - and left q, maxQ and the seed length unchecked; the seed is now required to be at least m bytes at decode as well, where a one-byte seed had been decoding silently and then deriving every one-time key from it. HSSPrivateKeyParameters checked neither its level count nor that it had been given a component key per level and a chaining signature per level below the root, and then indexed both lists, so a mismatch surfaced as IndexOutOfBoundsException - or, where a level happened to match, as a null chaining signature that only failed at signing time; the level is now checked after the reset that fills it in, since a null is legitimate on the way in. LMSPrivateKeyParameters.getInstance(byte[], byte[]) adopted the public key supplied beside the private one without comparing them, so a mismatched public key was simply reported by getPublicKey(); it now cross-checks the identifier, both parameter sets and, where the tree cache already holds it, the root, as the HSS entry point does. The decoders also now report a bad version or seed length as IOException rather than IllegalStateException, so a caller can catch one type for a malformed key, and the package-private LM-OTS public key decoder no longer declares throws Exception or dereferences an unrecognised typecode. The deprecated org.bouncycastle.pqc.crypto.lms copies carry the decoder corrections.\u003c/li\u003e\n\u003cli\u003eIn the LMS JCE layer, LMSKeyGenParameterSpec.fromNames knew all twenty LMS parameter-set names but only four of the sixteen LM-OTS ones, so none of the SP 800-208 n24 or SHAKE sets could be named; all sixteen are now present. KeyPairGenerator.initialize(int, SecureRandom) reports InvalidParameterException, which is what the JCA specifies and which extends the IllegalArgumentException it raised before, so existing catches still match. BCLMSPrivateKey.getIndex now takes the exhaustion check and the index read under the key's own monitor rather than as two separate calls, and two unused fields have gone from LMSSignatureSpi. Note that the LMS Signature claims its one-time key at the first update() rather than at sign(), so a Signature that is initialised and updated and then abandoned spends an index without producing a signature - the safe direction for a one-time scheme, and now documented on the SPI.\u003c/li\u003e\n\u003cli\u003eEvery other key pair generator that refuses a key size did the same thing the LMS one did above. KeyPairGenerator.initialize(int, SecureRandom) is documented to raise InvalidParameterException when the key size is not one the generator supports, and thirty of them raised a bare IllegalArgumentException instead, so a caller following the JCA and catching the documented type saw an exception escaping rather than a refusal. The ML-DSA, ML-KEM, SLH-DSA, Classic McEliece, FrodoKEM, NTRU and composite signature and KEM generators in the BC provider, and every generator in BCPQC, now raise InvalidParameterException - NewHope included, where the value is a key size it will not take rather than a mode of initialisation it does not offer. InvalidParameterException extends IllegalArgumentException, so callers written against the old behaviour go on catching it unchanged. The two RSA generators are corrected as well, and differently: theirs is a key size below a floor rather than a mode of initialisation they do not offer, and the refusal is raised by the lightweight RSAKeyGenerationParameters, which cannot name a java.security exception at all, so the RSA KeyPairGeneratorSpi now translates it - keeping the message verbatim and the original exception as the cause, through a new SecurityExceptions.invalidParameterException factory, since InvalidParameterException has no constructor that takes one. Of the 304 KeyPairGenerator services the two providers register, 299 now refuse a nonsense key size the way the JCA defines it and five accept it as a strength they can work with, with none left raising a bare IllegalArgumentException; that is asserted as a sweep over both providers rather than per algorithm, so a generator added later is covered without the test being touched. The jdk1.3 provider overlays of the four generators that have one carry the same change, and the jdk1.3 SecurityExceptions overlay gains the new factory along with the invalidAlgorithmParameterException one it had been missing.\u003c/li\u003e\n\u003cli\u003eKeyPairGenerator.initialize(AlgorithmParameterSpec, SecureRandom) had the same shape of problem as the int overload above, and only 44 of the 304 services the two providers register reported an unusable spec as the InvalidAlgorithmParameterException that method declares. The twenty-three PQC generators that resolve a parameter set by name - cmce, frodokem, mldsa, mlkem, slhdsa, aimer, bike, faest, falcon, haetae, hqc, mayo, mqom, ntru, ntruplus, both ntruprime variants, qruov, saber, sdith, smaugt, snova and sqisign, 230 services between them - case-folded the name they got back from the spec without checking it, so a spec with no getName() method, and a null spec, produced a NullPointerException from inside the fold; their own \u0026quot;is this name one I know\u0026quot; branch, which does report the declared exception, was unreachable. The two composite generators, whose parameter set is fixed by the algorithm name so that null is the only spec they accept, refused every other one with IllegalArgumentException. RSA answered correctly for a spec of the wrong type but not for one of the right type carrying values its lightweight parameters will not take - an even public exponent, or a key size below the floor - which is now translated the same way the int overload's is. All 304 services now report the declared exception, with the composites still taking the null spec that is right for them; note that InvalidAlgorithmParameterException is a checked exception and not an IllegalArgumentException, so a caller that was catching what these threw before has to catch the declared type instead.\u003c/li\u003e\n\u003cli\u003eAn HSS private key claimed the two records of its position under two different monitors. The top-level index and the bottom component key's one-time index q are independent records of the same position - the decoder requires them to agree, see the entry below - but generateLMSContext incremented the index under the HSS key's own monitor, released it, and only then claimed q under the component key's. A getEncoded() issued in between saw the index advanced and q not, and produced an encoding this implementation's own decoder rejects; and two threads meeting at a bottom-tree boundary could both pass the exhaustion test, take consecutive top-level indices and claim the same q, after which one of them was refused with \u0026quot;ots private key exhausted\u0026quot; by a key still reporting usages remaining, a top-level index had been spent with no signature made, and the two records stayed one apart for the rest of the key's life in that process - so it could no longer be encoded, cloned or sharded, and getIndex() and getUsagesRemaining() misreported by one. No one-time key was reused: the component key's claim is itself atomic, and the divergence runs index ahead of leaves, so the effect was on the key's usability rather than on the signatures it had made. Both records are now claimed under the one monitor, and the component key is claimed before the index is incremented so that an exhausted one leaves both untouched. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the same correction.\u003c/li\u003e\n\u003cli\u003eTimeStampToken parsed the attacker-controlled TSTInfo content of a time-stamp token (org.bouncycastle.tsp.TimeStampToken, reached from TimeStampResponse(byte[]) and (InputStream)) inside a try that caught only CMSException, so a well-formed RFC 3161 TimeStampResp whose embedded token carried a malformed TSTInfo - a SEQUENCE with fewer elements than the five mandatory fields, a non-SEQUENCE, truncated DER, or an unknown context tag - let an IllegalArgumentException or a NoSuchElementException escape the constructor's declared throws TSPException, IOException contract. A token signed by no signers or by more than one raised a bare IllegalArgumentException from the same constructor, before that try, for the same reason. Both are now reported as TSPException, matching the package-private TimeStampResponse(DLSequence) constructor and the existing getSignedAttributes guard in the same method; the signer-count refusal is a TSPValidationException, as the neighbouring check on the content type already was. Related, and the cause of the NoSuchElementException: asn1.tsp.TSTInfo read its five mandatory fields off the sequence with no bound on how many elements were actually there, so a short SEQUENCE left the enumeration to run out rather than being refused, and an oversize one was accepted with its extra elements absorbed into the optional slots. Decode now requires the five to ten elements RFC 3161 sec. 2.4.2 gives the type, which is what the sibling Accuracy and ArchiveTimeStamp decoders already did, so the failure is the IllegalArgumentException that getInstance is expected to raise (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2415\"\u003e#2415\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eNeither the HSS nor the XMSS^MT private key decoder checked its declared index against the traversal state stored beside it, although the two are independent records of the same position in the key and so can be compared. For HSS the records are the top-level index and the component keys' one-time indices q; for XMSS^MT they are the global index and the per-layer BDS states. A stored key whose index had been rolled back while its state stayed advanced - a partial write, a restore from backup, a buggy storage layer - was therefore accepted, and it then signed a second message under a one-time key the key had already used, producing a signature that verified, so nothing anywhere surfaced the reuse. RFC 8554 sec. 1 and RFC 8391 sec. 1.1 both require each one-time key to be used exactly once, and this is the failure those requirements exist to prevent; the single-tree XMSS decoder has tied its BDS state to its index since that state was first validated, and this brings the two multi-tree schemes into line. HSS decode now requires the declared index to equal the position the component q values imply - a level above the last contributes (q - 1) leaves of the levels beneath it, since its q has already advanced past the subtree it signed - and XMSS^MT decode now requires each present layer's BDS index to equal the leaf index that layer derives from the global index, allowing the one position where a layer has moved into a new subtree and its state legitimately still carries the previous subtree's final index. A layer with no state yet is unaffected, since those are built lazily at signing time. Related, and the same shape of omission: an XMSS or XMSS^MT private key encoding carries the tree root twice - the key's own root field and the root node of the BDS state stored beside it, which for XMSS^MT is the top layer's - and the two were never compared either. A corrupted root was accepted and then poisoned every signature the key made, because the root is hashed into the message digest: the signature did not verify and nothing indicated why. Decode now requires the two copies to agree. The BDS node values themselves are not checkable the way the LMS tree cache above is - a BDS authentication path, stack, retain or keep node does not have its children stored alongside it, so recomputing one means building a subtree, which is the work the state exists to avoid. Both checks are integer comparisons over the levels of the key, too small to measure against the surrounding decode, and both were verified not to reject any legitimate key by walking every index a key can reach: the full key space of the two-level HSS and the h=4/d=2, h=6/d=2, h=6/d=3, h=9/d=3 and h=8/d=4 XMSS^MT parameter sets, plus a three-level HSS key across a subtree boundary and an HSS shard. Since those node values cannot be recomputed, the encoded state now carries a checksum over itself instead, with the owning key's public seed hashed in front of it. Any corruption of the stored state is refused at decode rather than being loaded and then producing signatures that silently do not verify, and because the public seed is bound in, a state transplanted between two keys of the same parameter set is refused too, even though it is internally consistent and arrives with its own matching root. The public seed is bound rather than the secret seed or the PRF key deliberately: the state's own root and index are inside the encoding and so are already covered, hashing secret material would make the stored checksum a commitment to it for no gain in detection, and the PRF key does not influence the state at all. \u003cstrong\u003eThis is an error-detecting code and not integrity protection\u003c/strong\u003e - anyone able to rewrite the stored key recomputes it, so it establishes that the state is unchanged since it was written, never that it was correct when written, and the allocation bounds on the encoding remain the guard against a crafted one. It costs one SHA-256 over the state, measured at 5 to 8 microseconds each way for the h=10 and h=16 parameter sets, and 32 bytes of encoding. The state encoding was added earlier in this same cycle and has not been released, so the checksum is simply part of it rather than a new version: a state written by a 1.86 beta is rejected, which is recovered from by re-exporting the key. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the HSS check as well (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2414\"\u003e#2414\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eIn the XMSS and XMSS^MT JCE layer, KeyPairGenerator.initialize(int, SecureRandom) reports InvalidParameterException, which is what the JCA specifies and which extends the IllegalArgumentException it raised before, so existing catches still match. This is the XMSS counterpart of the same correction made to LMSKeyPairGeneratorSpi.\u003c/li\u003e\n\u003cli\u003eBCXMSSPrivateKey.getIndex and BCXMSSMTPrivateKey.getIndex took the exhaustion check and the index read as two separate calls on the key parameters. Each is atomic on its own, but the pair is not: a signature taken by another thread between them spends the last usage, so the check passes and the read that follows returns maxIndex + 1 - the one index past the end of the key, which is what the check exists to refuse, handed back as though it were the next one-time key to be used. Both reads are now taken under the key parameters' own monitor, the monitor their mutators hold, as BCLMSPrivateKey.getIndex was corrected to do. No one-time key is reused by this: the effect is on what the key reports about itself, not on the signatures it makes.\u003c/li\u003e\n\u003cli\u003eThe S/MIME example smoke test in the misc module (org.bouncycastle.mail.smime.examples.test.AllTests) drove SendSignedAndEncryptedMail against smtp.gmail.com, and that example finishes with Transport.send() under JavaMail's default settings, which have no connect timeout. Where outbound port 25 is refused the failure was swallowed and the test passed; where it is silently dropped, as on many home networks, the connect blocked and ./gradlew build hung in :misc:test indefinitely with \u0026quot;0 tests completed\u0026quot;. The test now delivers to an SMTP stub on a loopback port, with connect / read / write timeouts as a backstop, and asserts the message arrived (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2407\"\u003e#2407\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation took the traditional component public key bytes it feeds the KEM combiner from the recipient key's own encoding, while decapsulation recomputes the point from the private key and so always produced an uncompressed one. Section 4 of draft-ietf-lamps-pq-composite-kem requires an EC component to be carried as an uncompressed point, but a component key that encodes itself compressed - a BC EC key whose point format has been set through org.bouncycastle.jce.interfaces.ECPointEncoder, or a key from a provider that preserves a compressed encoding - was passed through as it came. Both sides then combined a different tradPK and derived different shared secrets, with no error reported on either: encapsulation and decapsulation both succeeded and the recipient simply could not decrypt. The EC component is now normalised to an uncompressed point wherever the engine serialises one, which covers the ephemeral key that forms the ciphertext as well. X25519 and X448 components have a single encoding and were unaffected, as were EC keys left in their default (uncompressed) format, whose shared secrets are unchanged. CompositePublicKey.getEncoded() took its component bytes the same way, so such a key also encoded to a composite key other implementations reject and whose bytes changed across an encode / decode / encode round trip - 1238 bytes rather than 1270 for MLKEM768-ECDH-P256, and for the composite ML-DSA keys sharing that method, 2006 rather than 2038 for MLDSA65-ECDSA-P256. It now normalises the component the same way. This is a write-side change only: a composite key carrying a compressed EC component is still decoded, since the component key factories accept either form, and continues to verify signatures as before - it simply re-encodes in the normalised form. The shared normalisation is org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil.getUncompressedSubjectPublicKeyBytes.\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation threw a NullPointerException, wrapped in an IllegalStateException out of KeyGenerator.generateKey(), when the SecureRandom it was given was null - which javax.crypto.KEM.newEncapsulator() documents as a request for the provider's default, and which KeyGenerator.init(spec, null) passes straight through. The three RSA-OAEP composites draw the traditional shared secret from that random directly, so they were the ones affected; the ECDH and X25519 / X448 composites escaped only because their component KeyPairGenerators default a random of their own. CompositeMLKEMEngine now defaults one through CryptoServicesRegistrar.getSecureRandom() on first use, as the composite KEM Cipher's wrap path already did, and as the KEM generators corrected earlier in this cycle now do. Related, the engine now also clears the ML-KEM component's shared secret alongside the traditional one on both the encapsulate and decapsulate paths - the copy handed back by getEncoded() was left in the heap - as section 3.5 of draft-ietf-lamps-pq-composite-kem requires.\u003c/li\u003e\n\u003cli\u003eCompositePublicKey.getAlgorithm() and CompositePrivateKey.getAlgorithm() returned null for all twelve Composite ML-KEM (draft-ietf-lamps-pq-composite-kem) parameter sets. Both classes resolved the name through the composite signature index only, which holds the composite ML-DSA OIDs, so a composite KEM key pair - generated, parsed from a certificate, or read from PKCS#8 - reported no algorithm at all, and the standard JCA idiom of reconstructing a key with KeyFactory.getInstance(key.getAlgorithm()) raised a NullPointerException. The lookup now falls back to the composite KEM index, so the name returned is the one the provider registers the algorithm under (e.g. MLKEM768-X25519-SHA3-256), matching the composite ML-DSA behaviour. The same single-index assumption made the CompositePublicKey(SubjectPublicKeyInfo) and CompositePrivateKey(PrivateKeyInfo) constructors reject a composite KEM key with \u0026quot;unable to create CompositePublicKey from SubjectPublicKeyInfo\u0026quot;; they now dispatch to the composite KEM key factory for those OIDs. Keys obtained through KeyFactory or through BouncyCastleProvider.getPublicKey / getPrivateKey were unaffected and are unchanged (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2404\"\u003e#2404\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe org.bouncycastle.jcajce.spec.KEMKDFSpec constructor stored a null otherInfo as given, so getOtherInfo() returned null, and three of the KDF branches KdfUtil.makeKeyBytes dispatches to - KMAC-128, KMAC-256 and SHAKE-256 - read the otherInfo length without a guard and threw NullPointerException out of the KEM operation, where the KDF2, KDF3 and HKDF branches tolerate a null through KDFParameters / HKDFParameters. The Builder of every spec in the package already mapped null to empty, so no provider path reached it, but the constructor is protected on a public class and KdfUtil is documented for callers building their own KEM integration; the deprecated KEMParameterSpec passes a null itself and escaped only because it also pins the KDF to null. The constructor now stores empty for a null, so getOtherInfo() never returns null, and a null and an explicitly empty otherInfo derive the same key.\u003c/li\u003e\n\u003cli\u003eQR-UOV signature verification accepted a signature encoding that was not canonical, so the encoding of a signature was not unique even after the trailing-byte fix of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e. Each F_q element of the signature is stored in ceil(log2 q) bits, one more bit pattern than the field has elements: q itself is representable and is arithmetically congruent to zero, so an element written as q verified exactly as the same element written as zero would, and the bits padding the last element out to the byte boundary were never read at all. Every zero element of a signature therefore carried a second encoding, and for the q = 7 parameter sets roughly one element in seven is zero - a single qruov_5_q7_L10 signature measured 256 spare bits, so on the order of 2^256 distinct byte strings verified for the one message and key. Verification now rejects any element outside [0, q) and any set padding bit; a signature produced by this or by the reference implementation is unaffected, as the KAT vectors of every parameter set confirm. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSNOVA signature verification ignored four bits inside the signature for any parameter set whose solution is an odd number of GF(16) nibbles - the SNOVA_24_5_5, SNOVA_25_8_3, SNOVA_29_6_5 and SNOVA_66_15_3 families, sixteen of the forty-four parameter sets. The last byte of the encoded solution carries a single nibble and the signer leaves the top four bits zero, but the decoder did not read them, so sixteen distinct byte strings verified for one signature. This is the same non-unique encoding github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e closed for bytes following the signature, applied inside it; the verifier now requires those bits to be zero. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSnovaPrivateKeyParameters did not validate the length of the private key encoding handed to it - the only one of the five schemes of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e that did not - and SnovaParameters.getPrivateKeyLength() reported the expanded (\u0026quot;ESK\u0026quot;) length even for a parameter set whose private key is the seed pair. A private key encoding reaches this constructor straight from a PKCS#8 blob, so a wrong length went undetected: a seed-form key with extra bytes appended was accepted and signed under a different derived key, and a short expanded-form key sized the signer's decode buffer negatively, throwing NegativeArraySizeException out of generateSignature() rather than being reported at construction. Related, the signing retry loop could not terminate: the vinegar values are derived from a single-byte counter, so only 256 distinct linear systems can be tried, and an expanded-form private key that is not a real central map is singular for all of them - generateSignature() then span forever rather than failing. The length is now checked at construction, getPrivateKeyLength() reports the length that parameter set's private key actually has, and the retry loop gives up after its 256 attempts as MAYO's does.\u003c/li\u003e\n\u003cli\u003eMayoSigner and MayoKeyPairGenerator did not clear several buffers holding secret key material that the MAYO reference implementation explicitly clears. Signing left the secret oil space O, the expanded L = (P1 + P1^t) * O + P2, and the M / VPV / Ox intermediates of the central map in place, having gone to the trouble of clearing eleven other buffers; key generation left the expanded seed, whose tail is the encoded oil space, and the P1 * O + P2 half of P; and the row-echelon step left the packed echelon form of the secret linear system and its pivot rows. Separately, if all 256 attempts at solving for the signature had given a rank-deficient system, signing emitted a signature built from the failed attempt's state instead of reporting the failure the reference returns, and AIMerSigner.generateSignature returned an empty array on failure, which a caller would hand on as though it were a signature. Both now throw.\u003c/li\u003e\n\u003cli\u003eFive PQC signature schemes - MAYO, SNOVA, QR-UOV, SQIsign and AIMer - returned the NIST crypto_sign \u0026quot;sm\u0026quot; signed-message envelope from generateSignature() rather than the signature. That envelope is an artefact of the reference KAT harness, which records the message alongside the signature so a vector file can be self-contained; it is not part of any of the five specifications, and no other BC signer emits it (Falcon's KAT test rebuilds the equivalent envelope in the test, which is where it belongs). Two consequences followed, both reaching the JCA Signature services of every parameter set of the five schemes in BouncyCastlePQCProvider. First, since the message was appended to the signature, verification had to skip whatever followed the signature proper, and it did so by checking only that the buffer was long enough - so any number of trailing bytes could be added to a valid signature, or the appended message replaced with unrelated data, and it still verified. A signature encoding was therefore not unique: anyone holding one valid signature could produce unlimited distinct byte strings that all verified for the same message and key, which breaks any use that treats the signature bytes as an identifier, deduplicates on them, or records them as evidence. Second, the envelope propagated into everything built on the operator layer: because ContentSigner hands the signature straight into the structure being signed, every X.509 certificate, CRL, CMS SignedData and TLS CertificateVerify BC produced with one of these algorithms carried a verbatim copy of the signed data inside its own signature field - a self-signed MAYO-1 certificate came to 3567 bytes where the same certificate is now 2020 - which no other implementation can parse as a signature, and which in a detached CMS signature meant the \u0026quot;detached\u0026quot; signature carried the content. generateSignature() now returns the bare signature, and verifySignature() requires exactly the parameter set's signature length, so appended or truncated data is rejected rather than ignored. \u003cstrong\u003eThis is a behavioural change for signatures produced by an earlier release\u003c/strong\u003e - MAYO and SNOVA from 1.84, QR-UOV, SQIsign and AIMer from 1.85 - which are no longer accepted in the envelope form they were emitted in; the signature bytes themselves are unchanged, so a stored value can be recovered by taking the leading signature-length bytes, or for AIMer, whose envelope was message || signature rather than signature || message, the trailing ones. The KAT tests now rebuild the envelope before comparing against the vector files, which continue to record it. Note that AIMer's verification had already been made length-exact during this cycle (see the entry below relating to github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2401\"\u003e#2401\u003c/a\u003e), so of the five only its envelope remained (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe MLS implementation did not bind an X.509 credential to the LeafNode's signature_key. LeafNode.verify() checked a leaf's signature against the signature_key declared in the leaf itself, while the X.509 credential's certificate chain was stored but never parsed or checked, so the certificate's public key was never required to match signature_key (RFC 9420 sec. 5.3). A leaf could therefore carry one party's certificate while being signed by an unrelated key and still be accepted under that party's identity through KeyPackage.verify() and the Group leaf-validation path. LeafNode.verify() now requires the end-entity certificate's subject public key, in the cipher suite's signature encoding, to equal signature_key for an X.509 credential, and rejects the leaf otherwise - including an empty chain or a certificate whose key type does not match the cipher suite; certificate-chain and identity validation to a trust anchor remain the application's responsibility per RFC 9420 sec. 5.3.1. A public org.bouncycastle.mls.codec.Certificate(byte[]) constructor and a Credential.getCertificates() accessor are added so callers can build and inspect X.509 credentials. Basic credentials are unaffected (CVE-2026-71885).\u003c/li\u003e\n\u003cli\u003eThe SecureRandom supplied to org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder.setSecureRandom() did not drive the content IV / nonce for any algorithm other than RC2. EnvelopedDataHelper.generateParameters passed the caller's SecureRandom to the AlgorithmParameterGenerator only in the RC2_CBC branch; every other content-encryption algorithm - AES-CBC, AES-GCM, AES-CCM, Camellia, ARIA, SEED and the rest - reached pGen.generateParameters() on an uninitialised generator, so the IV / nonce was drawn from a default SecureRandom and setSecureRandom() was silently ignored (the builder's javadoc states that random is used for IV/nonce generation). The generator is now initialised with the supplied random on the general path as well, so a caller who provides a specific randomness source - for a controlled or FIPS-approved DRBG, say - has it honoured for the content IV / nonce. The session-key generation path was unaffected and already used the supplied random. Because the content IV / nonce now comes from the supplied SecureRandom, the org.bouncycastle.crypto.util JournalingSecureRandom / JournaledAlgorithm reproducible-encryption support records it in the transcript: a resumed session reproduces the IV / nonce by regenerating it from the replayed randomness - build the resuming encryptor from the content-algorithm OID - rather than by reusing the AlgorithmIdentifier captured from the first encryption, which no longer keeps the transcript aligned.\u003c/li\u003e\n\u003cli\u003eThe NTRU LPRime, NTRU+ and SMAUG-T KEM generators threw a NullPointerException when constructed with a null SecureRandom, where every other KEM generator - including NTRU LPRime's own SNTRU Prime counterpart in the same package - defaults one through CryptoServicesRegistrar.getSecureRandom(). This is reachable from the lightweight API directly, and from javax.crypto.KEM, whose newEncapsulator() documents a null random as a request for the provider's default.\u003c/li\u003e\n\u003cli\u003eFrodoKEMEngine kept a single SHAKE instance in a field, so an engine reached concurrently produced wrong results. It is reached that way through org.bouncycastle.crypto.kems.FrodoKEMExtractor, which holds one engine for its lifetime: two threads extracting through one extractor interleaved the digest's absorb and squeeze phases, yielding shared secrets that silently did not match the sender's, or an IllegalStateException of \u0026quot;attempt to absorb while squeezing\u0026quot; from inside extractSecret. The digest is now built per call, as CMCEEngine's already was, which makes an extractor safe to share. Encapsulation was unaffected, since FrodoKEMGenerator builds an engine per call. Results for any single-threaded use are unchanged - the reference KAT vectors are byte-identical.\u003c/li\u003e\n\u003cli\u003eThe BCJSSE provider carried the TLS 1.2 coupling between the supported_groups extension and ECDSA over into TLS 1.3: an ECDSA signature scheme was treated as usable - offered in the signature_algorithms and signature_algorithms_cert extensions, and eligible when selecting the local credentials - only while the corresponding curve was among the named groups enabled for key exchange, both per context (a group unavailable for key agreement disabled the scheme outright) and per connection (the curve had to be in the supported_groups list about to be sent). RFC 8446 sec. 4.2.7 scopes supported_groups to key exchange only, with signature algorithms negotiated independently (sec. 4.2.3), so this incorrect restriction in TLS 1.3 has been removed. Ed25519, Ed448 and the RSA schemes were unaffected (as well as typical deployments using a default configuration for named groups).\u003c/li\u003e\n\u003cli\u003eThe bcmail module descriptor did not declare its javax.mail/javax.activation dependences, so a modular (module-path) consumer of the jar hit IllegalAccessError/module-resolution failures when the S/MIME classes touched the mail API. The descriptor now requires them optionally (requires static) under all four module names those libraries are known by - the automatic names mail and activation carried by the javax.mail:mail / javax.activation:activation artifacts, and the explicit names java.mail and java.activation carried by the newer com.sun.mail / com.sun.activation ones - a hard requires on any one name would break users of the others (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2389\"\u003e#2389\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFour type-coercion helpers in the OER / IEEE 1609.2 (ITS) decoder tested the wrong type in the identity fast path that lets a getInstance() factory return an argument that is already of the target type. org.bouncycastle.oer.its.ieee1609dot2.basetypes.UINT32.getInstance and org.bouncycastle.oer.its.etsi102941.basetypes.Version.getInstance guarded on UINT8 - a sibling of UINT32 under UintBase, and unrelated to Version - so passing a UINT8 threw ClassCastException, while passing an actual UINT32 or Version missed the fast path and fell through to ASN1Integer.getInstance, which rejects them: neither factory accepted its own type. org.bouncycastle.oer.its.etsi103097.EtsiTs103097DataEncryptedUnicast.getInstance guarded on its sibling EtsiTs103097DataEncrypted and then cast to the unicast type, so an EtsiTs103097DataEncrypted threw ClassCastException. org.bouncycastle.oer.OEROptional.getObject(Class) called value.getClass().isInstance(type) with the arguments transposed, which is always false because the argument is a java.lang.Class, so the cast path was dead and every optional field was resolved reflectively, failing with IllegalStateException for a target type with no static getInstance. Each guard now names the type it returns, matching the sibling UINT8 / UINT16 / UINT64 and EtsiTs103097DataEncrypted factories (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2373\"\u003e#2373\u003c/a\u003e).\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003eSee full diff in \u003ca href=\"https://github.com/bcgit/bc-java/commits\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003ecommonmark-java 0.29.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e[0.29.0] - 2026-06-20\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/42b4fb7adfe288ef13e9e27ab20aff7e91b0ab9d\"\u003e\u003ccode\u003e42b4fb7\u003c/code\u003e\u003c/a\u003e Prepare CHANGELOG for version 0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/b76e09d7a8362abb5f04e1d6b91dbd6da279a6fc\"\u003e\u003ccode\u003eb76e09d\u003c/code\u003e\u003c/a\u003e Limit how deep inline nodes may nest by default (100)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/49f65cb5cbec93cff713179990307145198e7061\"\u003e\u003ccode\u003e49f65cb\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing deeply nested emphasis\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/610f84b83e68c381e8f784ae4d044c80e1948b67\"\u003e\u003ccode\u003e610f84b\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological autolink email addresses\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/9f1d73897a56cbd74c39347af351a473e70297e1\"\u003e\u003ccode\u003e9f1d738\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological HTML block attributes\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/e13297e849995fdd582a85841067bff1d9c35ee5\"\u003e\u003ccode\u003ee13297e\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing pathological backticks\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/89d1bd3fa1524e8217ed61db5e8116c82434470f\"\u003e\u003ccode\u003e89d1bd3\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing with lots of \u003ccode\u003e\u0026lt;\u003c/...\n\n_Description has been truncated_","html_url":"https://github.com/amstaff666/openclaw-30754/pull/33","url":"https://dependabot.ecosyste.ms/api/v1/hosts/GitHub/repositories/amstaff666%2Fopenclaw-30754/issues/33","packages_url":"https://dependabot.ecosyste.ms/api/v1/issues/33/packages"},{"uuid":"5415582546","node_id":"PR_kwDOTCTti88AAAABDCJjuQ","number":26,"state":"closed","title":"Bump the android-deps group across 1 directory with 16 updates","user":"dependabot[bot]","labels":["dependencies","java"],"assignees":[],"locked":false,"comments_count":1,"pull_request":true,"closed_at":"2026-09-11T17:45:27.000Z","author_association":null,"state_reason":null,"created_at":"2026-09-10T17:54:11.000Z","updated_at":"2026-09-11T17:45:29.000Z","time_to_close":85876,"merged_at":null,"merged_by":null,"closed_by":null,"dependency_metadata":{"prefix":"Bump","group_name":"android-deps","update_count":16,"packages":[{"name":"gradle-wrapper","old_version":"9.5.1","new_version":"9.7.1","repository_url":"https://github.com/gradle/gradle"},{"name":"org.bouncycastle:bcprov-jdk18on","old_version":"1.84","new_version":"1.85.2","repository_url":"https://github.com/bcgit/bc-java"},{"name":"org.commonmark:commonmark","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-autolink","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-strikethrough","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-tables","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-task-list-items","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.junit.vintage:junit-vintage-engine","old_version":"6.1.0","new_version":"6.1.3","repository_url":"https://github.com/junit-team/junit-framework"},{"name":"io.kotest:kotest-assertions-core-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"io.kotest:kotest-runner-junit5-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"com.squareup.okhttp3:mockwebserver","old_version":"5.3.2","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.squareup.okhttp3:okhttp","old_version":"5.3.2","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.android.application","old_version":"9.2.1","new_version":"9.4.0"},{"name":"com.android.test","old_version":"9.2.1","new_version":"9.4.0"},{"name":"org.jetbrains.kotlin.plugin.compose","old_version":"2.4.0","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"},{"name":"org.jetbrains.kotlin.plugin.serialization","old_version":"2.4.0","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"}],"path":null,"ecosystem":"maven"},"body":"Bumps the android-deps group with 16 updates in the /apps/android directory:\n\n| Package | From | To |\n| --- | --- | --- |\n| [gradle-wrapper](https://github.com/gradle/gradle) | `9.5.1` | `9.7.1` |\n| [org.bouncycastle:bcprov-jdk18on](https://github.com/bcgit/bc-java) | `1.84` | `1.85.2` |\n| [org.commonmark:commonmark](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-autolink](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-strikethrough](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-tables](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-task-list-items](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.junit.vintage:junit-vintage-engine](https://github.com/junit-team/junit-framework) | `6.1.0` | `6.1.3` |\n| [io.kotest:kotest-assertions-core-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [io.kotest:kotest-runner-junit5-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [com.squareup.okhttp3:mockwebserver](https://github.com/lysine-dev/okhttp) | `5.3.2` | `5.5.0` |\n| [com.squareup.okhttp3:okhttp](https://github.com/lysine-dev/okhttp) | `5.3.2` | `5.5.0` |\n| com.android.application | `9.2.1` | `9.4.0` |\n| com.android.test | `9.2.1` | `9.4.0` |\n| [org.jetbrains.kotlin.plugin.compose](https://github.com/JetBrains/kotlin) | `2.4.0` | `2.4.20` |\n| [org.jetbrains.kotlin.plugin.serialization](https://github.com/JetBrains/kotlin) | `2.4.0` | `2.4.20` |\n\n\nUpdates `gradle-wrapper` from 9.5.1 to 9.7.1\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/gradle/gradle/releases\"\u003egradle-wrapper's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e9.7.1\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.1.\u003c/p\u003e\n\u003cp\u003eThis is a patch release for 9.7.0. We recommend using 9.7.1 instead of 9.7.0.\u003c/p\u003e\n\u003cp\u003eHere are the highlights of 9.7.0 release:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIsolated Projects graduates to incubating\u003c/li\u003e\n\u003cli\u003eBroader Configuration Cache compatibility\u003c/li\u003e\n\u003cli\u003eResilient Sync helps you fix broken builds\u003c/li\u003e\n\u003cli\u003eMore source locations in problem reports\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003ca href=\"https://docs.gradle.org/9.7.1/release-notes.html\"\u003eRead the Release Notes\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eWe would like to thank the following community members for their contributions to this release of Gradle:\n\u003ca href=\"https://github.com/aSemy\"\u003eAdam\u003c/a\u003e,\n\u003ca href=\"https://github.com/Gautam-aman\"\u003eAman Gautam\u003c/a\u003e,\n\u003ca href=\"https://github.com/YukiCodepth\"\u003eAman Kumar\u003c/a\u003e,\n\u003ca href=\"https://github.com/adubrouski\"\u003eAnton Dubrouski\u003c/a\u003e,\n\u003ca href=\"https://github.com/liutikas\"\u003eAurimas\u003c/a\u003e,\n\u003ca href=\"https://github.com/gbhavya07\"\u003egbhavya07\u003c/a\u003e,\n\u003ca href=\"https://github.com/joshfriend\"\u003eJosh Friend\u003c/a\u003e,\n\u003ca href=\"https://github.com/nicklauslittle-gov\"\u003enicklauslittle-gov\u003c/a\u003e,\n\u003ca href=\"https://github.com/psoni674\"\u003ePragati\u003c/a\u003e,\n\u003ca href=\"https://github.com/Project516\"\u003eproject516\u003c/a\u003e,\n\u003ca href=\"https://github.com/Uomocapra\"\u003eQin Mi\u003c/a\u003e,\n\u003ca href=\"https://github.com/rkdfx\"\u003eRavi\u003c/a\u003e,\n\u003ca href=\"https://github.com/sk-reddy17\"\u003esk-reddy17\u003c/a\u003e,\n\u003ca href=\"https://github.com/Suvrat1629\"\u003eSuvrat Acharya\u003c/a\u003e,\n\u003ca href=\"https://github.com/ShreckYe\"\u003eYongshun Ye\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eUpgrade instructions\u003c/h2\u003e\n\u003cp\u003eSwitch your build to use Gradle 9.7.1 by updating your wrapper:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e./gradlew :wrapper --gradle-version=9.7.1 \u0026amp;\u0026amp; ./gradlew :wrapper\r\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eSee the Gradle \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/upgrading_version_9.html\"\u003e9.x upgrade guide\u003c/a\u003e to learn about deprecations, breaking changes and other considerations when upgrading.\u003c/p\u003e\n\u003cp\u003eFor Java, Groovy, Kotlin and Android compatibility, see the \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/compatibility.html\"\u003efull compatibility notes\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eReporting problems\u003c/h2\u003e\n\u003cp\u003eIf you find a problem with this release, please file a bug on \u003ca href=\"https://github.com/gradle/gradle/issues\"\u003eGitHub Issues\u003c/a\u003e adhering to our issue guidelines.\nIf you're not sure you're encountering a bug, please use the \u003ca href=\"https://discuss.gradle.org/c/help-discuss\"\u003eforum\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eWe hope you will build happiness with Gradle, and we look forward to your feedback via \u003ca href=\"https://twitter.com/gradle\"\u003eTwitter\u003c/a\u003e or on \u003ca href=\"https://github.com/gradle\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003e9.7.0\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.0.\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/92f0512e7f06d84621afba191f75e265363890cf\"\u003e\u003ccode\u003e92f0512\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38892\"\u003e#38892\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/820ee75a99a179bbffa41bcedc6477b685fabb9f\"\u003e\u003ccode\u003e820ee75\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/82c23f9bd2a89b4cc644e1f90a28a8668feb3dee\"\u003e\u003ccode\u003e82c23f9\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering problem in KTS (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38878\"\u003e#38878\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/ef11a7268fe8cc8d6ab849ec911aa11220180553\"\u003e\u003ccode\u003eef11a72\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering issue\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/bb0d8a974a71b1003efea41e4046e98855cd5ff8\"\u003e\u003ccode\u003ebb0d8a9\u003c/code\u003e\u003c/a\u003e Make relevant tests polyglot (run for multiple DSLs)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/336e129d7f95c03486acafc97abf59734acfed48\"\u003e\u003ccode\u003e336e129\u003c/code\u003e\u003c/a\u003e Update signing configuration (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38874\"\u003e#38874\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/4bdf0da2dad9884d089a6062a45ea7183e7d735d\"\u003e\u003ccode\u003e4bdf0da\u003c/code\u003e\u003c/a\u003e Update signing configuration\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/cd9b92c1b82856248cf1dc58b50378238bec7b52\"\u003e\u003ccode\u003ecd9b92c\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38839\"\u003e#38839\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/5f4e381964897ad8d6b99e5a7c77f26dba3259fb\"\u003e\u003ccode\u003e5f4e381\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/1e08ab551367aeb5fb48b26e72807e1d2b27c939\"\u003e\u003ccode\u003e1e08ab5\u003c/code\u003e\u003c/a\u003e Keep type-use annotations in extracted ABI classes (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38810\"\u003e#38810\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/gradle/gradle/compare/v9.5.1...v9.7.1\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.bouncycastle:bcprov-jdk18on` from 1.84 to 1.85.2\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.md\"\u003eorg.bouncycastle:bcprov-jdk18on's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch1\u003eBouncy Castle Crypto Package - Release Notes\u003c/h1\u003e\n\u003ch2\u003e1.0 Introduction\u003c/h2\u003e\n\u003cp\u003eThe Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. The package is organised so that it contains a light-weight API suitable for use in any environment (including the J2ME) with the additional infrastructure to conform the algorithms to the JCE framework.\u003c/p\u003e\n\u003ch2\u003e2.0 Release History\u003c/h2\u003e\n\u003cp\u003e\u003c!-- raw HTML omitted --\u003e\u003c!-- raw HTML omitted --\u003e\u003c/p\u003e\n\u003ch3\u003e2.1.1 Version\u003c/h3\u003e\n\u003cp\u003eRelease: 1.86\u003cbr /\u003e\nDate: 2026, TBD\u003c/p\u003e\n\u003ch3\u003e2.1.2 Defects Fixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) let a subkey inherit the primary key's Key Flags when its own Subkey Binding signature carried no Key Flags subpacket, which made the two capability decisions taken for one subkey disagree. OpenPGPCertificate.OpenPGPComponentKey.isSigningKey() reads the effective flags, which fell back to the primary key's direct-key or primary user ID self-signature, so a subkey bound with no flags of its own counted as signing-capable; verifyEmbeddedPrimaryKeyBinding reads the binding signature's own flags, found no signing capability there, and so skipped the embedded Primary Key Binding (cross-certification) signature that RFC 9580 sec. 5.2.1.8 and sec. 10.1.3 require of a subkey that can issue signatures. A data signature made by such a subkey was therefore attributed to the certificate and reported valid by OpenPGPSignature.OpenPGPDocumentSignature.isValid() with the cross-certification requirement never applied, where GnuPG refuses the same certificate and message as not cross-certified. An attacker holding a third party's public signing subkey - which is public material - could bind it to their own primary key with a Subkey Binding signature they are able to make, carrying no Key Flags and no embedded Primary Key Binding signature, which they cannot make without the subkey's private key, and have that party's genuine signatures verify as valid under the attacker's own identity: misattribution of a real signature rather than a forgery of a new one, since the signature still has to be one the subkey actually made. Key Flags are a statement about the key the carrying signature refers to (RFC 9580 sec. 5.2.3.29), so a subkey no longer inherits them from the certificate-wide signatures of the primary key: a Subkey Binding signature that omits the subpacket now leaves the subkey with no capabilities rather than the primary's, which makes the flags the cross-certification check consults the same flags every other decision consults. Preferences and the other subpackets a direct-key signature carries are inherited as before, and the primary key itself - whose flags legitimately come from its direct-key or user ID self-signature - is unaffected. The low-level PGPSignature / PGPPublicKeyRing API performs no binding checks by design and is unchanged.\u003c/li\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) used a version 6 key that carried no valid Direct Key signature, falling back to the primary user ID binding as it correctly does for a version 4 key. RFC 9580 sec. 5.2.3.10 requires the opposite: \u0026quot;An implementation MUST ensure that a valid Direct Key signature is present before using a version 6 key. This prevents certain attacks where an adversary strips a self-signature specifying a Key Expiration Time or certain preferences.\u0026quot; The certificate grammar says the same structurally, the Direct Key signature being mandatory in the version 6 structure of sec. 10.1.1 and optional in the version 4 one of sec. 10.1.3. Because a version 6 certificate carries its key expiration, features and algorithm preferences on the Direct Key signature - the convention the RFC recommends and the one OpenPGPKeyGenerator follows, its user ID certification carrying no expiration at all - removing that single signature packet from a published certificate silently dropped the expiration along with the preferences and features: OpenPGPCertificate.getSignatureChainFor fell back to the user ID binding, the primary key was still reported bound, and getEncryptionKeys() and getSigningKeys() went on returning the subkeys of a key whose owner had set it to expire. The primary key fingerprint is unchanged by the removal, so a relying party pinning the key by fingerprint still treats it as the same key, and no private key or hash collision is involved; the natural moment for the strip is the key refresh that RFC 9580 names as the reason to refetch a key at all - to learn about changes in expiration, features, preferences and revocation - which is exactly the update it defeats. This is a downgrade rather than a forgery, nothing being attributed to a key that did not authorise it, and the concerning direction is encryption, to a key meant to have been retired. OpenPGPCertificate.isBoundBy now requires a valid Direct Key self-signature on a version 6 primary key before any component of the certificate - the primary key, its subkeys or its identities - is treated as bound, so a version 6 certificate stripped of it offers no keys at all rather than an unexpiring set. Version 4 certificates are unaffected: there the key expiration legitimately lives on the user ID self-signature and the fallback is correct, so it stays. The revocation-only version 6 certificate of sec. 10.1.2, which legitimately carries no Direct Key signature, is unaffected as well - its key was already refused as revoked, and reading the revocation does not go through the binding check.\u003c/li\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) ignored the OpenPGPPolicy a caller had configured when it verified the signatures on an inline message. OpenPGPMessageInputStream took the policy it sanitizes each document signature against from the implementation's own default rather than from the processor the signature is being verified by, so a policy supplied through the documented OpenPGPApi(implementation, policy) / OpenPGPMessageProcessor(implementation, policy) constructor - which is how OpenPGPApi.decryptAndOrVerifyMessage() plumbs the configured policy through - had no bearing on whether a signature was accepted, although the same processor already applied it to the decompressed-size bound. A caller who hardened the policy beyond the default therefore had a signature that policy rejects handed back from getResult().getSignatures() with isTestedCorrect() true, while OpenPGPSignature.isValid(policy) on that same signature reported the rejection. Both verify paths, the one-pass and the prefixed-signature one, now read the configured policy; the detached-signature processor already did.\u003c/li\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) went on offering the subkeys of a certificate whose primary key had expired. OpenPGPCertificate's binding check evaluated only a subkey's own Subkey Binding signature, so a primary key whose Key Expiration Time (RFC 9580 sec. 5.2.3.13) had passed still handed out a longer-lived encryption or signing subkey from getEncryptionKeys() / getSigningKeys(), leaving the certificate contradicting itself - getExpirationTime() in the past and getPrimaryKey().isBoundAt() false, while isBoundAt() on the subkey answered true. An expired primary key can no longer certify, so the subkeys it bound are not usable with it either, which is how GnuPG and Sequoia both treat such a certificate; primary key revocation already propagated, since a revocation appears in the subkey's signature chain, but expiration is not carried there. Relatedly, a subkey no longer inherits the primary key's validity period at all - sec. 5.2.3.13 counts that period from the creation time of the key the carrying self-signature is made on, so re-basing the primary key's period on a subkey created later than it gave that subkey an expiration date later than the primary key's own.\u003c/li\u003e\n\u003cli\u003eOpenPGPSignature.OpenPGPDocumentSignature.isValidAt(Date) in the high-level OpenPGP API reported a data signature as valid at an evaluation time past the signature's own Signature Expiration Time (RFC 9580 sec. 5.2.3.18, hashed subpacket type 3). The method checked that the signature was correct and that the issuing key was bound and signing-capable at that date, but never consulted the signature's own expiration, so it disagreed with isEffectiveAt(Date) on the same object and with its own javadoc, which names being effective as one of the three criteria of a valid signature. Signature expiration is a separate axis from the issuing key's Key Expiration Time that the binding checks already cover, and GnuPG, GPGME, git and Sequoia all keep the two apart and treat a signature past its expiration as not good. isValid() and isValid(policy) evaluate at the signature's creation time, where a signature is always inside its own window, and are unchanged.\u003c/li\u003e\n\u003cli\u003eThe lightweight LMSSigner and HSSSigner refused a key wrapped in ParametersWithRandom, which is how BcContentSignerBuilder passes a key whenever setSecureRandom() has been called - so BcHssLmsContentSignerBuilder built a working signer until a random was set and then failed with \u0026quot;Incorrect Key Parameters\u0026quot;, and the two signers themselves raised ClassCastException on the same input. All three now unwrap it, as the promoted ML-DSA and SLH-DSA signers already did. The random is accepted and not used: LMS derives its message randomiser C from the key's seed and the one-time index, so it is deterministic and cannot repeat while q does not. Note SP 800-208 sec. 6.1 asks for C to come from an approved random bit generator, which this implementation does not do; that is unchanged here, and a supplied random is now ignored rather than refused.\u003c/li\u003e\n\u003cli\u003eLMS signature verification did not apply two of the checks RFC 8554 sec. 5.4.2 requires before a signature is processed. Step 2g refuses a signature whose LMS typecode is not the one from the public key, and without it the path computation took its height and tree digest from the parameter set the signature named rather than the key's, so a signature claiming a height-25 parameter set drove a 25-level computation against a height-5 key. Step 2i refuses a leaf number q outside the tree, and without it an out-of-range q flowed into the node arithmetic and was left for the candidate-root comparison to catch. Neither was a forgery - the domain separation between D_LEAF and D_INTR and the final comparison saw to that - but both are attacker-chosen work the specification says to refuse up front. Both are now checked, and a signature failing either is still reported as not verifying rather than thrown out of Signature.verify(). The catch around the signature decode in LMSSigner and HSSSigner has also been narrowed to the decode itself, as the corresponding SPI was corrected to do for github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2408\"\u003e#2408\u003c/a\u003e: past the parse the engine reports an inconsistent signature by returning false rather than by throwing, so the wider catch caught nothing while standing ready to turn a future internal error into a quiet false.\u003c/li\u003e\n\u003cli\u003eThe LMS and HSS key parameter classes now apply at construction the checks their decoders apply, so a key built directly cannot be one the decoder would refuse. LMSPrivateKeyParameters accepted an identifier of any length although the decoder reads exactly 16 bytes - such a key encoded but could not be read back - and left q, maxQ and the seed length unchecked; the seed is now required to be at least m bytes at decode as well, where a one-byte seed had been decoding silently and then deriving every one-time key from it. HSSPrivateKeyParameters checked neither its level count nor that it had been given a component key per level and a chaining signature per level below the root, and then indexed both lists, so a mismatch surfaced as IndexOutOfBoundsException - or, where a level happened to match, as a null chaining signature that only failed at signing time; the level is now checked after the reset that fills it in, since a null is legitimate on the way in. LMSPrivateKeyParameters.getInstance(byte[], byte[]) adopted the public key supplied beside the private one without comparing them, so a mismatched public key was simply reported by getPublicKey(); it now cross-checks the identifier, both parameter sets and, where the tree cache already holds it, the root, as the HSS entry point does. The decoders also now report a bad version or seed length as IOException rather than IllegalStateException, so a caller can catch one type for a malformed key, and the package-private LM-OTS public key decoder no longer declares throws Exception or dereferences an unrecognised typecode. The deprecated org.bouncycastle.pqc.crypto.lms copies carry the decoder corrections.\u003c/li\u003e\n\u003cli\u003eIn the LMS JCE layer, LMSKeyGenParameterSpec.fromNames knew all twenty LMS parameter-set names but only four of the sixteen LM-OTS ones, so none of the SP 800-208 n24 or SHAKE sets could be named; all sixteen are now present. KeyPairGenerator.initialize(int, SecureRandom) reports InvalidParameterException, which is what the JCA specifies and which extends the IllegalArgumentException it raised before, so existing catches still match. BCLMSPrivateKey.getIndex now takes the exhaustion check and the index read under the key's own monitor rather than as two separate calls, and two unused fields have gone from LMSSignatureSpi. Note that the LMS Signature claims its one-time key at the first update() rather than at sign(), so a Signature that is initialised and updated and then abandoned spends an index without producing a signature - the safe direction for a one-time scheme, and now documented on the SPI.\u003c/li\u003e\n\u003cli\u003eEvery other key pair generator that refuses a key size did the same thing the LMS one did above. KeyPairGenerator.initialize(int, SecureRandom) is documented to raise InvalidParameterException when the key size is not one the generator supports, and thirty of them raised a bare IllegalArgumentException instead, so a caller following the JCA and catching the documented type saw an exception escaping rather than a refusal. The ML-DSA, ML-KEM, SLH-DSA, Classic McEliece, FrodoKEM, NTRU and composite signature and KEM generators in the BC provider, and every generator in BCPQC, now raise InvalidParameterException - NewHope included, where the value is a key size it will not take rather than a mode of initialisation it does not offer. InvalidParameterException extends IllegalArgumentException, so callers written against the old behaviour go on catching it unchanged. The two RSA generators are corrected as well, and differently: theirs is a key size below a floor rather than a mode of initialisation they do not offer, and the refusal is raised by the lightweight RSAKeyGenerationParameters, which cannot name a java.security exception at all, so the RSA KeyPairGeneratorSpi now translates it - keeping the message verbatim and the original exception as the cause, through a new SecurityExceptions.invalidParameterException factory, since InvalidParameterException has no constructor that takes one. Of the 304 KeyPairGenerator services the two providers register, 299 now refuse a nonsense key size the way the JCA defines it and five accept it as a strength they can work with, with none left raising a bare IllegalArgumentException; that is asserted as a sweep over both providers rather than per algorithm, so a generator added later is covered without the test being touched. The jdk1.3 provider overlays of the four generators that have one carry the same change, and the jdk1.3 SecurityExceptions overlay gains the new factory along with the invalidAlgorithmParameterException one it had been missing.\u003c/li\u003e\n\u003cli\u003eKeyPairGenerator.initialize(AlgorithmParameterSpec, SecureRandom) had the same shape of problem as the int overload above, and only 44 of the 304 services the two providers register reported an unusable spec as the InvalidAlgorithmParameterException that method declares. The twenty-three PQC generators that resolve a parameter set by name - cmce, frodokem, mldsa, mlkem, slhdsa, aimer, bike, faest, falcon, haetae, hqc, mayo, mqom, ntru, ntruplus, both ntruprime variants, qruov, saber, sdith, smaugt, snova and sqisign, 230 services between them - case-folded the name they got back from the spec without checking it, so a spec with no getName() method, and a null spec, produced a NullPointerException from inside the fold; their own \u0026quot;is this name one I know\u0026quot; branch, which does report the declared exception, was unreachable. The two composite generators, whose parameter set is fixed by the algorithm name so that null is the only spec they accept, refused every other one with IllegalArgumentException. RSA answered correctly for a spec of the wrong type but not for one of the right type carrying values its lightweight parameters will not take - an even public exponent, or a key size below the floor - which is now translated the same way the int overload's is. All 304 services now report the declared exception, with the composites still taking the null spec that is right for them; note that InvalidAlgorithmParameterException is a checked exception and not an IllegalArgumentException, so a caller that was catching what these threw before has to catch the declared type instead.\u003c/li\u003e\n\u003cli\u003eAn HSS private key claimed the two records of its position under two different monitors. The top-level index and the bottom component key's one-time index q are independent records of the same position - the decoder requires them to agree, see the entry below - but generateLMSContext incremented the index under the HSS key's own monitor, released it, and only then claimed q under the component key's. A getEncoded() issued in between saw the index advanced and q not, and produced an encoding this implementation's own decoder rejects; and two threads meeting at a bottom-tree boundary could both pass the exhaustion test, take consecutive top-level indices and claim the same q, after which one of them was refused with \u0026quot;ots private key exhausted\u0026quot; by a key still reporting usages remaining, a top-level index had been spent with no signature made, and the two records stayed one apart for the rest of the key's life in that process - so it could no longer be encoded, cloned or sharded, and getIndex() and getUsagesRemaining() misreported by one. No one-time key was reused: the component key's claim is itself atomic, and the divergence runs index ahead of leaves, so the effect was on the key's usability rather than on the signatures it had made. Both records are now claimed under the one monitor, and the component key is claimed before the index is incremented so that an exhausted one leaves both untouched. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the same correction.\u003c/li\u003e\n\u003cli\u003eTimeStampToken parsed the attacker-controlled TSTInfo content of a time-stamp token (org.bouncycastle.tsp.TimeStampToken, reached from TimeStampResponse(byte[]) and (InputStream)) inside a try that caught only CMSException, so a well-formed RFC 3161 TimeStampResp whose embedded token carried a malformed TSTInfo - a SEQUENCE with fewer elements than the five mandatory fields, a non-SEQUENCE, truncated DER, or an unknown context tag - let an IllegalArgumentException or a NoSuchElementException escape the constructor's declared throws TSPException, IOException contract. A token signed by no signers or by more than one raised a bare IllegalArgumentException from the same constructor, before that try, for the same reason. Both are now reported as TSPException, matching the package-private TimeStampResponse(DLSequence) constructor and the existing getSignedAttributes guard in the same method; the signer-count refusal is a TSPValidationException, as the neighbouring check on the content type already was. Related, and the cause of the NoSuchElementException: asn1.tsp.TSTInfo read its five mandatory fields off the sequence with no bound on how many elements were actually there, so a short SEQUENCE left the enumeration to run out rather than being refused, and an oversize one was accepted with its extra elements absorbed into the optional slots. Decode now requires the five to ten elements RFC 3161 sec. 2.4.2 gives the type, which is what the sibling Accuracy and ArchiveTimeStamp decoders already did, so the failure is the IllegalArgumentException that getInstance is expected to raise (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2415\"\u003e#2415\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eNeither the HSS nor the XMSS^MT private key decoder checked its declared index against the traversal state stored beside it, although the two are independent records of the same position in the key and so can be compared. For HSS the records are the top-level index and the component keys' one-time indices q; for XMSS^MT they are the global index and the per-layer BDS states. A stored key whose index had been rolled back while its state stayed advanced - a partial write, a restore from backup, a buggy storage layer - was therefore accepted, and it then signed a second message under a one-time key the key had already used, producing a signature that verified, so nothing anywhere surfaced the reuse. RFC 8554 sec. 1 and RFC 8391 sec. 1.1 both require each one-time key to be used exactly once, and this is the failure those requirements exist to prevent; the single-tree XMSS decoder has tied its BDS state to its index since that state was first validated, and this brings the two multi-tree schemes into line. HSS decode now requires the declared index to equal the position the component q values imply - a level above the last contributes (q - 1) leaves of the levels beneath it, since its q has already advanced past the subtree it signed - and XMSS^MT decode now requires each present layer's BDS index to equal the leaf index that layer derives from the global index, allowing the one position where a layer has moved into a new subtree and its state legitimately still carries the previous subtree's final index. A layer with no state yet is unaffected, since those are built lazily at signing time. Related, and the same shape of omission: an XMSS or XMSS^MT private key encoding carries the tree root twice - the key's own root field and the root node of the BDS state stored beside it, which for XMSS^MT is the top layer's - and the two were never compared either. A corrupted root was accepted and then poisoned every signature the key made, because the root is hashed into the message digest: the signature did not verify and nothing indicated why. Decode now requires the two copies to agree. The BDS node values themselves are not checkable the way the LMS tree cache above is - a BDS authentication path, stack, retain or keep node does not have its children stored alongside it, so recomputing one means building a subtree, which is the work the state exists to avoid. Both checks are integer comparisons over the levels of the key, too small to measure against the surrounding decode, and both were verified not to reject any legitimate key by walking every index a key can reach: the full key space of the two-level HSS and the h=4/d=2, h=6/d=2, h=6/d=3, h=9/d=3 and h=8/d=4 XMSS^MT parameter sets, plus a three-level HSS key across a subtree boundary and an HSS shard. Since those node values cannot be recomputed, the encoded state now carries a checksum over itself instead, with the owning key's public seed hashed in front of it. Any corruption of the stored state is refused at decode rather than being loaded and then producing signatures that silently do not verify, and because the public seed is bound in, a state transplanted between two keys of the same parameter set is refused too, even though it is internally consistent and arrives with its own matching root. The public seed is bound rather than the secret seed or the PRF key deliberately: the state's own root and index are inside the encoding and so are already covered, hashing secret material would make the stored checksum a commitment to it for no gain in detection, and the PRF key does not influence the state at all. \u003cstrong\u003eThis is an error-detecting code and not integrity protection\u003c/strong\u003e - anyone able to rewrite the stored key recomputes it, so it establishes that the state is unchanged since it was written, never that it was correct when written, and the allocation bounds on the encoding remain the guard against a crafted one. It costs one SHA-256 over the state, measured at 5 to 8 microseconds each way for the h=10 and h=16 parameter sets, and 32 bytes of encoding. The state encoding was added earlier in this same cycle and has not been released, so the checksum is simply part of it rather than a new version: a state written by a 1.86 beta is rejected, which is recovered from by re-exporting the key. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the HSS check as well (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2414\"\u003e#2414\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eIn the XMSS and XMSS^MT JCE layer, KeyPairGenerator.initialize(int, SecureRandom) reports InvalidParameterException, which is what the JCA specifies and which extends the IllegalArgumentException it raised before, so existing catches still match. This is the XMSS counterpart of the same correction made to LMSKeyPairGeneratorSpi.\u003c/li\u003e\n\u003cli\u003eBCXMSSPrivateKey.getIndex and BCXMSSMTPrivateKey.getIndex took the exhaustion check and the index read as two separate calls on the key parameters. Each is atomic on its own, but the pair is not: a signature taken by another thread between them spends the last usage, so the check passes and the read that follows returns maxIndex + 1 - the one index past the end of the key, which is what the check exists to refuse, handed back as though it were the next one-time key to be used. Both reads are now taken under the key parameters' own monitor, the monitor their mutators hold, as BCLMSPrivateKey.getIndex was corrected to do. No one-time key is reused by this: the effect is on what the key reports about itself, not on the signatures it makes.\u003c/li\u003e\n\u003cli\u003eThe S/MIME example smoke test in the misc module (org.bouncycastle.mail.smime.examples.test.AllTests) drove SendSignedAndEncryptedMail against smtp.gmail.com, and that example finishes with Transport.send() under JavaMail's default settings, which have no connect timeout. Where outbound port 25 is refused the failure was swallowed and the test passed; where it is silently dropped, as on many home networks, the connect blocked and ./gradlew build hung in :misc:test indefinitely with \u0026quot;0 tests completed\u0026quot;. The test now delivers to an SMTP stub on a loopback port, with connect / read / write timeouts as a backstop, and asserts the message arrived (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2407\"\u003e#2407\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation took the traditional component public key bytes it feeds the KEM combiner from the recipient key's own encoding, while decapsulation recomputes the point from the private key and so always produced an uncompressed one. Section 4 of draft-ietf-lamps-pq-composite-kem requires an EC component to be carried as an uncompressed point, but a component key that encodes itself compressed - a BC EC key whose point format has been set through org.bouncycastle.jce.interfaces.ECPointEncoder, or a key from a provider that preserves a compressed encoding - was passed through as it came. Both sides then combined a different tradPK and derived different shared secrets, with no error reported on either: encapsulation and decapsulation both succeeded and the recipient simply could not decrypt. The EC component is now normalised to an uncompressed point wherever the engine serialises one, which covers the ephemeral key that forms the ciphertext as well. X25519 and X448 components have a single encoding and were unaffected, as were EC keys left in their default (uncompressed) format, whose shared secrets are unchanged. CompositePublicKey.getEncoded() took its component bytes the same way, so such a key also encoded to a composite key other implementations reject and whose bytes changed across an encode / decode / encode round trip - 1238 bytes rather than 1270 for MLKEM768-ECDH-P256, and for the composite ML-DSA keys sharing that method, 2006 rather than 2038 for MLDSA65-ECDSA-P256. It now normalises the component the same way. This is a write-side change only: a composite key carrying a compressed EC component is still decoded, since the component key factories accept either form, and continues to verify signatures as before - it simply re-encodes in the normalised form. The shared normalisation is org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil.getUncompressedSubjectPublicKeyBytes.\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation threw a NullPointerException, wrapped in an IllegalStateException out of KeyGenerator.generateKey(), when the SecureRandom it was given was null - which javax.crypto.KEM.newEncapsulator() documents as a request for the provider's default, and which KeyGenerator.init(spec, null) passes straight through. The three RSA-OAEP composites draw the traditional shared secret from that random directly, so they were the ones affected; the ECDH and X25519 / X448 composites escaped only because their component KeyPairGenerators default a random of their own. CompositeMLKEMEngine now defaults one through CryptoServicesRegistrar.getSecureRandom() on first use, as the composite KEM Cipher's wrap path already did, and as the KEM generators corrected earlier in this cycle now do. Related, the engine now also clears the ML-KEM component's shared secret alongside the traditional one on both the encapsulate and decapsulate paths - the copy handed back by getEncoded() was left in the heap - as section 3.5 of draft-ietf-lamps-pq-composite-kem requires.\u003c/li\u003e\n\u003cli\u003eCompositePublicKey.getAlgorithm() and CompositePrivateKey.getAlgorithm() returned null for all twelve Composite ML-KEM (draft-ietf-lamps-pq-composite-kem) parameter sets. Both classes resolved the name through the composite signature index only, which holds the composite ML-DSA OIDs, so a composite KEM key pair - generated, parsed from a certificate, or read from PKCS#8 - reported no algorithm at all, and the standard JCA idiom of reconstructing a key with KeyFactory.getInstance(key.getAlgorithm()) raised a NullPointerException. The lookup now falls back to the composite KEM index, so the name returned is the one the provider registers the algorithm under (e.g. MLKEM768-X25519-SHA3-256), matching the composite ML-DSA behaviour. The same single-index assumption made the CompositePublicKey(SubjectPublicKeyInfo) and CompositePrivateKey(PrivateKeyInfo) constructors reject a composite KEM key with \u0026quot;unable to create CompositePublicKey from SubjectPublicKeyInfo\u0026quot;; they now dispatch to the composite KEM key factory for those OIDs. Keys obtained through KeyFactory or through BouncyCastleProvider.getPublicKey / getPrivateKey were unaffected and are unchanged (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2404\"\u003e#2404\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe org.bouncycastle.jcajce.spec.KEMKDFSpec constructor stored a null otherInfo as given, so getOtherInfo() returned null, and three of the KDF branches KdfUtil.makeKeyBytes dispatches to - KMAC-128, KMAC-256 and SHAKE-256 - read the otherInfo length without a guard and threw NullPointerException out of the KEM operation, where the KDF2, KDF3 and HKDF branches tolerate a null through KDFParameters / HKDFParameters. The Builder of every spec in the package already mapped null to empty, so no provider path reached it, but the constructor is protected on a public class and KdfUtil is documented for callers building their own KEM integration; the deprecated KEMParameterSpec passes a null itself and escaped only because it also pins the KDF to null. The constructor now stores empty for a null, so getOtherInfo() never returns null, and a null and an explicitly empty otherInfo derive the same key.\u003c/li\u003e\n\u003cli\u003eQR-UOV signature verification accepted a signature encoding that was not canonical, so the encoding of a signature was not unique even after the trailing-byte fix of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e. Each F_q element of the signature is stored in ceil(log2 q) bits, one more bit pattern than the field has elements: q itself is representable and is arithmetically congruent to zero, so an element written as q verified exactly as the same element written as zero would, and the bits padding the last element out to the byte boundary were never read at all. Every zero element of a signature therefore carried a second encoding, and for the q = 7 parameter sets roughly one element in seven is zero - a single qruov_5_q7_L10 signature measured 256 spare bits, so on the order of 2^256 distinct byte strings verified for the one message and key. Verification now rejects any element outside [0, q) and any set padding bit; a signature produced by this or by the reference implementation is unaffected, as the KAT vectors of every parameter set confirm. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSNOVA signature verification ignored four bits inside the signature for any parameter set whose solution is an odd number of GF(16) nibbles - the SNOVA_24_5_5, SNOVA_25_8_3, SNOVA_29_6_5 and SNOVA_66_15_3 families, sixteen of the forty-four parameter sets. The last byte of the encoded solution carries a single nibble and the signer leaves the top four bits zero, but the decoder did not read them, so sixteen distinct byte strings verified for one signature. This is the same non-unique encoding github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e closed for bytes following the signature, applied inside it; the verifier now requires those bits to be zero. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSnovaPrivateKeyParameters did not validate the length of the private key encoding handed to it - the only one of the five schemes of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e that did not - and SnovaParameters.getPrivateKeyLength() reported the expanded (\u0026quot;ESK\u0026quot;) length even for a parameter set whose private key is the seed pair. A private key encoding reaches this constructor straight from a PKCS#8 blob, so a wrong length went undetected: a seed-form key with extra bytes appended was accepted and signed under a different derived key, and a short expanded-form key sized the signer's decode buffer negatively, throwing NegativeArraySizeException out of generateSignature() rather than being reported at construction. Related, the signing retry loop could not terminate: the vinegar values are derived from a single-byte counter, so only 256 distinct linear systems can be tried, and an expanded-form private key that is not a real central map is singular for all of them - generateSignature() then span forever rather than failing. The length is now checked at construction, getPrivateKeyLength() reports the length that parameter set's private key actually has, and the retry loop gives up after its 256 attempts as MAYO's does.\u003c/li\u003e\n\u003cli\u003eMayoSigner and MayoKeyPairGenerator did not clear several buffers holding secret key material that the MAYO reference implementation explicitly clears. Signing left the secret oil space O, the expanded L = (P1 + P1^t) * O + P2, and the M / VPV / Ox intermediates of the central map in place, having gone to the trouble of clearing eleven other buffers; key generation left the expanded seed, whose tail is the encoded oil space, and the P1 * O + P2 half of P; and the row-echelon step left the packed echelon form of the secret linear system and its pivot rows. Separately, if all 256 attempts at solving for the signature had given a rank-deficient system, signing emitted a signature built from the failed attempt's state instead of reporting the failure the reference returns, and AIMerSigner.generateSignature returned an empty array on failure, which a caller would hand on as though it were a signature. Both now throw.\u003c/li\u003e\n\u003cli\u003eFive PQC signature schemes - MAYO, SNOVA, QR-UOV, SQIsign and AIMer - returned the NIST crypto_sign \u0026quot;sm\u0026quot; signed-message envelope from generateSignature() rather than the signature. That envelope is an artefact of the reference KAT harness, which records the message alongside the signature so a vector file can be self-contained; it is not part of any of the five specifications, and no other BC signer emits it (Falcon's KAT test rebuilds the equivalent envelope in the test, which is where it belongs). Two consequences followed, both reaching the JCA Signature services of every parameter set of the five schemes in BouncyCastlePQCProvider. First, since the message was appended to the signature, verification had to skip whatever followed the signature proper, and it did so by checking only that the buffer was long enough - so any number of trailing bytes could be added to a valid signature, or the appended message replaced with unrelated data, and it still verified. A signature encoding was therefore not unique: anyone holding one valid signature could produce unlimited distinct byte strings that all verified for the same message and key, which breaks any use that treats the signature bytes as an identifier, deduplicates on them, or records them as evidence. Second, the envelope propagated into everything built on the operator layer: because ContentSigner hands the signature straight into the structure being signed, every X.509 certificate, CRL, CMS SignedData and TLS CertificateVerify BC produced with one of these algorithms carried a verbatim copy of the signed data inside its own signature field - a self-signed MAYO-1 certificate came to 3567 bytes where the same certificate is now 2020 - which no other implementation can parse as a signature, and which in a detached CMS signature meant the \u0026quot;detached\u0026quot; signature carried the content. generateSignature() now returns the bare signature, and verifySignature() requires exactly the parameter set's signature length, so appended or truncated data is rejected rather than ignored. \u003cstrong\u003eThis is a behavioural change for signatures produced by an earlier release\u003c/strong\u003e - MAYO and SNOVA from 1.84, QR-UOV, SQIsign and AIMer from 1.85 - which are no longer accepted in the envelope form they were emitted in; the signature bytes themselves are unchanged, so a stored value can be recovered by taking the leading signature-length bytes, or for AIMer, whose envelope was message || signature rather than signature || message, the trailing ones. The KAT tests now rebuild the envelope before comparing against the vector files, which continue to record it. Note that AIMer's verification had already been made length-exact during this cycle (see the entry below relating to github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2401\"\u003e#2401\u003c/a\u003e), so of the five only its envelope remained (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe MLS implementation did not bind an X.509 credential to the LeafNode's signature_key. LeafNode.verify() checked a leaf's signature against the signature_key declared in the leaf itself, while the X.509 credential's certificate chain was stored but never parsed or checked, so the certificate's public key was never required to match signature_key (RFC 9420 sec. 5.3). A leaf could therefore carry one party's certificate while being signed by an unrelated key and still be accepted under that party's identity through KeyPackage.verify() and the Group leaf-validation path. LeafNode.verify() now requires the end-entity certificate's subject public key, in the cipher suite's signature encoding, to equal signature_key for an X.509 credential, and rejects the leaf otherwise - including an empty chain or a certificate whose key type does not match the cipher suite; certificate-chain and identity validation to a trust anchor remain the application's responsibility per RFC 9420 sec. 5.3.1. A public org.bouncycastle.mls.codec.Certificate(byte[]) constructor and a Credential.getCertificates() accessor are added so callers can build and inspect X.509 credentials. Basic credentials are unaffected.\u003c/li\u003e\n\u003cli\u003eThe SecureRandom supplied to org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder.setSecureRandom() did not drive the content IV / nonce for any algorithm other than RC2. EnvelopedDataHelper.generateParameters passed the caller's SecureRandom to the AlgorithmParameterGenerator only in the RC2_CBC branch; every other content-encryption algorithm - AES-CBC, AES-GCM, AES-CCM, Camellia, ARIA, SEED and the rest - reached pGen.generateParameters() on an uninitialised generator, so the IV / nonce was drawn from a default SecureRandom and setSecureRandom() was silently ignored (the builder's javadoc states that random is used for IV/nonce generation). The generator is now initialised with the supplied random on the general path as well, so a caller who provides a specific randomness source - for a controlled or FIPS-approved DRBG, say - has it honoured for the content IV / nonce. The session-key generation path was unaffected and already used the supplied random. Because the content IV / nonce now comes from the supplied SecureRandom, the org.bouncycastle.crypto.util JournalingSecureRandom / JournaledAlgorithm reproducible-encryption support records it in the transcript: a resumed session reproduces the IV / nonce by regenerating it from the replayed randomness - build the resuming encryptor from the content-algorithm OID - rather than by reusing the AlgorithmIdentifier captured from the first encryption, which no longer keeps the transcript aligned.\u003c/li\u003e\n\u003cli\u003eThe NTRU LPRime, NTRU+ and SMAUG-T KEM generators threw a NullPointerException when constructed with a null SecureRandom, where every other KEM generator - including NTRU LPRime's own SNTRU Prime counterpart in the same package - defaults one through CryptoServicesRegistrar.getSecureRandom(). This is reachable from the lightweight API directly, and from javax.crypto.KEM, whose newEncapsulator() documents a null random as a request for the provider's default.\u003c/li\u003e\n\u003cli\u003eFrodoKEMEngine kept a single SHAKE instance in a field, so an engine reached concurrently produced wrong results. It is reached that way through org.bouncycastle.crypto.kems.FrodoKEMExtractor, which holds one engine for its lifetime: two threads extracting through one extractor interleaved the digest's absorb and squeeze phases, yielding shared secrets that silently did not match the sender's, or an IllegalStateException of \u0026quot;attempt to absorb while squeezing\u0026quot; from inside extractSecret. The digest is now built per call, as CMCEEngine's already was, which makes an extractor safe to share. Encapsulation was unaffected, since FrodoKEMGenerator builds an engine per call. Results for any single-threaded use are unchanged - the reference KAT vectors are byte-identical.\u003c/li\u003e\n\u003cli\u003eThe BCJSSE provider carried the TLS 1.2 coupling between the supported_groups extension and ECDSA over into TLS 1.3: an ECDSA signature scheme was treated as usable - offered in the signature_algorithms and signature_algorithms_cert extensions, and eligible when selecting the local credentials - only while the corresponding curve was among the named groups enabled for key exchange, both per context (a group unavailable for key agreement disabled the scheme outright) and per connection (the curve had to be in the supported_groups list about to be sent). RFC 8446 sec. 4.2.7 scopes supported_groups to key exchange only, with signature algorithms negotiated independently (sec. 4.2.3), so this incorrect restriction in TLS 1.3 has been removed. Ed25519, Ed448 and the RSA schemes were unaffected (as well as typical deployments using a default configuration for named groups).\u003c/li\u003e\n\u003cli\u003eThe bcmail module descriptor did not declare its javax.mail/javax.activation dependences, so a modular (module-path) consumer of the jar hit IllegalAccessError/module-resolution failures when the S/MIME classes touched the mail API. The descriptor now requires them optionally (requires static) under all four module names those libraries are known by - the automatic names mail and activation carried by the javax.mail:mail / javax.activation:activation artifacts, and the explicit names java.mail and java.activation carried by the newer com.sun.mail / com.sun.activation ones - a hard requires on any one name would break users of the others (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2389\"\u003e#2389\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFour type-coercion helpers in the OER / IEEE 1609.2 (ITS) decoder tested the wrong type in the identity fast path that lets a getInstance() factory return an argument that is already of the target type. org.bouncycastle.oer.its.ieee1609dot2.basetypes.UINT32.getInstance and org.bouncycastle.oer.its.etsi102941.basetypes.Version.getInstance guarded on UINT8 - a sibling of UINT32 under UintBase, and unrelated to Version - so passing a UINT8 threw ClassCastException, while passing an actual UINT32 or Version missed the fast path and fell through to ASN1Integer.getInstance, which rejects them: neither factory accepted its own type. org.bouncycastle.oer.its.etsi103097.EtsiTs103097DataEncryptedUnicast.getInstance guarded on its sibling EtsiTs103097DataEncrypted and then cast to the unicast type, so an EtsiTs103097DataEncrypted threw ClassCastException. org.bouncycastle.oer.OEROptional.getObject(Class) called value.getClass().isInstance(type) with the arguments transposed, which is always false because the argument is a java.lang.Class, so the cast path was dead and every optional field was resolved reflectively, failing with IllegalStateException for a target type with no static getInstance. Each guard now names the type it returns, matching the sibling UINT8 / UINT16 / UINT64 and EtsiTs103097DataEncrypted factories (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2373\"\u003e#2373\u003c/a\u003e).\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003eSee full diff in \u003ca href=\"https://github.com/bcgit/bc-java/commits\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003ecommonmark-java 0.29.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e[0.29.0] - 2026-06-20\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/42b4fb7adfe288ef13e9e27ab20aff7e91b0ab9d\"\u003e\u003ccode\u003e42b4fb7\u003c/code\u003e\u003c/a\u003e Prepare CHANGELOG for version 0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/b76e09d7a8362abb5f04e1d6b91dbd6da279a6fc\"\u003e\u003ccode\u003eb76e09d\u003c/code\u003e\u003c/a\u003e Limit how deep inline nodes may nest by default (100)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/49f65cb5cbec93cff713179990307145198e7061\"\u003e\u003ccode\u003e49f65cb\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing deeply nested emphasis\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/610f84b83e68c381e8f784ae4d044c80e1948b67\"\u003e\u003ccode\u003e610f84b\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological autolink email addresses\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/9f1d73897a56cbd74c39347af351a473e70297e1\"\u003e\u003ccode\u003e9f1d738\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological HTML block attributes\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/e13297e849995fdd582a85841067bff1d9c35ee5\"\u003e\u003ccode\u003ee13297e\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing pathological backticks\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/89d1bd3fa1524e8217ed61db5e8116c82434470f\"\u003e\u003ccode\u003e89d1bd3\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing with lots of \u003ccode\u003e\u0026lt;\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/commonmark/commonmark-java/compare/commonmark-parent-0.28.0...commonmark-parent-0.30.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark-ext-autolink` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:...\n\n_Description has been truncated_","html_url":"https://github.com/brahminib/support-claw/pull/26","url":"https://dependabot.ecosyste.ms/api/v1/hosts/GitHub/repositories/brahminib%2Fsupport-claw/issues/26","packages_url":"https://dependabot.ecosyste.ms/api/v1/issues/26/packages"},{"uuid":"5411138290","node_id":"PR_kwDOTMZbOc8AAAABC-kAMA","number":16,"state":"open","title":"Bump the android-deps group across 1 directory with 21 updates","user":"dependabot[bot]","labels":["dependencies","java"],"assignees":[],"locked":false,"comments_count":1,"pull_request":true,"closed_at":null,"author_association":null,"state_reason":null,"created_at":"2026-09-10T10:41:20.000Z","updated_at":"2026-09-10T10:42:28.000Z","time_to_close":null,"merged_at":null,"merged_by":null,"closed_by":null,"dependency_metadata":{"prefix":"Bump","group_name":"android-deps","update_count":21,"packages":[{"name":"gradle-wrapper","old_version":"9.4.1","new_version":"9.7.1","repository_url":"https://github.com/gradle/gradle"},{"name":"androidx.core:core-ktx","old_version":"1.18.0","new_version":"1.19.0"},{"name":"org.bouncycastle:bcprov-jdk18on","old_version":"1.84","new_version":"1.85.2","repository_url":"https://github.com/bcgit/bc-java"},{"name":"org.commonmark:commonmark","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-autolink","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-strikethrough","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-tables","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-task-list-items","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"dnsjava:dnsjava","old_version":"3.6.4","new_version":"3.6.5","repository_url":"https://github.com/dnsjava/dnsjava"},{"name":"org.junit.vintage:junit-vintage-engine","old_version":"6.0.3","new_version":"6.1.3","repository_url":"https://github.com/junit-team/junit-framework"},{"name":"io.kotest:kotest-assertions-core-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"io.kotest:kotest-runner-junit5-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"org.jetbrains.kotlinx:kotlinx-coroutines-android","old_version":"1.10.2","new_version":"1.11.0","repository_url":"https://github.com/Kotlin/kotlinx.coroutines"},{"name":"org.jetbrains.kotlinx:kotlinx-coroutines-test","old_version":"1.10.2","new_version":"1.11.0","repository_url":"https://github.com/Kotlin/kotlinx.coroutines"},{"name":"com.google.android.material:material","old_version":"1.13.0","new_version":"1.14.0","repository_url":"https://github.com/material-components/material-components-android"},{"name":"com.squareup.okhttp3:mockwebserver","old_version":"5.3.2","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.squareup.okhttp3:okhttp","old_version":"5.3.2","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.android.application","old_version":"9.2.0","new_version":"9.4.0"},{"name":"com.android.test","old_version":"9.2.0","new_version":"9.4.0"},{"name":"org.jetbrains.kotlin.plugin.compose","old_version":"2.3.21","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"},{"name":"org.jetbrains.kotlin.plugin.serialization","old_version":"2.3.21","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"}],"path":null,"ecosystem":"maven"},"body":"Bumps the android-deps group with 21 updates in the /apps/android directory:\n\n| Package | From | To |\n| --- | --- | --- |\n| [gradle-wrapper](https://github.com/gradle/gradle) | `9.4.1` | `9.7.1` |\n| androidx.core:core-ktx | `1.18.0` | `1.19.0` |\n| [org.bouncycastle:bcprov-jdk18on](https://github.com/bcgit/bc-java) | `1.84` | `1.85.2` |\n| [org.commonmark:commonmark](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-autolink](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-strikethrough](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-tables](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-task-list-items](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [dnsjava:dnsjava](https://github.com/dnsjava/dnsjava) | `3.6.4` | `3.6.5` |\n| [org.junit.vintage:junit-vintage-engine](https://github.com/junit-team/junit-framework) | `6.0.3` | `6.1.3` |\n| [io.kotest:kotest-assertions-core-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [io.kotest:kotest-runner-junit5-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [org.jetbrains.kotlinx:kotlinx-coroutines-android](https://github.com/Kotlin/kotlinx.coroutines) | `1.10.2` | `1.11.0` |\n| [org.jetbrains.kotlinx:kotlinx-coroutines-test](https://github.com/Kotlin/kotlinx.coroutines) | `1.10.2` | `1.11.0` |\n| [com.google.android.material:material](https://github.com/material-components/material-components-android) | `1.13.0` | `1.14.0` |\n| [com.squareup.okhttp3:mockwebserver](https://github.com/lysine-dev/okhttp) | `5.3.2` | `5.5.0` |\n| [com.squareup.okhttp3:okhttp](https://github.com/lysine-dev/okhttp) | `5.3.2` | `5.5.0` |\n| com.android.application | `9.2.0` | `9.4.0` |\n| com.android.test | `9.2.0` | `9.4.0` |\n| [org.jetbrains.kotlin.plugin.compose](https://github.com/JetBrains/kotlin) | `2.3.21` | `2.4.20` |\n| [org.jetbrains.kotlin.plugin.serialization](https://github.com/JetBrains/kotlin) | `2.3.21` | `2.4.20` |\n\n\nUpdates `gradle-wrapper` from 9.4.1 to 9.7.1\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/gradle/gradle/releases\"\u003egradle-wrapper's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e9.7.1\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.1.\u003c/p\u003e\n\u003cp\u003eThis is a patch release for 9.7.0. We recommend using 9.7.1 instead of 9.7.0.\u003c/p\u003e\n\u003cp\u003eHere are the highlights of 9.7.0 release:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIsolated Projects graduates to incubating\u003c/li\u003e\n\u003cli\u003eBroader Configuration Cache compatibility\u003c/li\u003e\n\u003cli\u003eResilient Sync helps you fix broken builds\u003c/li\u003e\n\u003cli\u003eMore source locations in problem reports\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003ca href=\"https://docs.gradle.org/9.7.1/release-notes.html\"\u003eRead the Release Notes\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eWe would like to thank the following community members for their contributions to this release of Gradle:\n\u003ca href=\"https://github.com/aSemy\"\u003eAdam\u003c/a\u003e,\n\u003ca href=\"https://github.com/Gautam-aman\"\u003eAman Gautam\u003c/a\u003e,\n\u003ca href=\"https://github.com/YukiCodepth\"\u003eAman Kumar\u003c/a\u003e,\n\u003ca href=\"https://github.com/adubrouski\"\u003eAnton Dubrouski\u003c/a\u003e,\n\u003ca href=\"https://github.com/liutikas\"\u003eAurimas\u003c/a\u003e,\n\u003ca href=\"https://github.com/gbhavya07\"\u003egbhavya07\u003c/a\u003e,\n\u003ca href=\"https://github.com/joshfriend\"\u003eJosh Friend\u003c/a\u003e,\n\u003ca href=\"https://github.com/nicklauslittle-gov\"\u003enicklauslittle-gov\u003c/a\u003e,\n\u003ca href=\"https://github.com/psoni674\"\u003ePragati\u003c/a\u003e,\n\u003ca href=\"https://github.com/Project516\"\u003eproject516\u003c/a\u003e,\n\u003ca href=\"https://github.com/Uomocapra\"\u003eQin Mi\u003c/a\u003e,\n\u003ca href=\"https://github.com/rkdfx\"\u003eRavi\u003c/a\u003e,\n\u003ca href=\"https://github.com/sk-reddy17\"\u003esk-reddy17\u003c/a\u003e,\n\u003ca href=\"https://github.com/Suvrat1629\"\u003eSuvrat Acharya\u003c/a\u003e,\n\u003ca href=\"https://github.com/ShreckYe\"\u003eYongshun Ye\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eUpgrade instructions\u003c/h2\u003e\n\u003cp\u003eSwitch your build to use Gradle 9.7.1 by updating your wrapper:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e./gradlew :wrapper --gradle-version=9.7.1 \u0026amp;\u0026amp; ./gradlew :wrapper\r\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eSee the Gradle \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/upgrading_version_9.html\"\u003e9.x upgrade guide\u003c/a\u003e to learn about deprecations, breaking changes and other considerations when upgrading.\u003c/p\u003e\n\u003cp\u003eFor Java, Groovy, Kotlin and Android compatibility, see the \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/compatibility.html\"\u003efull compatibility notes\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eReporting problems\u003c/h2\u003e\n\u003cp\u003eIf you find a problem with this release, please file a bug on \u003ca href=\"https://github.com/gradle/gradle/issues\"\u003eGitHub Issues\u003c/a\u003e adhering to our issue guidelines.\nIf you're not sure you're encountering a bug, please use the \u003ca href=\"https://discuss.gradle.org/c/help-discuss\"\u003eforum\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eWe hope you will build happiness with Gradle, and we look forward to your feedback via \u003ca href=\"https://twitter.com/gradle\"\u003eTwitter\u003c/a\u003e or on \u003ca href=\"https://github.com/gradle\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003e9.7.0\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.0.\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/92f0512e7f06d84621afba191f75e265363890cf\"\u003e\u003ccode\u003e92f0512\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38892\"\u003e#38892\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/820ee75a99a179bbffa41bcedc6477b685fabb9f\"\u003e\u003ccode\u003e820ee75\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/82c23f9bd2a89b4cc644e1f90a28a8668feb3dee\"\u003e\u003ccode\u003e82c23f9\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering problem in KTS (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38878\"\u003e#38878\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/ef11a7268fe8cc8d6ab849ec911aa11220180553\"\u003e\u003ccode\u003eef11a72\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering issue\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/bb0d8a974a71b1003efea41e4046e98855cd5ff8\"\u003e\u003ccode\u003ebb0d8a9\u003c/code\u003e\u003c/a\u003e Make relevant tests polyglot (run for multiple DSLs)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/336e129d7f95c03486acafc97abf59734acfed48\"\u003e\u003ccode\u003e336e129\u003c/code\u003e\u003c/a\u003e Update signing configuration (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38874\"\u003e#38874\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/4bdf0da2dad9884d089a6062a45ea7183e7d735d\"\u003e\u003ccode\u003e4bdf0da\u003c/code\u003e\u003c/a\u003e Update signing configuration\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/cd9b92c1b82856248cf1dc58b50378238bec7b52\"\u003e\u003ccode\u003ecd9b92c\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38839\"\u003e#38839\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/5f4e381964897ad8d6b99e5a7c77f26dba3259fb\"\u003e\u003ccode\u003e5f4e381\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/1e08ab551367aeb5fb48b26e72807e1d2b27c939\"\u003e\u003ccode\u003e1e08ab5\u003c/code\u003e\u003c/a\u003e Keep type-use annotations in extracted ABI classes (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38810\"\u003e#38810\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/gradle/gradle/compare/v9.4.1...v9.7.1\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `androidx.core:core-ktx` from 1.18.0 to 1.19.0\n\nUpdates `org.bouncycastle:bcprov-jdk18on` from 1.84 to 1.85.2\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.md\"\u003eorg.bouncycastle:bcprov-jdk18on's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch1\u003eBouncy Castle Crypto Package - Release Notes\u003c/h1\u003e\n\u003ch2\u003e1.0 Introduction\u003c/h2\u003e\n\u003cp\u003eThe Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. The package is organised so that it contains a light-weight API suitable for use in any environment (including the J2ME) with the additional infrastructure to conform the algorithms to the JCE framework.\u003c/p\u003e\n\u003ch2\u003e2.0 Release History\u003c/h2\u003e\n\u003cp\u003e\u003c!-- raw HTML omitted --\u003e\u003c!-- raw HTML omitted --\u003e\u003c/p\u003e\n\u003ch3\u003e2.1.1 Version\u003c/h3\u003e\n\u003cp\u003eRelease: 1.86\u003cbr /\u003e\nDate: 2026, TBD\u003c/p\u003e\n\u003ch3\u003e2.1.2 Defects Fixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) let a subkey inherit the primary key's Key Flags when its own Subkey Binding signature carried no Key Flags subpacket, which made the two capability decisions taken for one subkey disagree. OpenPGPCertificate.OpenPGPComponentKey.isSigningKey() reads the effective flags, which fell back to the primary key's direct-key or primary user ID self-signature, so a subkey bound with no flags of its own counted as signing-capable; verifyEmbeddedPrimaryKeyBinding reads the binding signature's own flags, found no signing capability there, and so skipped the embedded Primary Key Binding (cross-certification) signature that RFC 9580 sec. 5.2.1.8 and sec. 10.1.3 require of a subkey that can issue signatures. A data signature made by such a subkey was therefore attributed to the certificate and reported valid by OpenPGPSignature.OpenPGPDocumentSignature.isValid() with the cross-certification requirement never applied, where GnuPG refuses the same certificate and message as not cross-certified. An attacker holding a third party's public signing subkey - which is public material - could bind it to their own primary key with a Subkey Binding signature they are able to make, carrying no Key Flags and no embedded Primary Key Binding signature, which they cannot make without the subkey's private key, and have that party's genuine signatures verify as valid under the attacker's own identity: misattribution of a real signature rather than a forgery of a new one, since the signature still has to be one the subkey actually made. Key Flags are a statement about the key the carrying signature refers to (RFC 9580 sec. 5.2.3.29), so a subkey no longer inherits them from the certificate-wide signatures of the primary key: a Subkey Binding signature that omits the subpacket now leaves the subkey with no capabilities rather than the primary's, which makes the flags the cross-certification check consults the same flags every other decision consults. Preferences and the other subpackets a direct-key signature carries are inherited as before, and the primary key itself - whose flags legitimately come from its direct-key or user ID self-signature - is unaffected. The low-level PGPSignature / PGPPublicKeyRing API performs no binding checks by design and is unchanged.\u003c/li\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) used a version 6 key that carried no valid Direct Key signature, falling back to the primary user ID binding as it correctly does for a version 4 key. RFC 9580 sec. 5.2.3.10 requires the opposite: \u0026quot;An implementation MUST ensure that a valid Direct Key signature is present before using a version 6 key. This prevents certain attacks where an adversary strips a self-signature specifying a Key Expiration Time or certain preferences.\u0026quot; The certificate grammar says the same structurally, the Direct Key signature being mandatory in the version 6 structure of sec. 10.1.1 and optional in the version 4 one of sec. 10.1.3. Because a version 6 certificate carries its key expiration, features and algorithm preferences on the Direct Key signature - the convention the RFC recommends and the one OpenPGPKeyGenerator follows, its user ID certification carrying no expiration at all - removing that single signature packet from a published certificate silently dropped the expiration along with the preferences and features: OpenPGPCertificate.getSignatureChainFor fell back to the user ID binding, the primary key was still reported bound, and getEncryptionKeys() and getSigningKeys() went on returning the subkeys of a key whose owner had set it to expire. The primary key fingerprint is unchanged by the removal, so a relying party pinning the key by fingerprint still treats it as the same key, and no private key or hash collision is involved; the natural moment for the strip is the key refresh that RFC 9580 names as the reason to refetch a key at all - to learn about changes in expiration, features, preferences and revocation - which is exactly the update it defeats. This is a downgrade rather than a forgery, nothing being attributed to a key that did not authorise it, and the concerning direction is encryption, to a key meant to have been retired. OpenPGPCertificate.isBoundBy now requires a valid Direct Key self-signature on a version 6 primary key before any component of the certificate - the primary key, its subkeys or its identities - is treated as bound, so a version 6 certificate stripped of it offers no keys at all rather than an unexpiring set. Version 4 certificates are unaffected: there the key expiration legitimately lives on the user ID self-signature and the fallback is correct, so it stays. The revocation-only version 6 certificate of sec. 10.1.2, which legitimately carries no Direct Key signature, is unaffected as well - its key was already refused as revoked, and reading the revocation does not go through the binding check.\u003c/li\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) ignored the OpenPGPPolicy a caller had configured when it verified the signatures on an inline message. OpenPGPMessageInputStream took the policy it sanitizes each document signature against from the implementation's own default rather than from the processor the signature is being verified by, so a policy supplied through the documented OpenPGPApi(implementation, policy) / OpenPGPMessageProcessor(implementation, policy) constructor - which is how OpenPGPApi.decryptAndOrVerifyMessage() plumbs the configured policy through - had no bearing on whether a signature was accepted, although the same processor already applied it to the decompressed-size bound. A caller who hardened the policy beyond the default therefore had a signature that policy rejects handed back from getResult().getSignatures() with isTestedCorrect() true, while OpenPGPSignature.isValid(policy) on that same signature reported the rejection. Both verify paths, the one-pass and the prefixed-signature one, now read the configured policy; the detached-signature processor already did.\u003c/li\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) went on offering the subkeys of a certificate whose primary key had expired. OpenPGPCertificate's binding check evaluated only a subkey's own Subkey Binding signature, so a primary key whose Key Expiration Time (RFC 9580 sec. 5.2.3.13) had passed still handed out a longer-lived encryption or signing subkey from getEncryptionKeys() / getSigningKeys(), leaving the certificate contradicting itself - getExpirationTime() in the past and getPrimaryKey().isBoundAt() false, while isBoundAt() on the subkey answered true. An expired primary key can no longer certify, so the subkeys it bound are not usable with it either, which is how GnuPG and Sequoia both treat such a certificate; primary key revocation already propagated, since a revocation appears in the subkey's signature chain, but expiration is not carried there. Relatedly, a subkey no longer inherits the primary key's validity period at all - sec. 5.2.3.13 counts that period from the creation time of the key the carrying self-signature is made on, so re-basing the primary key's period on a subkey created later than it gave that subkey an expiration date later than the primary key's own.\u003c/li\u003e\n\u003cli\u003eOpenPGPSignature.OpenPGPDocumentSignature.isValidAt(Date) in the high-level OpenPGP API reported a data signature as valid at an evaluation time past the signature's own Signature Expiration Time (RFC 9580 sec. 5.2.3.18, hashed subpacket type 3). The method checked that the signature was correct and that the issuing key was bound and signing-capable at that date, but never consulted the signature's own expiration, so it disagreed with isEffectiveAt(Date) on the same object and with its own javadoc, which names being effective as one of the three criteria of a valid signature. Signature expiration is a separate axis from the issuing key's Key Expiration Time that the binding checks already cover, and GnuPG, GPGME, git and Sequoia all keep the two apart and treat a signature past its expiration as not good. isValid() and isValid(policy) evaluate at the signature's creation time, where a signature is always inside its own window, and are unchanged.\u003c/li\u003e\n\u003cli\u003eThe lightweight LMSSigner and HSSSigner refused a key wrapped in ParametersWithRandom, which is how BcContentSignerBuilder passes a key whenever setSecureRandom() has been called - so BcHssLmsContentSignerBuilder built a working signer until a random was set and then failed with \u0026quot;Incorrect Key Parameters\u0026quot;, and the two signers themselves raised ClassCastException on the same input. All three now unwrap it, as the promoted ML-DSA and SLH-DSA signers already did. The random is accepted and not used: LMS derives its message randomiser C from the key's seed and the one-time index, so it is deterministic and cannot repeat while q does not. Note SP 800-208 sec. 6.1 asks for C to come from an approved random bit generator, which this implementation does not do; that is unchanged here, and a supplied random is now ignored rather than refused.\u003c/li\u003e\n\u003cli\u003eLMS signature verification did not apply two of the checks RFC 8554 sec. 5.4.2 requires before a signature is processed. Step 2g refuses a signature whose LMS typecode is not the one from the public key, and without it the path computation took its height and tree digest from the parameter set the signature named rather than the key's, so a signature claiming a height-25 parameter set drove a 25-level computation against a height-5 key. Step 2i refuses a leaf number q outside the tree, and without it an out-of-range q flowed into the node arithmetic and was left for the candidate-root comparison to catch. Neither was a forgery - the domain separation between D_LEAF and D_INTR and the final comparison saw to that - but both are attacker-chosen work the specification says to refuse up front. Both are now checked, and a signature failing either is still reported as not verifying rather than thrown out of Signature.verify(). The catch around the signature decode in LMSSigner and HSSSigner has also been narrowed to the decode itself, as the corresponding SPI was corrected to do for github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2408\"\u003e#2408\u003c/a\u003e: past the parse the engine reports an inconsistent signature by returning false rather than by throwing, so the wider catch caught nothing while standing ready to turn a future internal error into a quiet false.\u003c/li\u003e\n\u003cli\u003eThe LMS and HSS key parameter classes now apply at construction the checks their decoders apply, so a key built directly cannot be one the decoder would refuse. LMSPrivateKeyParameters accepted an identifier of any length although the decoder reads exactly 16 bytes - such a key encoded but could not be read back - and left q, maxQ and the seed length unchecked; the seed is now required to be at least m bytes at decode as well, where a one-byte seed had been decoding silently and then deriving every one-time key from it. HSSPrivateKeyParameters checked neither its level count nor that it had been given a component key per level and a chaining signature per level below the root, and then indexed both lists, so a mismatch surfaced as IndexOutOfBoundsException - or, where a level happened to match, as a null chaining signature that only failed at signing time; the level is now checked after the reset that fills it in, since a null is legitimate on the way in. LMSPrivateKeyParameters.getInstance(byte[], byte[]) adopted the public key supplied beside the private one without comparing them, so a mismatched public key was simply reported by getPublicKey(); it now cross-checks the identifier, both parameter sets and, where the tree cache already holds it, the root, as the HSS entry point does. The decoders also now report a bad version or seed length as IOException rather than IllegalStateException, so a caller can catch one type for a malformed key, and the package-private LM-OTS public key decoder no longer declares throws Exception or dereferences an unrecognised typecode. The deprecated org.bouncycastle.pqc.crypto.lms copies carry the decoder corrections.\u003c/li\u003e\n\u003cli\u003eIn the LMS JCE layer, LMSKeyGenParameterSpec.fromNames knew all twenty LMS parameter-set names but only four of the sixteen LM-OTS ones, so none of the SP 800-208 n24 or SHAKE sets could be named; all sixteen are now present. KeyPairGenerator.initialize(int, SecureRandom) reports InvalidParameterException, which is what the JCA specifies and which extends the IllegalArgumentException it raised before, so existing catches still match. BCLMSPrivateKey.getIndex now takes the exhaustion check and the index read under the key's own monitor rather than as two separate calls, and two unused fields have gone from LMSSignatureSpi. Note that the LMS Signature claims its one-time key at the first update() rather than at sign(), so a Signature that is initialised and updated and then abandoned spends an index without producing a signature - the safe direction for a one-time scheme, and now documented on the SPI.\u003c/li\u003e\n\u003cli\u003eEvery other key pair generator that refuses a key size did the same thing the LMS one did above. KeyPairGenerator.initialize(int, SecureRandom) is documented to raise InvalidParameterException when the key size is not one the generator supports, and thirty of them raised a bare IllegalArgumentException instead, so a caller following the JCA and catching the documented type saw an exception escaping rather than a refusal. The ML-DSA, ML-KEM, SLH-DSA, Classic McEliece, FrodoKEM, NTRU and composite signature and KEM generators in the BC provider, and every generator in BCPQC, now raise InvalidParameterException - NewHope included, where the value is a key size it will not take rather than a mode of initialisation it does not offer. InvalidParameterException extends IllegalArgumentException, so callers written against the old behaviour go on catching it unchanged. The two RSA generators are corrected as well, and differently: theirs is a key size below a floor rather than a mode of initialisation they do not offer, and the refusal is raised by the lightweight RSAKeyGenerationParameters, which cannot name a java.security exception at all, so the RSA KeyPairGeneratorSpi now translates it - keeping the message verbatim and the original exception as the cause, through a new SecurityExceptions.invalidParameterException factory, since InvalidParameterException has no constructor that takes one. Of the 304 KeyPairGenerator services the two providers register, 299 now refuse a nonsense key size the way the JCA defines it and five accept it as a strength they can work with, with none left raising a bare IllegalArgumentException; that is asserted as a sweep over both providers rather than per algorithm, so a generator added later is covered without the test being touched. The jdk1.3 provider overlays of the four generators that have one carry the same change, and the jdk1.3 SecurityExceptions overlay gains the new factory along with the invalidAlgorithmParameterException one it had been missing.\u003c/li\u003e\n\u003cli\u003eKeyPairGenerator.initialize(AlgorithmParameterSpec, SecureRandom) had the same shape of problem as the int overload above, and only 44 of the 304 services the two providers register reported an unusable spec as the InvalidAlgorithmParameterException that method declares. The twenty-three PQC generators that resolve a parameter set by name - cmce, frodokem, mldsa, mlkem, slhdsa, aimer, bike, faest, falcon, haetae, hqc, mayo, mqom, ntru, ntruplus, both ntruprime variants, qruov, saber, sdith, smaugt, snova and sqisign, 230 services between them - case-folded the name they got back from the spec without checking it, so a spec with no getName() method, and a null spec, produced a NullPointerException from inside the fold; their own \u0026quot;is this name one I know\u0026quot; branch, which does report the declared exception, was unreachable. The two composite generators, whose parameter set is fixed by the algorithm name so that null is the only spec they accept, refused every other one with IllegalArgumentException. RSA answered correctly for a spec of the wrong type but not for one of the right type carrying values its lightweight parameters will not take - an even public exponent, or a key size below the floor - which is now translated the same way the int overload's is. All 304 services now report the declared exception, with the composites still taking the null spec that is right for them; note that InvalidAlgorithmParameterException is a checked exception and not an IllegalArgumentException, so a caller that was catching what these threw before has to catch the declared type instead.\u003c/li\u003e\n\u003cli\u003eAn HSS private key claimed the two records of its position under two different monitors. The top-level index and the bottom component key's one-time index q are independent records of the same position - the decoder requires them to agree, see the entry below - but generateLMSContext incremented the index under the HSS key's own monitor, released it, and only then claimed q under the component key's. A getEncoded() issued in between saw the index advanced and q not, and produced an encoding this implementation's own decoder rejects; and two threads meeting at a bottom-tree boundary could both pass the exhaustion test, take consecutive top-level indices and claim the same q, after which one of them was refused with \u0026quot;ots private key exhausted\u0026quot; by a key still reporting usages remaining, a top-level index had been spent with no signature made, and the two records stayed one apart for the rest of the key's life in that process - so it could no longer be encoded, cloned or sharded, and getIndex() and getUsagesRemaining() misreported by one. No one-time key was reused: the component key's claim is itself atomic, and the divergence runs index ahead of leaves, so the effect was on the key's usability rather than on the signatures it had made. Both records are now claimed under the one monitor, and the component key is claimed before the index is incremented so that an exhausted one leaves both untouched. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the same correction.\u003c/li\u003e\n\u003cli\u003eTimeStampToken parsed the attacker-controlled TSTInfo content of a time-stamp token (org.bouncycastle.tsp.TimeStampToken, reached from TimeStampResponse(byte[]) and (InputStream)) inside a try that caught only CMSException, so a well-formed RFC 3161 TimeStampResp whose embedded token carried a malformed TSTInfo - a SEQUENCE with fewer elements than the five mandatory fields, a non-SEQUENCE, truncated DER, or an unknown context tag - let an IllegalArgumentException or a NoSuchElementException escape the constructor's declared throws TSPException, IOException contract. A token signed by no signers or by more than one raised a bare IllegalArgumentException from the same constructor, before that try, for the same reason. Both are now reported as TSPException, matching the package-private TimeStampResponse(DLSequence) constructor and the existing getSignedAttributes guard in the same method; the signer-count refusal is a TSPValidationException, as the neighbouring check on the content type already was. Related, and the cause of the NoSuchElementException: asn1.tsp.TSTInfo read its five mandatory fields off the sequence with no bound on how many elements were actually there, so a short SEQUENCE left the enumeration to run out rather than being refused, and an oversize one was accepted with its extra elements absorbed into the optional slots. Decode now requires the five to ten elements RFC 3161 sec. 2.4.2 gives the type, which is what the sibling Accuracy and ArchiveTimeStamp decoders already did, so the failure is the IllegalArgumentException that getInstance is expected to raise (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2415\"\u003e#2415\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eNeither the HSS nor the XMSS^MT private key decoder checked its declared index against the traversal state stored beside it, although the two are independent records of the same position in the key and so can be compared. For HSS the records are the top-level index and the component keys' one-time indices q; for XMSS^MT they are the global index and the per-layer BDS states. A stored key whose index had been rolled back while its state stayed advanced - a partial write, a restore from backup, a buggy storage layer - was therefore accepted, and it then signed a second message under a one-time key the key had already used, producing a signature that verified, so nothing anywhere surfaced the reuse. RFC 8554 sec. 1 and RFC 8391 sec. 1.1 both require each one-time key to be used exactly once, and this is the failure those requirements exist to prevent; the single-tree XMSS decoder has tied its BDS state to its index since that state was first validated, and this brings the two multi-tree schemes into line. HSS decode now requires the declared index to equal the position the component q values imply - a level above the last contributes (q - 1) leaves of the levels beneath it, since its q has already advanced past the subtree it signed - and XMSS^MT decode now requires each present layer's BDS index to equal the leaf index that layer derives from the global index, allowing the one position where a layer has moved into a new subtree and its state legitimately still carries the previous subtree's final index. A layer with no state yet is unaffected, since those are built lazily at signing time. Related, and the same shape of omission: an XMSS or XMSS^MT private key encoding carries the tree root twice - the key's own root field and the root node of the BDS state stored beside it, which for XMSS^MT is the top layer's - and the two were never compared either. A corrupted root was accepted and then poisoned every signature the key made, because the root is hashed into the message digest: the signature did not verify and nothing indicated why. Decode now requires the two copies to agree. The BDS node values themselves are not checkable the way the LMS tree cache above is - a BDS authentication path, stack, retain or keep node does not have its children stored alongside it, so recomputing one means building a subtree, which is the work the state exists to avoid. Both checks are integer comparisons over the levels of the key, too small to measure against the surrounding decode, and both were verified not to reject any legitimate key by walking every index a key can reach: the full key space of the two-level HSS and the h=4/d=2, h=6/d=2, h=6/d=3, h=9/d=3 and h=8/d=4 XMSS^MT parameter sets, plus a three-level HSS key across a subtree boundary and an HSS shard. Since those node values cannot be recomputed, the encoded state now carries a checksum over itself instead, with the owning key's public seed hashed in front of it. Any corruption of the stored state is refused at decode rather than being loaded and then producing signatures that silently do not verify, and because the public seed is bound in, a state transplanted between two keys of the same parameter set is refused too, even though it is internally consistent and arrives with its own matching root. The public seed is bound rather than the secret seed or the PRF key deliberately: the state's own root and index are inside the encoding and so are already covered, hashing secret material would make the stored checksum a commitment to it for no gain in detection, and the PRF key does not influence the state at all. \u003cstrong\u003eThis is an error-detecting code and not integrity protection\u003c/strong\u003e - anyone able to rewrite the stored key recomputes it, so it establishes that the state is unchanged since it was written, never that it was correct when written, and the allocation bounds on the encoding remain the guard against a crafted one. It costs one SHA-256 over the state, measured at 5 to 8 microseconds each way for the h=10 and h=16 parameter sets, and 32 bytes of encoding. The state encoding was added earlier in this same cycle and has not been released, so the checksum is simply part of it rather than a new version: a state written by a 1.86 beta is rejected, which is recovered from by re-exporting the key. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the HSS check as well (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2414\"\u003e#2414\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eIn the XMSS and XMSS^MT JCE layer, KeyPairGenerator.initialize(int, SecureRandom) reports InvalidParameterException, which is what the JCA specifies and which extends the IllegalArgumentException it raised before, so existing catches still match. This is the XMSS counterpart of the same correction made to LMSKeyPairGeneratorSpi.\u003c/li\u003e\n\u003cli\u003eBCXMSSPrivateKey.getIndex and BCXMSSMTPrivateKey.getIndex took the exhaustion check and the index read as two separate calls on the key parameters. Each is atomic on its own, but the pair is not: a signature taken by another thread between them spends the last usage, so the check passes and the read that follows returns maxIndex + 1 - the one index past the end of the key, which is what the check exists to refuse, handed back as though it were the next one-time key to be used. Both reads are now taken under the key parameters' own monitor, the monitor their mutators hold, as BCLMSPrivateKey.getIndex was corrected to do. No one-time key is reused by this: the effect is on what the key reports about itself, not on the signatures it makes.\u003c/li\u003e\n\u003cli\u003eThe S/MIME example smoke test in the misc module (org.bouncycastle.mail.smime.examples.test.AllTests) drove SendSignedAndEncryptedMail against smtp.gmail.com, and that example finishes with Transport.send() under JavaMail's default settings, which have no connect timeout. Where outbound port 25 is refused the failure was swallowed and the test passed; where it is silently dropped, as on many home networks, the connect blocked and ./gradlew build hung in :misc:test indefinitely with \u0026quot;0 tests completed\u0026quot;. The test now delivers to an SMTP stub on a loopback port, with connect / read / write timeouts as a backstop, and asserts the message arrived (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2407\"\u003e#2407\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation took the traditional component public key bytes it feeds the KEM combiner from the recipient key's own encoding, while decapsulation recomputes the point from the private key and so always produced an uncompressed one. Section 4 of draft-ietf-lamps-pq-composite-kem requires an EC component to be carried as an uncompressed point, but a component key that encodes itself compressed - a BC EC key whose point format has been set through org.bouncycastle.jce.interfaces.ECPointEncoder, or a key from a provider that preserves a compressed encoding - was passed through as it came. Both sides then combined a different tradPK and derived different shared secrets, with no error reported on either: encapsulation and decapsulation both succeeded and the recipient simply could not decrypt. The EC component is now normalised to an uncompressed point wherever the engine serialises one, which covers the ephemeral key that forms the ciphertext as well. X25519 and X448 components have a single encoding and were unaffected, as were EC keys left in their default (uncompressed) format, whose shared secrets are unchanged. CompositePublicKey.getEncoded() took its component bytes the same way, so such a key also encoded to a composite key other implementations reject and whose bytes changed across an encode / decode / encode round trip - 1238 bytes rather than 1270 for MLKEM768-ECDH-P256, and for the composite ML-DSA keys sharing that method, 2006 rather than 2038 for MLDSA65-ECDSA-P256. It now normalises the component the same way. This is a write-side change only: a composite key carrying a compressed EC component is still decoded, since the component key factories accept either form, and continues to verify signatures as before - it simply re-encodes in the normalised form. The shared normalisation is org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil.getUncompressedSubjectPublicKeyBytes.\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation threw a NullPointerException, wrapped in an IllegalStateException out of KeyGenerator.generateKey(), when the SecureRandom it was given was null - which javax.crypto.KEM.newEncapsulator() documents as a request for the provider's default, and which KeyGenerator.init(spec, null) passes straight through. The three RSA-OAEP composites draw the traditional shared secret from that random directly, so they were the ones affected; the ECDH and X25519 / X448 composites escaped only because their component KeyPairGenerators default a random of their own. CompositeMLKEMEngine now defaults one through CryptoServicesRegistrar.getSecureRandom() on first use, as the composite KEM Cipher's wrap path already did, and as the KEM generators corrected earlier in this cycle now do. Related, the engine now also clears the ML-KEM component's shared secret alongside the traditional one on both the encapsulate and decapsulate paths - the copy handed back by getEncoded() was left in the heap - as section 3.5 of draft-ietf-lamps-pq-composite-kem requires.\u003c/li\u003e\n\u003cli\u003eCompositePublicKey.getAlgorithm() and CompositePrivateKey.getAlgorithm() returned null for all twelve Composite ML-KEM (draft-ietf-lamps-pq-composite-kem) parameter sets. Both classes resolved the name through the composite signature index only, which holds the composite ML-DSA OIDs, so a composite KEM key pair - generated, parsed from a certificate, or read from PKCS#8 - reported no algorithm at all, and the standard JCA idiom of reconstructing a key with KeyFactory.getInstance(key.getAlgorithm()) raised a NullPointerException. The lookup now falls back to the composite KEM index, so the name returned is the one the provider registers the algorithm under (e.g. MLKEM768-X25519-SHA3-256), matching the composite ML-DSA behaviour. The same single-index assumption made the CompositePublicKey(SubjectPublicKeyInfo) and CompositePrivateKey(PrivateKeyInfo) constructors reject a composite KEM key with \u0026quot;unable to create CompositePublicKey from SubjectPublicKeyInfo\u0026quot;; they now dispatch to the composite KEM key factory for those OIDs. Keys obtained through KeyFactory or through BouncyCastleProvider.getPublicKey / getPrivateKey were unaffected and are unchanged (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2404\"\u003e#2404\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe org.bouncycastle.jcajce.spec.KEMKDFSpec constructor stored a null otherInfo as given, so getOtherInfo() returned null, and three of the KDF branches KdfUtil.makeKeyBytes dispatches to - KMAC-128, KMAC-256 and SHAKE-256 - read the otherInfo length without a guard and threw NullPointerException out of the KEM operation, where the KDF2, KDF3 and HKDF branches tolerate a null through KDFParameters / HKDFParameters. The Builder of every spec in the package already mapped null to empty, so no provider path reached it, but the constructor is protected on a public class and KdfUtil is documented for callers building their own KEM integration; the deprecated KEMParameterSpec passes a null itself and escaped only because it also pins the KDF to null. The constructor now stores empty for a null, so getOtherInfo() never returns null, and a null and an explicitly empty otherInfo derive the same key.\u003c/li\u003e\n\u003cli\u003eQR-UOV signature verification accepted a signature encoding that was not canonical, so the encoding of a signature was not unique even after the trailing-byte fix of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e. Each F_q element of the signature is stored in ceil(log2 q) bits, one more bit pattern than the field has elements: q itself is representable and is arithmetically congruent to zero, so an element written as q verified exactly as the same element written as zero would, and the bits padding the last element out to the byte boundary were never read at all. Every zero element of a signature therefore carried a second encoding, and for the q = 7 parameter sets roughly one element in seven is zero - a single qruov_5_q7_L10 signature measured 256 spare bits, so on the order of 2^256 distinct byte strings verified for the one message and key. Verification now rejects any element outside [0, q) and any set padding bit; a signature produced by this or by the reference implementation is unaffected, as the KAT vectors of every parameter set confirm. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSNOVA signature verification ignored four bits inside the signature for any parameter set whose solution is an odd number of GF(16) nibbles - the SNOVA_24_5_5, SNOVA_25_8_3, SNOVA_29_6_5 and SNOVA_66_15_3 families, sixteen of the forty-four parameter sets. The last byte of the encoded solution carries a single nibble and the signer leaves the top four bits zero, but the decoder did not read them, so sixteen distinct byte strings verified for one signature. This is the same non-unique encoding github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e closed for bytes following the signature, applied inside it; the verifier now requires those bits to be zero. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSnovaPrivateKeyParameters did not validate the length of the private key encoding handed to it - the only one of the five schemes of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e that did not - and SnovaParameters.getPrivateKeyLength() reported the expanded (\u0026quot;ESK\u0026quot;) length even for a parameter set whose private key is the seed pair. A private key encoding reaches this constructor straight from a PKCS#8 blob, so a wrong length went undetected: a seed-form key with extra bytes appended was accepted and signed under a different derived key, and a short expanded-form key sized the signer's decode buffer negatively, throwing NegativeArraySizeException out of generateSignature() rather than being reported at construction. Related, the signing retry loop could not terminate: the vinegar values are derived from a single-byte counter, so only 256 distinct linear systems can be tried, and an expanded-form private key that is not a real central map is singular for all of them - generateSignature() then span forever rather than failing. The length is now checked at construction, getPrivateKeyLength() reports the length that parameter set's private key actually has, and the retry loop gives up after its 256 attempts as MAYO's does.\u003c/li\u003e\n\u003cli\u003eMayoSigner and MayoKeyPairGenerator did not clear several buffers holding secret key material that the MAYO reference implementation explicitly clears. Signing left the secret oil space O, the expanded L = (P1 + P1^t) * O + P2, and the M / VPV / Ox intermediates of the central map in place, having gone to the trouble of clearing eleven other buffers; key generation left the expanded seed, whose tail is the encoded oil space, and the P1 * O + P2 half of P; and the row-echelon step left the packed echelon form of the secret linear system and its pivot rows. Separately, if all 256 attempts at solving for the signature had given a rank-deficient system, signing emitted a signature built from the failed attempt's state instead of reporting the failure the reference returns, and AIMerSigner.generateSignature returned an empty array on failure, which a caller would hand on as though it were a signature. Both now throw.\u003c/li\u003e\n\u003cli\u003eFive PQC signature schemes - MAYO, SNOVA, QR-UOV, SQIsign and AIMer - returned the NIST crypto_sign \u0026quot;sm\u0026quot; signed-message envelope from generateSignature() rather than the signature. That envelope is an artefact of the reference KAT harness, which records the message alongside the signature so a vector file can be self-contained; it is not part of any of the five specifications, and no other BC signer emits it (Falcon's KAT test rebuilds the equivalent envelope in the test, which is where it belongs). Two consequences followed, both reaching the JCA Signature services of every parameter set of the five schemes in BouncyCastlePQCProvider. First, since the message was appended to the signature, verification had to skip whatever followed the signature proper, and it did so by checking only that the buffer was long enough - so any number of trailing bytes could be added to a valid signature, or the appended message replaced with unrelated data, and it still verified. A signature encoding was therefore not unique: anyone holding one valid signature could produce unlimited distinct byte strings that all verified for the same message and key, which breaks any use that treats the signature bytes as an identifier, deduplicates on them, or records them as evidence. Second, the envelope propagated into everything built on the operator layer: because ContentSigner hands the signature straight into the structure being signed, every X.509 certificate, CRL, CMS SignedData and TLS CertificateVerify BC produced with one of these algorithms carried a verbatim copy of the signed data inside its own signature field - a self-signed MAYO-1 certificate came to 3567 bytes where the same certificate is now 2020 - which no other implementation can parse as a signature, and which in a detached CMS signature meant the \u0026quot;detached\u0026quot; signature carried the content. generateSignature() now returns the bare signature, and verifySignature() requires exactly the parameter set's signature length, so appended or truncated data is rejected rather than ignored. \u003cstrong\u003eThis is a behavioural change for signatures produced by an earlier release\u003c/strong\u003e - MAYO and SNOVA from 1.84, QR-UOV, SQIsign and AIMer from 1.85 - which are no longer accepted in the envelope form they were emitted in; the signature bytes themselves are unchanged, so a stored value can be recovered by taking the leading signature-length bytes, or for AIMer, whose envelope was message || signature rather than signature || message, the trailing ones. The KAT tests now rebuild the envelope before comparing against the vector files, which continue to record it. Note that AIMer's verification had already been made length-exact during this cycle (see the entry below relating to github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2401\"\u003e#2401\u003c/a\u003e), so of the five only its envelope remained (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe MLS implementation did not bind an X.509 credential to the LeafNode's signature_key. LeafNode.verify() checked a leaf's signature against the signature_key declared in the leaf itself, while the X.509 credential's certificate chain was stored but never parsed or checked, so the certificate's public key was never required to match signature_key (RFC 9420 sec. 5.3). A leaf could therefore carry one party's certificate while being signed by an unrelated key and still be accepted under that party's identity through KeyPackage.verify() and the Group leaf-validation path. LeafNode.verify() now requires the end-entity certificate's subject public key, in the cipher suite's signature encoding, to equal signature_key for an X.509 credential, and rejects the leaf otherwise - including an empty chain or a certificate whose key type does not match the cipher suite; certificate-chain and identity validation to a trust anchor remain the application's responsibility per RFC 9420 sec. 5.3.1. A public org.bouncycastle.mls.codec.Certificate(byte[]) constructor and a Credential.getCertificates() accessor are added so callers can build and inspect X.509 credentials. Basic credentials are unaffected.\u003c/li\u003e\n\u003cli\u003eThe SecureRandom supplied to org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder.setSecureRandom() did not drive the content IV / nonce for any algorithm other than RC2. EnvelopedDataHelper.generateParameters passed the caller's SecureRandom to the AlgorithmParameterGenerator only in the RC2_CBC branch; every other content-encryption algorithm - AES-CBC, AES-GCM, AES-CCM, Camellia, ARIA, SEED and the rest - reached pGen.generateParameters() on an uninitialised generator, so the IV / nonce was drawn from a default SecureRandom and setSecureRandom() was silently ignored (the builder's javadoc states that random is used for IV/nonce generation). The generator is now initialised with the supplied random on the general path as well, so a caller who provides a specific randomness source - for a controlled or FIPS-approved DRBG, say - has it honoured for the content IV / nonce. The session-key generation path was unaffected and already used the supplied random. Because the content IV / nonce now comes from the supplied SecureRandom, the org.bouncycastle.crypto.util JournalingSecureRandom / JournaledAlgorithm reproducible-encryption support records it in the transcript: a resumed session reproduces the IV / nonce by regenerating it from the replayed randomness - build the resuming encryptor from the content-algorithm OID - rather than by reusing the AlgorithmIdentifier captured from the first encryption, which no longer keeps the transcript aligned.\u003c/li\u003e\n\u003cli\u003eThe NTRU LPRime, NTRU+ and SMAUG-T KEM generators threw a NullPointerException when constructed with a null SecureRandom, where every other KEM generator - including NTRU LPRime's own SNTRU Prime counterpart in the same package - defaults one through CryptoServicesRegistrar.getSecureRandom(). This is reachable from the lightweight API directly, and from javax.crypto.KEM, whose newEncapsulator() documents a null random as a request for the provider's default.\u003c/li\u003e\n\u003cli\u003eFrodoKEMEngine kept a single SHAKE instance in a field, so an engine reached concurrently produced wrong results. It is reached that way through org.bouncycastle.crypto.kems.FrodoKEMExtractor, which holds one engine for its lifetime: two threads extracting through one extractor interleaved the digest's absorb and squeeze phases, yielding shared secrets that silently did not match the sender's, or an IllegalStateException of \u0026quot;attempt to absorb while squeezing\u0026quot; from inside extractSecret. The digest is now built per call, as CMCEEngine's already was, which makes an extractor safe to share. Encapsulation was unaffected, since FrodoKEMGenerator builds an engine per call. Results for any single-threaded use are unchanged - the reference KAT vectors are byte-identical.\u003c/li\u003e\n\u003cli\u003eThe BCJSSE provider carried the TLS 1.2 coupling between the supported_groups extension and ECDSA over into TLS 1.3: an ECDSA signature scheme was treated as usable - offered in the signature_algorithms and signature_algorithms_cert extensions, and eligible when selecting the local credentials - only while the corresponding curve was among the named groups enabled for key exchange, both per context (a group unavailable for key agreement disabled the scheme outright) and per connection (the curve had to be in the supported_groups list about to be sent). RFC 8446 sec. 4.2.7 scopes supported_groups to key exchange only, with signature algorithms negotiated independently (sec. 4.2.3), so this incorrect restriction in TLS 1.3 has been removed. Ed25519, Ed448 and the RSA schemes were unaffected (as well as typical deployments using a default configuration for named groups).\u003c/li\u003e\n\u003cli\u003eThe bcmail module descriptor did not declare its javax.mail/javax.activation dependences, so a modular (module-path) consumer of the jar hit IllegalAccessError/module-resolution failures when the S/MIME classes touched the mail API. The descriptor now requires them optionally (requires static) under all four module names those libraries are known by - the automatic names mail and activation carried by the javax.mail:mail / javax.activation:activation artifacts, and the explicit names java.mail and java.activation carried by the newer com.sun.mail / com.sun.activation ones - a hard requires on any one name would break users of the others (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2389\"\u003e#2389\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFour type-coercion helpers in the OER / IEEE 1609.2 (ITS) decoder tested the wrong type in the identity fast path that lets a getInstance() factory return an argument that is already of the target type. org.bouncycastle.oer.its.ieee1609dot2.basetypes.UINT32.getInstance and org.bouncycastle.oer.its.etsi102941.basetypes.Version.getInstance guarded on UINT8 - a sibling of UINT32 under UintBase, and unrelated to Version - so passing a UINT8 threw ClassCastException, while passing an actual UINT32 or Version missed the fast path and fell through to ASN1Integer.getInstance, which rejects them: neither factory accepted its own type. org.bouncycastle.oer.its.etsi103097.EtsiTs103097DataEncryptedUnicast.getInstance guarded on its sibling EtsiTs103097DataEncrypted and then cast to the unicast type, so an EtsiTs103097DataEncrypted threw ClassCastException. org.bouncycastle.oer.OEROptional.getObject(Class) called value.getClass().isInstance(type) with the arguments transposed, which is always false because the argument is a java.lang.Class, so the cast path was dead and every optional field was resolved reflectively, failing with IllegalStateException for a target type with no static getInstance. Each guard now names the type it returns, matching the sibling UINT8 / UINT16 / UINT64 and EtsiTs103097DataEncrypted factories (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2373\"\u003e#2373\u003c/a\u003e).\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003eSee full diff in \u003ca href=\"https://github.com/bcgit/bc-java/commits\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003ecommonmark-java 0.29.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e[0.29.0] - 2026-06-20\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/42b4fb7adfe288ef13e9e27ab20aff7e91b0ab9d\"\u003e\u003ccode\u003e42b4fb7\u003c/code\u003e\u003c/a\u003e Prepare CHANGELOG for version 0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/b76e09d7a8362abb5f04e1d6b91dbd6da279a6fc\"\u003e\u003ccode\u003eb76e09d\u003c/code\u003e\u003c/a\u003e Limit how deep inline nodes may nest by default (100)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/49f65cb5cbec93cff713179990307145198e7061\"\u003e\u003ccode\u003e49f65cb\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing deeply nested emphasis\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/610f84b83e68c381e8f784ae4d044c80e1948b67\"\u003e\u003ccode\u003e610f84b\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological autolink email addresses\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/9f1d73897a56cbd74c39347af351a473e70297e1\"\u003e\u003ccode\u003e9f1d738\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological HTML block attributes\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/e13297e849995fdd582a85841067bff1d9c35ee5\"\u003e\u003ccode\u003ee13297e\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing pathological backticks\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-j...\n\n_Description has been truncated_","html_url":"https://github.com/SevenAILab/geo-demo/pull/16","url":"https://dependabot.ecosyste.ms/api/v1/hosts/GitHub/repositories/SevenAILab%2Fgeo-demo/issues/16","packages_url":"https://dependabot.ecosyste.ms/api/v1/issues/16/packages"},{"uuid":"5408368480","node_id":"PR_kwDOTa7xfM8AAAABC8URIQ","number":23,"state":"open","title":"Bump the android-deps group across 1 directory with 21 updates","user":"dependabot[bot]","labels":["dependencies","java"],"assignees":[],"locked":false,"comments_count":1,"pull_request":true,"closed_at":null,"author_association":null,"state_reason":null,"created_at":"2026-09-10T05:53:15.000Z","updated_at":"2026-09-10T06:09:40.000Z","time_to_close":null,"merged_at":null,"merged_by":null,"closed_by":null,"dependency_metadata":{"prefix":"Bump","group_name":"android-deps","update_count":21,"packages":[{"name":"gradle-wrapper","old_version":"9.6.1","new_version":"9.7.1","repository_url":"https://github.com/gradle/gradle"},{"name":"androidx.appcompat:appcompat","old_version":"1.7.1","new_version":"1.8.0"},{"name":"org.bouncycastle:bcprov-jdk18on","old_version":"1.85","new_version":"1.85.2","repository_url":"https://github.com/bcgit/bc-java"},{"name":"org.commonmark:commonmark","old_version":"0.29.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-autolink","old_version":"0.29.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-strikethrough","old_version":"0.29.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-tables","old_version":"0.29.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-task-list-items","old_version":"0.29.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"io.coil-kt.coil3:coil-compose","old_version":"3.5.0","new_version":"3.6.2","repository_url":"https://github.com/coil-kt/coil"},{"name":"io.coil-kt.coil3:coil-svg","old_version":"3.5.0","new_version":"3.6.2","repository_url":"https://github.com/coil-kt/coil"},{"name":"org.junit.vintage:junit-vintage-engine","old_version":"6.1.2","new_version":"6.1.3","repository_url":"https://github.com/junit-team/junit-framework"},{"name":"io.kotest:kotest-assertions-core-jvm","old_version":"6.2.2","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"io.kotest:kotest-runner-junit5-jvm","old_version":"6.2.2","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"com.squareup.okhttp3:mockwebserver","old_version":"5.4.0","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.squareup.okhttp3:okhttp","old_version":"5.4.0","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.android.application","old_version":"9.3.0","new_version":"9.4.0"},{"name":"com.android.library","old_version":"9.3.0","new_version":"9.4.0"},{"name":"com.android.test","old_version":"9.3.0","new_version":"9.4.0"},{"name":"org.jetbrains.kotlin.plugin.compose","old_version":"2.4.0","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"},{"name":"org.jetbrains.kotlin.plugin.serialization","old_version":"2.4.0","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"},{"name":"com.google.devtools.ksp","old_version":"2.3.10","new_version":"2.3.11","repository_url":"https://github.com/google/ksp"}],"path":null,"ecosystem":"maven"},"body":"Bumps the android-deps group with 21 updates in the /apps/android directory:\n\n| Package | From | To |\n| --- | --- | --- |\n| [gradle-wrapper](https://github.com/gradle/gradle) | `9.6.1` | `9.7.1` |\n| androidx.appcompat:appcompat | `1.7.1` | `1.8.0` |\n| [org.bouncycastle:bcprov-jdk18on](https://github.com/bcgit/bc-java) | `1.85` | `1.85.2` |\n| [org.commonmark:commonmark](https://github.com/commonmark/commonmark-java) | `0.29.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-autolink](https://github.com/commonmark/commonmark-java) | `0.29.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-strikethrough](https://github.com/commonmark/commonmark-java) | `0.29.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-tables](https://github.com/commonmark/commonmark-java) | `0.29.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-task-list-items](https://github.com/commonmark/commonmark-java) | `0.29.0` | `0.30.0` |\n| [io.coil-kt.coil3:coil-compose](https://github.com/coil-kt/coil) | `3.5.0` | `3.6.2` |\n| [io.coil-kt.coil3:coil-svg](https://github.com/coil-kt/coil) | `3.5.0` | `3.6.2` |\n| [org.junit.vintage:junit-vintage-engine](https://github.com/junit-team/junit-framework) | `6.1.2` | `6.1.3` |\n| [io.kotest:kotest-assertions-core-jvm](https://github.com/kotest/kotest) | `6.2.2` | `6.2.4` |\n| [io.kotest:kotest-runner-junit5-jvm](https://github.com/kotest/kotest) | `6.2.2` | `6.2.4` |\n| [com.squareup.okhttp3:mockwebserver](https://github.com/lysine-dev/okhttp) | `5.4.0` | `5.5.0` |\n| [com.squareup.okhttp3:okhttp](https://github.com/lysine-dev/okhttp) | `5.4.0` | `5.5.0` |\n| com.android.application | `9.3.0` | `9.4.0` |\n| com.android.library | `9.3.0` | `9.4.0` |\n| com.android.test | `9.3.0` | `9.4.0` |\n| [org.jetbrains.kotlin.plugin.compose](https://github.com/JetBrains/kotlin) | `2.4.0` | `2.4.20` |\n| [org.jetbrains.kotlin.plugin.serialization](https://github.com/JetBrains/kotlin) | `2.4.0` | `2.4.20` |\n| [com.google.devtools.ksp](https://github.com/google/ksp) | `2.3.10` | `2.3.11` |\n\n\nUpdates `gradle-wrapper` from 9.6.1 to 9.7.1\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/gradle/gradle/releases\"\u003egradle-wrapper's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e9.7.1\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.1.\u003c/p\u003e\n\u003cp\u003eThis is a patch release for 9.7.0. We recommend using 9.7.1 instead of 9.7.0.\u003c/p\u003e\n\u003cp\u003eHere are the highlights of 9.7.0 release:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIsolated Projects graduates to incubating\u003c/li\u003e\n\u003cli\u003eBroader Configuration Cache compatibility\u003c/li\u003e\n\u003cli\u003eResilient Sync helps you fix broken builds\u003c/li\u003e\n\u003cli\u003eMore source locations in problem reports\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003ca href=\"https://docs.gradle.org/9.7.1/release-notes.html\"\u003eRead the Release Notes\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eWe would like to thank the following community members for their contributions to this release of Gradle:\n\u003ca href=\"https://github.com/aSemy\"\u003eAdam\u003c/a\u003e,\n\u003ca href=\"https://github.com/Gautam-aman\"\u003eAman Gautam\u003c/a\u003e,\n\u003ca href=\"https://github.com/YukiCodepth\"\u003eAman Kumar\u003c/a\u003e,\n\u003ca href=\"https://github.com/adubrouski\"\u003eAnton Dubrouski\u003c/a\u003e,\n\u003ca href=\"https://github.com/liutikas\"\u003eAurimas\u003c/a\u003e,\n\u003ca href=\"https://github.com/gbhavya07\"\u003egbhavya07\u003c/a\u003e,\n\u003ca href=\"https://github.com/joshfriend\"\u003eJosh Friend\u003c/a\u003e,\n\u003ca href=\"https://github.com/nicklauslittle-gov\"\u003enicklauslittle-gov\u003c/a\u003e,\n\u003ca href=\"https://github.com/psoni674\"\u003ePragati\u003c/a\u003e,\n\u003ca href=\"https://github.com/Project516\"\u003eproject516\u003c/a\u003e,\n\u003ca href=\"https://github.com/Uomocapra\"\u003eQin Mi\u003c/a\u003e,\n\u003ca href=\"https://github.com/rkdfx\"\u003eRavi\u003c/a\u003e,\n\u003ca href=\"https://github.com/sk-reddy17\"\u003esk-reddy17\u003c/a\u003e,\n\u003ca href=\"https://github.com/Suvrat1629\"\u003eSuvrat Acharya\u003c/a\u003e,\n\u003ca href=\"https://github.com/ShreckYe\"\u003eYongshun Ye\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eUpgrade instructions\u003c/h2\u003e\n\u003cp\u003eSwitch your build to use Gradle 9.7.1 by updating your wrapper:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e./gradlew :wrapper --gradle-version=9.7.1 \u0026amp;\u0026amp; ./gradlew :wrapper\r\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eSee the Gradle \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/upgrading_version_9.html\"\u003e9.x upgrade guide\u003c/a\u003e to learn about deprecations, breaking changes and other considerations when upgrading.\u003c/p\u003e\n\u003cp\u003eFor Java, Groovy, Kotlin and Android compatibility, see the \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/compatibility.html\"\u003efull compatibility notes\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eReporting problems\u003c/h2\u003e\n\u003cp\u003eIf you find a problem with this release, please file a bug on \u003ca href=\"https://github.com/gradle/gradle/issues\"\u003eGitHub Issues\u003c/a\u003e adhering to our issue guidelines.\nIf you're not sure you're encountering a bug, please use the \u003ca href=\"https://discuss.gradle.org/c/help-discuss\"\u003eforum\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eWe hope you will build happiness with Gradle, and we look forward to your feedback via \u003ca href=\"https://twitter.com/gradle\"\u003eTwitter\u003c/a\u003e or on \u003ca href=\"https://github.com/gradle\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003e9.7.0\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.0.\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/92f0512e7f06d84621afba191f75e265363890cf\"\u003e\u003ccode\u003e92f0512\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38892\"\u003e#38892\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/820ee75a99a179bbffa41bcedc6477b685fabb9f\"\u003e\u003ccode\u003e820ee75\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/82c23f9bd2a89b4cc644e1f90a28a8668feb3dee\"\u003e\u003ccode\u003e82c23f9\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering problem in KTS (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38878\"\u003e#38878\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/ef11a7268fe8cc8d6ab849ec911aa11220180553\"\u003e\u003ccode\u003eef11a72\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering issue\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/bb0d8a974a71b1003efea41e4046e98855cd5ff8\"\u003e\u003ccode\u003ebb0d8a9\u003c/code\u003e\u003c/a\u003e Make relevant tests polyglot (run for multiple DSLs)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/336e129d7f95c03486acafc97abf59734acfed48\"\u003e\u003ccode\u003e336e129\u003c/code\u003e\u003c/a\u003e Update signing configuration (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38874\"\u003e#38874\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/4bdf0da2dad9884d089a6062a45ea7183e7d735d\"\u003e\u003ccode\u003e4bdf0da\u003c/code\u003e\u003c/a\u003e Update signing configuration\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/cd9b92c1b82856248cf1dc58b50378238bec7b52\"\u003e\u003ccode\u003ecd9b92c\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38839\"\u003e#38839\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/5f4e381964897ad8d6b99e5a7c77f26dba3259fb\"\u003e\u003ccode\u003e5f4e381\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/1e08ab551367aeb5fb48b26e72807e1d2b27c939\"\u003e\u003ccode\u003e1e08ab5\u003c/code\u003e\u003c/a\u003e Keep type-use annotations in extracted ABI classes (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38810\"\u003e#38810\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/gradle/gradle/compare/v9.6.1...v9.7.1\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `androidx.appcompat:appcompat` from 1.7.1 to 1.8.0\n\nUpdates `org.bouncycastle:bcprov-jdk18on` from 1.85 to 1.85.2\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.md\"\u003eorg.bouncycastle:bcprov-jdk18on's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch1\u003eBouncy Castle Crypto Package - Release Notes\u003c/h1\u003e\n\u003ch2\u003e1.0 Introduction\u003c/h2\u003e\n\u003cp\u003eThe Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. The package is organised so that it contains a light-weight API suitable for use in any environment (including the J2ME) with the additional infrastructure to conform the algorithms to the JCE framework.\u003c/p\u003e\n\u003ch2\u003e2.0 Release History\u003c/h2\u003e\n\u003cp\u003e\u003c!-- raw HTML omitted --\u003e\u003c!-- raw HTML omitted --\u003e\u003c/p\u003e\n\u003ch3\u003e2.1.1 Version\u003c/h3\u003e\n\u003cp\u003eRelease: 1.86\u003cbr /\u003e\nDate: 2026, TBD\u003c/p\u003e\n\u003ch3\u003e2.1.2 Defects Fixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) let a subkey inherit the primary key's Key Flags when its own Subkey Binding signature carried no Key Flags subpacket, which made the two capability decisions taken for one subkey disagree. OpenPGPCertificate.OpenPGPComponentKey.isSigningKey() reads the effective flags, which fell back to the primary key's direct-key or primary user ID self-signature, so a subkey bound with no flags of its own counted as signing-capable; verifyEmbeddedPrimaryKeyBinding reads the binding signature's own flags, found no signing capability there, and so skipped the embedded Primary Key Binding (cross-certification) signature that RFC 9580 sec. 5.2.1.8 and sec. 10.1.3 require of a subkey that can issue signatures. A data signature made by such a subkey was therefore attributed to the certificate and reported valid by OpenPGPSignature.OpenPGPDocumentSignature.isValid() with the cross-certification requirement never applied, where GnuPG refuses the same certificate and message as not cross-certified. An attacker holding a third party's public signing subkey - which is public material - could bind it to their own primary key with a Subkey Binding signature they are able to make, carrying no Key Flags and no embedded Primary Key Binding signature, which they cannot make without the subkey's private key, and have that party's genuine signatures verify as valid under the attacker's own identity: misattribution of a real signature rather than a forgery of a new one, since the signature still has to be one the subkey actually made. Key Flags are a statement about the key the carrying signature refers to (RFC 9580 sec. 5.2.3.29), so a subkey no longer inherits them from the certificate-wide signatures of the primary key: a Subkey Binding signature that omits the subpacket now leaves the subkey with no capabilities rather than the primary's, which makes the flags the cross-certification check consults the same flags every other decision consults. Preferences and the other subpackets a direct-key signature carries are inherited as before, and the primary key itself - whose flags legitimately come from its direct-key or user ID self-signature - is unaffected. The low-level PGPSignature / PGPPublicKeyRing API performs no binding checks by design and is unchanged.\u003c/li\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) used a version 6 key that carried no valid Direct Key signature, falling back to the primary user ID binding as it correctly does for a version 4 key. RFC 9580 sec. 5.2.3.10 requires the opposite: \u0026quot;An implementation MUST ensure that a valid Direct Key signature is present before using a version 6 key. This prevents certain attacks where an adversary strips a self-signature specifying a Key Expiration Time or certain preferences.\u0026quot; The certificate grammar says the same structurally, the Direct Key signature being mandatory in the version 6 structure of sec. 10.1.1 and optional in the version 4 one of sec. 10.1.3. Because a version 6 certificate carries its key expiration, features and algorithm preferences on the Direct Key signature - the convention the RFC recommends and the one OpenPGPKeyGenerator follows, its user ID certification carrying no expiration at all - removing that single signature packet from a published certificate silently dropped the expiration along with the preferences and features: OpenPGPCertificate.getSignatureChainFor fell back to the user ID binding, the primary key was still reported bound, and getEncryptionKeys() and getSigningKeys() went on returning the subkeys of a key whose owner had set it to expire. The primary key fingerprint is unchanged by the removal, so a relying party pinning the key by fingerprint still treats it as the same key, and no private key or hash collision is involved; the natural moment for the strip is the key refresh that RFC 9580 names as the reason to refetch a key at all - to learn about changes in expiration, features, preferences and revocation - which is exactly the update it defeats. This is a downgrade rather than a forgery, nothing being attributed to a key that did not authorise it, and the concerning direction is encryption, to a key meant to have been retired. OpenPGPCertificate.isBoundBy now requires a valid Direct Key self-signature on a version 6 primary key before any component of the certificate - the primary key, its subkeys or its identities - is treated as bound, so a version 6 certificate stripped of it offers no keys at all rather than an unexpiring set. Version 4 certificates are unaffected: there the key expiration legitimately lives on the user ID self-signature and the fallback is correct, so it stays. The revocation-only version 6 certificate of sec. 10.1.2, which legitimately carries no Direct Key signature, is unaffected as well - its key was already refused as revoked, and reading the revocation does not go through the binding check.\u003c/li\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) ignored the OpenPGPPolicy a caller had configured when it verified the signatures on an inline message. OpenPGPMessageInputStream took the policy it sanitizes each document signature against from the implementation's own default rather than from the processor the signature is being verified by, so a policy supplied through the documented OpenPGPApi(implementation, policy) / OpenPGPMessageProcessor(implementation, policy) constructor - which is how OpenPGPApi.decryptAndOrVerifyMessage() plumbs the configured policy through - had no bearing on whether a signature was accepted, although the same processor already applied it to the decompressed-size bound. A caller who hardened the policy beyond the default therefore had a signature that policy rejects handed back from getResult().getSignatures() with isTestedCorrect() true, while OpenPGPSignature.isValid(policy) on that same signature reported the rejection. Both verify paths, the one-pass and the prefixed-signature one, now read the configured policy; the detached-signature processor already did.\u003c/li\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) went on offering the subkeys of a certificate whose primary key had expired. OpenPGPCertificate's binding check evaluated only a subkey's own Subkey Binding signature, so a primary key whose Key Expiration Time (RFC 9580 sec. 5.2.3.13) had passed still handed out a longer-lived encryption or signing subkey from getEncryptionKeys() / getSigningKeys(), leaving the certificate contradicting itself - getExpirationTime() in the past and getPrimaryKey().isBoundAt() false, while isBoundAt() on the subkey answered true. An expired primary key can no longer certify, so the subkeys it bound are not usable with it either, which is how GnuPG and Sequoia both treat such a certificate; primary key revocation already propagated, since a revocation appears in the subkey's signature chain, but expiration is not carried there. Relatedly, a subkey no longer inherits the primary key's validity period at all - sec. 5.2.3.13 counts that period from the creation time of the key the carrying self-signature is made on, so re-basing the primary key's period on a subkey created later than it gave that subkey an expiration date later than the primary key's own.\u003c/li\u003e\n\u003cli\u003eOpenPGPSignature.OpenPGPDocumentSignature.isValidAt(Date) in the high-level OpenPGP API reported a data signature as valid at an evaluation time past the signature's own Signature Expiration Time (RFC 9580 sec. 5.2.3.18, hashed subpacket type 3). The method checked that the signature was correct and that the issuing key was bound and signing-capable at that date, but never consulted the signature's own expiration, so it disagreed with isEffectiveAt(Date) on the same object and with its own javadoc, which names being effective as one of the three criteria of a valid signature. Signature expiration is a separate axis from the issuing key's Key Expiration Time that the binding checks already cover, and GnuPG, GPGME, git and Sequoia all keep the two apart and treat a signature past its expiration as not good. isValid() and isValid(policy) evaluate at the signature's creation time, where a signature is always inside its own window, and are unchanged.\u003c/li\u003e\n\u003cli\u003eThe lightweight LMSSigner and HSSSigner refused a key wrapped in ParametersWithRandom, which is how BcContentSignerBuilder passes a key whenever setSecureRandom() has been called - so BcHssLmsContentSignerBuilder built a working signer until a random was set and then failed with \u0026quot;Incorrect Key Parameters\u0026quot;, and the two signers themselves raised ClassCastException on the same input. All three now unwrap it, as the promoted ML-DSA and SLH-DSA signers already did. The random is accepted and not used: LMS derives its message randomiser C from the key's seed and the one-time index, so it is deterministic and cannot repeat while q does not. Note SP 800-208 sec. 6.1 asks for C to come from an approved random bit generator, which this implementation does not do; that is unchanged here, and a supplied random is now ignored rather than refused.\u003c/li\u003e\n\u003cli\u003eLMS signature verification did not apply two of the checks RFC 8554 sec. 5.4.2 requires before a signature is processed. Step 2g refuses a signature whose LMS typecode is not the one from the public key, and without it the path computation took its height and tree digest from the parameter set the signature named rather than the key's, so a signature claiming a height-25 parameter set drove a 25-level computation against a height-5 key. Step 2i refuses a leaf number q outside the tree, and without it an out-of-range q flowed into the node arithmetic and was left for the candidate-root comparison to catch. Neither was a forgery - the domain separation between D_LEAF and D_INTR and the final comparison saw to that - but both are attacker-chosen work the specification says to refuse up front. Both are now checked, and a signature failing either is still reported as not verifying rather than thrown out of Signature.verify(). The catch around the signature decode in LMSSigner and HSSSigner has also been narrowed to the decode itself, as the corresponding SPI was corrected to do for github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2408\"\u003e#2408\u003c/a\u003e: past the parse the engine reports an inconsistent signature by returning false rather than by throwing, so the wider catch caught nothing while standing ready to turn a future internal error into a quiet false.\u003c/li\u003e\n\u003cli\u003eThe LMS and HSS key parameter classes now apply at construction the checks their decoders apply, so a key built directly cannot be one the decoder would refuse. LMSPrivateKeyParameters accepted an identifier of any length although the decoder reads exactly 16 bytes - such a key encoded but could not be read back - and left q, maxQ and the seed length unchecked; the seed is now required to be at least m bytes at decode as well, where a one-byte seed had been decoding silently and then deriving every one-time key from it. HSSPrivateKeyParameters checked neither its level count nor that it had been given a component key per level and a chaining signature per level below the root, and then indexed both lists, so a mismatch surfaced as IndexOutOfBoundsException - or, where a level happened to match, as a null chaining signature that only failed at signing time; the level is now checked after the reset that fills it in, since a null is legitimate on the way in. LMSPrivateKeyParameters.getInstance(byte[], byte[]) adopted the public key supplied beside the private one without comparing them, so a mismatched public key was simply reported by getPublicKey(); it now cross-checks the identifier, both parameter sets and, where the tree cache already holds it, the root, as the HSS entry point does. The decoders also now report a bad version or seed length as IOException rather than IllegalStateException, so a caller can catch one type for a malformed key, and the package-private LM-OTS public key decoder no longer declares throws Exception or dereferences an unrecognised typecode. The deprecated org.bouncycastle.pqc.crypto.lms copies carry the decoder corrections.\u003c/li\u003e\n\u003cli\u003eIn the LMS JCE layer, LMSKeyGenParameterSpec.fromNames knew all twenty LMS parameter-set names but only four of the sixteen LM-OTS ones, so none of the SP 800-208 n24 or SHAKE sets could be named; all sixteen are now present. KeyPairGenerator.initialize(int, SecureRandom) reports InvalidParameterException, which is what the JCA specifies and which extends the IllegalArgumentException it raised before, so existing catches still match. BCLMSPrivateKey.getIndex now takes the exhaustion check and the index read under the key's own monitor rather than as two separate calls, and two unused fields have gone from LMSSignatureSpi. Note that the LMS Signature claims its one-time key at the first update() rather than at sign(), so a Signature that is initialised and updated and then abandoned spends an index without producing a signature - the safe direction for a one-time scheme, and now documented on the SPI.\u003c/li\u003e\n\u003cli\u003eEvery other key pair generator that refuses a key size did the same thing the LMS one did above. KeyPairGenerator.initialize(int, SecureRandom) is documented to raise InvalidParameterException when the key size is not one the generator supports, and thirty of them raised a bare IllegalArgumentException instead, so a caller following the JCA and catching the documented type saw an exception escaping rather than a refusal. The ML-DSA, ML-KEM, SLH-DSA, Classic McEliece, FrodoKEM, NTRU and composite signature and KEM generators in the BC provider, and every generator in BCPQC, now raise InvalidParameterException - NewHope included, where the value is a key size it will not take rather than a mode of initialisation it does not offer. InvalidParameterException extends IllegalArgumentException, so callers written against the old behaviour go on catching it unchanged. The two RSA generators are corrected as well, and differently: theirs is a key size below a floor rather than a mode of initialisation they do not offer, and the refusal is raised by the lightweight RSAKeyGenerationParameters, which cannot name a java.security exception at all, so the RSA KeyPairGeneratorSpi now translates it - keeping the message verbatim and the original exception as the cause, through a new SecurityExceptions.invalidParameterException factory, since InvalidParameterException has no constructor that takes one. Of the 304 KeyPairGenerator services the two providers register, 299 now refuse a nonsense key size the way the JCA defines it and five accept it as a strength they can work with, with none left raising a bare IllegalArgumentException; that is asserted as a sweep over both providers rather than per algorithm, so a generator added later is covered without the test being touched. The jdk1.3 provider overlays of the four generators that have one carry the same change, and the jdk1.3 SecurityExceptions overlay gains the new factory along with the invalidAlgorithmParameterException one it had been missing.\u003c/li\u003e\n\u003cli\u003eKeyPairGenerator.initialize(AlgorithmParameterSpec, SecureRandom) had the same shape of problem as the int overload above, and only 44 of the 304 services the two providers register reported an unusable spec as the InvalidAlgorithmParameterException that method declares. The twenty-three PQC generators that resolve a parameter set by name - cmce, frodokem, mldsa, mlkem, slhdsa, aimer, bike, faest, falcon, haetae, hqc, mayo, mqom, ntru, ntruplus, both ntruprime variants, qruov, saber, sdith, smaugt, snova and sqisign, 230 services between them - case-folded the name they got back from the spec without checking it, so a spec with no getName() method, and a null spec, produced a NullPointerException from inside the fold; their own \u0026quot;is this name one I know\u0026quot; branch, which does report the declared exception, was unreachable. The two composite generators, whose parameter set is fixed by the algorithm name so that null is the only spec they accept, refused every other one with IllegalArgumentException. RSA answered correctly for a spec of the wrong type but not for one of the right type carrying values its lightweight parameters will not take - an even public exponent, or a key size below the floor - which is now translated the same way the int overload's is. All 304 services now report the declared exception, with the composites still taking the null spec that is right for them; note that InvalidAlgorithmParameterException is a checked exception and not an IllegalArgumentException, so a caller that was catching what these threw before has to catch the declared type instead.\u003c/li\u003e\n\u003cli\u003eAn HSS private key claimed the two records of its position under two different monitors. The top-level index and the bottom component key's one-time index q are independent records of the same position - the decoder requires them to agree, see the entry below - but generateLMSContext incremented the index under the HSS key's own monitor, released it, and only then claimed q under the component key's. A getEncoded() issued in between saw the index advanced and q not, and produced an encoding this implementation's own decoder rejects; and two threads meeting at a bottom-tree boundary could both pass the exhaustion test, take consecutive top-level indices and claim the same q, after which one of them was refused with \u0026quot;ots private key exhausted\u0026quot; by a key still reporting usages remaining, a top-level index had been spent with no signature made, and the two records stayed one apart for the rest of the key's life in that process - so it could no longer be encoded, cloned or sharded, and getIndex() and getUsagesRemaining() misreported by one. No one-time key was reused: the component key's claim is itself atomic, and the divergence runs index ahead of leaves, so the effect was on the key's usability rather than on the signatures it had made. Both records are now claimed under the one monitor, and the component key is claimed before the index is incremented so that an exhausted one leaves both untouched. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the same correction.\u003c/li\u003e\n\u003cli\u003eTimeStampToken parsed the attacker-controlled TSTInfo content of a time-stamp token (org.bouncycastle.tsp.TimeStampToken, reached from TimeStampResponse(byte[]) and (InputStream)) inside a try that caught only CMSException, so a well-formed RFC 3161 TimeStampResp whose embedded token carried a malformed TSTInfo - a SEQUENCE with fewer elements than the five mandatory fields, a non-SEQUENCE, truncated DER, or an unknown context tag - let an IllegalArgumentException or a NoSuchElementException escape the constructor's declared throws TSPException, IOException contract. A token signed by no signers or by more than one raised a bare IllegalArgumentException from the same constructor, before that try, for the same reason. Both are now reported as TSPException, matching the package-private TimeStampResponse(DLSequence) constructor and the existing getSignedAttributes guard in the same method; the signer-count refusal is a TSPValidationException, as the neighbouring check on the content type already was. Related, and the cause of the NoSuchElementException: asn1.tsp.TSTInfo read its five mandatory fields off the sequence with no bound on how many elements were actually there, so a short SEQUENCE left the enumeration to run out rather than being refused, and an oversize one was accepted with its extra elements absorbed into the optional slots. Decode now requires the five to ten elements RFC 3161 sec. 2.4.2 gives the type, which is what the sibling Accuracy and ArchiveTimeStamp decoders already did, so the failure is the IllegalArgumentException that getInstance is expected to raise (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2415\"\u003e#2415\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eNeither the HSS nor the XMSS^MT private key decoder checked its declared index against the traversal state stored beside it, although the two are independent records of the same position in the key and so can be compared. For HSS the records are the top-level index and the component keys' one-time indices q; for XMSS^MT they are the global index and the per-layer BDS states. A stored key whose index had been rolled back while its state stayed advanced - a partial write, a restore from backup, a buggy storage layer - was therefore accepted, and it then signed a second message under a one-time key the key had already used, producing a signature that verified, so nothing anywhere surfaced the reuse. RFC 8554 sec. 1 and RFC 8391 sec. 1.1 both require each one-time key to be used exactly once, and this is the failure those requirements exist to prevent; the single-tree XMSS decoder has tied its BDS state to its index since that state was first validated, and this brings the two multi-tree schemes into line. HSS decode now requires the declared index to equal the position the component q values imply - a level above the last contributes (q - 1) leaves of the levels beneath it, since its q has already advanced past the subtree it signed - and XMSS^MT decode now requires each present layer's BDS index to equal the leaf index that layer derives from the global index, allowing the one position where a layer has moved into a new subtree and its state legitimately still carries the previous subtree's final index. A layer with no state yet is unaffected, since those are built lazily at signing time. Related, and the same shape of omission: an XMSS or XMSS^MT private key encoding carries the tree root twice - the key's own root field and the root node of the BDS state stored beside it, which for XMSS^MT is the top layer's - and the two were never compared either. A corrupted root was accepted and then poisoned every signature the key made, because the root is hashed into the message digest: the signature did not verify and nothing indicated why. Decode now requires the two copies to agree. The BDS node values themselves are not checkable the way the LMS tree cache above is - a BDS authentication path, stack, retain or keep node does not have its children stored alongside it, so recomputing one means building a subtree, which is the work the state exists to avoid. Both checks are integer comparisons over the levels of the key, too small to measure against the surrounding decode, and both were verified not to reject any legitimate key by walking every index a key can reach: the full key space of the two-level HSS and the h=4/d=2, h=6/d=2, h=6/d=3, h=9/d=3 and h=8/d=4 XMSS^MT parameter sets, plus a three-level HSS key across a subtree boundary and an HSS shard. Since those node values cannot be recomputed, the encoded state now carries a checksum over itself instead, with the owning key's public seed hashed in front of it. Any corruption of the stored state is refused at decode rather than being loaded and then producing signatures that silently do not verify, and because the public seed is bound in, a state transplanted between two keys of the same parameter set is refused too, even though it is internally consistent and arrives with its own matching root. The public seed is bound rather than the secret seed or the PRF key deliberately: the state's own root and index are inside the encoding and so are already covered, hashing secret material would make the stored checksum a commitment to it for no gain in detection, and the PRF key does not influence the state at all. \u003cstrong\u003eThis is an error-detecting code and not integrity protection\u003c/strong\u003e - anyone able to rewrite the stored key recomputes it, so it establishes that the state is unchanged since it was written, never that it was correct when written, and the allocation bounds on the encoding remain the guard against a crafted one. It costs one SHA-256 over the state, measured at 5 to 8 microseconds each way for the h=10 and h=16 parameter sets, and 32 bytes of encoding. The state encoding was added earlier in this same cycle and has not been released, so the checksum is simply part of it rather than a new version: a state written by a 1.86 beta is rejected, which is recovered from by re-exporting the key. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the HSS check as well (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2414\"\u003e#2414\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eIn the XMSS and XMSS^MT JCE layer, KeyPairGenerator.initialize(int, SecureRandom) reports InvalidParameterException, which is what the JCA specifies and which extends the IllegalArgumentException it raised before, so existing catches still match. This is the XMSS counterpart of the same correction made to LMSKeyPairGeneratorSpi.\u003c/li\u003e\n\u003cli\u003eBCXMSSPrivateKey.getIndex and BCXMSSMTPrivateKey.getIndex took the exhaustion check and the index read as two separate calls on the key parameters. Each is atomic on its own, but the pair is not: a signature taken by another thread between them spends the last usage, so the check passes and the read that follows returns maxIndex + 1 - the one index past the end of the key, which is what the check exists to refuse, handed back as though it were the next one-time key to be used. Both reads are now taken under the key parameters' own monitor, the monitor their mutators hold, as BCLMSPrivateKey.getIndex was corrected to do. No one-time key is reused by this: the effect is on what the key reports about itself, not on the signatures it makes.\u003c/li\u003e\n\u003cli\u003eThe S/MIME example smoke test in the misc module (org.bouncycastle.mail.smime.examples.test.AllTests) drove SendSignedAndEncryptedMail against smtp.gmail.com, and that example finishes with Transport.send() under JavaMail's default settings, which have no connect timeout. Where outbound port 25 is refused the failure was swallowed and the test passed; where it is silently dropped, as on many home networks, the connect blocked and ./gradlew build hung in :misc:test indefinitely with \u0026quot;0 tests completed\u0026quot;. The test now delivers to an SMTP stub on a loopback port, with connect / read / write timeouts as a backstop, and asserts the message arrived (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2407\"\u003e#2407\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation took the traditional component public key bytes it feeds the KEM combiner from the recipient key's own encoding, while decapsulation recomputes the point from the private key and so always produced an uncompressed one. Section 4 of draft-ietf-lamps-pq-composite-kem requires an EC component to be carried as an uncompressed point, but a component key that encodes itself compressed - a BC EC key whose point format has been set through org.bouncycastle.jce.interfaces.ECPointEncoder, or a key from a provider that preserves a compressed encoding - was passed through as it came. Both sides then combined a different tradPK and derived different shared secrets, with no error reported on either: encapsulation and decapsulation both succeeded and the recipient simply could not decrypt. The EC component is now normalised to an uncompressed point wherever the engine serialises one, which covers the ephemeral key that forms the ciphertext as well. X25519 and X448 components have a single encoding and were unaffected, as were EC keys left in their default (uncompressed) format, whose shared secrets are unchanged. CompositePublicKey.getEncoded() took its component bytes the same way, so such a key also encoded to a composite key other implementations reject and whose bytes changed across an encode / decode / encode round trip - 1238 bytes rather than 1270 for MLKEM768-ECDH-P256, and for the composite ML-DSA keys sharing that method, 2006 rather than 2038 for MLDSA65-ECDSA-P256. It now normalises the component the same way. This is a write-side change only: a composite key carrying a compressed EC component is still decoded, since the component key factories accept either form, and continues to verify signatures as before - it simply re-encodes in the normalised form. The shared normalisation is org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil.getUncompressedSubjectPublicKeyBytes.\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation threw a NullPointerException, wrapped in an IllegalStateException out of KeyGenerator.generateKey(), when the SecureRandom it was given was null - which javax.crypto.KEM.newEncapsulator() documents as a request for the provider's default, and which KeyGenerator.init(spec, null) passes straight through. The three RSA-OAEP composites draw the traditional shared secret from that random directly, so they were the ones affected; the ECDH and X25519 / X448 composites escaped only because their component KeyPairGenerators default a random of their own. CompositeMLKEMEngine now defaults one through CryptoServicesRegistrar.getSecureRandom() on first use, as the composite KEM Cipher's wrap path already did, and as the KEM generators corrected earlier in this cycle now do. Related, the engine now also clears the ML-KEM component's shared secret alongside the traditional one on both the encapsulate and decapsulate paths - the copy handed back by getEncoded() was left in the heap - as section 3.5 of draft-ietf-lamps-pq-composite-kem requires.\u003c/li\u003e\n\u003cli\u003eCompositePublicKey.getAlgorithm() and CompositePrivateKey.getAlgorithm() returned null for all twelve Composite ML-KEM (draft-ietf-lamps-pq-composite-kem) parameter sets. Both classes resolved the name through the composite signature index only, which holds the composite ML-DSA OIDs, so a composite KEM key pair - generated, parsed from a certificate, or read from PKCS#8 - reported no algorithm at all, and the standard JCA idiom of reconstructing a key with KeyFactory.getInstance(key.getAlgorithm()) raised a NullPointerException. The lookup now falls back to the composite KEM index, so the name returned is the one the provider registers the algorithm under (e.g. MLKEM768-X25519-SHA3-256), matching the composite ML-DSA behaviour. The same single-index assumption made the CompositePublicKey(SubjectPublicKeyInfo) and CompositePrivateKey(PrivateKeyInfo) constructors reject a composite KEM key with \u0026quot;unable to create CompositePublicKey from SubjectPublicKeyInfo\u0026quot;; they now dispatch to the composite KEM key factory for those OIDs. Keys obtained through KeyFactory or through BouncyCastleProvider.getPublicKey / getPrivateKey were unaffected and are unchanged (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2404\"\u003e#2404\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe org.bouncycastle.jcajce.spec.KEMKDFSpec constructor stored a null otherInfo as given, so getOtherInfo() returned null, and three of the KDF branches KdfUtil.makeKeyBytes dispatches to - KMAC-128, KMAC-256 and SHAKE-256 - read the otherInfo length without a guard and threw NullPointerException out of the KEM operation, where the KDF2, KDF3 and HKDF branches tolerate a null through KDFParameters / HKDFParameters. The Builder of every spec in the package already mapped null to empty, so no provider path reached it, but the constructor is protected on a public class and KdfUtil is documented for callers building their own KEM integration; the deprecated KEMParameterSpec passes a null itself and escaped only because it also pins the KDF to null. The constructor now stores empty for a null, so getOtherInfo() never returns null, and a null and an explicitly empty otherInfo derive the same key.\u003c/li\u003e\n\u003cli\u003eQR-UOV signature verification accepted a signature encoding that was not canonical, so the encoding of a signature was not unique even after the trailing-byte fix of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e. Each F_q element of the signature is stored in ceil(log2 q) bits, one more bit pattern than the field has elements: q itself is representable and is arithmetically congruent to zero, so an element written as q verified exactly as the same element written as zero would, and the bits padding the last element out to the byte boundary were never read at all. Every zero element of a signature therefore carried a second encoding, and for the q = 7 parameter sets roughly one element in seven is zero - a single qruov_5_q7_L10 signature measured 256 spare bits, so on the order of 2^256 distinct byte strings verified for the one message and key. Verification now rejects any element outside [0, q) and any set padding bit; a signature produced by this or by the reference implementation is unaffected, as the KAT vectors of every parameter set confirm. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSNOVA signature verification ignored four bits inside the signature for any parameter set whose solution is an odd number of GF(16) nibbles - the SNOVA_24_5_5, SNOVA_25_8_3, SNOVA_29_6_5 and SNOVA_66_15_3 families, sixteen of the forty-four parameter sets. The last byte of the encoded solution carries a single nibble and the signer leaves the top four bits zero, but the decoder did not read them, so sixteen distinct byte strings verified for one signature. This is the same non-unique encoding github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e closed for bytes following the signature, applied inside it; the verifier now requires those bits to be zero. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSnovaPrivateKeyParameters did not validate the length of the private key encoding handed to it - the only one of the five schemes of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e that did not - and SnovaParameters.getPrivateKeyLength() reported the expanded (\u0026quot;ESK\u0026quot;) length even for a parameter set whose private key is the seed pair. A private key encoding reaches this constructor straight from a PKCS#8 blob, so a wrong length went undetected: a seed-form key with extra bytes appended was accepted and signed under a different derived key, and a short expanded-form key sized the signer's decode buffer negatively, throwing NegativeArraySizeException out of generateSignature() rather than being reported at construction. Related, the signing retry loop could not terminate: the vinegar values are derived from a single-byte counter, so only 256 distinct linear systems can be tried, and an expanded-form private key that is not a real central map is singular for all of them - generateSignature() then span forever rather than failing. The length is now checked at construction, getPrivateKeyLength() reports the length that parameter set's private key actually has, and the retry loop gives up after its 256 attempts as MAYO's does.\u003c/li\u003e\n\u003cli\u003eMayoSigner and MayoKeyPairGenerator did not clear several buffers holding secret key material that the MAYO reference implementation explicitly clears. Signing left the secret oil space O, the expanded L = (P1 + P1^t) * O + P2, and the M / VPV / Ox intermediates of the central map in place, having gone to the trouble of clearing eleven other buffers; key generation left the expanded seed, whose tail is the encoded oil space, and the P1 * O + P2 half of P; and the row-echelon step left the packed echelon form of the secret linear system and its pivot rows. Separately, if all 256 attempts at solving for the signature had given a rank-deficient system, signing emitted a signature built from the failed attempt's state instead of reporting the failure the reference returns, and AIMerSigner.generateSignature returned an empty array on failure, which a caller would hand on as though it were a signature. Both now throw.\u003c/li\u003e\n\u003cli\u003eFive PQC signature schemes - MAYO, SNOVA, QR-UOV, SQIsign and AIMer - returned the NIST crypto_sign \u0026quot;sm\u0026quot; signed-message envelope from generateSignature() rather than the signature. That envelope is an artefact of the reference KAT harness, which records the message alongside the signature so a vector file can be self-contained; it is not part of any of the five specifications, and no other BC signer emits it (Falcon's KAT test rebuilds the equivalent envelope in the test, which is where it belongs). Two consequences followed, both reaching the JCA Signature services of every parameter set of the five schemes in BouncyCastlePQCProvider. First, since the message was appended to the signature, verification had to skip whatever followed the signature proper, and it did so by checking only that the buffer was long enough - so any number of trailing bytes could be added to a valid signature, or the appended message replaced with unrelated data, and it still verified. A signature encoding was therefore not unique: anyone holding one valid signature could produce unlimited distinct byte strings that all verified for the same message and key, which breaks any use that treats the signature bytes as an identifier, deduplicates on them, or records them as evidence. Second, the envelope propagated into everything built on the operator layer: because ContentSigner hands the signature straight into the structure being signed, every X.509 certificate, CRL, CMS SignedData and TLS CertificateVerify BC produced with one of these algorithms carried a verbatim copy of the signed data inside its own signature field - a self-signed MAYO-1 certificate came to 3567 bytes where the same certificate is now 2020 - which no other implementation can parse as a signature, and which in a detached CMS signature meant the \u0026quot;detached\u0026quot; signature carried the content. generateSignature() now returns the bare signature, and verifySignature() requires exactly the parameter set's signature length, so appended or truncated data is rejected rather than ignored. \u003cstrong\u003eThis is a behavioural change for signatures produced by an earlier release\u003c/strong\u003e - MAYO and SNOVA from 1.84, QR-UOV, SQIsign and AIMer from 1.85 - which are no longer accepted in the envelope form they were emitted in; the signature bytes themselves are unchanged, so a stored value can be recovered by taking the leading signature-length bytes, or for AIMer, whose envelope was message || signature rather than signature || message, the trailing ones. The KAT tests now rebuild the envelope before comparing against the vector files, which continue to record it. Note that AIMer's verification had already been made length-exact during this cycle (see the entry below relating to github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2401\"\u003e#2401\u003c/a\u003e), so of the five only its envelope remained (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe MLS implementation did not bind an X.509 credential to the LeafNode's signature_key. LeafNode.verify() checked a leaf's signature against the signature_key declared in the leaf itself, while the X.509 credential's certificate chain was stored but never parsed or checked, so the certificate's public key was never required to match signature_key (RFC 9420 sec. 5.3). A leaf could therefore carry one party's certificate while being signed by an unrelated key and still be accepted under that party's identity through KeyPackage.verify() and the Group leaf-validation path. LeafNode.verify() now requires the end-entity certificate's subject public key, in the cipher suite's signature encoding, to equal signature_key for an X.509 credential, and rejects the leaf otherwise - including an empty chain or a certificate whose key type does not match the cipher suite; certificate-chain and identity validation to a trust anchor remain the application's responsibility per RFC 9420 sec. 5.3.1. A public org.bouncycastle.mls.codec.Certificate(byte[]) constructor and a Credential.getCertificates() accessor are added so callers can build and inspect X.509 credentials. Basic credentials are unaffected.\u003c/li\u003e\n\u003cli\u003eThe SecureRandom supplied to org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder.setSecureRandom() did not drive the content IV / nonce for any algorithm other than RC2. EnvelopedDataHelper.generateParameters passed the caller's SecureRandom to the AlgorithmParameterGenerator only in the RC2_CBC branch; every other content-encryption algorithm - AES-CBC, AES-GCM, AES-CCM, Camellia, ARIA, SEED and the rest - reached pGen.generateParameters() on an uninitialised generator, so the IV / nonce was drawn from a default SecureRandom and setSecureRandom() was silently ignored (the builder's javadoc states that random is used for IV/nonce generation). The generator is now initialised with the supplied random on the general path as well, so a caller who provides a specific randomness source - for a controlled or FIPS-approved DRBG, say - has it honoured for the content IV / nonce. The session-key generation path was unaffected and already used the supplied random. Because the content IV / nonce now comes from the supplied SecureRandom, the org.bouncycastle.crypto.util JournalingSecureRandom / JournaledAlgorithm reproducible-encryption support records it in the transcript: a resumed session reproduces the IV / nonce by regenerating it from the replayed randomness - build the resuming encryptor from the content-algorithm OID - rather than by reusing the AlgorithmIdentifier captured from the first encryption, which no longer keeps the transcript aligned.\u003c/li\u003e\n\u003cli\u003eThe NTRU LPRime, NTRU+ and SMAUG-T KEM generators threw a NullPointerException when constructed with a null SecureRandom, where every other KEM generator - including NTRU LPRime's own SNTRU Prime counterpart in the same package - defaults one through CryptoServicesRegistrar.getSecureRandom(). This is reachable from the lightweight API directly, and from javax.crypto.KEM, whose newEncapsulator() documents a null random as a request for the provider's default.\u003c/li\u003e\n\u003cli\u003eFrodoKEMEngine kept a single SHAKE instance in a field, so an engine reached concurrently produced wrong results. It is reached that way through org.bouncycastle.crypto.kems.FrodoKEMExtractor, which holds one engine for its lifetime: two threads extracting through one extractor interleaved the digest's absorb and squeeze phases, yielding shared secrets that silently did not match the sender's, or an IllegalStateException of \u0026quot;attempt to absorb while squeezing\u0026quot; from inside extractSecret. The digest is now built per call, as CMCEEngine's already was, which makes an extractor safe to share. Encapsulation was unaffected, since FrodoKEMGenerator builds an engine per call. Results for any single-threaded use are unchanged - the reference KAT vectors are byte-identical.\u003c/li\u003e\n\u003cli\u003eThe BCJSSE provider carried the TLS 1.2 coupling between the supported_groups extension and ECDSA over into TLS 1.3: an ECDSA signature scheme was treated as usable - offered in the signature_algorithms and signature_algorithms_cert extensions, and eligible when selecting the local credentials - only while the corresponding curve was among the named groups enabled for key exchange, both per context (a group unavailable for key agreement disabled the scheme outright) and per connection (the curve had to be in the supported_groups list about to be sent). RFC 8446 sec. 4.2.7 scopes supported_groups to key exchange only, with signature algorithms negotiated independently (sec. 4.2.3), so this incorrect restriction in TLS 1.3 has been removed. Ed25519, Ed448 and the RSA schemes were unaffected (as well as typical deployments using a default configuration for named groups).\u003c/li\u003e\n\u003cli\u003eThe bcmail module descriptor did not declare its javax.mail/javax.activation dependences, so a modular (module-path) consumer of the jar hit IllegalAccessError/module-resolution failures when the S/MIME classes touched the mail API. The descriptor now requires them optionally (requires static) under all four module names those libraries are known by - the automatic names mail and activation carried by the javax.mail:mail / javax.activation:activation artifacts, and the explicit names java.mail and java.activation carried by the newer com.sun.mail / com.sun.activation ones - a hard requires on any one name would break users of the others (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2389\"\u003e#2389\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFour type-coercion helpers in the OER / IEEE 1609.2 (ITS) decoder tested the wrong type in the identity fast path that lets a getInstance() factory return an argument that is already of the target type. org.bouncycastle.oer.its.ieee1609dot2.basetypes.UINT32.getInstance and org.bouncycastle.oer.its.etsi102941.basetypes.Version.getInstance guarded on UINT8 - a sibling of UINT32 under UintBase, and unrelated to Version - so passing a UINT8 threw ClassCastException, while passing an actual UINT32 or Version missed the fast path and fell through to ASN1Integer.getInstance, which rejects them: neither factory accepted its own type. org.bouncycastle.oer.its.etsi103097.EtsiTs103097DataEncryptedUnicast.getInstance guarded on its sibling EtsiTs103097DataEncrypted and then cast to the unicast type, so an EtsiTs103097DataEncrypted threw ClassCastException. org.bouncycastle.oer.OEROptional.getObject(Class) called value.getClass().isInstance(type) with the arguments transposed, which is always false because the argument is a java.lang.Class, so the cast path was dead and every optional field was resolved reflectively, failing with IllegalStateException for a target type with no static getInstance. Each guard now names the type it returns, matching the sibling UINT8 / UINT16 / UINT64 and EtsiTs103097DataEncrypted factories (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2373\"\u003e#2373\u003c/a\u003e).\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003eSee full diff in \u003ca href=\"https://github.com/bcgit/bc-java/commits\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark` from 0.29.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/blockquote\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/blockquote\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/42b4fb7adfe288ef13e9e27ab20aff7e91b0ab9d\"\u003e\u003ccode\u003e42b4fb7\u003c/code\u003e\u003c/a\u003e Prepare CHANGELOG for version 0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/b76e09d7a8362abb5f04e1d6b91dbd6da279a6fc\"\u003e\u003ccode\u003eb76e09d\u003c/code\u003e\u003c/a\u003e Limit how deep inline nodes may nest by default (100)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/49f65cb5cbec93cff713179990307145198e7061\"\u003e\u003ccode\u003e49f65cb\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing deeply nested emphasis\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/610f84b83e68c381e8f784ae4d044c80e1948b67\"\u003e\u003ccode\u003e610f84b\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological autolink email addresses\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/9f1d73897a56cbd74c39347af351a473e70297e1\"\u003e\u003ccode\u003e9f1d738\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological HTML block attributes\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/e13297e849995fdd582a85841067bff1d9c35ee5\"\u003e\u003ccode\u003ee13297e\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing pathological backticks\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/89d1bd3fa1524e8217ed61db5e8116c82434470f\"\u003e\u003ccode\u003e89d1bd3\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing with lots of \u003ccode\u003e\u0026lt;\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/commonmark/commonmark-java/compare/commonmark-parent-0.29.0...commonmark-parent-0.30.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark-ext-autolink` from 0.29.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark-ext-autolink's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/blockquote\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003e...\n\n_Description has been truncated_","html_url":"https://github.com/essentiaMarco/openclaw-slim/pull/23","url":"https://dependabot.ecosyste.ms/api/v1/hosts/GitHub/repositories/essentiaMarco%2Fopenclaw-slim/issues/23","packages_url":"https://dependabot.ecosyste.ms/api/v1/issues/23/packages"},{"uuid":"5405831278","node_id":"PR_kwDOS7tr488AAAABC6SmLQ","number":43,"state":"closed","title":"chore(deps): bump the android-deps group across 1 directory with 21 updates","user":"dependabot[bot]","labels":["dependencies","java"],"assignees":[],"locked":false,"comments_count":1,"pull_request":true,"closed_at":"2026-09-11T23:24:55.000Z","author_association":null,"state_reason":null,"created_at":"2026-09-09T23:32:25.000Z","updated_at":"2026-09-11T23:24:57.000Z","time_to_close":172350,"merged_at":null,"merged_by":null,"closed_by":null,"dependency_metadata":{"prefix":"chore(deps): bump","group_name":"android-deps","update_count":21,"packages":[{"name":"gradle-wrapper","old_version":"9.4.1","new_version":"9.7.1","repository_url":"https://github.com/gradle/gradle"},{"name":"androidx.core:core-ktx","old_version":"1.18.0","new_version":"1.19.0"},{"name":"org.bouncycastle:bcprov-jdk18on","old_version":"1.84","new_version":"1.85.2","repository_url":"https://github.com/bcgit/bc-java"},{"name":"org.commonmark:commonmark","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-autolink","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-strikethrough","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-tables","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-task-list-items","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"dnsjava:dnsjava","old_version":"3.6.4","new_version":"3.6.5","repository_url":"https://github.com/dnsjava/dnsjava"},{"name":"org.junit.vintage:junit-vintage-engine","old_version":"6.0.3","new_version":"6.1.3","repository_url":"https://github.com/junit-team/junit-framework"},{"name":"io.kotest:kotest-assertions-core-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"io.kotest:kotest-runner-junit5-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"org.jetbrains.kotlinx:kotlinx-coroutines-android","old_version":"1.10.2","new_version":"1.11.0","repository_url":"https://github.com/Kotlin/kotlinx.coroutines"},{"name":"org.jetbrains.kotlinx:kotlinx-coroutines-test","old_version":"1.10.2","new_version":"1.11.0","repository_url":"https://github.com/Kotlin/kotlinx.coroutines"},{"name":"com.google.android.material:material","old_version":"1.13.0","new_version":"1.14.0","repository_url":"https://github.com/material-components/material-components-android"},{"name":"com.squareup.okhttp3:mockwebserver","old_version":"5.3.2","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.squareup.okhttp3:okhttp","old_version":"5.3.2","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.android.application","old_version":"9.2.0","new_version":"9.4.0"},{"name":"com.android.test","old_version":"9.2.0","new_version":"9.4.0"},{"name":"org.jetbrains.kotlin.plugin.compose","old_version":"2.3.21","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"},{"name":"org.jetbrains.kotlin.plugin.serialization","old_version":"2.3.21","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"}],"path":null,"ecosystem":"maven"},"body":"Bumps the android-deps group with 21 updates in the /apps/android directory:\n\n| Package | From | To |\n| --- | --- | --- |\n| [gradle-wrapper](https://github.com/gradle/gradle) | `9.4.1` | `9.7.1` |\n| androidx.core:core-ktx | `1.18.0` | `1.19.0` |\n| [org.bouncycastle:bcprov-jdk18on](https://github.com/bcgit/bc-java) | `1.84` | `1.85.2` |\n| [org.commonmark:commonmark](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-autolink](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-strikethrough](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-tables](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-task-list-items](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [dnsjava:dnsjava](https://github.com/dnsjava/dnsjava) | `3.6.4` | `3.6.5` |\n| [org.junit.vintage:junit-vintage-engine](https://github.com/junit-team/junit-framework) | `6.0.3` | `6.1.3` |\n| [io.kotest:kotest-assertions-core-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [io.kotest:kotest-runner-junit5-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [org.jetbrains.kotlinx:kotlinx-coroutines-android](https://github.com/Kotlin/kotlinx.coroutines) | `1.10.2` | `1.11.0` |\n| [org.jetbrains.kotlinx:kotlinx-coroutines-test](https://github.com/Kotlin/kotlinx.coroutines) | `1.10.2` | `1.11.0` |\n| [com.google.android.material:material](https://github.com/material-components/material-components-android) | `1.13.0` | `1.14.0` |\n| [com.squareup.okhttp3:mockwebserver](https://github.com/lysine-dev/okhttp) | `5.3.2` | `5.5.0` |\n| [com.squareup.okhttp3:okhttp](https://github.com/lysine-dev/okhttp) | `5.3.2` | `5.5.0` |\n| com.android.application | `9.2.0` | `9.4.0` |\n| com.android.test | `9.2.0` | `9.4.0` |\n| [org.jetbrains.kotlin.plugin.compose](https://github.com/JetBrains/kotlin) | `2.3.21` | `2.4.20` |\n| [org.jetbrains.kotlin.plugin.serialization](https://github.com/JetBrains/kotlin) | `2.3.21` | `2.4.20` |\n\n\nUpdates `gradle-wrapper` from 9.4.1 to 9.7.1\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/gradle/gradle/releases\"\u003egradle-wrapper's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e9.7.1\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.1.\u003c/p\u003e\n\u003cp\u003eThis is a patch release for 9.7.0. We recommend using 9.7.1 instead of 9.7.0.\u003c/p\u003e\n\u003cp\u003eHere are the highlights of 9.7.0 release:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIsolated Projects graduates to incubating\u003c/li\u003e\n\u003cli\u003eBroader Configuration Cache compatibility\u003c/li\u003e\n\u003cli\u003eResilient Sync helps you fix broken builds\u003c/li\u003e\n\u003cli\u003eMore source locations in problem reports\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003ca href=\"https://docs.gradle.org/9.7.1/release-notes.html\"\u003eRead the Release Notes\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eWe would like to thank the following community members for their contributions to this release of Gradle:\n\u003ca href=\"https://github.com/aSemy\"\u003eAdam\u003c/a\u003e,\n\u003ca href=\"https://github.com/Gautam-aman\"\u003eAman Gautam\u003c/a\u003e,\n\u003ca href=\"https://github.com/YukiCodepth\"\u003eAman Kumar\u003c/a\u003e,\n\u003ca href=\"https://github.com/adubrouski\"\u003eAnton Dubrouski\u003c/a\u003e,\n\u003ca href=\"https://github.com/liutikas\"\u003eAurimas\u003c/a\u003e,\n\u003ca href=\"https://github.com/gbhavya07\"\u003egbhavya07\u003c/a\u003e,\n\u003ca href=\"https://github.com/joshfriend\"\u003eJosh Friend\u003c/a\u003e,\n\u003ca href=\"https://github.com/nicklauslittle-gov\"\u003enicklauslittle-gov\u003c/a\u003e,\n\u003ca href=\"https://github.com/psoni674\"\u003ePragati\u003c/a\u003e,\n\u003ca href=\"https://github.com/Project516\"\u003eproject516\u003c/a\u003e,\n\u003ca href=\"https://github.com/Uomocapra\"\u003eQin Mi\u003c/a\u003e,\n\u003ca href=\"https://github.com/rkdfx\"\u003eRavi\u003c/a\u003e,\n\u003ca href=\"https://github.com/sk-reddy17\"\u003esk-reddy17\u003c/a\u003e,\n\u003ca href=\"https://github.com/Suvrat1629\"\u003eSuvrat Acharya\u003c/a\u003e,\n\u003ca href=\"https://github.com/ShreckYe\"\u003eYongshun Ye\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eUpgrade instructions\u003c/h2\u003e\n\u003cp\u003eSwitch your build to use Gradle 9.7.1 by updating your wrapper:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e./gradlew :wrapper --gradle-version=9.7.1 \u0026amp;\u0026amp; ./gradlew :wrapper\r\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eSee the Gradle \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/upgrading_version_9.html\"\u003e9.x upgrade guide\u003c/a\u003e to learn about deprecations, breaking changes and other considerations when upgrading.\u003c/p\u003e\n\u003cp\u003eFor Java, Groovy, Kotlin and Android compatibility, see the \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/compatibility.html\"\u003efull compatibility notes\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eReporting problems\u003c/h2\u003e\n\u003cp\u003eIf you find a problem with this release, please file a bug on \u003ca href=\"https://github.com/gradle/gradle/issues\"\u003eGitHub Issues\u003c/a\u003e adhering to our issue guidelines.\nIf you're not sure you're encountering a bug, please use the \u003ca href=\"https://discuss.gradle.org/c/help-discuss\"\u003eforum\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eWe hope you will build happiness with Gradle, and we look forward to your feedback via \u003ca href=\"https://twitter.com/gradle\"\u003eTwitter\u003c/a\u003e or on \u003ca href=\"https://github.com/gradle\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003e9.7.0\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.0.\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/92f0512e7f06d84621afba191f75e265363890cf\"\u003e\u003ccode\u003e92f0512\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38892\"\u003e#38892\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/820ee75a99a179bbffa41bcedc6477b685fabb9f\"\u003e\u003ccode\u003e820ee75\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/82c23f9bd2a89b4cc644e1f90a28a8668feb3dee\"\u003e\u003ccode\u003e82c23f9\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering problem in KTS (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38878\"\u003e#38878\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/ef11a7268fe8cc8d6ab849ec911aa11220180553\"\u003e\u003ccode\u003eef11a72\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering issue\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/bb0d8a974a71b1003efea41e4046e98855cd5ff8\"\u003e\u003ccode\u003ebb0d8a9\u003c/code\u003e\u003c/a\u003e Make relevant tests polyglot (run for multiple DSLs)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/336e129d7f95c03486acafc97abf59734acfed48\"\u003e\u003ccode\u003e336e129\u003c/code\u003e\u003c/a\u003e Update signing configuration (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38874\"\u003e#38874\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/4bdf0da2dad9884d089a6062a45ea7183e7d735d\"\u003e\u003ccode\u003e4bdf0da\u003c/code\u003e\u003c/a\u003e Update signing configuration\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/cd9b92c1b82856248cf1dc58b50378238bec7b52\"\u003e\u003ccode\u003ecd9b92c\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38839\"\u003e#38839\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/5f4e381964897ad8d6b99e5a7c77f26dba3259fb\"\u003e\u003ccode\u003e5f4e381\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/1e08ab551367aeb5fb48b26e72807e1d2b27c939\"\u003e\u003ccode\u003e1e08ab5\u003c/code\u003e\u003c/a\u003e Keep type-use annotations in extracted ABI classes (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38810\"\u003e#38810\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/gradle/gradle/compare/v9.4.1...v9.7.1\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `androidx.core:core-ktx` from 1.18.0 to 1.19.0\n\nUpdates `org.bouncycastle:bcprov-jdk18on` from 1.84 to 1.85.2\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.md\"\u003eorg.bouncycastle:bcprov-jdk18on's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch1\u003eBouncy Castle Crypto Package - Release Notes\u003c/h1\u003e\n\u003ch2\u003e1.0 Introduction\u003c/h2\u003e\n\u003cp\u003eThe Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. The package is organised so that it contains a light-weight API suitable for use in any environment (including the J2ME) with the additional infrastructure to conform the algorithms to the JCE framework.\u003c/p\u003e\n\u003ch2\u003e2.0 Release History\u003c/h2\u003e\n\u003cp\u003e\u003c!-- raw HTML omitted --\u003e\u003c!-- raw HTML omitted --\u003e\u003c/p\u003e\n\u003ch3\u003e2.1.1 Version\u003c/h3\u003e\n\u003cp\u003eRelease: 1.86\u003cbr /\u003e\nDate: 2026, TBD\u003c/p\u003e\n\u003ch3\u003e2.1.2 Defects Fixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) let a subkey inherit the primary key's Key Flags when its own Subkey Binding signature carried no Key Flags subpacket, which made the two capability decisions taken for one subkey disagree. OpenPGPCertificate.OpenPGPComponentKey.isSigningKey() reads the effective flags, which fell back to the primary key's direct-key or primary user ID self-signature, so a subkey bound with no flags of its own counted as signing-capable; verifyEmbeddedPrimaryKeyBinding reads the binding signature's own flags, found no signing capability there, and so skipped the embedded Primary Key Binding (cross-certification) signature that RFC 9580 sec. 5.2.1.8 and sec. 10.1.3 require of a subkey that can issue signatures. A data signature made by such a subkey was therefore attributed to the certificate and reported valid by OpenPGPSignature.OpenPGPDocumentSignature.isValid() with the cross-certification requirement never applied, where GnuPG refuses the same certificate and message as not cross-certified. An attacker holding a third party's public signing subkey - which is public material - could bind it to their own primary key with a Subkey Binding signature they are able to make, carrying no Key Flags and no embedded Primary Key Binding signature, which they cannot make without the subkey's private key, and have that party's genuine signatures verify as valid under the attacker's own identity: misattribution of a real signature rather than a forgery of a new one, since the signature still has to be one the subkey actually made. Key Flags are a statement about the key the carrying signature refers to (RFC 9580 sec. 5.2.3.29), so a subkey no longer inherits them from the certificate-wide signatures of the primary key: a Subkey Binding signature that omits the subpacket now leaves the subkey with no capabilities rather than the primary's, which makes the flags the cross-certification check consults the same flags every other decision consults. Preferences and the other subpackets a direct-key signature carries are inherited as before, and the primary key itself - whose flags legitimately come from its direct-key or user ID self-signature - is unaffected. The low-level PGPSignature / PGPPublicKeyRing API performs no binding checks by design and is unchanged.\u003c/li\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) used a version 6 key that carried no valid Direct Key signature, falling back to the primary user ID binding as it correctly does for a version 4 key. RFC 9580 sec. 5.2.3.10 requires the opposite: \u0026quot;An implementation MUST ensure that a valid Direct Key signature is present before using a version 6 key. This prevents certain attacks where an adversary strips a self-signature specifying a Key Expiration Time or certain preferences.\u0026quot; The certificate grammar says the same structurally, the Direct Key signature being mandatory in the version 6 structure of sec. 10.1.1 and optional in the version 4 one of sec. 10.1.3. Because a version 6 certificate carries its key expiration, features and algorithm preferences on the Direct Key signature - the convention the RFC recommends and the one OpenPGPKeyGenerator follows, its user ID certification carrying no expiration at all - removing that single signature packet from a published certificate silently dropped the expiration along with the preferences and features: OpenPGPCertificate.getSignatureChainFor fell back to the user ID binding, the primary key was still reported bound, and getEncryptionKeys() and getSigningKeys() went on returning the subkeys of a key whose owner had set it to expire. The primary key fingerprint is unchanged by the removal, so a relying party pinning the key by fingerprint still treats it as the same key, and no private key or hash collision is involved; the natural moment for the strip is the key refresh that RFC 9580 names as the reason to refetch a key at all - to learn about changes in expiration, features, preferences and revocation - which is exactly the update it defeats. This is a downgrade rather than a forgery, nothing being attributed to a key that did not authorise it, and the concerning direction is encryption, to a key meant to have been retired. OpenPGPCertificate.isBoundBy now requires a valid Direct Key self-signature on a version 6 primary key before any component of the certificate - the primary key, its subkeys or its identities - is treated as bound, so a version 6 certificate stripped of it offers no keys at all rather than an unexpiring set. Version 4 certificates are unaffected: there the key expiration legitimately lives on the user ID self-signature and the fallback is correct, so it stays. The revocation-only version 6 certificate of sec. 10.1.2, which legitimately carries no Direct Key signature, is unaffected as well - its key was already refused as revoked, and reading the revocation does not go through the binding check.\u003c/li\u003e\n\u003cli\u003eThe lightweight LMSSigner and HSSSigner refused a key wrapped in ParametersWithRandom, which is how BcContentSignerBuilder passes a key whenever setSecureRandom() has been called - so BcHssLmsContentSignerBuilder built a working signer until a random was set and then failed with \u0026quot;Incorrect Key Parameters\u0026quot;, and the two signers themselves raised ClassCastException on the same input. All three now unwrap it, as the promoted ML-DSA and SLH-DSA signers already did. The random is accepted and not used: LMS derives its message randomiser C from the key's seed and the one-time index, so it is deterministic and cannot repeat while q does not. Note SP 800-208 sec. 6.1 asks for C to come from an approved random bit generator, which this implementation does not do; that is unchanged here, and a supplied random is now ignored rather than refused.\u003c/li\u003e\n\u003cli\u003eLMS signature verification did not apply two of the checks RFC 8554 sec. 5.4.2 requires before a signature is processed. Step 2g refuses a signature whose LMS typecode is not the one from the public key, and without it the path computation took its height and tree digest from the parameter set the signature named rather than the key's, so a signature claiming a height-25 parameter set drove a 25-level computation against a height-5 key. Step 2i refuses a leaf number q outside the tree, and without it an out-of-range q flowed into the node arithmetic and was left for the candidate-root comparison to catch. Neither was a forgery - the domain separation between D_LEAF and D_INTR and the final comparison saw to that - but both are attacker-chosen work the specification says to refuse up front. Both are now checked, and a signature failing either is still reported as not verifying rather than thrown out of Signature.verify(). The catch around the signature decode in LMSSigner and HSSSigner has also been narrowed to the decode itself, as the corresponding SPI was corrected to do for github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2408\"\u003e#2408\u003c/a\u003e: past the parse the engine reports an inconsistent signature by returning false rather than by throwing, so the wider catch caught nothing while standing ready to turn a future internal error into a quiet false.\u003c/li\u003e\n\u003cli\u003eThe LMS and HSS key parameter classes now apply at construction the checks their decoders apply, so a key built directly cannot be one the decoder would refuse. LMSPrivateKeyParameters accepted an identifier of any length although the decoder reads exactly 16 bytes - such a key encoded but could not be read back - and left q, maxQ and the seed length unchecked; the seed is now required to be at least m bytes at decode as well, where a one-byte seed had been decoding silently and then deriving every one-time key from it. HSSPrivateKeyParameters checked neither its level count nor that it had been given a component key per level and a chaining signature per level below the root, and then indexed both lists, so a mismatch surfaced as IndexOutOfBoundsException - or, where a level happened to match, as a null chaining signature that only failed at signing time; the level is now checked after the reset that fills it in, since a null is legitimate on the way in. LMSPrivateKeyParameters.getInstance(byte[], byte[]) adopted the public key supplied beside the private one without comparing them, so a mismatched public key was simply reported by getPublicKey(); it now cross-checks the identifier, both parameter sets and, where the tree cache already holds it, the root, as the HSS entry point does. The decoders also now report a bad version or seed length as IOException rather than IllegalStateException, so a caller can catch one type for a malformed key, and the package-private LM-OTS public key decoder no longer declares throws Exception or dereferences an unrecognised typecode. The deprecated org.bouncycastle.pqc.crypto.lms copies carry the decoder corrections.\u003c/li\u003e\n\u003cli\u003eIn the LMS JCE layer, LMSKeyGenParameterSpec.fromNames knew all twenty LMS parameter-set names but only four of the sixteen LM-OTS ones, so none of the SP 800-208 n24 or SHAKE sets could be named; all sixteen are now present. KeyPairGenerator.initialize(int, SecureRandom) reports InvalidParameterException, which is what the JCA specifies and which extends the IllegalArgumentException it raised before, so existing catches still match. BCLMSPrivateKey.getIndex now takes the exhaustion check and the index read under the key's own monitor rather than as two separate calls, and two unused fields have gone from LMSSignatureSpi. Note that the LMS Signature claims its one-time key at the first update() rather than at sign(), so a Signature that is initialised and updated and then abandoned spends an index without producing a signature - the safe direction for a one-time scheme, and now documented on the SPI.\u003c/li\u003e\n\u003cli\u003eEvery other key pair generator that refuses a key size did the same thing the LMS one did above. KeyPairGenerator.initialize(int, SecureRandom) is documented to raise InvalidParameterException when the key size is not one the generator supports, and thirty of them raised a bare IllegalArgumentException instead, so a caller following the JCA and catching the documented type saw an exception escaping rather than a refusal. The ML-DSA, ML-KEM, SLH-DSA, Classic McEliece, FrodoKEM, NTRU and composite signature and KEM generators in the BC provider, and every generator in BCPQC, now raise InvalidParameterException - NewHope included, where the value is a key size it will not take rather than a mode of initialisation it does not offer. InvalidParameterException extends IllegalArgumentException, so callers written against the old behaviour go on catching it unchanged. The two RSA generators are corrected as well, and differently: theirs is a key size below a floor rather than a mode of initialisation they do not offer, and the refusal is raised by the lightweight RSAKeyGenerationParameters, which cannot name a java.security exception at all, so the RSA KeyPairGeneratorSpi now translates it - keeping the message verbatim and the original exception as the cause, through a new SecurityExceptions.invalidParameterException factory, since InvalidParameterException has no constructor that takes one. Of the 304 KeyPairGenerator services the two providers register, 299 now refuse a nonsense key size the way the JCA defines it and five accept it as a strength they can work with, with none left raising a bare IllegalArgumentException; that is asserted as a sweep over both providers rather than per algorithm, so a generator added later is covered without the test being touched. The jdk1.3 provider overlays of the four generators that have one carry the same change, and the jdk1.3 SecurityExceptions overlay gains the new factory along with the invalidAlgorithmParameterException one it had been missing.\u003c/li\u003e\n\u003cli\u003eKeyPairGenerator.initialize(AlgorithmParameterSpec, SecureRandom) had the same shape of problem as the int overload above, and only 44 of the 304 services the two providers register reported an unusable spec as the InvalidAlgorithmParameterException that method declares. The twenty-three PQC generators that resolve a parameter set by name - cmce, frodokem, mldsa, mlkem, slhdsa, aimer, bike, faest, falcon, haetae, hqc, mayo, mqom, ntru, ntruplus, both ntruprime variants, qruov, saber, sdith, smaugt, snova and sqisign, 230 services between them - case-folded the name they got back from the spec without checking it, so a spec with no getName() method, and a null spec, produced a NullPointerException from inside the fold; their own \u0026quot;is this name one I know\u0026quot; branch, which does report the declared exception, was unreachable. The two composite generators, whose parameter set is fixed by the algorithm name so that null is the only spec they accept, refused every other one with IllegalArgumentException. RSA answered correctly for a spec of the wrong type but not for one of the right type carrying values its lightweight parameters will not take - an even public exponent, or a key size below the floor - which is now translated the same way the int overload's is. All 304 services now report the declared exception, with the composites still taking the null spec that is right for them; note that InvalidAlgorithmParameterException is a checked exception and not an IllegalArgumentException, so a caller that was catching what these threw before has to catch the declared type instead.\u003c/li\u003e\n\u003cli\u003eAn HSS private key claimed the two records of its position under two different monitors. The top-level index and the bottom component key's one-time index q are independent records of the same position - the decoder requires them to agree, see the entry below - but generateLMSContext incremented the index under the HSS key's own monitor, released it, and only then claimed q under the component key's. A getEncoded() issued in between saw the index advanced and q not, and produced an encoding this implementation's own decoder rejects; and two threads meeting at a bottom-tree boundary could both pass the exhaustion test, take consecutive top-level indices and claim the same q, after which one of them was refused with \u0026quot;ots private key exhausted\u0026quot; by a key still reporting usages remaining, a top-level index had been spent with no signature made, and the two records stayed one apart for the rest of the key's life in that process - so it could no longer be encoded, cloned or sharded, and getIndex() and getUsagesRemaining() misreported by one. No one-time key was reused: the component key's claim is itself atomic, and the divergence runs index ahead of leaves, so the effect was on the key's usability rather than on the signatures it had made. Both records are now claimed under the one monitor, and the component key is claimed before the index is incremented so that an exhausted one leaves both untouched. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the same correction.\u003c/li\u003e\n\u003cli\u003eTimeStampToken parsed the attacker-controlled TSTInfo content of a time-stamp token (org.bouncycastle.tsp.TimeStampToken, reached from TimeStampResponse(byte[]) and (InputStream)) inside a try that caught only CMSException, so a well-formed RFC 3161 TimeStampResp whose embedded token carried a malformed TSTInfo - a SEQUENCE with fewer elements than the five mandatory fields, a non-SEQUENCE, truncated DER, or an unknown context tag - let an IllegalArgumentException or a NoSuchElementException escape the constructor's declared throws TSPException, IOException contract. A token signed by no signers or by more than one raised a bare IllegalArgumentException from the same constructor, before that try, for the same reason. Both are now reported as TSPException, matching the package-private TimeStampResponse(DLSequence) constructor and the existing getSignedAttributes guard in the same method; the signer-count refusal is a TSPValidationException, as the neighbouring check on the content type already was. Related, and the cause of the NoSuchElementException: asn1.tsp.TSTInfo read its five mandatory fields off the sequence with no bound on how many elements were actually there, so a short SEQUENCE left the enumeration to run out rather than being refused, and an oversize one was accepted with its extra elements absorbed into the optional slots. Decode now requires the five to ten elements RFC 3161 sec. 2.4.2 gives the type, which is what the sibling Accuracy and ArchiveTimeStamp decoders already did, so the failure is the IllegalArgumentException that getInstance is expected to raise (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2415\"\u003e#2415\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eNeither the HSS nor the XMSS^MT private key decoder checked its declared index against the traversal state stored beside it, although the two are independent records of the same position in the key and so can be compared. For HSS the records are the top-level index and the component keys' one-time indices q; for XMSS^MT they are the global index and the per-layer BDS states. A stored key whose index had been rolled back while its state stayed advanced - a partial write, a restore from backup, a buggy storage layer - was therefore accepted, and it then signed a second message under a one-time key the key had already used, producing a signature that verified, so nothing anywhere surfaced the reuse. RFC 8554 sec. 1 and RFC 8391 sec. 1.1 both require each one-time key to be used exactly once, and this is the failure those requirements exist to prevent; the single-tree XMSS decoder has tied its BDS state to its index since that state was first validated, and this brings the two multi-tree schemes into line. HSS decode now requires the declared index to equal the position the component q values imply - a level above the last contributes (q - 1) leaves of the levels beneath it, since its q has already advanced past the subtree it signed - and XMSS^MT decode now requires each present layer's BDS index to equal the leaf index that layer derives from the global index, allowing the one position where a layer has moved into a new subtree and its state legitimately still carries the previous subtree's final index. A layer with no state yet is unaffected, since those are built lazily at signing time. Related, and the same shape of omission: an XMSS or XMSS^MT private key encoding carries the tree root twice - the key's own root field and the root node of the BDS state stored beside it, which for XMSS^MT is the top layer's - and the two were never compared either. A corrupted root was accepted and then poisoned every signature the key made, because the root is hashed into the message digest: the signature did not verify and nothing indicated why. Decode now requires the two copies to agree. The BDS node values themselves are not checkable the way the LMS tree cache above is - a BDS authentication path, stack, retain or keep node does not have its children stored alongside it, so recomputing one means building a subtree, which is the work the state exists to avoid. Both checks are integer comparisons over the levels of the key, too small to measure against the surrounding decode, and both were verified not to reject any legitimate key by walking every index a key can reach: the full key space of the two-level HSS and the h=4/d=2, h=6/d=2, h=6/d=3, h=9/d=3 and h=8/d=4 XMSS^MT parameter sets, plus a three-level HSS key across a subtree boundary and an HSS shard. Since those node values cannot be recomputed, the encoded state now carries a checksum over itself instead, with the owning key's public seed hashed in front of it. Any corruption of the stored state is refused at decode rather than being loaded and then producing signatures that silently do not verify, and because the public seed is bound in, a state transplanted between two keys of the same parameter set is refused too, even though it is internally consistent and arrives with its own matching root. The public seed is bound rather than the secret seed or the PRF key deliberately: the state's own root and index are inside the encoding and so are already covered, hashing secret material would make the stored checksum a commitment to it for no gain in detection, and the PRF key does not influence the state at all. \u003cstrong\u003eThis is an error-detecting code and not integrity protection\u003c/strong\u003e - anyone able to rewrite the stored key recomputes it, so it establishes that the state is unchanged since it was written, never that it was correct when written, and the allocation bounds on the encoding remain the guard against a crafted one. It costs one SHA-256 over the state, measured at 5 to 8 microseconds each way for the h=10 and h=16 parameter sets, and 32 bytes of encoding. The state encoding was added earlier in this same cycle and has not been released, so the checksum is simply part of it rather than a new version: a state written by a 1.86 beta is rejected, which is recovered from by re-exporting the key. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the HSS check as well (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2414\"\u003e#2414\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe S/MIME example smoke test in the misc module (org.bouncycastle.mail.smime.examples.test.AllTests) drove SendSignedAndEncryptedMail against smtp.gmail.com, and that example finishes with Transport.send() under JavaMail's default settings, which have no connect timeout. Where outbound port 25 is refused the failure was swallowed and the test passed; where it is silently dropped, as on many home networks, the connect blocked and ./gradlew build hung in :misc:test indefinitely with \u0026quot;0 tests completed\u0026quot;. The test now delivers to an SMTP stub on a loopback port, with connect / read / write timeouts as a backstop, and asserts the message arrived (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2407\"\u003e#2407\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation took the traditional component public key bytes it feeds the KEM combiner from the recipient key's own encoding, while decapsulation recomputes the point from the private key and so always produced an uncompressed one. Section 4 of draft-ietf-lamps-pq-composite-kem requires an EC component to be carried as an uncompressed point, but a component key that encodes itself compressed - a BC EC key whose point format has been set through org.bouncycastle.jce.interfaces.ECPointEncoder, or a key from a provider that preserves a compressed encoding - was passed through as it came. Both sides then combined a different tradPK and derived different shared secrets, with no error reported on either: encapsulation and decapsulation both succeeded and the recipient simply could not decrypt. The EC component is now normalised to an uncompressed point wherever the engine serialises one, which covers the ephemeral key that forms the ciphertext as well. X25519 and X448 components have a single encoding and were unaffected, as were EC keys left in their default (uncompressed) format, whose shared secrets are unchanged. CompositePublicKey.getEncoded() took its component bytes the same way, so such a key also encoded to a composite key other implementations reject and whose bytes changed across an encode / decode / encode round trip - 1238 bytes rather than 1270 for MLKEM768-ECDH-P256, and for the composite ML-DSA keys sharing that method, 2006 rather than 2038 for MLDSA65-ECDSA-P256. It now normalises the component the same way. This is a write-side change only: a composite key carrying a compressed EC component is still decoded, since the component key factories accept either form, and continues to verify signatures as before - it simply re-encodes in the normalised form. The shared normalisation is org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil.getUncompressedSubjectPublicKeyBytes.\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation threw a NullPointerException, wrapped in an IllegalStateException out of KeyGenerator.generateKey(), when the SecureRandom it was given was null - which javax.crypto.KEM.newEncapsulator() documents as a request for the provider's default, and which KeyGenerator.init(spec, null) passes straight through. The three RSA-OAEP composites draw the traditional shared secret from that random directly, so they were the ones affected; the ECDH and X25519 / X448 composites escaped only because their component KeyPairGenerators default a random of their own. CompositeMLKEMEngine now defaults one through CryptoServicesRegistrar.getSecureRandom() on first use, as the composite KEM Cipher's wrap path already did, and as the KEM generators corrected earlier in this cycle now do. Related, the engine now also clears the ML-KEM component's shared secret alongside the traditional one on both the encapsulate and decapsulate paths - the copy handed back by getEncoded() was left in the heap - as section 3.5 of draft-ietf-lamps-pq-composite-kem requires.\u003c/li\u003e\n\u003cli\u003eCompositePublicKey.getAlgorithm() and CompositePrivateKey.getAlgorithm() returned null for all twelve Composite ML-KEM (draft-ietf-lamps-pq-composite-kem) parameter sets. Both classes resolved the name through the composite signature index only, which holds the composite ML-DSA OIDs, so a composite KEM key pair - generated, parsed from a certificate, or read from PKCS#8 - reported no algorithm at all, and the standard JCA idiom of reconstructing a key with KeyFactory.getInstance(key.getAlgorithm()) raised a NullPointerException. The lookup now falls back to the composite KEM index, so the name returned is the one the provider registers the algorithm under (e.g. MLKEM768-X25519-SHA3-256), matching the composite ML-DSA behaviour. The same single-index assumption made the CompositePublicKey(SubjectPublicKeyInfo) and CompositePrivateKey(PrivateKeyInfo) constructors reject a composite KEM key with \u0026quot;unable to create CompositePublicKey from SubjectPublicKeyInfo\u0026quot;; they now dispatch to the composite KEM key factory for those OIDs. Keys obtained through KeyFactory or through BouncyCastleProvider.getPublicKey / getPrivateKey were unaffected and are unchanged (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2404\"\u003e#2404\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe org.bouncycastle.jcajce.spec.KEMKDFSpec constructor stored a null otherInfo as given, so getOtherInfo() returned null, and three of the KDF branches KdfUtil.makeKeyBytes dispatches to - KMAC-128, KMAC-256 and SHAKE-256 - read the otherInfo length without a guard and threw NullPointerException out of the KEM operation, where the KDF2, KDF3 and HKDF branches tolerate a null through KDFParameters / HKDFParameters. The Builder of every spec in the package already mapped null to empty, so no provider path reached it, but the constructor is protected on a public class and KdfUtil is documented for callers building their own KEM integration; the deprecated KEMParameterSpec passes a null itself and escaped only because it also pins the KDF to null. The constructor now stores empty for a null, so getOtherInfo() never returns null, and a null and an explicitly empty otherInfo derive the same key.\u003c/li\u003e\n\u003cli\u003eQR-UOV signature verification accepted a signature encoding that was not canonical, so the encoding of a signature was not unique even after the trailing-byte fix of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e. Each F_q element of the signature is stored in ceil(log2 q) bits, one more bit pattern than the field has elements: q itself is representable and is arithmetically congruent to zero, so an element written as q verified exactly as the same element written as zero would, and the bits padding the last element out to the byte boundary were never read at all. Every zero element of a signature therefore carried a second encoding, and for the q = 7 parameter sets roughly one element in seven is zero - a single qruov_5_q7_L10 signature measured 256 spare bits, so on the order of 2^256 distinct byte strings verified for the one message and key. Verification now rejects any element outside [0, q) and any set padding bit; a signature produced by this or by the reference implementation is unaffected, as the KAT vectors of every parameter set confirm. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSNOVA signature verification ignored four bits inside the signature for any parameter set whose solution is an odd number of GF(16) nibbles - the SNOVA_24_5_5, SNOVA_25_8_3, SNOVA_29_6_5 and SNOVA_66_15_3 families, sixteen of the forty-four parameter sets. The last byte of the encoded solution carries a single nibble and the signer leaves the top four bits zero, but the decoder did not read them, so sixteen distinct byte strings verified for one signature. This is the same non-unique encoding github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e closed for bytes following the signature, applied inside it; the verifier now requires those bits to be zero. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSnovaPrivateKeyParameters did not validate the length of the private key encoding handed to it - the only one of the five schemes of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e that did not - and SnovaParameters.getPrivateKeyLength() reported the expanded (\u0026quot;ESK\u0026quot;) length even for a parameter set whose private key is the seed pair. A private key encoding reaches this constructor straight from a PKCS#8 blob, so a wrong length went undetected: a seed-form key with extra bytes appended was accepted and signed under a different derived key, and a short expanded-form key sized the signer's decode buffer negatively, throwing NegativeArraySizeException out of generateSignature() rather than being reported at construction. Related, the signing retry loop could not terminate: the vinegar values are derived from a single-byte counter, so only 256 distinct linear systems can be tried, and an expanded-form private key that is not a real central map is singular for all of them - generateSignature() then span forever rather than failing. The length is now checked at construction, getPrivateKeyLength() reports the length that parameter set's private key actually has, and the retry loop gives up after its 256 attempts as MAYO's does.\u003c/li\u003e\n\u003cli\u003eMayoSigner and MayoKeyPairGenerator did not clear several buffers holding secret key material that the MAYO reference implementation explicitly clears. Signing left the secret oil space O, the expanded L = (P1 + P1^t) * O + P2, and the M / VPV / Ox intermediates of the central map in place, having gone to the trouble of clearing eleven other buffers; key generation left the expanded seed, whose tail is the encoded oil space, and the P1 * O + P2 half of P; and the row-echelon step left the packed echelon form of the secret linear system and its pivot rows. Separately, if all 256 attempts at solving for the signature had given a rank-deficient system, signing emitted a signature built from the failed attempt's state instead of reporting the failure the reference returns, and AIMerSigner.generateSignature returned an empty array on failure, which a caller would hand on as though it were a signature. Both now throw.\u003c/li\u003e\n\u003cli\u003eFive PQC signature schemes - MAYO, SNOVA, QR-UOV, SQIsign and AIMer - returned the NIST crypto_sign \u0026quot;sm\u0026quot; signed-message envelope from generateSignature() rather than the signature. That envelope is an artefact of the reference KAT harness, which records the message alongside the signature so a vector file can be self-contained; it is not part of any of the five specifications, and no other BC signer emits it (Falcon's KAT test rebuilds the equivalent envelope in the test, which is where it belongs). Two consequences followed, both reaching the JCA Signature services of every parameter set of the five schemes in BouncyCastlePQCProvider. First, since the message was appended to the signature, verification had to skip whatever followed the signature proper, and it did so by checking only that the buffer was long enough - so any number of trailing bytes could be added to a valid signature, or the appended message replaced with unrelated data, and it still verified. A signature encoding was therefore not unique: anyone holding one valid signature could produce unlimited distinct byte strings that all verified for the same message and key, which breaks any use that treats the signature bytes as an identifier, deduplicates on them, or records them as evidence. Second, the envelope propagated into everything built on the operator layer: because ContentSigner hands the signature straight into the structure being signed, every X.509 certificate, CRL, CMS SignedData and TLS CertificateVerify BC produced with one of these algorithms carried a verbatim copy of the signed data inside its own signature field - a self-signed MAYO-1 certificate came to 3567 bytes where the same certificate is now 2020 - which no other implementation can parse as a signature, and which in a detached CMS signature meant the \u0026quot;detached\u0026quot; signature carried the content. generateSignature() now returns the bare signature, and verifySignature() requires exactly the parameter set's signature length, so appended or truncated data is rejected rather than ignored. \u003cstrong\u003eThis is a behavioural change for signatures produced by an earlier release\u003c/strong\u003e - MAYO and SNOVA from 1.84, QR-UOV, SQIsign and AIMer from 1.85 - which are no longer accepted in the envelope form they were emitted in; the signature bytes themselves are unchanged, so a stored value can be recovered by taking the leading signature-length bytes, or for AIMer, whose envelope was message || signature rather than signature || message, the trailing ones. The KAT tests now rebuild the envelope before comparing against the vector files, which continue to record it. Note that AIMer's verification had already been made length-exact during this cycle (see the entry below relating to github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2401\"\u003e#2401\u003c/a\u003e), so of the five only its envelope remained (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe MLS implementation did not bind an X.509 credential to the LeafNode's signature_key. LeafNode.verify() checked a leaf's signature against the signature_key declared in the leaf itself, while the X.509 credential's certificate chain was stored but never parsed or checked, so the certificate's public key was never required to match signature_key (RFC 9420 sec. 5.3). A leaf could therefore carry one party's certificate while being signed by an unrelated key and still be accepted under that party's identity through KeyPackage.verify() and the Group leaf-validation path. LeafNode.verify() now requires the end-entity certificate's subject public key, in the cipher suite's signature encoding, to equal signature_key for an X.509 credential, and rejects the leaf otherwise - including an empty chain or a certificate whose key type does not match the cipher suite; certificate-chain and identity validation to a trust anchor remain the application's responsibility per RFC 9420 sec. 5.3.1. A public org.bouncycastle.mls.codec.Certificate(byte[]) constructor and a Credential.getCertificates() accessor are added so callers can build and inspect X.509 credentials. Basic credentials are unaffected.\u003c/li\u003e\n\u003cli\u003eThe SecureRandom supplied to org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder.setSecureRandom() did not drive the content IV / nonce for any algorithm other than RC2. EnvelopedDataHelper.generateParameters passed the caller's SecureRandom to the AlgorithmParameterGenerator only in the RC2_CBC branch; every other content-encryption algorithm - AES-CBC, AES-GCM, AES-CCM, Camellia, ARIA, SEED and the rest - reached pGen.generateParameters() on an uninitialised generator, so the IV / nonce was drawn from a default SecureRandom and setSecureRandom() was silently ignored (the builder's javadoc states that random is used for IV/nonce generation). The generator is now initialised with the supplied random on the general path as well, so a caller who provides a specific randomness source - for a controlled or FIPS-approved DRBG, say - has it honoured for the content IV / nonce. The session-key generation path was unaffected and already used the supplied random. Because the content IV / nonce now comes from the supplied SecureRandom, the org.bouncycastle.crypto.util JournalingSecureRandom / JournaledAlgorithm reproducible-encryption support records it in the transcript: a resumed session reproduces the IV / nonce by regenerating it from the replayed randomness - build the resuming encryptor from the content-algorithm OID - rather than by reusing the AlgorithmIdentifier captured from the first encryption, which no longer keeps the transcript aligned.\u003c/li\u003e\n\u003cli\u003eThe NTRU LPRime, NTRU+ and SMAUG-T KEM generators threw a NullPointerException when constructed with a null SecureRandom, where every other KEM generator - including NTRU LPRime's own SNTRU Prime counterpart in the same package - defaults one through CryptoServicesRegistrar.getSecureRandom(). This is reachable from the lightweight API directly, and from javax.crypto.KEM, whose newEncapsulator() documents a null random as a request for the provider's default.\u003c/li\u003e\n\u003cli\u003eFrodoKEMEngine kept a single SHAKE instance in a field, so an engine reached concurrently produced wrong results. It is reached that way through org.bouncycastle.crypto.kems.FrodoKEMExtractor, which holds one engine for its lifetime: two threads extracting through one extractor interleaved the digest's absorb and squeeze phases, yielding shared secrets that silently did not match the sender's, or an IllegalStateException of \u0026quot;attempt to absorb while squeezing\u0026quot; from inside extractSecret. The digest is now built per call, as CMCEEngine's already was, which makes an extractor safe to share. Encapsulation was unaffected, since FrodoKEMGenerator builds an engine per call. Results for any single-threaded use are unchanged - the reference KAT vectors are byte-identical.\u003c/li\u003e\n\u003cli\u003eThe BCJSSE provider carried the TLS 1.2 coupling between the supported_groups extension and ECDSA over into TLS 1.3: an ECDSA signature scheme was treated as usable - offered in the signature_algorithms and signature_algorithms_cert extensions, and eligible when selecting the local credentials - only while the corresponding curve was among the named groups enabled for key exchange, both per context (a group unavailable for key agreement disabled the scheme outright) and per connection (the curve had to be in the supported_groups list about to be sent). RFC 8446 sec. 4.2.7 scopes supported_groups to key exchange only, with signature algorithms negotiated independently (sec. 4.2.3), so this incorrect restriction in TLS 1.3 has been removed. Ed25519, Ed448 and the RSA schemes were unaffected (as well as typical deployments using a default configuration for named groups).\u003c/li\u003e\n\u003cli\u003eThe bcmail module descriptor did not declare its javax.mail/javax.activation dependences, so a modular (module-path) consumer of the jar hit IllegalAccessError/module-resolution failures when the S/MIME classes touched the mail API. The descriptor now requires them optionally (requires static) under all four module names those libraries are known by - the automatic names mail and activation carried by the javax.mail:mail / javax.activation:activation artifacts, and the explicit names java.mail and java.activation carried by the newer com.sun.mail / com.sun.activation ones - a hard requires on any one name would break users of the others (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2389\"\u003e#2389\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFour type-coercion helpers in the OER / IEEE 1609.2 (ITS) decoder tested the wrong type in the identity fast path that lets a getInstance() factory return an argument that is already of the target type. org.bouncycastle.oer.its.ieee1609dot2.basetypes.UINT32.getInstance and org.bouncycastle.oer.its.etsi102941.basetypes.Version.getInstance guarded on UINT8 - a sibling of UINT32 under UintBase, and unrelated to Version - so passing a UINT8 threw ClassCastException, while passing an actual UINT32 or Version missed the fast path and fell through to ASN1Integer.getInstance, which rejects them: neither factory accepted its own type. org.bouncycastle.oer.its.etsi103097.EtsiTs103097DataEncryptedUnicast.getInstance guarded on its sibling EtsiTs103097DataEncrypted and then cast to the unicast type, so an EtsiTs103097DataEncrypted threw ClassCastException. org.bouncycastle.oer.OEROptional.getObject(Class) called value.getClass().isInstance(type) with the arguments transposed, which is always false because the argument is a java.lang.Class, so the cast path was dead and every optional field was resolved reflectively, failing with IllegalStateException for a target type with no static getInstance. Each guard now names the type it returns, matching the sibling UINT8 / UINT16 / UINT64 and EtsiTs103097DataEncrypted factories (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2373\"\u003e#2373\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eDefaultAlgorithmNameFinder and DefaultSignatureNameFinder had no entries at all for the ShangMi algorithms, so an SM2 signature AlgorithmIdentifier that DefaultSignatureAlgorithmIdentifierFinder itself produces came back named only by its OID string - getAlgorithmName(GMObjectIdentifiers.sm2sign_with_sm3) returned \u0026quot;1.2.156.10197.1.501\u0026quot; and hasAlgorithmName returned false. Both finders now name sm2sign_with_sm3 as SM3WITHSM2 and sm2sign_with_sha256 as SHA256WITHSM2, and DefaultAlgorithmNameFinder additionally names the sm3 digest. All three resolve through the BC provider, as Signature and MessageDigest respectively. The remaining GM arc - the SM4 cipher modes, the sm2encrypt variants, and the SM1 / SM6 / SSF33 ciphers BC does not implement - is still unnamed (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2377\"\u003e#2377\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe RFC 4998 evidence-record classes compared the digest AlgorithmIdentifier named by a time-stamp authority with the one their own DigestCalculator uses, and did so with AlgorithmIdentifier.equals(), which compares the encodings. A TSA that names SHA-256 with an explicit NULL parameters field - DigiCert among them - therefore failed against BC's own calculator, which names it with the parameters absent, and ERSArchiveTimeStampGenerator.generateArchiveTimeStamp rejected the response with \u0026quot;time stamp imprint for wrong algorithm\u0026quot;. Both spellings name the same digest and RFC 5754 sec. 2 requires a receiver to accept either, while requiring that identifiers be generated with the parameters absent, which BC already does. The three affected comparisons - the two in ERSArchiveTimeStampGenerator and the digest check in ERSEvidenceRecord.renew - now use the new AlgorithmIdentifier.areEquivalent, which matches on the algorithm and treats an absent parameters field and NULL as the same, and the consistency check across an evidence record's archive time stamp chain uses it too. An identifier carrying an actual parameter structure is never equivalent to one carrying none (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2379\"\u003e#2379\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eEDIPartyName.toASN1Primitive emitted the nameAssigner and partyName DirectoryStrings without their context tags, so an EDIPartyName built through its public constructor could not be parsed back by EDIPartyName.getInstance, which correctly requires them. RFC 5280 sec. 4.2.1.6 tags both members [0] and [1], and those tags are explicit despite the module's IMPLICIT TAGS because DirectoryString is a CHOICE, which X.680 does not allow to be tagged implicitly - the decoder already had this right. The encoder now matches it. Note the type was added during the 1.85 cycle and GeneralName validates its ediPartyName alternative through it, so a GeneralName carrying an untagged ediPartyName - including one BC itself produced - is rejected where 1.84 passed it through unexamined; the untagged form is not read leniently (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2380\"\u003e#2380\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eRSASSA-PSS could not be used with a RIPEMD digest through the JCA API. Nothing registered the RIPEMD PSS signatures, so Signature.getInstance(\u0026quot;RIPEMD160WITHRSAANDMGF1\u0026quot;) raised NoSuchAlgorithmException, and the generic RSASSA-PSS route with an explicit PSSParameterSpec failed too: org.bouncycastle.jcajce.provider.util.DigestFactory.getDigest returned null for a RIPEMD name, and isSameDigest - an allow-list of the SHA families and MD5 - reported two identical RIPEMD names as different digests, so the spec was rejected with \u0026quot;digest algorithm for MGF should be the same as for PSS parameters\u0026quot;. isSameDigest now answers true for equal names whatever the digest, which also covers Whirlpool, SM3, GOST3411 and anything else outside that allow-list; DigestFactory recognises RIPEMD128, RIPEMD160 and RIPEMD256 by name and OID; the three PSS signatures are registered with MGF1 over the same digest and a salt of the digest length; and DefaultSignatureAlgorithmIdentifierFinder gains the matching RIPEMD*WITHRSAANDMGF1 entries with their RSASSA-PSS-params, so the operator/JcaContentSignerBuilder path works as well. Note BC continues to require the PSS hash and the MGF1 hash to be the same, which RFC 8017 does not itself demand (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2381\"\u003e#2381\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe opt-in key-size validation on CMS key-transport recipients (org.bouncycastle.cms.jcajce.JceKeyTransRecipient.setKeySizeValidation(true)) never ran for a message using RFC 9709 CEK derivation (id-alg-cek-hkdf-sha256): the branch that should have selected the actual content-encryption algorithm carried in the KDF AlgorithmIdentifier's parameters compared the encrypted-key byte array against the id-alg-cek-hkdf-sha256 object identifier - a comparison that is always false - so the check fell through to a key-size lookup on the outer KDF OID, which has no registered key size, and silently checked nothing. A key-transport EnvelopedData/AuthEnvelopedData whose transported (and HKDF-derived) content-encryption key did not match the key size of the advertised content-encryption algorithm was therefore accepted even with validation enabled. The recipient now dispatches on the content-encryption AlgorithmIdentifier's algorithm OID, so key-size validation of RFC 9709 messages checks the recovered key against the inner content-encryption algorithm. Messages with a matching key size, non-HKDF messages, and recipients that do not enable validation are unaffected.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003eSee full diff in \u003ca href=\"https://github.com/bcgit/bc-java/commits\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003ecommonmark-java 0.29.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e[0.29.0] - 2026-06-20\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/comm...\n\n_Description has been truncated_","html_url":"https://github.com/greench-ai/GreenchClaw/pull/43","url":"https://dependabot.ecosyste.ms/api/v1/hosts/GitHub/repositories/greench-ai%2FGreenchClaw/issues/43","packages_url":"https://dependabot.ecosyste.ms/api/v1/issues/43/packages"},{"uuid":"5405355443","node_id":"PR_kwDOUIXVxs8AAAABC56M1A","number":11,"state":"closed","title":"chore(deps): bump the android-deps group across 1 directory with 16 updates","user":"dependabot[bot]","labels":["dependencies","java"],"assignees":[],"locked":false,"comments_count":1,"pull_request":true,"closed_at":"2026-09-11T22:18:04.000Z","author_association":null,"state_reason":null,"created_at":"2026-09-09T22:22:36.000Z","updated_at":"2026-09-11T22:18:08.000Z","time_to_close":172528,"merged_at":null,"merged_by":null,"closed_by":null,"dependency_metadata":{"prefix":"chore(deps): bump","group_name":"android-deps","update_count":16,"packages":[{"name":"gradle-wrapper","old_version":"9.5.1","new_version":"9.7.1","repository_url":"https://github.com/gradle/gradle"},{"name":"org.bouncycastle:bcprov-jdk18on","old_version":"1.84","new_version":"1.85.2","repository_url":"https://github.com/bcgit/bc-java"},{"name":"org.commonmark:commonmark","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-autolink","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-strikethrough","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-tables","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-task-list-items","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.junit.vintage:junit-vintage-engine","old_version":"6.1.0","new_version":"6.1.3","repository_url":"https://github.com/junit-team/junit-framework"},{"name":"io.kotest:kotest-assertions-core-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"io.kotest:kotest-runner-junit5-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"com.squareup.okhttp3:mockwebserver","old_version":"5.3.2","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.squareup.okhttp3:okhttp","old_version":"5.3.2","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.android.application","old_version":"9.2.1","new_version":"9.4.0"},{"name":"com.android.test","old_version":"9.2.1","new_version":"9.4.0"},{"name":"org.jetbrains.kotlin.plugin.compose","old_version":"2.4.0","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"},{"name":"org.jetbrains.kotlin.plugin.serialization","old_version":"2.4.0","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"}],"path":null,"ecosystem":"maven"},"body":"Bumps the android-deps group with 16 updates in the /apps/android directory:\n\n| Package | From | To |\n| --- | --- | --- |\n| [gradle-wrapper](https://github.com/gradle/gradle) | `9.5.1` | `9.7.1` |\n| [org.bouncycastle:bcprov-jdk18on](https://github.com/bcgit/bc-java) | `1.84` | `1.85.2` |\n| [org.commonmark:commonmark](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-autolink](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-strikethrough](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-tables](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-task-list-items](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.junit.vintage:junit-vintage-engine](https://github.com/junit-team/junit-framework) | `6.1.0` | `6.1.3` |\n| [io.kotest:kotest-assertions-core-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [io.kotest:kotest-runner-junit5-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [com.squareup.okhttp3:mockwebserver](https://github.com/lysine-dev/okhttp) | `5.3.2` | `5.5.0` |\n| [com.squareup.okhttp3:okhttp](https://github.com/lysine-dev/okhttp) | `5.3.2` | `5.5.0` |\n| com.android.application | `9.2.1` | `9.4.0` |\n| com.android.test | `9.2.1` | `9.4.0` |\n| [org.jetbrains.kotlin.plugin.compose](https://github.com/JetBrains/kotlin) | `2.4.0` | `2.4.20` |\n| [org.jetbrains.kotlin.plugin.serialization](https://github.com/JetBrains/kotlin) | `2.4.0` | `2.4.20` |\n\n\nUpdates `gradle-wrapper` from 9.5.1 to 9.7.1\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/gradle/gradle/releases\"\u003egradle-wrapper's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e9.7.1\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.1.\u003c/p\u003e\n\u003cp\u003eThis is a patch release for 9.7.0. We recommend using 9.7.1 instead of 9.7.0.\u003c/p\u003e\n\u003cp\u003eHere are the highlights of 9.7.0 release:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIsolated Projects graduates to incubating\u003c/li\u003e\n\u003cli\u003eBroader Configuration Cache compatibility\u003c/li\u003e\n\u003cli\u003eResilient Sync helps you fix broken builds\u003c/li\u003e\n\u003cli\u003eMore source locations in problem reports\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003ca href=\"https://docs.gradle.org/9.7.1/release-notes.html\"\u003eRead the Release Notes\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eWe would like to thank the following community members for their contributions to this release of Gradle:\n\u003ca href=\"https://github.com/aSemy\"\u003eAdam\u003c/a\u003e,\n\u003ca href=\"https://github.com/Gautam-aman\"\u003eAman Gautam\u003c/a\u003e,\n\u003ca href=\"https://github.com/YukiCodepth\"\u003eAman Kumar\u003c/a\u003e,\n\u003ca href=\"https://github.com/adubrouski\"\u003eAnton Dubrouski\u003c/a\u003e,\n\u003ca href=\"https://github.com/liutikas\"\u003eAurimas\u003c/a\u003e,\n\u003ca href=\"https://github.com/gbhavya07\"\u003egbhavya07\u003c/a\u003e,\n\u003ca href=\"https://github.com/joshfriend\"\u003eJosh Friend\u003c/a\u003e,\n\u003ca href=\"https://github.com/nicklauslittle-gov\"\u003enicklauslittle-gov\u003c/a\u003e,\n\u003ca href=\"https://github.com/psoni674\"\u003ePragati\u003c/a\u003e,\n\u003ca href=\"https://github.com/Project516\"\u003eproject516\u003c/a\u003e,\n\u003ca href=\"https://github.com/Uomocapra\"\u003eQin Mi\u003c/a\u003e,\n\u003ca href=\"https://github.com/rkdfx\"\u003eRavi\u003c/a\u003e,\n\u003ca href=\"https://github.com/sk-reddy17\"\u003esk-reddy17\u003c/a\u003e,\n\u003ca href=\"https://github.com/Suvrat1629\"\u003eSuvrat Acharya\u003c/a\u003e,\n\u003ca href=\"https://github.com/ShreckYe\"\u003eYongshun Ye\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eUpgrade instructions\u003c/h2\u003e\n\u003cp\u003eSwitch your build to use Gradle 9.7.1 by updating your wrapper:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e./gradlew :wrapper --gradle-version=9.7.1 \u0026amp;\u0026amp; ./gradlew :wrapper\r\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eSee the Gradle \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/upgrading_version_9.html\"\u003e9.x upgrade guide\u003c/a\u003e to learn about deprecations, breaking changes and other considerations when upgrading.\u003c/p\u003e\n\u003cp\u003eFor Java, Groovy, Kotlin and Android compatibility, see the \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/compatibility.html\"\u003efull compatibility notes\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eReporting problems\u003c/h2\u003e\n\u003cp\u003eIf you find a problem with this release, please file a bug on \u003ca href=\"https://github.com/gradle/gradle/issues\"\u003eGitHub Issues\u003c/a\u003e adhering to our issue guidelines.\nIf you're not sure you're encountering a bug, please use the \u003ca href=\"https://discuss.gradle.org/c/help-discuss\"\u003eforum\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eWe hope you will build happiness with Gradle, and we look forward to your feedback via \u003ca href=\"https://twitter.com/gradle\"\u003eTwitter\u003c/a\u003e or on \u003ca href=\"https://github.com/gradle\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003e9.7.0\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.0.\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/92f0512e7f06d84621afba191f75e265363890cf\"\u003e\u003ccode\u003e92f0512\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38892\"\u003e#38892\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/820ee75a99a179bbffa41bcedc6477b685fabb9f\"\u003e\u003ccode\u003e820ee75\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/82c23f9bd2a89b4cc644e1f90a28a8668feb3dee\"\u003e\u003ccode\u003e82c23f9\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering problem in KTS (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38878\"\u003e#38878\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/ef11a7268fe8cc8d6ab849ec911aa11220180553\"\u003e\u003ccode\u003eef11a72\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering issue\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/bb0d8a974a71b1003efea41e4046e98855cd5ff8\"\u003e\u003ccode\u003ebb0d8a9\u003c/code\u003e\u003c/a\u003e Make relevant tests polyglot (run for multiple DSLs)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/336e129d7f95c03486acafc97abf59734acfed48\"\u003e\u003ccode\u003e336e129\u003c/code\u003e\u003c/a\u003e Update signing configuration (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38874\"\u003e#38874\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/4bdf0da2dad9884d089a6062a45ea7183e7d735d\"\u003e\u003ccode\u003e4bdf0da\u003c/code\u003e\u003c/a\u003e Update signing configuration\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/cd9b92c1b82856248cf1dc58b50378238bec7b52\"\u003e\u003ccode\u003ecd9b92c\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38839\"\u003e#38839\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/5f4e381964897ad8d6b99e5a7c77f26dba3259fb\"\u003e\u003ccode\u003e5f4e381\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/1e08ab551367aeb5fb48b26e72807e1d2b27c939\"\u003e\u003ccode\u003e1e08ab5\u003c/code\u003e\u003c/a\u003e Keep type-use annotations in extracted ABI classes (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38810\"\u003e#38810\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/gradle/gradle/compare/v9.5.1...v9.7.1\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.bouncycastle:bcprov-jdk18on` from 1.84 to 1.85.2\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.md\"\u003eorg.bouncycastle:bcprov-jdk18on's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch1\u003eBouncy Castle Crypto Package - Release Notes\u003c/h1\u003e\n\u003ch2\u003e1.0 Introduction\u003c/h2\u003e\n\u003cp\u003eThe Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. The package is organised so that it contains a light-weight API suitable for use in any environment (including the J2ME) with the additional infrastructure to conform the algorithms to the JCE framework.\u003c/p\u003e\n\u003ch2\u003e2.0 Release History\u003c/h2\u003e\n\u003cp\u003e\u003c!-- raw HTML omitted --\u003e\u003c!-- raw HTML omitted --\u003e\u003c/p\u003e\n\u003ch3\u003e2.1.1 Version\u003c/h3\u003e\n\u003cp\u003eRelease: 1.86\u003cbr /\u003e\nDate: 2026, TBD\u003c/p\u003e\n\u003ch3\u003e2.1.2 Defects Fixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) let a subkey inherit the primary key's Key Flags when its own Subkey Binding signature carried no Key Flags subpacket, which made the two capability decisions taken for one subkey disagree. OpenPGPCertificate.OpenPGPComponentKey.isSigningKey() reads the effective flags, which fell back to the primary key's direct-key or primary user ID self-signature, so a subkey bound with no flags of its own counted as signing-capable; verifyEmbeddedPrimaryKeyBinding reads the binding signature's own flags, found no signing capability there, and so skipped the embedded Primary Key Binding (cross-certification) signature that RFC 9580 sec. 5.2.1.8 and sec. 10.1.3 require of a subkey that can issue signatures. A data signature made by such a subkey was therefore attributed to the certificate and reported valid by OpenPGPSignature.OpenPGPDocumentSignature.isValid() with the cross-certification requirement never applied, where GnuPG refuses the same certificate and message as not cross-certified. An attacker holding a third party's public signing subkey - which is public material - could bind it to their own primary key with a Subkey Binding signature they are able to make, carrying no Key Flags and no embedded Primary Key Binding signature, which they cannot make without the subkey's private key, and have that party's genuine signatures verify as valid under the attacker's own identity: misattribution of a real signature rather than a forgery of a new one, since the signature still has to be one the subkey actually made. Key Flags are a statement about the key the carrying signature refers to (RFC 9580 sec. 5.2.3.29), so a subkey no longer inherits them from the certificate-wide signatures of the primary key: a Subkey Binding signature that omits the subpacket now leaves the subkey with no capabilities rather than the primary's, which makes the flags the cross-certification check consults the same flags every other decision consults. Preferences and the other subpackets a direct-key signature carries are inherited as before, and the primary key itself - whose flags legitimately come from its direct-key or user ID self-signature - is unaffected. The low-level PGPSignature / PGPPublicKeyRing API performs no binding checks by design and is unchanged.\u003c/li\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) used a version 6 key that carried no valid Direct Key signature, falling back to the primary user ID binding as it correctly does for a version 4 key. RFC 9580 sec. 5.2.3.10 requires the opposite: \u0026quot;An implementation MUST ensure that a valid Direct Key signature is present before using a version 6 key. This prevents certain attacks where an adversary strips a self-signature specifying a Key Expiration Time or certain preferences.\u0026quot; The certificate grammar says the same structurally, the Direct Key signature being mandatory in the version 6 structure of sec. 10.1.1 and optional in the version 4 one of sec. 10.1.3. Because a version 6 certificate carries its key expiration, features and algorithm preferences on the Direct Key signature - the convention the RFC recommends and the one OpenPGPKeyGenerator follows, its user ID certification carrying no expiration at all - removing that single signature packet from a published certificate silently dropped the expiration along with the preferences and features: OpenPGPCertificate.getSignatureChainFor fell back to the user ID binding, the primary key was still reported bound, and getEncryptionKeys() and getSigningKeys() went on returning the subkeys of a key whose owner had set it to expire. The primary key fingerprint is unchanged by the removal, so a relying party pinning the key by fingerprint still treats it as the same key, and no private key or hash collision is involved; the natural moment for the strip is the key refresh that RFC 9580 names as the reason to refetch a key at all - to learn about changes in expiration, features, preferences and revocation - which is exactly the update it defeats. This is a downgrade rather than a forgery, nothing being attributed to a key that did not authorise it, and the concerning direction is encryption, to a key meant to have been retired. OpenPGPCertificate.isBoundBy now requires a valid Direct Key self-signature on a version 6 primary key before any component of the certificate - the primary key, its subkeys or its identities - is treated as bound, so a version 6 certificate stripped of it offers no keys at all rather than an unexpiring set. Version 4 certificates are unaffected: there the key expiration legitimately lives on the user ID self-signature and the fallback is correct, so it stays. The revocation-only version 6 certificate of sec. 10.1.2, which legitimately carries no Direct Key signature, is unaffected as well - its key was already refused as revoked, and reading the revocation does not go through the binding check.\u003c/li\u003e\n\u003cli\u003eThe lightweight LMSSigner and HSSSigner refused a key wrapped in ParametersWithRandom, which is how BcContentSignerBuilder passes a key whenever setSecureRandom() has been called - so BcHssLmsContentSignerBuilder built a working signer until a random was set and then failed with \u0026quot;Incorrect Key Parameters\u0026quot;, and the two signers themselves raised ClassCastException on the same input. All three now unwrap it, as the promoted ML-DSA and SLH-DSA signers already did. The random is accepted and not used: LMS derives its message randomiser C from the key's seed and the one-time index, so it is deterministic and cannot repeat while q does not. Note SP 800-208 sec. 6.1 asks for C to come from an approved random bit generator, which this implementation does not do; that is unchanged here, and a supplied random is now ignored rather than refused.\u003c/li\u003e\n\u003cli\u003eLMS signature verification did not apply two of the checks RFC 8554 sec. 5.4.2 requires before a signature is processed. Step 2g refuses a signature whose LMS typecode is not the one from the public key, and without it the path computation took its height and tree digest from the parameter set the signature named rather than the key's, so a signature claiming a height-25 parameter set drove a 25-level computation against a height-5 key. Step 2i refuses a leaf number q outside the tree, and without it an out-of-range q flowed into the node arithmetic and was left for the candidate-root comparison to catch. Neither was a forgery - the domain separation between D_LEAF and D_INTR and the final comparison saw to that - but both are attacker-chosen work the specification says to refuse up front. Both are now checked, and a signature failing either is still reported as not verifying rather than thrown out of Signature.verify(). The catch around the signature decode in LMSSigner and HSSSigner has also been narrowed to the decode itself, as the corresponding SPI was corrected to do for github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2408\"\u003e#2408\u003c/a\u003e: past the parse the engine reports an inconsistent signature by returning false rather than by throwing, so the wider catch caught nothing while standing ready to turn a future internal error into a quiet false.\u003c/li\u003e\n\u003cli\u003eThe LMS and HSS key parameter classes now apply at construction the checks their decoders apply, so a key built directly cannot be one the decoder would refuse. LMSPrivateKeyParameters accepted an identifier of any length although the decoder reads exactly 16 bytes - such a key encoded but could not be read back - and left q, maxQ and the seed length unchecked; the seed is now required to be at least m bytes at decode as well, where a one-byte seed had been decoding silently and then deriving every one-time key from it. HSSPrivateKeyParameters checked neither its level count nor that it had been given a component key per level and a chaining signature per level below the root, and then indexed both lists, so a mismatch surfaced as IndexOutOfBoundsException - or, where a level happened to match, as a null chaining signature that only failed at signing time; the level is now checked after the reset that fills it in, since a null is legitimate on the way in. LMSPrivateKeyParameters.getInstance(byte[], byte[]) adopted the public key supplied beside the private one without comparing them, so a mismatched public key was simply reported by getPublicKey(); it now cross-checks the identifier, both parameter sets and, where the tree cache already holds it, the root, as the HSS entry point does. The decoders also now report a bad version or seed length as IOException rather than IllegalStateException, so a caller can catch one type for a malformed key, and the package-private LM-OTS public key decoder no longer declares throws Exception or dereferences an unrecognised typecode. The deprecated org.bouncycastle.pqc.crypto.lms copies carry the decoder corrections.\u003c/li\u003e\n\u003cli\u003eIn the LMS JCE layer, LMSKeyGenParameterSpec.fromNames knew all twenty LMS parameter-set names but only four of the sixteen LM-OTS ones, so none of the SP 800-208 n24 or SHAKE sets could be named; all sixteen are now present. KeyPairGenerator.initialize(int, SecureRandom) reports InvalidParameterException, which is what the JCA specifies and which extends the IllegalArgumentException it raised before, so existing catches still match. BCLMSPrivateKey.getIndex now takes the exhaustion check and the index read under the key's own monitor rather than as two separate calls, and two unused fields have gone from LMSSignatureSpi. Note that the LMS Signature claims its one-time key at the first update() rather than at sign(), so a Signature that is initialised and updated and then abandoned spends an index without producing a signature - the safe direction for a one-time scheme, and now documented on the SPI.\u003c/li\u003e\n\u003cli\u003eEvery other key pair generator that refuses a key size did the same thing the LMS one did above. KeyPairGenerator.initialize(int, SecureRandom) is documented to raise InvalidParameterException when the key size is not one the generator supports, and thirty of them raised a bare IllegalArgumentException instead, so a caller following the JCA and catching the documented type saw an exception escaping rather than a refusal. The ML-DSA, ML-KEM, SLH-DSA, Classic McEliece, FrodoKEM, NTRU and composite signature and KEM generators in the BC provider, and every generator in BCPQC, now raise InvalidParameterException - NewHope included, where the value is a key size it will not take rather than a mode of initialisation it does not offer. InvalidParameterException extends IllegalArgumentException, so callers written against the old behaviour go on catching it unchanged. The two RSA generators are corrected as well, and differently: theirs is a key size below a floor rather than a mode of initialisation they do not offer, and the refusal is raised by the lightweight RSAKeyGenerationParameters, which cannot name a java.security exception at all, so the RSA KeyPairGeneratorSpi now translates it - keeping the message verbatim and the original exception as the cause, through a new SecurityExceptions.invalidParameterException factory, since InvalidParameterException has no constructor that takes one. Of the 304 KeyPairGenerator services the two providers register, 299 now refuse a nonsense key size the way the JCA defines it and five accept it as a strength they can work with, with none left raising a bare IllegalArgumentException; that is asserted as a sweep over both providers rather than per algorithm, so a generator added later is covered without the test being touched. The jdk1.3 provider overlays of the four generators that have one carry the same change, and the jdk1.3 SecurityExceptions overlay gains the new factory along with the invalidAlgorithmParameterException one it had been missing.\u003c/li\u003e\n\u003cli\u003eKeyPairGenerator.initialize(AlgorithmParameterSpec, SecureRandom) had the same shape of problem as the int overload above, and only 44 of the 304 services the two providers register reported an unusable spec as the InvalidAlgorithmParameterException that method declares. The twenty-three PQC generators that resolve a parameter set by name - cmce, frodokem, mldsa, mlkem, slhdsa, aimer, bike, faest, falcon, haetae, hqc, mayo, mqom, ntru, ntruplus, both ntruprime variants, qruov, saber, sdith, smaugt, snova and sqisign, 230 services between them - case-folded the name they got back from the spec without checking it, so a spec with no getName() method, and a null spec, produced a NullPointerException from inside the fold; their own \u0026quot;is this name one I know\u0026quot; branch, which does report the declared exception, was unreachable. The two composite generators, whose parameter set is fixed by the algorithm name so that null is the only spec they accept, refused every other one with IllegalArgumentException. RSA answered correctly for a spec of the wrong type but not for one of the right type carrying values its lightweight parameters will not take - an even public exponent, or a key size below the floor - which is now translated the same way the int overload's is. All 304 services now report the declared exception, with the composites still taking the null spec that is right for them; note that InvalidAlgorithmParameterException is a checked exception and not an IllegalArgumentException, so a caller that was catching what these threw before has to catch the declared type instead.\u003c/li\u003e\n\u003cli\u003eAn HSS private key claimed the two records of its position under two different monitors. The top-level index and the bottom component key's one-time index q are independent records of the same position - the decoder requires them to agree, see the entry below - but generateLMSContext incremented the index under the HSS key's own monitor, released it, and only then claimed q under the component key's. A getEncoded() issued in between saw the index advanced and q not, and produced an encoding this implementation's own decoder rejects; and two threads meeting at a bottom-tree boundary could both pass the exhaustion test, take consecutive top-level indices and claim the same q, after which one of them was refused with \u0026quot;ots private key exhausted\u0026quot; by a key still reporting usages remaining, a top-level index had been spent with no signature made, and the two records stayed one apart for the rest of the key's life in that process - so it could no longer be encoded, cloned or sharded, and getIndex() and getUsagesRemaining() misreported by one. No one-time key was reused: the component key's claim is itself atomic, and the divergence runs index ahead of leaves, so the effect was on the key's usability rather than on the signatures it had made. Both records are now claimed under the one monitor, and the component key is claimed before the index is incremented so that an exhausted one leaves both untouched. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the same correction.\u003c/li\u003e\n\u003cli\u003eTimeStampToken parsed the attacker-controlled TSTInfo content of a time-stamp token (org.bouncycastle.tsp.TimeStampToken, reached from TimeStampResponse(byte[]) and (InputStream)) inside a try that caught only CMSException, so a well-formed RFC 3161 TimeStampResp whose embedded token carried a malformed TSTInfo - a SEQUENCE with fewer elements than the five mandatory fields, a non-SEQUENCE, truncated DER, or an unknown context tag - let an IllegalArgumentException or a NoSuchElementException escape the constructor's declared throws TSPException, IOException contract. A token signed by no signers or by more than one raised a bare IllegalArgumentException from the same constructor, before that try, for the same reason. Both are now reported as TSPException, matching the package-private TimeStampResponse(DLSequence) constructor and the existing getSignedAttributes guard in the same method; the signer-count refusal is a TSPValidationException, as the neighbouring check on the content type already was. Related, and the cause of the NoSuchElementException: asn1.tsp.TSTInfo read its five mandatory fields off the sequence with no bound on how many elements were actually there, so a short SEQUENCE left the enumeration to run out rather than being refused, and an oversize one was accepted with its extra elements absorbed into the optional slots. Decode now requires the five to ten elements RFC 3161 sec. 2.4.2 gives the type, which is what the sibling Accuracy and ArchiveTimeStamp decoders already did, so the failure is the IllegalArgumentException that getInstance is expected to raise (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2415\"\u003e#2415\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eNeither the HSS nor the XMSS^MT private key decoder checked its declared index against the traversal state stored beside it, although the two are independent records of the same position in the key and so can be compared. For HSS the records are the top-level index and the component keys' one-time indices q; for XMSS^MT they are the global index and the per-layer BDS states. A stored key whose index had been rolled back while its state stayed advanced - a partial write, a restore from backup, a buggy storage layer - was therefore accepted, and it then signed a second message under a one-time key the key had already used, producing a signature that verified, so nothing anywhere surfaced the reuse. RFC 8554 sec. 1 and RFC 8391 sec. 1.1 both require each one-time key to be used exactly once, and this is the failure those requirements exist to prevent; the single-tree XMSS decoder has tied its BDS state to its index since that state was first validated, and this brings the two multi-tree schemes into line. HSS decode now requires the declared index to equal the position the component q values imply - a level above the last contributes (q - 1) leaves of the levels beneath it, since its q has already advanced past the subtree it signed - and XMSS^MT decode now requires each present layer's BDS index to equal the leaf index that layer derives from the global index, allowing the one position where a layer has moved into a new subtree and its state legitimately still carries the previous subtree's final index. A layer with no state yet is unaffected, since those are built lazily at signing time. Related, and the same shape of omission: an XMSS or XMSS^MT private key encoding carries the tree root twice - the key's own root field and the root node of the BDS state stored beside it, which for XMSS^MT is the top layer's - and the two were never compared either. A corrupted root was accepted and then poisoned every signature the key made, because the root is hashed into the message digest: the signature did not verify and nothing indicated why. Decode now requires the two copies to agree. The BDS node values themselves are not checkable the way the LMS tree cache above is - a BDS authentication path, stack, retain or keep node does not have its children stored alongside it, so recomputing one means building a subtree, which is the work the state exists to avoid. Both checks are integer comparisons over the levels of the key, too small to measure against the surrounding decode, and both were verified not to reject any legitimate key by walking every index a key can reach: the full key space of the two-level HSS and the h=4/d=2, h=6/d=2, h=6/d=3, h=9/d=3 and h=8/d=4 XMSS^MT parameter sets, plus a three-level HSS key across a subtree boundary and an HSS shard. Since those node values cannot be recomputed, the encoded state now carries a checksum over itself instead, with the owning key's public seed hashed in front of it. Any corruption of the stored state is refused at decode rather than being loaded and then producing signatures that silently do not verify, and because the public seed is bound in, a state transplanted between two keys of the same parameter set is refused too, even though it is internally consistent and arrives with its own matching root. The public seed is bound rather than the secret seed or the PRF key deliberately: the state's own root and index are inside the encoding and so are already covered, hashing secret material would make the stored checksum a commitment to it for no gain in detection, and the PRF key does not influence the state at all. \u003cstrong\u003eThis is an error-detecting code and not integrity protection\u003c/strong\u003e - anyone able to rewrite the stored key recomputes it, so it establishes that the state is unchanged since it was written, never that it was correct when written, and the allocation bounds on the encoding remain the guard against a crafted one. It costs one SHA-256 over the state, measured at 5 to 8 microseconds each way for the h=10 and h=16 parameter sets, and 32 bytes of encoding. The state encoding was added earlier in this same cycle and has not been released, so the checksum is simply part of it rather than a new version: a state written by a 1.86 beta is rejected, which is recovered from by re-exporting the key. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the HSS check as well (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2414\"\u003e#2414\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe S/MIME example smoke test in the misc module (org.bouncycastle.mail.smime.examples.test.AllTests) drove SendSignedAndEncryptedMail against smtp.gmail.com, and that example finishes with Transport.send() under JavaMail's default settings, which have no connect timeout. Where outbound port 25 is refused the failure was swallowed and the test passed; where it is silently dropped, as on many home networks, the connect blocked and ./gradlew build hung in :misc:test indefinitely with \u0026quot;0 tests completed\u0026quot;. The test now delivers to an SMTP stub on a loopback port, with connect / read / write timeouts as a backstop, and asserts the message arrived (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2407\"\u003e#2407\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation took the traditional component public key bytes it feeds the KEM combiner from the recipient key's own encoding, while decapsulation recomputes the point from the private key and so always produced an uncompressed one. Section 4 of draft-ietf-lamps-pq-composite-kem requires an EC component to be carried as an uncompressed point, but a component key that encodes itself compressed - a BC EC key whose point format has been set through org.bouncycastle.jce.interfaces.ECPointEncoder, or a key from a provider that preserves a compressed encoding - was passed through as it came. Both sides then combined a different tradPK and derived different shared secrets, with no error reported on either: encapsulation and decapsulation both succeeded and the recipient simply could not decrypt. The EC component is now normalised to an uncompressed point wherever the engine serialises one, which covers the ephemeral key that forms the ciphertext as well. X25519 and X448 components have a single encoding and were unaffected, as were EC keys left in their default (uncompressed) format, whose shared secrets are unchanged. CompositePublicKey.getEncoded() took its component bytes the same way, so such a key also encoded to a composite key other implementations reject and whose bytes changed across an encode / decode / encode round trip - 1238 bytes rather than 1270 for MLKEM768-ECDH-P256, and for the composite ML-DSA keys sharing that method, 2006 rather than 2038 for MLDSA65-ECDSA-P256. It now normalises the component the same way. This is a write-side change only: a composite key carrying a compressed EC component is still decoded, since the component key factories accept either form, and continues to verify signatures as before - it simply re-encodes in the normalised form. The shared normalisation is org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil.getUncompressedSubjectPublicKeyBytes.\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation threw a NullPointerException, wrapped in an IllegalStateException out of KeyGenerator.generateKey(), when the SecureRandom it was given was null - which javax.crypto.KEM.newEncapsulator() documents as a request for the provider's default, and which KeyGenerator.init(spec, null) passes straight through. The three RSA-OAEP composites draw the traditional shared secret from that random directly, so they were the ones affected; the ECDH and X25519 / X448 composites escaped only because their component KeyPairGenerators default a random of their own. CompositeMLKEMEngine now defaults one through CryptoServicesRegistrar.getSecureRandom() on first use, as the composite KEM Cipher's wrap path already did, and as the KEM generators corrected earlier in this cycle now do. Related, the engine now also clears the ML-KEM component's shared secret alongside the traditional one on both the encapsulate and decapsulate paths - the copy handed back by getEncoded() was left in the heap - as section 3.5 of draft-ietf-lamps-pq-composite-kem requires.\u003c/li\u003e\n\u003cli\u003eCompositePublicKey.getAlgorithm() and CompositePrivateKey.getAlgorithm() returned null for all twelve Composite ML-KEM (draft-ietf-lamps-pq-composite-kem) parameter sets. Both classes resolved the name through the composite signature index only, which holds the composite ML-DSA OIDs, so a composite KEM key pair - generated, parsed from a certificate, or read from PKCS#8 - reported no algorithm at all, and the standard JCA idiom of reconstructing a key with KeyFactory.getInstance(key.getAlgorithm()) raised a NullPointerException. The lookup now falls back to the composite KEM index, so the name returned is the one the provider registers the algorithm under (e.g. MLKEM768-X25519-SHA3-256), matching the composite ML-DSA behaviour. The same single-index assumption made the CompositePublicKey(SubjectPublicKeyInfo) and CompositePrivateKey(PrivateKeyInfo) constructors reject a composite KEM key with \u0026quot;unable to create CompositePublicKey from SubjectPublicKeyInfo\u0026quot;; they now dispatch to the composite KEM key factory for those OIDs. Keys obtained through KeyFactory or through BouncyCastleProvider.getPublicKey / getPrivateKey were unaffected and are unchanged (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2404\"\u003e#2404\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe org.bouncycastle.jcajce.spec.KEMKDFSpec constructor stored a null otherInfo as given, so getOtherInfo() returned null, and three of the KDF branches KdfUtil.makeKeyBytes dispatches to - KMAC-128, KMAC-256 and SHAKE-256 - read the otherInfo length without a guard and threw NullPointerException out of the KEM operation, where the KDF2, KDF3 and HKDF branches tolerate a null through KDFParameters / HKDFParameters. The Builder of every spec in the package already mapped null to empty, so no provider path reached it, but the constructor is protected on a public class and KdfUtil is documented for callers building their own KEM integration; the deprecated KEMParameterSpec passes a null itself and escaped only because it also pins the KDF to null. The constructor now stores empty for a null, so getOtherInfo() never returns null, and a null and an explicitly empty otherInfo derive the same key.\u003c/li\u003e\n\u003cli\u003eQR-UOV signature verification accepted a signature encoding that was not canonical, so the encoding of a signature was not unique even after the trailing-byte fix of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e. Each F_q element of the signature is stored in ceil(log2 q) bits, one more bit pattern than the field has elements: q itself is representable and is arithmetically congruent to zero, so an element written as q verified exactly as the same element written as zero would, and the bits padding the last element out to the byte boundary were never read at all. Every zero element of a signature therefore carried a second encoding, and for the q = 7 parameter sets roughly one element in seven is zero - a single qruov_5_q7_L10 signature measured 256 spare bits, so on the order of 2^256 distinct byte strings verified for the one message and key. Verification now rejects any element outside [0, q) and any set padding bit; a signature produced by this or by the reference implementation is unaffected, as the KAT vectors of every parameter set confirm. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSNOVA signature verification ignored four bits inside the signature for any parameter set whose solution is an odd number of GF(16) nibbles - the SNOVA_24_5_5, SNOVA_25_8_3, SNOVA_29_6_5 and SNOVA_66_15_3 families, sixteen of the forty-four parameter sets. The last byte of the encoded solution carries a single nibble and the signer leaves the top four bits zero, but the decoder did not read them, so sixteen distinct byte strings verified for one signature. This is the same non-unique encoding github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e closed for bytes following the signature, applied inside it; the verifier now requires those bits to be zero. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSnovaPrivateKeyParameters did not validate the length of the private key encoding handed to it - the only one of the five schemes of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e that did not - and SnovaParameters.getPrivateKeyLength() reported the expanded (\u0026quot;ESK\u0026quot;) length even for a parameter set whose private key is the seed pair. A private key encoding reaches this constructor straight from a PKCS#8 blob, so a wrong length went undetected: a seed-form key with extra bytes appended was accepted and signed under a different derived key, and a short expanded-form key sized the signer's decode buffer negatively, throwing NegativeArraySizeException out of generateSignature() rather than being reported at construction. Related, the signing retry loop could not terminate: the vinegar values are derived from a single-byte counter, so only 256 distinct linear systems can be tried, and an expanded-form private key that is not a real central map is singular for all of them - generateSignature() then span forever rather than failing. The length is now checked at construction, getPrivateKeyLength() reports the length that parameter set's private key actually has, and the retry loop gives up after its 256 attempts as MAYO's does.\u003c/li\u003e\n\u003cli\u003eMayoSigner and MayoKeyPairGenerator did not clear several buffers holding secret key material that the MAYO reference implementation explicitly clears. Signing left the secret oil space O, the expanded L = (P1 + P1^t) * O + P2, and the M / VPV / Ox intermediates of the central map in place, having gone to the trouble of clearing eleven other buffers; key generation left the expanded seed, whose tail is the encoded oil space, and the P1 * O + P2 half of P; and the row-echelon step left the packed echelon form of the secret linear system and its pivot rows. Separately, if all 256 attempts at solving for the signature had given a rank-deficient system, signing emitted a signature built from the failed attempt's state instead of reporting the failure the reference returns, and AIMerSigner.generateSignature returned an empty array on failure, which a caller would hand on as though it were a signature. Both now throw.\u003c/li\u003e\n\u003cli\u003eFive PQC signature schemes - MAYO, SNOVA, QR-UOV, SQIsign and AIMer - returned the NIST crypto_sign \u0026quot;sm\u0026quot; signed-message envelope from generateSignature() rather than the signature. That envelope is an artefact of the reference KAT harness, which records the message alongside the signature so a vector file can be self-contained; it is not part of any of the five specifications, and no other BC signer emits it (Falcon's KAT test rebuilds the equivalent envelope in the test, which is where it belongs). Two consequences followed, both reaching the JCA Signature services of every parameter set of the five schemes in BouncyCastlePQCProvider. First, since the message was appended to the signature, verification had to skip whatever followed the signature proper, and it did so by checking only that the buffer was long enough - so any number of trailing bytes could be added to a valid signature, or the appended message replaced with unrelated data, and it still verified. A signature encoding was therefore not unique: anyone holding one valid signature could produce unlimited distinct byte strings that all verified for the same message and key, which breaks any use that treats the signature bytes as an identifier, deduplicates on them, or records them as evidence. Second, the envelope propagated into everything built on the operator layer: because ContentSigner hands the signature straight into the structure being signed, every X.509 certificate, CRL, CMS SignedData and TLS CertificateVerify BC produced with one of these algorithms carried a verbatim copy of the signed data inside its own signature field - a self-signed MAYO-1 certificate came to 3567 bytes where the same certificate is now 2020 - which no other implementation can parse as a signature, and which in a detached CMS signature meant the \u0026quot;detached\u0026quot; signature carried the content. generateSignature() now returns the bare signature, and verifySignature() requires exactly the parameter set's signature length, so appended or truncated data is rejected rather than ignored. \u003cstrong\u003eThis is a behavioural change for signatures produced by an earlier release\u003c/strong\u003e - MAYO and SNOVA from 1.84, QR-UOV, SQIsign and AIMer from 1.85 - which are no longer accepted in the envelope form they were emitted in; the signature bytes themselves are unchanged, so a stored value can be recovered by taking the leading signature-length bytes, or for AIMer, whose envelope was message || signature rather than signature || message, the trailing ones. The KAT tests now rebuild the envelope before comparing against the vector files, which continue to record it. Note that AIMer's verification had already been made length-exact during this cycle (see the entry below relating to github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2401\"\u003e#2401\u003c/a\u003e), so of the five only its envelope remained (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe MLS implementation did not bind an X.509 credential to the LeafNode's signature_key. LeafNode.verify() checked a leaf's signature against the signature_key declared in the leaf itself, while the X.509 credential's certificate chain was stored but never parsed or checked, so the certificate's public key was never required to match signature_key (RFC 9420 sec. 5.3). A leaf could therefore carry one party's certificate while being signed by an unrelated key and still be accepted under that party's identity through KeyPackage.verify() and the Group leaf-validation path. LeafNode.verify() now requires the end-entity certificate's subject public key, in the cipher suite's signature encoding, to equal signature_key for an X.509 credential, and rejects the leaf otherwise - including an empty chain or a certificate whose key type does not match the cipher suite; certificate-chain and identity validation to a trust anchor remain the application's responsibility per RFC 9420 sec. 5.3.1. A public org.bouncycastle.mls.codec.Certificate(byte[]) constructor and a Credential.getCertificates() accessor are added so callers can build and inspect X.509 credentials. Basic credentials are unaffected.\u003c/li\u003e\n\u003cli\u003eThe SecureRandom supplied to org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder.setSecureRandom() did not drive the content IV / nonce for any algorithm other than RC2. EnvelopedDataHelper.generateParameters passed the caller's SecureRandom to the AlgorithmParameterGenerator only in the RC2_CBC branch; every other content-encryption algorithm - AES-CBC, AES-GCM, AES-CCM, Camellia, ARIA, SEED and the rest - reached pGen.generateParameters() on an uninitialised generator, so the IV / nonce was drawn from a default SecureRandom and setSecureRandom() was silently ignored (the builder's javadoc states that random is used for IV/nonce generation). The generator is now initialised with the supplied random on the general path as well, so a caller who provides a specific randomness source - for a controlled or FIPS-approved DRBG, say - has it honoured for the content IV / nonce. The session-key generation path was unaffected and already used the supplied random. Because the content IV / nonce now comes from the supplied SecureRandom, the org.bouncycastle.crypto.util JournalingSecureRandom / JournaledAlgorithm reproducible-encryption support records it in the transcript: a resumed session reproduces the IV / nonce by regenerating it from the replayed randomness - build the resuming encryptor from the content-algorithm OID - rather than by reusing the AlgorithmIdentifier captured from the first encryption, which no longer keeps the transcript aligned.\u003c/li\u003e\n\u003cli\u003eThe NTRU LPRime, NTRU+ and SMAUG-T KEM generators threw a NullPointerException when constructed with a null SecureRandom, where every other KEM generator - including NTRU LPRime's own SNTRU Prime counterpart in the same package - defaults one through CryptoServicesRegistrar.getSecureRandom(). This is reachable from the lightweight API directly, and from javax.crypto.KEM, whose newEncapsulator() documents a null random as a request for the provider's default.\u003c/li\u003e\n\u003cli\u003eFrodoKEMEngine kept a single SHAKE instance in a field, so an engine reached concurrently produced wrong results. It is reached that way through org.bouncycastle.crypto.kems.FrodoKEMExtractor, which holds one engine for its lifetime: two threads extracting through one extractor interleaved the digest's absorb and squeeze phases, yielding shared secrets that silently did not match the sender's, or an IllegalStateException of \u0026quot;attempt to absorb while squeezing\u0026quot; from inside extractSecret. The digest is now built per call, as CMCEEngine's already was, which makes an extractor safe to share. Encapsulation was unaffected, since FrodoKEMGenerator builds an engine per call. Results for any single-threaded use are unchanged - the reference KAT vectors are byte-identical.\u003c/li\u003e\n\u003cli\u003eThe BCJSSE provider carried the TLS 1.2 coupling between the supported_groups extension and ECDSA over into TLS 1.3: an ECDSA signature scheme was treated as usable - offered in the signature_algorithms and signature_algorithms_cert extensions, and eligible when selecting the local credentials - only while the corresponding curve was among the named groups enabled for key exchange, both per context (a group unavailable for key agreement disabled the scheme outright) and per connection (the curve had to be in the supported_groups list about to be sent). RFC 8446 sec. 4.2.7 scopes supported_groups to key exchange only, with signature algorithms negotiated independently (sec. 4.2.3), so this incorrect restriction in TLS 1.3 has been removed. Ed25519, Ed448 and the RSA schemes were unaffected (as well as typical deployments using a default configuration for named groups).\u003c/li\u003e\n\u003cli\u003eThe bcmail module descriptor did not declare its javax.mail/javax.activation dependences, so a modular (module-path) consumer of the jar hit IllegalAccessError/module-resolution failures when the S/MIME classes touched the mail API. The descriptor now requires them optionally (requires static) under all four module names those libraries are known by - the automatic names mail and activation carried by the javax.mail:mail / javax.activation:activation artifacts, and the explicit names java.mail and java.activation carried by the newer com.sun.mail / com.sun.activation ones - a hard requires on any one name would break users of the others (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2389\"\u003e#2389\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFour type-coercion helpers in the OER / IEEE 1609.2 (ITS) decoder tested the wrong type in the identity fast path that lets a getInstance() factory return an argument that is already of the target type. org.bouncycastle.oer.its.ieee1609dot2.basetypes.UINT32.getInstance and org.bouncycastle.oer.its.etsi102941.basetypes.Version.getInstance guarded on UINT8 - a sibling of UINT32 under UintBase, and unrelated to Version - so passing a UINT8 threw ClassCastException, while passing an actual UINT32 or Version missed the fast path and fell through to ASN1Integer.getInstance, which rejects them: neither factory accepted its own type. org.bouncycastle.oer.its.etsi103097.EtsiTs103097DataEncryptedUnicast.getInstance guarded on its sibling EtsiTs103097DataEncrypted and then cast to the unicast type, so an EtsiTs103097DataEncrypted threw ClassCastException. org.bouncycastle.oer.OEROptional.getObject(Class) called value.getClass().isInstance(type) with the arguments transposed, which is always false because the argument is a java.lang.Class, so the cast path was dead and every optional field was resolved reflectively, failing with IllegalStateException for a target type with no static getInstance. Each guard now names the type it returns, matching the sibling UINT8 / UINT16 / UINT64 and EtsiTs103097DataEncrypted factories (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2373\"\u003e#2373\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eDefaultAlgorithmNameFinder and DefaultSignatureNameFinder had no entries at all for the ShangMi algorithms, so an SM2 signature AlgorithmIdentifier that DefaultSignatureAlgorithmIdentifierFinder itself produces came back named only by its OID string - getAlgorithmName(GMObjectIdentifiers.sm2sign_with_sm3) returned \u0026quot;1.2.156.10197.1.501\u0026quot; and hasAlgorithmName returned false. Both finders now name sm2sign_with_sm3 as SM3WITHSM2 and sm2sign_with_sha256 as SHA256WITHSM2, and DefaultAlgorithmNameFinder additionally names the sm3 digest. All three resolve through the BC provider, as Signature and MessageDigest respectively. The remaining GM arc - the SM4 cipher modes, the sm2encrypt variants, and the SM1 / SM6 / SSF33 ciphers BC does not implement - is still unnamed (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2377\"\u003e#2377\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe RFC 4998 evidence-record classes compared the digest AlgorithmIdentifier named by a time-stamp authority with the one their own DigestCalculator uses, and did so with AlgorithmIdentifier.equals(), which compares the encodings. A TSA that names SHA-256 with an explicit NULL parameters field - DigiCert among them - therefore failed against BC's own calculator, which names it with the parameters absent, and ERSArchiveTimeStampGenerator.generateArchiveTimeStamp rejected the response with \u0026quot;time stamp imprint for wrong algorithm\u0026quot;. Both spellings name the same digest and RFC 5754 sec. 2 requires a receiver to accept either, while requiring that identifiers be generated with the parameters absent, which BC already does. The three affected comparisons - the two in ERSArchiveTimeStampGenerator and the digest check in ERSEvidenceRecord.renew - now use the new AlgorithmIdentifier.areEquivalent, which matches on the algorithm and treats an absent parameters field and NULL as the same, and the consistency check across an evidence record's archive time stamp chain uses it too. An identifier carrying an actual parameter structure is never equivalent to one carrying none (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2379\"\u003e#2379\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eEDIPartyName.toASN1Primitive emitted the nameAssigner and partyName DirectoryStrings without their context tags, so an EDIPartyName built through its public constructor could not be parsed back by EDIPartyName.getInstance, which correctly requires them. RFC 5280 sec. 4.2.1.6 tags both members [0] and [1], and those tags are explicit despite the module's IMPLICIT TAGS because DirectoryString is a CHOICE, which X.680 does not allow to be tagged implicitly - the decoder already had this right. The encoder now matches it. Note the type was added during the 1.85 cycle and GeneralName validates its ediPartyName alternative through it, so a GeneralName carrying an untagged ediPartyName - including one BC itself produced - is rejected where 1.84 passed it through unexamined; the untagged form is not read leniently (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2380\"\u003e#2380\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eRSASSA-PSS could not be used with a RIPEMD digest through the JCA API. Nothing registered the RIPEMD PSS signatures, so Signature.getInstance(\u0026quot;RIPEMD160WITHRSAANDMGF1\u0026quot;) raised NoSuchAlgorithmException, and the generic RSASSA-PSS route with an explicit PSSParameterSpec failed too: org.bouncycastle.jcajce.provider.util.DigestFactory.getDigest returned null for a RIPEMD name, and isSameDigest - an allow-list of the SHA families and MD5 - reported two identical RIPEMD names as different digests, so the spec was rejected with \u0026quot;digest algorithm for MGF should be the same as for PSS parameters\u0026quot;. isSameDigest now answers true for equal names whatever the digest, which also covers Whirlpool, SM3, GOST3411 and anything else outside that allow-list; DigestFactory recognises RIPEMD128, RIPEMD160 and RIPEMD256 by name and OID; the three PSS signatures are registered with MGF1 over the same digest and a salt of the digest length; and DefaultSignatureAlgorithmIdentifierFinder gains the matching RIPEMD*WITHRSAANDMGF1 entries with their RSASSA-PSS-params, so the operator/JcaContentSignerBuilder path works as well. Note BC continues to require the PSS hash and the MGF1 hash to be the same, which RFC 8017 does not itself demand (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2381\"\u003e#2381\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe opt-in key-size validation on CMS key-transport recipients (org.bouncycastle.cms.jcajce.JceKeyTransRecipient.setKeySizeValidation(true)) never ran for a message using RFC 9709 CEK derivation (id-alg-cek-hkdf-sha256): the branch that should have selected the actual content-encryption algorithm carried in the KDF AlgorithmIdentifier's parameters compared the encrypted-key byte array against the id-alg-cek-hkdf-sha256 object identifier - a comparison that is always false - so the check fell through to a key-size lookup on the outer KDF OID, which has no registered key size, and silently checked nothing. A key-transport EnvelopedData/AuthEnvelopedData whose transported (and HKDF-derived) content-encryption key did not match the key size of the advertised content-encryption algorithm was therefore accepted even with validation enabled. The recipient now dispatches on the content-encryption AlgorithmIdentifier's algorithm OID, so key-size validation of RFC 9709 messages checks the recovered key against the inner content-encryption algorithm. Messages with a matching key size, non-HKDF messages, and recipients that do not enable validation are unaffected.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003eSee full diff in \u003ca href=\"https://github.com/bcgit/bc-java/commits\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003ecommonmark-java 0.29.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e[0.29.0] - 2026-06-20\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/42b4fb7adfe288ef13e9e27ab20aff7e91b0ab9d\"\u003e\u003ccode\u003e42b4fb7\u003c/code\u003e\u003c/a\u003e Prepare CHANGELOG for version 0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/b76e09d7a8362abb5f04e1d6b91dbd6da279a6fc\"\u003e\u003ccode\u003eb76e09d\u003c/code\u003e\u003c/a\u003e Limit how deep inline nodes may nest by default (100)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/49f65cb5cbec93cff713179990307145198e7061\"\u003e\u003ccode\u003e49f65cb\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing deeply nested emphasis\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/c...\n\n_Description has been truncated_","html_url":"https://github.com/engsathiago/EVE-Agent/pull/11","url":"https://dependabot.ecosyste.ms/api/v1/hosts/GitHub/repositories/engsathiago%2FEVE-Agent/issues/11","packages_url":"https://dependabot.ecosyste.ms/api/v1/issues/11/packages"},{"uuid":"5404956375","node_id":"PR_kwDOTCWVXc8AAAABC5loaQ","number":41,"state":"closed","title":"chore(deps): bump the android-deps group across 1 directory with 21 updates","user":"dependabot[bot]","labels":["dependencies","java"],"assignees":[],"locked":false,"comments_count":1,"pull_request":true,"closed_at":"2026-09-11T21:25:00.000Z","author_association":null,"state_reason":null,"created_at":"2026-09-09T21:32:45.000Z","updated_at":"2026-09-11T21:25:02.000Z","time_to_close":172335,"merged_at":null,"merged_by":null,"closed_by":null,"dependency_metadata":{"prefix":"chore(deps): bump","group_name":"android-deps","update_count":21,"packages":[{"name":"gradle-wrapper","old_version":"9.4.1","new_version":"9.7.1","repository_url":"https://github.com/gradle/gradle"},{"name":"androidx.core:core-ktx","old_version":"1.18.0","new_version":"1.19.0"},{"name":"org.bouncycastle:bcprov-jdk18on","old_version":"1.84","new_version":"1.85.2","repository_url":"https://github.com/bcgit/bc-java"},{"name":"org.commonmark:commonmark","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-autolink","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-strikethrough","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-tables","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-task-list-items","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"dnsjava:dnsjava","old_version":"3.6.4","new_version":"3.6.5","repository_url":"https://github.com/dnsjava/dnsjava"},{"name":"org.junit.vintage:junit-vintage-engine","old_version":"6.0.3","new_version":"6.1.3","repository_url":"https://github.com/junit-team/junit-framework"},{"name":"io.kotest:kotest-assertions-core-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"io.kotest:kotest-runner-junit5-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"org.jetbrains.kotlinx:kotlinx-coroutines-android","old_version":"1.10.2","new_version":"1.11.0","repository_url":"https://github.com/Kotlin/kotlinx.coroutines"},{"name":"org.jetbrains.kotlinx:kotlinx-coroutines-test","old_version":"1.10.2","new_version":"1.11.0","repository_url":"https://github.com/Kotlin/kotlinx.coroutines"},{"name":"com.google.android.material:material","old_version":"1.13.0","new_version":"1.14.0","repository_url":"https://github.com/material-components/material-components-android"},{"name":"com.squareup.okhttp3:mockwebserver","old_version":"5.3.2","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.squareup.okhttp3:okhttp","old_version":"5.3.2","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.android.application","old_version":"9.2.0","new_version":"9.4.0"},{"name":"com.android.test","old_version":"9.2.0","new_version":"9.4.0"},{"name":"org.jetbrains.kotlin.plugin.compose","old_version":"2.3.21","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"},{"name":"org.jetbrains.kotlin.plugin.serialization","old_version":"2.3.21","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"}],"path":null,"ecosystem":"maven"},"body":"Bumps the android-deps group with 21 updates in the /apps/android directory:\n\n| Package | From | To |\n| --- | --- | --- |\n| [gradle-wrapper](https://github.com/gradle/gradle) | `9.4.1` | `9.7.1` |\n| androidx.core:core-ktx | `1.18.0` | `1.19.0` |\n| [org.bouncycastle:bcprov-jdk18on](https://github.com/bcgit/bc-java) | `1.84` | `1.85.2` |\n| [org.commonmark:commonmark](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-autolink](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-strikethrough](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-tables](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-task-list-items](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [dnsjava:dnsjava](https://github.com/dnsjava/dnsjava) | `3.6.4` | `3.6.5` |\n| [org.junit.vintage:junit-vintage-engine](https://github.com/junit-team/junit-framework) | `6.0.3` | `6.1.3` |\n| [io.kotest:kotest-assertions-core-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [io.kotest:kotest-runner-junit5-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [org.jetbrains.kotlinx:kotlinx-coroutines-android](https://github.com/Kotlin/kotlinx.coroutines) | `1.10.2` | `1.11.0` |\n| [org.jetbrains.kotlinx:kotlinx-coroutines-test](https://github.com/Kotlin/kotlinx.coroutines) | `1.10.2` | `1.11.0` |\n| [com.google.android.material:material](https://github.com/material-components/material-components-android) | `1.13.0` | `1.14.0` |\n| [com.squareup.okhttp3:mockwebserver](https://github.com/lysine-dev/okhttp) | `5.3.2` | `5.5.0` |\n| [com.squareup.okhttp3:okhttp](https://github.com/lysine-dev/okhttp) | `5.3.2` | `5.5.0` |\n| com.android.application | `9.2.0` | `9.4.0` |\n| com.android.test | `9.2.0` | `9.4.0` |\n| [org.jetbrains.kotlin.plugin.compose](https://github.com/JetBrains/kotlin) | `2.3.21` | `2.4.20` |\n| [org.jetbrains.kotlin.plugin.serialization](https://github.com/JetBrains/kotlin) | `2.3.21` | `2.4.20` |\n\n\nUpdates `gradle-wrapper` from 9.4.1 to 9.7.1\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/gradle/gradle/releases\"\u003egradle-wrapper's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e9.7.1\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.1.\u003c/p\u003e\n\u003cp\u003eThis is a patch release for 9.7.0. We recommend using 9.7.1 instead of 9.7.0.\u003c/p\u003e\n\u003cp\u003eHere are the highlights of 9.7.0 release:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIsolated Projects graduates to incubating\u003c/li\u003e\n\u003cli\u003eBroader Configuration Cache compatibility\u003c/li\u003e\n\u003cli\u003eResilient Sync helps you fix broken builds\u003c/li\u003e\n\u003cli\u003eMore source locations in problem reports\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003ca href=\"https://docs.gradle.org/9.7.1/release-notes.html\"\u003eRead the Release Notes\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eWe would like to thank the following community members for their contributions to this release of Gradle:\n\u003ca href=\"https://github.com/aSemy\"\u003eAdam\u003c/a\u003e,\n\u003ca href=\"https://github.com/Gautam-aman\"\u003eAman Gautam\u003c/a\u003e,\n\u003ca href=\"https://github.com/YukiCodepth\"\u003eAman Kumar\u003c/a\u003e,\n\u003ca href=\"https://github.com/adubrouski\"\u003eAnton Dubrouski\u003c/a\u003e,\n\u003ca href=\"https://github.com/liutikas\"\u003eAurimas\u003c/a\u003e,\n\u003ca href=\"https://github.com/gbhavya07\"\u003egbhavya07\u003c/a\u003e,\n\u003ca href=\"https://github.com/joshfriend\"\u003eJosh Friend\u003c/a\u003e,\n\u003ca href=\"https://github.com/nicklauslittle-gov\"\u003enicklauslittle-gov\u003c/a\u003e,\n\u003ca href=\"https://github.com/psoni674\"\u003ePragati\u003c/a\u003e,\n\u003ca href=\"https://github.com/Project516\"\u003eproject516\u003c/a\u003e,\n\u003ca href=\"https://github.com/Uomocapra\"\u003eQin Mi\u003c/a\u003e,\n\u003ca href=\"https://github.com/rkdfx\"\u003eRavi\u003c/a\u003e,\n\u003ca href=\"https://github.com/sk-reddy17\"\u003esk-reddy17\u003c/a\u003e,\n\u003ca href=\"https://github.com/Suvrat1629\"\u003eSuvrat Acharya\u003c/a\u003e,\n\u003ca href=\"https://github.com/ShreckYe\"\u003eYongshun Ye\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eUpgrade instructions\u003c/h2\u003e\n\u003cp\u003eSwitch your build to use Gradle 9.7.1 by updating your wrapper:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e./gradlew :wrapper --gradle-version=9.7.1 \u0026amp;\u0026amp; ./gradlew :wrapper\r\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eSee the Gradle \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/upgrading_version_9.html\"\u003e9.x upgrade guide\u003c/a\u003e to learn about deprecations, breaking changes and other considerations when upgrading.\u003c/p\u003e\n\u003cp\u003eFor Java, Groovy, Kotlin and Android compatibility, see the \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/compatibility.html\"\u003efull compatibility notes\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eReporting problems\u003c/h2\u003e\n\u003cp\u003eIf you find a problem with this release, please file a bug on \u003ca href=\"https://github.com/gradle/gradle/issues\"\u003eGitHub Issues\u003c/a\u003e adhering to our issue guidelines.\nIf you're not sure you're encountering a bug, please use the \u003ca href=\"https://discuss.gradle.org/c/help-discuss\"\u003eforum\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eWe hope you will build happiness with Gradle, and we look forward to your feedback via \u003ca href=\"https://twitter.com/gradle\"\u003eTwitter\u003c/a\u003e or on \u003ca href=\"https://github.com/gradle\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003e9.7.0\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.0.\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/92f0512e7f06d84621afba191f75e265363890cf\"\u003e\u003ccode\u003e92f0512\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38892\"\u003e#38892\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/820ee75a99a179bbffa41bcedc6477b685fabb9f\"\u003e\u003ccode\u003e820ee75\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/82c23f9bd2a89b4cc644e1f90a28a8668feb3dee\"\u003e\u003ccode\u003e82c23f9\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering problem in KTS (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38878\"\u003e#38878\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/ef11a7268fe8cc8d6ab849ec911aa11220180553\"\u003e\u003ccode\u003eef11a72\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering issue\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/bb0d8a974a71b1003efea41e4046e98855cd5ff8\"\u003e\u003ccode\u003ebb0d8a9\u003c/code\u003e\u003c/a\u003e Make relevant tests polyglot (run for multiple DSLs)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/336e129d7f95c03486acafc97abf59734acfed48\"\u003e\u003ccode\u003e336e129\u003c/code\u003e\u003c/a\u003e Update signing configuration (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38874\"\u003e#38874\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/4bdf0da2dad9884d089a6062a45ea7183e7d735d\"\u003e\u003ccode\u003e4bdf0da\u003c/code\u003e\u003c/a\u003e Update signing configuration\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/cd9b92c1b82856248cf1dc58b50378238bec7b52\"\u003e\u003ccode\u003ecd9b92c\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38839\"\u003e#38839\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/5f4e381964897ad8d6b99e5a7c77f26dba3259fb\"\u003e\u003ccode\u003e5f4e381\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/1e08ab551367aeb5fb48b26e72807e1d2b27c939\"\u003e\u003ccode\u003e1e08ab5\u003c/code\u003e\u003c/a\u003e Keep type-use annotations in extracted ABI classes (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38810\"\u003e#38810\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/gradle/gradle/compare/v9.4.1...v9.7.1\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `androidx.core:core-ktx` from 1.18.0 to 1.19.0\n\nUpdates `org.bouncycastle:bcprov-jdk18on` from 1.84 to 1.85.2\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.md\"\u003eorg.bouncycastle:bcprov-jdk18on's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch1\u003eBouncy Castle Crypto Package - Release Notes\u003c/h1\u003e\n\u003ch2\u003e1.0 Introduction\u003c/h2\u003e\n\u003cp\u003eThe Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. The package is organised so that it contains a light-weight API suitable for use in any environment (including the J2ME) with the additional infrastructure to conform the algorithms to the JCE framework.\u003c/p\u003e\n\u003ch2\u003e2.0 Release History\u003c/h2\u003e\n\u003cp\u003e\u003c!-- raw HTML omitted --\u003e\u003c!-- raw HTML omitted --\u003e\u003c/p\u003e\n\u003ch3\u003e2.1.1 Version\u003c/h3\u003e\n\u003cp\u003eRelease: 1.86\u003cbr /\u003e\nDate: 2026, TBD\u003c/p\u003e\n\u003ch3\u003e2.1.2 Defects Fixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) let a subkey inherit the primary key's Key Flags when its own Subkey Binding signature carried no Key Flags subpacket, which made the two capability decisions taken for one subkey disagree. OpenPGPCertificate.OpenPGPComponentKey.isSigningKey() reads the effective flags, which fell back to the primary key's direct-key or primary user ID self-signature, so a subkey bound with no flags of its own counted as signing-capable; verifyEmbeddedPrimaryKeyBinding reads the binding signature's own flags, found no signing capability there, and so skipped the embedded Primary Key Binding (cross-certification) signature that RFC 9580 sec. 5.2.1.8 and sec. 10.1.3 require of a subkey that can issue signatures. A data signature made by such a subkey was therefore attributed to the certificate and reported valid by OpenPGPSignature.OpenPGPDocumentSignature.isValid() with the cross-certification requirement never applied, where GnuPG refuses the same certificate and message as not cross-certified. An attacker holding a third party's public signing subkey - which is public material - could bind it to their own primary key with a Subkey Binding signature they are able to make, carrying no Key Flags and no embedded Primary Key Binding signature, which they cannot make without the subkey's private key, and have that party's genuine signatures verify as valid under the attacker's own identity: misattribution of a real signature rather than a forgery of a new one, since the signature still has to be one the subkey actually made. Key Flags are a statement about the key the carrying signature refers to (RFC 9580 sec. 5.2.3.29), so a subkey no longer inherits them from the certificate-wide signatures of the primary key: a Subkey Binding signature that omits the subpacket now leaves the subkey with no capabilities rather than the primary's, which makes the flags the cross-certification check consults the same flags every other decision consults. Preferences and the other subpackets a direct-key signature carries are inherited as before, and the primary key itself - whose flags legitimately come from its direct-key or user ID self-signature - is unaffected. The low-level PGPSignature / PGPPublicKeyRing API performs no binding checks by design and is unchanged.\u003c/li\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) used a version 6 key that carried no valid Direct Key signature, falling back to the primary user ID binding as it correctly does for a version 4 key. RFC 9580 sec. 5.2.3.10 requires the opposite: \u0026quot;An implementation MUST ensure that a valid Direct Key signature is present before using a version 6 key. This prevents certain attacks where an adversary strips a self-signature specifying a Key Expiration Time or certain preferences.\u0026quot; The certificate grammar says the same structurally, the Direct Key signature being mandatory in the version 6 structure of sec. 10.1.1 and optional in the version 4 one of sec. 10.1.3. Because a version 6 certificate carries its key expiration, features and algorithm preferences on the Direct Key signature - the convention the RFC recommends and the one OpenPGPKeyGenerator follows, its user ID certification carrying no expiration at all - removing that single signature packet from a published certificate silently dropped the expiration along with the preferences and features: OpenPGPCertificate.getSignatureChainFor fell back to the user ID binding, the primary key was still reported bound, and getEncryptionKeys() and getSigningKeys() went on returning the subkeys of a key whose owner had set it to expire. The primary key fingerprint is unchanged by the removal, so a relying party pinning the key by fingerprint still treats it as the same key, and no private key or hash collision is involved; the natural moment for the strip is the key refresh that RFC 9580 names as the reason to refetch a key at all - to learn about changes in expiration, features, preferences and revocation - which is exactly the update it defeats. This is a downgrade rather than a forgery, nothing being attributed to a key that did not authorise it, and the concerning direction is encryption, to a key meant to have been retired. OpenPGPCertificate.isBoundBy now requires a valid Direct Key self-signature on a version 6 primary key before any component of the certificate - the primary key, its subkeys or its identities - is treated as bound, so a version 6 certificate stripped of it offers no keys at all rather than an unexpiring set. Version 4 certificates are unaffected: there the key expiration legitimately lives on the user ID self-signature and the fallback is correct, so it stays. The revocation-only version 6 certificate of sec. 10.1.2, which legitimately carries no Direct Key signature, is unaffected as well - its key was already refused as revoked, and reading the revocation does not go through the binding check.\u003c/li\u003e\n\u003cli\u003eThe lightweight LMSSigner and HSSSigner refused a key wrapped in ParametersWithRandom, which is how BcContentSignerBuilder passes a key whenever setSecureRandom() has been called - so BcHssLmsContentSignerBuilder built a working signer until a random was set and then failed with \u0026quot;Incorrect Key Parameters\u0026quot;, and the two signers themselves raised ClassCastException on the same input. All three now unwrap it, as the promoted ML-DSA and SLH-DSA signers already did. The random is accepted and not used: LMS derives its message randomiser C from the key's seed and the one-time index, so it is deterministic and cannot repeat while q does not. Note SP 800-208 sec. 6.1 asks for C to come from an approved random bit generator, which this implementation does not do; that is unchanged here, and a supplied random is now ignored rather than refused.\u003c/li\u003e\n\u003cli\u003eLMS signature verification did not apply two of the checks RFC 8554 sec. 5.4.2 requires before a signature is processed. Step 2g refuses a signature whose LMS typecode is not the one from the public key, and without it the path computation took its height and tree digest from the parameter set the signature named rather than the key's, so a signature claiming a height-25 parameter set drove a 25-level computation against a height-5 key. Step 2i refuses a leaf number q outside the tree, and without it an out-of-range q flowed into the node arithmetic and was left for the candidate-root comparison to catch. Neither was a forgery - the domain separation between D_LEAF and D_INTR and the final comparison saw to that - but both are attacker-chosen work the specification says to refuse up front. Both are now checked, and a signature failing either is still reported as not verifying rather than thrown out of Signature.verify(). The catch around the signature decode in LMSSigner and HSSSigner has also been narrowed to the decode itself, as the corresponding SPI was corrected to do for github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2408\"\u003e#2408\u003c/a\u003e: past the parse the engine reports an inconsistent signature by returning false rather than by throwing, so the wider catch caught nothing while standing ready to turn a future internal error into a quiet false.\u003c/li\u003e\n\u003cli\u003eThe LMS and HSS key parameter classes now apply at construction the checks their decoders apply, so a key built directly cannot be one the decoder would refuse. LMSPrivateKeyParameters accepted an identifier of any length although the decoder reads exactly 16 bytes - such a key encoded but could not be read back - and left q, maxQ and the seed length unchecked; the seed is now required to be at least m bytes at decode as well, where a one-byte seed had been decoding silently and then deriving every one-time key from it. HSSPrivateKeyParameters checked neither its level count nor that it had been given a component key per level and a chaining signature per level below the root, and then indexed both lists, so a mismatch surfaced as IndexOutOfBoundsException - or, where a level happened to match, as a null chaining signature that only failed at signing time; the level is now checked after the reset that fills it in, since a null is legitimate on the way in. LMSPrivateKeyParameters.getInstance(byte[], byte[]) adopted the public key supplied beside the private one without comparing them, so a mismatched public key was simply reported by getPublicKey(); it now cross-checks the identifier, both parameter sets and, where the tree cache already holds it, the root, as the HSS entry point does. The decoders also now report a bad version or seed length as IOException rather than IllegalStateException, so a caller can catch one type for a malformed key, and the package-private LM-OTS public key decoder no longer declares throws Exception or dereferences an unrecognised typecode. The deprecated org.bouncycastle.pqc.crypto.lms copies carry the decoder corrections.\u003c/li\u003e\n\u003cli\u003eIn the LMS JCE layer, LMSKeyGenParameterSpec.fromNames knew all twenty LMS parameter-set names but only four of the sixteen LM-OTS ones, so none of the SP 800-208 n24 or SHAKE sets could be named; all sixteen are now present. KeyPairGenerator.initialize(int, SecureRandom) reports InvalidParameterException, which is what the JCA specifies and which extends the IllegalArgumentException it raised before, so existing catches still match. BCLMSPrivateKey.getIndex now takes the exhaustion check and the index read under the key's own monitor rather than as two separate calls, and two unused fields have gone from LMSSignatureSpi. Note that the LMS Signature claims its one-time key at the first update() rather than at sign(), so a Signature that is initialised and updated and then abandoned spends an index without producing a signature - the safe direction for a one-time scheme, and now documented on the SPI.\u003c/li\u003e\n\u003cli\u003eEvery other key pair generator that refuses a key size did the same thing the LMS one did above. KeyPairGenerator.initialize(int, SecureRandom) is documented to raise InvalidParameterException when the key size is not one the generator supports, and thirty of them raised a bare IllegalArgumentException instead, so a caller following the JCA and catching the documented type saw an exception escaping rather than a refusal. The ML-DSA, ML-KEM, SLH-DSA, Classic McEliece, FrodoKEM, NTRU and composite signature and KEM generators in the BC provider, and every generator in BCPQC, now raise InvalidParameterException - NewHope included, where the value is a key size it will not take rather than a mode of initialisation it does not offer. InvalidParameterException extends IllegalArgumentException, so callers written against the old behaviour go on catching it unchanged. The two RSA generators are corrected as well, and differently: theirs is a key size below a floor rather than a mode of initialisation they do not offer, and the refusal is raised by the lightweight RSAKeyGenerationParameters, which cannot name a java.security exception at all, so the RSA KeyPairGeneratorSpi now translates it - keeping the message verbatim and the original exception as the cause, through a new SecurityExceptions.invalidParameterException factory, since InvalidParameterException has no constructor that takes one. Of the 304 KeyPairGenerator services the two providers register, 299 now refuse a nonsense key size the way the JCA defines it and five accept it as a strength they can work with, with none left raising a bare IllegalArgumentException; that is asserted as a sweep over both providers rather than per algorithm, so a generator added later is covered without the test being touched. The jdk1.3 provider overlays of the four generators that have one carry the same change, and the jdk1.3 SecurityExceptions overlay gains the new factory along with the invalidAlgorithmParameterException one it had been missing.\u003c/li\u003e\n\u003cli\u003eKeyPairGenerator.initialize(AlgorithmParameterSpec, SecureRandom) had the same shape of problem as the int overload above, and only 44 of the 304 services the two providers register reported an unusable spec as the InvalidAlgorithmParameterException that method declares. The twenty-three PQC generators that resolve a parameter set by name - cmce, frodokem, mldsa, mlkem, slhdsa, aimer, bike, faest, falcon, haetae, hqc, mayo, mqom, ntru, ntruplus, both ntruprime variants, qruov, saber, sdith, smaugt, snova and sqisign, 230 services between them - case-folded the name they got back from the spec without checking it, so a spec with no getName() method, and a null spec, produced a NullPointerException from inside the fold; their own \u0026quot;is this name one I know\u0026quot; branch, which does report the declared exception, was unreachable. The two composite generators, whose parameter set is fixed by the algorithm name so that null is the only spec they accept, refused every other one with IllegalArgumentException. RSA answered correctly for a spec of the wrong type but not for one of the right type carrying values its lightweight parameters will not take - an even public exponent, or a key size below the floor - which is now translated the same way the int overload's is. All 304 services now report the declared exception, with the composites still taking the null spec that is right for them; note that InvalidAlgorithmParameterException is a checked exception and not an IllegalArgumentException, so a caller that was catching what these threw before has to catch the declared type instead.\u003c/li\u003e\n\u003cli\u003eAn HSS private key claimed the two records of its position under two different monitors. The top-level index and the bottom component key's one-time index q are independent records of the same position - the decoder requires them to agree, see the entry below - but generateLMSContext incremented the index under the HSS key's own monitor, released it, and only then claimed q under the component key's. A getEncoded() issued in between saw the index advanced and q not, and produced an encoding this implementation's own decoder rejects; and two threads meeting at a bottom-tree boundary could both pass the exhaustion test, take consecutive top-level indices and claim the same q, after which one of them was refused with \u0026quot;ots private key exhausted\u0026quot; by a key still reporting usages remaining, a top-level index had been spent with no signature made, and the two records stayed one apart for the rest of the key's life in that process - so it could no longer be encoded, cloned or sharded, and getIndex() and getUsagesRemaining() misreported by one. No one-time key was reused: the component key's claim is itself atomic, and the divergence runs index ahead of leaves, so the effect was on the key's usability rather than on the signatures it had made. Both records are now claimed under the one monitor, and the component key is claimed before the index is incremented so that an exhausted one leaves both untouched. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the same correction.\u003c/li\u003e\n\u003cli\u003eTimeStampToken parsed the attacker-controlled TSTInfo content of a time-stamp token (org.bouncycastle.tsp.TimeStampToken, reached from TimeStampResponse(byte[]) and (InputStream)) inside a try that caught only CMSException, so a well-formed RFC 3161 TimeStampResp whose embedded token carried a malformed TSTInfo - a SEQUENCE with fewer elements than the five mandatory fields, a non-SEQUENCE, truncated DER, or an unknown context tag - let an IllegalArgumentException or a NoSuchElementException escape the constructor's declared throws TSPException, IOException contract. A token signed by no signers or by more than one raised a bare IllegalArgumentException from the same constructor, before that try, for the same reason. Both are now reported as TSPException, matching the package-private TimeStampResponse(DLSequence) constructor and the existing getSignedAttributes guard in the same method; the signer-count refusal is a TSPValidationException, as the neighbouring check on the content type already was. Related, and the cause of the NoSuchElementException: asn1.tsp.TSTInfo read its five mandatory fields off the sequence with no bound on how many elements were actually there, so a short SEQUENCE left the enumeration to run out rather than being refused, and an oversize one was accepted with its extra elements absorbed into the optional slots. Decode now requires the five to ten elements RFC 3161 sec. 2.4.2 gives the type, which is what the sibling Accuracy and ArchiveTimeStamp decoders already did, so the failure is the IllegalArgumentException that getInstance is expected to raise (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2415\"\u003e#2415\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eNeither the HSS nor the XMSS^MT private key decoder checked its declared index against the traversal state stored beside it, although the two are independent records of the same position in the key and so can be compared. For HSS the records are the top-level index and the component keys' one-time indices q; for XMSS^MT they are the global index and the per-layer BDS states. A stored key whose index had been rolled back while its state stayed advanced - a partial write, a restore from backup, a buggy storage layer - was therefore accepted, and it then signed a second message under a one-time key the key had already used, producing a signature that verified, so nothing anywhere surfaced the reuse. RFC 8554 sec. 1 and RFC 8391 sec. 1.1 both require each one-time key to be used exactly once, and this is the failure those requirements exist to prevent; the single-tree XMSS decoder has tied its BDS state to its index since that state was first validated, and this brings the two multi-tree schemes into line. HSS decode now requires the declared index to equal the position the component q values imply - a level above the last contributes (q - 1) leaves of the levels beneath it, since its q has already advanced past the subtree it signed - and XMSS^MT decode now requires each present layer's BDS index to equal the leaf index that layer derives from the global index, allowing the one position where a layer has moved into a new subtree and its state legitimately still carries the previous subtree's final index. A layer with no state yet is unaffected, since those are built lazily at signing time. Related, and the same shape of omission: an XMSS or XMSS^MT private key encoding carries the tree root twice - the key's own root field and the root node of the BDS state stored beside it, which for XMSS^MT is the top layer's - and the two were never compared either. A corrupted root was accepted and then poisoned every signature the key made, because the root is hashed into the message digest: the signature did not verify and nothing indicated why. Decode now requires the two copies to agree. The BDS node values themselves are not checkable the way the LMS tree cache above is - a BDS authentication path, stack, retain or keep node does not have its children stored alongside it, so recomputing one means building a subtree, which is the work the state exists to avoid. Both checks are integer comparisons over the levels of the key, too small to measure against the surrounding decode, and both were verified not to reject any legitimate key by walking every index a key can reach: the full key space of the two-level HSS and the h=4/d=2, h=6/d=2, h=6/d=3, h=9/d=3 and h=8/d=4 XMSS^MT parameter sets, plus a three-level HSS key across a subtree boundary and an HSS shard. Since those node values cannot be recomputed, the encoded state now carries a checksum over itself instead, with the owning key's public seed hashed in front of it. Any corruption of the stored state is refused at decode rather than being loaded and then producing signatures that silently do not verify, and because the public seed is bound in, a state transplanted between two keys of the same parameter set is refused too, even though it is internally consistent and arrives with its own matching root. The public seed is bound rather than the secret seed or the PRF key deliberately: the state's own root and index are inside the encoding and so are already covered, hashing secret material would make the stored checksum a commitment to it for no gain in detection, and the PRF key does not influence the state at all. \u003cstrong\u003eThis is an error-detecting code and not integrity protection\u003c/strong\u003e - anyone able to rewrite the stored key recomputes it, so it establishes that the state is unchanged since it was written, never that it was correct when written, and the allocation bounds on the encoding remain the guard against a crafted one. It costs one SHA-256 over the state, measured at 5 to 8 microseconds each way for the h=10 and h=16 parameter sets, and 32 bytes of encoding. The state encoding was added earlier in this same cycle and has not been released, so the checksum is simply part of it rather than a new version: a state written by a 1.86 beta is rejected, which is recovered from by re-exporting the key. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the HSS check as well (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2414\"\u003e#2414\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe S/MIME example smoke test in the misc module (org.bouncycastle.mail.smime.examples.test.AllTests) drove SendSignedAndEncryptedMail against smtp.gmail.com, and that example finishes with Transport.send() under JavaMail's default settings, which have no connect timeout. Where outbound port 25 is refused the failure was swallowed and the test passed; where it is silently dropped, as on many home networks, the connect blocked and ./gradlew build hung in :misc:test indefinitely with \u0026quot;0 tests completed\u0026quot;. The test now delivers to an SMTP stub on a loopback port, with connect / read / write timeouts as a backstop, and asserts the message arrived (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2407\"\u003e#2407\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation took the traditional component public key bytes it feeds the KEM combiner from the recipient key's own encoding, while decapsulation recomputes the point from the private key and so always produced an uncompressed one. Section 4 of draft-ietf-lamps-pq-composite-kem requires an EC component to be carried as an uncompressed point, but a component key that encodes itself compressed - a BC EC key whose point format has been set through org.bouncycastle.jce.interfaces.ECPointEncoder, or a key from a provider that preserves a compressed encoding - was passed through as it came. Both sides then combined a different tradPK and derived different shared secrets, with no error reported on either: encapsulation and decapsulation both succeeded and the recipient simply could not decrypt. The EC component is now normalised to an uncompressed point wherever the engine serialises one, which covers the ephemeral key that forms the ciphertext as well. X25519 and X448 components have a single encoding and were unaffected, as were EC keys left in their default (uncompressed) format, whose shared secrets are unchanged. CompositePublicKey.getEncoded() took its component bytes the same way, so such a key also encoded to a composite key other implementations reject and whose bytes changed across an encode / decode / encode round trip - 1238 bytes rather than 1270 for MLKEM768-ECDH-P256, and for the composite ML-DSA keys sharing that method, 2006 rather than 2038 for MLDSA65-ECDSA-P256. It now normalises the component the same way. This is a write-side change only: a composite key carrying a compressed EC component is still decoded, since the component key factories accept either form, and continues to verify signatures as before - it simply re-encodes in the normalised form. The shared normalisation is org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil.getUncompressedSubjectPublicKeyBytes.\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation threw a NullPointerException, wrapped in an IllegalStateException out of KeyGenerator.generateKey(), when the SecureRandom it was given was null - which javax.crypto.KEM.newEncapsulator() documents as a request for the provider's default, and which KeyGenerator.init(spec, null) passes straight through. The three RSA-OAEP composites draw the traditional shared secret from that random directly, so they were the ones affected; the ECDH and X25519 / X448 composites escaped only because their component KeyPairGenerators default a random of their own. CompositeMLKEMEngine now defaults one through CryptoServicesRegistrar.getSecureRandom() on first use, as the composite KEM Cipher's wrap path already did, and as the KEM generators corrected earlier in this cycle now do. Related, the engine now also clears the ML-KEM component's shared secret alongside the traditional one on both the encapsulate and decapsulate paths - the copy handed back by getEncoded() was left in the heap - as section 3.5 of draft-ietf-lamps-pq-composite-kem requires.\u003c/li\u003e\n\u003cli\u003eCompositePublicKey.getAlgorithm() and CompositePrivateKey.getAlgorithm() returned null for all twelve Composite ML-KEM (draft-ietf-lamps-pq-composite-kem) parameter sets. Both classes resolved the name through the composite signature index only, which holds the composite ML-DSA OIDs, so a composite KEM key pair - generated, parsed from a certificate, or read from PKCS#8 - reported no algorithm at all, and the standard JCA idiom of reconstructing a key with KeyFactory.getInstance(key.getAlgorithm()) raised a NullPointerException. The lookup now falls back to the composite KEM index, so the name returned is the one the provider registers the algorithm under (e.g. MLKEM768-X25519-SHA3-256), matching the composite ML-DSA behaviour. The same single-index assumption made the CompositePublicKey(SubjectPublicKeyInfo) and CompositePrivateKey(PrivateKeyInfo) constructors reject a composite KEM key with \u0026quot;unable to create CompositePublicKey from SubjectPublicKeyInfo\u0026quot;; they now dispatch to the composite KEM key factory for those OIDs. Keys obtained through KeyFactory or through BouncyCastleProvider.getPublicKey / getPrivateKey were unaffected and are unchanged (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2404\"\u003e#2404\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe org.bouncycastle.jcajce.spec.KEMKDFSpec constructor stored a null otherInfo as given, so getOtherInfo() returned null, and three of the KDF branches KdfUtil.makeKeyBytes dispatches to - KMAC-128, KMAC-256 and SHAKE-256 - read the otherInfo length without a guard and threw NullPointerException out of the KEM operation, where the KDF2, KDF3 and HKDF branches tolerate a null through KDFParameters / HKDFParameters. The Builder of every spec in the package already mapped null to empty, so no provider path reached it, but the constructor is protected on a public class and KdfUtil is documented for callers building their own KEM integration; the deprecated KEMParameterSpec passes a null itself and escaped only because it also pins the KDF to null. The constructor now stores empty for a null, so getOtherInfo() never returns null, and a null and an explicitly empty otherInfo derive the same key.\u003c/li\u003e\n\u003cli\u003eQR-UOV signature verification accepted a signature encoding that was not canonical, so the encoding of a signature was not unique even after the trailing-byte fix of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e. Each F_q element of the signature is stored in ceil(log2 q) bits, one more bit pattern than the field has elements: q itself is representable and is arithmetically congruent to zero, so an element written as q verified exactly as the same element written as zero would, and the bits padding the last element out to the byte boundary were never read at all. Every zero element of a signature therefore carried a second encoding, and for the q = 7 parameter sets roughly one element in seven is zero - a single qruov_5_q7_L10 signature measured 256 spare bits, so on the order of 2^256 distinct byte strings verified for the one message and key. Verification now rejects any element outside [0, q) and any set padding bit; a signature produced by this or by the reference implementation is unaffected, as the KAT vectors of every parameter set confirm. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSNOVA signature verification ignored four bits inside the signature for any parameter set whose solution is an odd number of GF(16) nibbles - the SNOVA_24_5_5, SNOVA_25_8_3, SNOVA_29_6_5 and SNOVA_66_15_3 families, sixteen of the forty-four parameter sets. The last byte of the encoded solution carries a single nibble and the signer leaves the top four bits zero, but the decoder did not read them, so sixteen distinct byte strings verified for one signature. This is the same non-unique encoding github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e closed for bytes following the signature, applied inside it; the verifier now requires those bits to be zero. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSnovaPrivateKeyParameters did not validate the length of the private key encoding handed to it - the only one of the five schemes of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e that did not - and SnovaParameters.getPrivateKeyLength() reported the expanded (\u0026quot;ESK\u0026quot;) length even for a parameter set whose private key is the seed pair. A private key encoding reaches this constructor straight from a PKCS#8 blob, so a wrong length went undetected: a seed-form key with extra bytes appended was accepted and signed under a different derived key, and a short expanded-form key sized the signer's decode buffer negatively, throwing NegativeArraySizeException out of generateSignature() rather than being reported at construction. Related, the signing retry loop could not terminate: the vinegar values are derived from a single-byte counter, so only 256 distinct linear systems can be tried, and an expanded-form private key that is not a real central map is singular for all of them - generateSignature() then span forever rather than failing. The length is now checked at construction, getPrivateKeyLength() reports the length that parameter set's private key actually has, and the retry loop gives up after its 256 attempts as MAYO's does.\u003c/li\u003e\n\u003cli\u003eMayoSigner and MayoKeyPairGenerator did not clear several buffers holding secret key material that the MAYO reference implementation explicitly clears. Signing left the secret oil space O, the expanded L = (P1 + P1^t) * O + P2, and the M / VPV / Ox intermediates of the central map in place, having gone to the trouble of clearing eleven other buffers; key generation left the expanded seed, whose tail is the encoded oil space, and the P1 * O + P2 half of P; and the row-echelon step left the packed echelon form of the secret linear system and its pivot rows. Separately, if all 256 attempts at solving for the signature had given a rank-deficient system, signing emitted a signature built from the failed attempt's state instead of reporting the failure the reference returns, and AIMerSigner.generateSignature returned an empty array on failure, which a caller would hand on as though it were a signature. Both now throw.\u003c/li\u003e\n\u003cli\u003eFive PQC signature schemes - MAYO, SNOVA, QR-UOV, SQIsign and AIMer - returned the NIST crypto_sign \u0026quot;sm\u0026quot; signed-message envelope from generateSignature() rather than the signature. That envelope is an artefact of the reference KAT harness, which records the message alongside the signature so a vector file can be self-contained; it is not part of any of the five specifications, and no other BC signer emits it (Falcon's KAT test rebuilds the equivalent envelope in the test, which is where it belongs). Two consequences followed, both reaching the JCA Signature services of every parameter set of the five schemes in BouncyCastlePQCProvider. First, since the message was appended to the signature, verification had to skip whatever followed the signature proper, and it did so by checking only that the buffer was long enough - so any number of trailing bytes could be added to a valid signature, or the appended message replaced with unrelated data, and it still verified. A signature encoding was therefore not unique: anyone holding one valid signature could produce unlimited distinct byte strings that all verified for the same message and key, which breaks any use that treats the signature bytes as an identifier, deduplicates on them, or records them as evidence. Second, the envelope propagated into everything built on the operator layer: because ContentSigner hands the signature straight into the structure being signed, every X.509 certificate, CRL, CMS SignedData and TLS CertificateVerify BC produced with one of these algorithms carried a verbatim copy of the signed data inside its own signature field - a self-signed MAYO-1 certificate came to 3567 bytes where the same certificate is now 2020 - which no other implementation can parse as a signature, and which in a detached CMS signature meant the \u0026quot;detached\u0026quot; signature carried the content. generateSignature() now returns the bare signature, and verifySignature() requires exactly the parameter set's signature length, so appended or truncated data is rejected rather than ignored. \u003cstrong\u003eThis is a behavioural change for signatures produced by an earlier release\u003c/strong\u003e - MAYO and SNOVA from 1.84, QR-UOV, SQIsign and AIMer from 1.85 - which are no longer accepted in the envelope form they were emitted in; the signature bytes themselves are unchanged, so a stored value can be recovered by taking the leading signature-length bytes, or for AIMer, whose envelope was message || signature rather than signature || message, the trailing ones. The KAT tests now rebuild the envelope before comparing against the vector files, which continue to record it. Note that AIMer's verification had already been made length-exact during this cycle (see the entry below relating to github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2401\"\u003e#2401\u003c/a\u003e), so of the five only its envelope remained (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe MLS implementation did not bind an X.509 credential to the LeafNode's signature_key. LeafNode.verify() checked a leaf's signature against the signature_key declared in the leaf itself, while the X.509 credential's certificate chain was stored but never parsed or checked, so the certificate's public key was never required to match signature_key (RFC 9420 sec. 5.3). A leaf could therefore carry one party's certificate while being signed by an unrelated key and still be accepted under that party's identity through KeyPackage.verify() and the Group leaf-validation path. LeafNode.verify() now requires the end-entity certificate's subject public key, in the cipher suite's signature encoding, to equal signature_key for an X.509 credential, and rejects the leaf otherwise - including an empty chain or a certificate whose key type does not match the cipher suite; certificate-chain and identity validation to a trust anchor remain the application's responsibility per RFC 9420 sec. 5.3.1. A public org.bouncycastle.mls.codec.Certificate(byte[]) constructor and a Credential.getCertificates() accessor are added so callers can build and inspect X.509 credentials. Basic credentials are unaffected.\u003c/li\u003e\n\u003cli\u003eThe SecureRandom supplied to org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder.setSecureRandom() did not drive the content IV / nonce for any algorithm other than RC2. EnvelopedDataHelper.generateParameters passed the caller's SecureRandom to the AlgorithmParameterGenerator only in the RC2_CBC branch; every other content-encryption algorithm - AES-CBC, AES-GCM, AES-CCM, Camellia, ARIA, SEED and the rest - reached pGen.generateParameters() on an uninitialised generator, so the IV / nonce was drawn from a default SecureRandom and setSecureRandom() was silently ignored (the builder's javadoc states that random is used for IV/nonce generation). The generator is now initialised with the supplied random on the general path as well, so a caller who provides a specific randomness source - for a controlled or FIPS-approved DRBG, say - has it honoured for the content IV / nonce. The session-key generation path was unaffected and already used the supplied random. Because the content IV / nonce now comes from the supplied SecureRandom, the org.bouncycastle.crypto.util JournalingSecureRandom / JournaledAlgorithm reproducible-encryption support records it in the transcript: a resumed session reproduces the IV / nonce by regenerating it from the replayed randomness - build the resuming encryptor from the content-algorithm OID - rather than by reusing the AlgorithmIdentifier captured from the first encryption, which no longer keeps the transcript aligned.\u003c/li\u003e\n\u003cli\u003eThe NTRU LPRime, NTRU+ and SMAUG-T KEM generators threw a NullPointerException when constructed with a null SecureRandom, where every other KEM generator - including NTRU LPRime's own SNTRU Prime counterpart in the same package - defaults one through CryptoServicesRegistrar.getSecureRandom(). This is reachable from the lightweight API directly, and from javax.crypto.KEM, whose newEncapsulator() documents a null random as a request for the provider's default.\u003c/li\u003e\n\u003cli\u003eFrodoKEMEngine kept a single SHAKE instance in a field, so an engine reached concurrently produced wrong results. It is reached that way through org.bouncycastle.crypto.kems.FrodoKEMExtractor, which holds one engine for its lifetime: two threads extracting through one extractor interleaved the digest's absorb and squeeze phases, yielding shared secrets that silently did not match the sender's, or an IllegalStateException of \u0026quot;attempt to absorb while squeezing\u0026quot; from inside extractSecret. The digest is now built per call, as CMCEEngine's already was, which makes an extractor safe to share. Encapsulation was unaffected, since FrodoKEMGenerator builds an engine per call. Results for any single-threaded use are unchanged - the reference KAT vectors are byte-identical.\u003c/li\u003e\n\u003cli\u003eThe BCJSSE provider carried the TLS 1.2 coupling between the supported_groups extension and ECDSA over into TLS 1.3: an ECDSA signature scheme was treated as usable - offered in the signature_algorithms and signature_algorithms_cert extensions, and eligible when selecting the local credentials - only while the corresponding curve was among the named groups enabled for key exchange, both per context (a group unavailable for key agreement disabled the scheme outright) and per connection (the curve had to be in the supported_groups list about to be sent). RFC 8446 sec. 4.2.7 scopes supported_groups to key exchange only, with signature algorithms negotiated independently (sec. 4.2.3), so this incorrect restriction in TLS 1.3 has been removed. Ed25519, Ed448 and the RSA schemes were unaffected (as well as typical deployments using a default configuration for named groups).\u003c/li\u003e\n\u003cli\u003eThe bcmail module descriptor did not declare its javax.mail/javax.activation dependences, so a modular (module-path) consumer of the jar hit IllegalAccessError/module-resolution failures when the S/MIME classes touched the mail API. The descriptor now requires them optionally (requires static) under all four module names those libraries are known by - the automatic names mail and activation carried by the javax.mail:mail / javax.activation:activation artifacts, and the explicit names java.mail and java.activation carried by the newer com.sun.mail / com.sun.activation ones - a hard requires on any one name would break users of the others (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2389\"\u003e#2389\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFour type-coercion helpers in the OER / IEEE 1609.2 (ITS) decoder tested the wrong type in the identity fast path that lets a getInstance() factory return an argument that is already of the target type. org.bouncycastle.oer.its.ieee1609dot2.basetypes.UINT32.getInstance and org.bouncycastle.oer.its.etsi102941.basetypes.Version.getInstance guarded on UINT8 - a sibling of UINT32 under UintBase, and unrelated to Version - so passing a UINT8 threw ClassCastException, while passing an actual UINT32 or Version missed the fast path and fell through to ASN1Integer.getInstance, which rejects them: neither factory accepted its own type. org.bouncycastle.oer.its.etsi103097.EtsiTs103097DataEncryptedUnicast.getInstance guarded on its sibling EtsiTs103097DataEncrypted and then cast to the unicast type, so an EtsiTs103097DataEncrypted threw ClassCastException. org.bouncycastle.oer.OEROptional.getObject(Class) called value.getClass().isInstance(type) with the arguments transposed, which is always false because the argument is a java.lang.Class, so the cast path was dead and every optional field was resolved reflectively, failing with IllegalStateException for a target type with no static getInstance. Each guard now names the type it returns, matching the sibling UINT8 / UINT16 / UINT64 and EtsiTs103097DataEncrypted factories (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2373\"\u003e#2373\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eDefaultAlgorithmNameFinder and DefaultSignatureNameFinder had no entries at all for the ShangMi algorithms, so an SM2 signature AlgorithmIdentifier that DefaultSignatureAlgorithmIdentifierFinder itself produces came back named only by its OID string - getAlgorithmName(GMObjectIdentifiers.sm2sign_with_sm3) returned \u0026quot;1.2.156.10197.1.501\u0026quot; and hasAlgorithmName returned false. Both finders now name sm2sign_with_sm3 as SM3WITHSM2 and sm2sign_with_sha256 as SHA256WITHSM2, and DefaultAlgorithmNameFinder additionally names the sm3 digest. All three resolve through the BC provider, as Signature and MessageDigest respectively. The remaining GM arc - the SM4 cipher modes, the sm2encrypt variants, and the SM1 / SM6 / SSF33 ciphers BC does not implement - is still unnamed (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2377\"\u003e#2377\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe RFC 4998 evidence-record classes compared the digest AlgorithmIdentifier named by a time-stamp authority with the one their own DigestCalculator uses, and did so with AlgorithmIdentifier.equals(), which compares the encodings. A TSA that names SHA-256 with an explicit NULL parameters field - DigiCert among them - therefore failed against BC's own calculator, which names it with the parameters absent, and ERSArchiveTimeStampGenerator.generateArchiveTimeStamp rejected the response with \u0026quot;time stamp imprint for wrong algorithm\u0026quot;. Both spellings name the same digest and RFC 5754 sec. 2 requires a receiver to accept either, while requiring that identifiers be generated with the parameters absent, which BC already does. The three affected comparisons - the two in ERSArchiveTimeStampGenerator and the digest check in ERSEvidenceRecord.renew - now use the new AlgorithmIdentifier.areEquivalent, which matches on the algorithm and treats an absent parameters field and NULL as the same, and the consistency check across an evidence record's archive time stamp chain uses it too. An identifier carrying an actual parameter structure is never equivalent to one carrying none (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2379\"\u003e#2379\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eEDIPartyName.toASN1Primitive emitted the nameAssigner and partyName DirectoryStrings without their context tags, so an EDIPartyName built through its public constructor could not be parsed back by EDIPartyName.getInstance, which correctly requires them. RFC 5280 sec. 4.2.1.6 tags both members [0] and [1], and those tags are explicit despite the module's IMPLICIT TAGS because DirectoryString is a CHOICE, which X.680 does not allow to be tagged implicitly - the decoder already had this right. The encoder now matches it. Note the type was added during the 1.85 cycle and GeneralName validates its ediPartyName alternative through it, so a GeneralName carrying an untagged ediPartyName - including one BC itself produced - is rejected where 1.84 passed it through unexamined; the untagged form is not read leniently (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2380\"\u003e#2380\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eRSASSA-PSS could not be used with a RIPEMD digest through the JCA API. Nothing registered the RIPEMD PSS signatures, so Signature.getInstance(\u0026quot;RIPEMD160WITHRSAANDMGF1\u0026quot;) raised NoSuchAlgorithmException, and the generic RSASSA-PSS route with an explicit PSSParameterSpec failed too: org.bouncycastle.jcajce.provider.util.DigestFactory.getDigest returned null for a RIPEMD name, and isSameDigest - an allow-list of the SHA families and MD5 - reported two identical RIPEMD names as different digests, so the spec was rejected with \u0026quot;digest algorithm for MGF should be the same as for PSS parameters\u0026quot;. isSameDigest now answers true for equal names whatever the digest, which also covers Whirlpool, SM3, GOST3411 and anything else outside that allow-list; DigestFactory recognises RIPEMD128, RIPEMD160 and RIPEMD256 by name and OID; the three PSS signatures are registered with MGF1 over the same digest and a salt of the digest length; and DefaultSignatureAlgorithmIdentifierFinder gains the matching RIPEMD*WITHRSAANDMGF1 entries with their RSASSA-PSS-params, so the operator/JcaContentSignerBuilder path works as well. Note BC continues to require the PSS hash and the MGF1 hash to be the same, which RFC 8017 does not itself demand (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2381\"\u003e#2381\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe opt-in key-size validation on CMS key-transport recipients (org.bouncycastle.cms.jcajce.JceKeyTransRecipient.setKeySizeValidation(true)) never ran for a message using RFC 9709 CEK derivation (id-alg-cek-hkdf-sha256): the branch that should have selected the actual content-encryption algorithm carried in the KDF AlgorithmIdentifier's parameters compared the encrypted-key byte array against the id-alg-cek-hkdf-sha256 object identifier - a comparison that is always false - so the check fell through to a key-size lookup on the outer KDF OID, which has no registered key size, and silently checked nothing. A key-transport EnvelopedData/AuthEnvelopedData whose transported (and HKDF-derived) content-encryption key did not match the key size of the advertised content-encryption algorithm was therefore accepted even with validation enabled. The recipient now dispatches on the content-encryption AlgorithmIdentifier's algorithm OID, so key-size validation of RFC 9709 messages checks the recovered key against the inner content-encryption algorithm. Messages with a matching key size, non-HKDF messages, and recipients that do not enable validation are unaffected.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003eSee full diff in \u003ca href=\"https://github.com/bcgit/bc-java/commits\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003ecommonmark-java 0.29.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e[0.29.0] - 2026-06-20\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/comm...\n\n_Description has been truncated_","html_url":"https://github.com/stevewow/openclaw/pull/41","url":"https://dependabot.ecosyste.ms/api/v1/hosts/GitHub/repositories/stevewow%2Fopenclaw/issues/41","packages_url":"https://dependabot.ecosyste.ms/api/v1/issues/41/packages"},{"uuid":"5404784348","node_id":"PR_kwDOTdoxEM8AAAABC5c9bA","number":13,"state":"closed","title":"Bump the android-deps group across 1 directory with 17 updates","user":"dependabot[bot]","labels":["dependencies","java"],"assignees":[],"locked":false,"comments_count":1,"pull_request":true,"closed_at":"2026-09-11T21:07:46.000Z","author_association":null,"state_reason":null,"created_at":"2026-09-09T21:11:02.000Z","updated_at":"2026-09-11T21:07:48.000Z","time_to_close":172604,"merged_at":null,"merged_by":null,"closed_by":null,"dependency_metadata":{"prefix":"Bump","group_name":"android-deps","update_count":17,"packages":[{"name":"gradle-wrapper","old_version":"9.6.1","new_version":"9.7.1","repository_url":"https://github.com/gradle/gradle"},{"name":"org.bouncycastle:bcprov-jdk18on","old_version":"1.84","new_version":"1.85.2","repository_url":"https://github.com/bcgit/bc-java"},{"name":"org.commonmark:commonmark","old_version":"0.29.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-autolink","old_version":"0.29.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-strikethrough","old_version":"0.29.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-tables","old_version":"0.29.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-task-list-items","old_version":"0.29.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.junit.vintage:junit-vintage-engine","old_version":"6.1.1","new_version":"6.1.3","repository_url":"https://github.com/junit-team/junit-framework"},{"name":"io.kotest:kotest-assertions-core-jvm","old_version":"6.2.1","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"io.kotest:kotest-runner-junit5-jvm","old_version":"6.2.1","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"com.squareup.okhttp3:mockwebserver","old_version":"5.4.0","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.squareup.okhttp3:okhttp","old_version":"5.4.0","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.android.application","old_version":"9.2.1","new_version":"9.4.0"},{"name":"com.android.test","old_version":"9.2.1","new_version":"9.4.0"},{"name":"org.jetbrains.kotlin.plugin.compose","old_version":"2.4.0","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"},{"name":"org.jetbrains.kotlin.plugin.serialization","old_version":"2.4.0","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"},{"name":"com.google.devtools.ksp","old_version":"2.3.9","new_version":"2.3.11","repository_url":"https://github.com/google/ksp"}],"path":null,"ecosystem":"maven"},"body":"Bumps the android-deps group with 17 updates in the /apps/android directory:\n\n| Package | From | To |\n| --- | --- | --- |\n| [gradle-wrapper](https://github.com/gradle/gradle) | `9.6.1` | `9.7.1` |\n| [org.bouncycastle:bcprov-jdk18on](https://github.com/bcgit/bc-java) | `1.84` | `1.85.2` |\n| [org.commonmark:commonmark](https://github.com/commonmark/commonmark-java) | `0.29.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-autolink](https://github.com/commonmark/commonmark-java) | `0.29.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-strikethrough](https://github.com/commonmark/commonmark-java) | `0.29.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-tables](https://github.com/commonmark/commonmark-java) | `0.29.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-task-list-items](https://github.com/commonmark/commonmark-java) | `0.29.0` | `0.30.0` |\n| [org.junit.vintage:junit-vintage-engine](https://github.com/junit-team/junit-framework) | `6.1.1` | `6.1.3` |\n| [io.kotest:kotest-assertions-core-jvm](https://github.com/kotest/kotest) | `6.2.1` | `6.2.4` |\n| [io.kotest:kotest-runner-junit5-jvm](https://github.com/kotest/kotest) | `6.2.1` | `6.2.4` |\n| [com.squareup.okhttp3:mockwebserver](https://github.com/lysine-dev/okhttp) | `5.4.0` | `5.5.0` |\n| [com.squareup.okhttp3:okhttp](https://github.com/lysine-dev/okhttp) | `5.4.0` | `5.5.0` |\n| com.android.application | `9.2.1` | `9.4.0` |\n| com.android.test | `9.2.1` | `9.4.0` |\n| [org.jetbrains.kotlin.plugin.compose](https://github.com/JetBrains/kotlin) | `2.4.0` | `2.4.20` |\n| [org.jetbrains.kotlin.plugin.serialization](https://github.com/JetBrains/kotlin) | `2.4.0` | `2.4.20` |\n| [com.google.devtools.ksp](https://github.com/google/ksp) | `2.3.9` | `2.3.11` |\n\n\nUpdates `gradle-wrapper` from 9.6.1 to 9.7.1\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/gradle/gradle/releases\"\u003egradle-wrapper's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e9.7.1\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.1.\u003c/p\u003e\n\u003cp\u003eThis is a patch release for 9.7.0. We recommend using 9.7.1 instead of 9.7.0.\u003c/p\u003e\n\u003cp\u003eHere are the highlights of 9.7.0 release:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIsolated Projects graduates to incubating\u003c/li\u003e\n\u003cli\u003eBroader Configuration Cache compatibility\u003c/li\u003e\n\u003cli\u003eResilient Sync helps you fix broken builds\u003c/li\u003e\n\u003cli\u003eMore source locations in problem reports\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003ca href=\"https://docs.gradle.org/9.7.1/release-notes.html\"\u003eRead the Release Notes\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eWe would like to thank the following community members for their contributions to this release of Gradle:\n\u003ca href=\"https://github.com/aSemy\"\u003eAdam\u003c/a\u003e,\n\u003ca href=\"https://github.com/Gautam-aman\"\u003eAman Gautam\u003c/a\u003e,\n\u003ca href=\"https://github.com/YukiCodepth\"\u003eAman Kumar\u003c/a\u003e,\n\u003ca href=\"https://github.com/adubrouski\"\u003eAnton Dubrouski\u003c/a\u003e,\n\u003ca href=\"https://github.com/liutikas\"\u003eAurimas\u003c/a\u003e,\n\u003ca href=\"https://github.com/gbhavya07\"\u003egbhavya07\u003c/a\u003e,\n\u003ca href=\"https://github.com/joshfriend\"\u003eJosh Friend\u003c/a\u003e,\n\u003ca href=\"https://github.com/nicklauslittle-gov\"\u003enicklauslittle-gov\u003c/a\u003e,\n\u003ca href=\"https://github.com/psoni674\"\u003ePragati\u003c/a\u003e,\n\u003ca href=\"https://github.com/Project516\"\u003eproject516\u003c/a\u003e,\n\u003ca href=\"https://github.com/Uomocapra\"\u003eQin Mi\u003c/a\u003e,\n\u003ca href=\"https://github.com/rkdfx\"\u003eRavi\u003c/a\u003e,\n\u003ca href=\"https://github.com/sk-reddy17\"\u003esk-reddy17\u003c/a\u003e,\n\u003ca href=\"https://github.com/Suvrat1629\"\u003eSuvrat Acharya\u003c/a\u003e,\n\u003ca href=\"https://github.com/ShreckYe\"\u003eYongshun Ye\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eUpgrade instructions\u003c/h2\u003e\n\u003cp\u003eSwitch your build to use Gradle 9.7.1 by updating your wrapper:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e./gradlew :wrapper --gradle-version=9.7.1 \u0026amp;\u0026amp; ./gradlew :wrapper\r\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eSee the Gradle \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/upgrading_version_9.html\"\u003e9.x upgrade guide\u003c/a\u003e to learn about deprecations, breaking changes and other considerations when upgrading.\u003c/p\u003e\n\u003cp\u003eFor Java, Groovy, Kotlin and Android compatibility, see the \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/compatibility.html\"\u003efull compatibility notes\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eReporting problems\u003c/h2\u003e\n\u003cp\u003eIf you find a problem with this release, please file a bug on \u003ca href=\"https://github.com/gradle/gradle/issues\"\u003eGitHub Issues\u003c/a\u003e adhering to our issue guidelines.\nIf you're not sure you're encountering a bug, please use the \u003ca href=\"https://discuss.gradle.org/c/help-discuss\"\u003eforum\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eWe hope you will build happiness with Gradle, and we look forward to your feedback via \u003ca href=\"https://twitter.com/gradle\"\u003eTwitter\u003c/a\u003e or on \u003ca href=\"https://github.com/gradle\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003e9.7.0\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.0.\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/92f0512e7f06d84621afba191f75e265363890cf\"\u003e\u003ccode\u003e92f0512\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38892\"\u003e#38892\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/820ee75a99a179bbffa41bcedc6477b685fabb9f\"\u003e\u003ccode\u003e820ee75\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/82c23f9bd2a89b4cc644e1f90a28a8668feb3dee\"\u003e\u003ccode\u003e82c23f9\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering problem in KTS (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38878\"\u003e#38878\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/ef11a7268fe8cc8d6ab849ec911aa11220180553\"\u003e\u003ccode\u003eef11a72\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering issue\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/bb0d8a974a71b1003efea41e4046e98855cd5ff8\"\u003e\u003ccode\u003ebb0d8a9\u003c/code\u003e\u003c/a\u003e Make relevant tests polyglot (run for multiple DSLs)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/336e129d7f95c03486acafc97abf59734acfed48\"\u003e\u003ccode\u003e336e129\u003c/code\u003e\u003c/a\u003e Update signing configuration (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38874\"\u003e#38874\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/4bdf0da2dad9884d089a6062a45ea7183e7d735d\"\u003e\u003ccode\u003e4bdf0da\u003c/code\u003e\u003c/a\u003e Update signing configuration\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/cd9b92c1b82856248cf1dc58b50378238bec7b52\"\u003e\u003ccode\u003ecd9b92c\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38839\"\u003e#38839\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/5f4e381964897ad8d6b99e5a7c77f26dba3259fb\"\u003e\u003ccode\u003e5f4e381\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/1e08ab551367aeb5fb48b26e72807e1d2b27c939\"\u003e\u003ccode\u003e1e08ab5\u003c/code\u003e\u003c/a\u003e Keep type-use annotations in extracted ABI classes (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38810\"\u003e#38810\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/gradle/gradle/compare/v9.6.1...v9.7.1\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.bouncycastle:bcprov-jdk18on` from 1.84 to 1.85.2\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.md\"\u003eorg.bouncycastle:bcprov-jdk18on's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch1\u003eBouncy Castle Crypto Package - Release Notes\u003c/h1\u003e\n\u003ch2\u003e1.0 Introduction\u003c/h2\u003e\n\u003cp\u003eThe Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. The package is organised so that it contains a light-weight API suitable for use in any environment (including the J2ME) with the additional infrastructure to conform the algorithms to the JCE framework.\u003c/p\u003e\n\u003ch2\u003e2.0 Release History\u003c/h2\u003e\n\u003cp\u003e\u003c!-- raw HTML omitted --\u003e\u003c!-- raw HTML omitted --\u003e\u003c/p\u003e\n\u003ch3\u003e2.1.1 Version\u003c/h3\u003e\n\u003cp\u003eRelease: 1.86\u003cbr /\u003e\nDate: 2026, TBD\u003c/p\u003e\n\u003ch3\u003e2.1.2 Defects Fixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) let a subkey inherit the primary key's Key Flags when its own Subkey Binding signature carried no Key Flags subpacket, which made the two capability decisions taken for one subkey disagree. OpenPGPCertificate.OpenPGPComponentKey.isSigningKey() reads the effective flags, which fell back to the primary key's direct-key or primary user ID self-signature, so a subkey bound with no flags of its own counted as signing-capable; verifyEmbeddedPrimaryKeyBinding reads the binding signature's own flags, found no signing capability there, and so skipped the embedded Primary Key Binding (cross-certification) signature that RFC 9580 sec. 5.2.1.8 and sec. 10.1.3 require of a subkey that can issue signatures. A data signature made by such a subkey was therefore attributed to the certificate and reported valid by OpenPGPSignature.OpenPGPDocumentSignature.isValid() with the cross-certification requirement never applied, where GnuPG refuses the same certificate and message as not cross-certified. An attacker holding a third party's public signing subkey - which is public material - could bind it to their own primary key with a Subkey Binding signature they are able to make, carrying no Key Flags and no embedded Primary Key Binding signature, which they cannot make without the subkey's private key, and have that party's genuine signatures verify as valid under the attacker's own identity: misattribution of a real signature rather than a forgery of a new one, since the signature still has to be one the subkey actually made. Key Flags are a statement about the key the carrying signature refers to (RFC 9580 sec. 5.2.3.29), so a subkey no longer inherits them from the certificate-wide signatures of the primary key: a Subkey Binding signature that omits the subpacket now leaves the subkey with no capabilities rather than the primary's, which makes the flags the cross-certification check consults the same flags every other decision consults. Preferences and the other subpackets a direct-key signature carries are inherited as before, and the primary key itself - whose flags legitimately come from its direct-key or user ID self-signature - is unaffected. The low-level PGPSignature / PGPPublicKeyRing API performs no binding checks by design and is unchanged.\u003c/li\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) used a version 6 key that carried no valid Direct Key signature, falling back to the primary user ID binding as it correctly does for a version 4 key. RFC 9580 sec. 5.2.3.10 requires the opposite: \u0026quot;An implementation MUST ensure that a valid Direct Key signature is present before using a version 6 key. This prevents certain attacks where an adversary strips a self-signature specifying a Key Expiration Time or certain preferences.\u0026quot; The certificate grammar says the same structurally, the Direct Key signature being mandatory in the version 6 structure of sec. 10.1.1 and optional in the version 4 one of sec. 10.1.3. Because a version 6 certificate carries its key expiration, features and algorithm preferences on the Direct Key signature - the convention the RFC recommends and the one OpenPGPKeyGenerator follows, its user ID certification carrying no expiration at all - removing that single signature packet from a published certificate silently dropped the expiration along with the preferences and features: OpenPGPCertificate.getSignatureChainFor fell back to the user ID binding, the primary key was still reported bound, and getEncryptionKeys() and getSigningKeys() went on returning the subkeys of a key whose owner had set it to expire. The primary key fingerprint is unchanged by the removal, so a relying party pinning the key by fingerprint still treats it as the same key, and no private key or hash collision is involved; the natural moment for the strip is the key refresh that RFC 9580 names as the reason to refetch a key at all - to learn about changes in expiration, features, preferences and revocation - which is exactly the update it defeats. This is a downgrade rather than a forgery, nothing being attributed to a key that did not authorise it, and the concerning direction is encryption, to a key meant to have been retired. OpenPGPCertificate.isBoundBy now requires a valid Direct Key self-signature on a version 6 primary key before any component of the certificate - the primary key, its subkeys or its identities - is treated as bound, so a version 6 certificate stripped of it offers no keys at all rather than an unexpiring set. Version 4 certificates are unaffected: there the key expiration legitimately lives on the user ID self-signature and the fallback is correct, so it stays. The revocation-only version 6 certificate of sec. 10.1.2, which legitimately carries no Direct Key signature, is unaffected as well - its key was already refused as revoked, and reading the revocation does not go through the binding check.\u003c/li\u003e\n\u003cli\u003eThe lightweight LMSSigner and HSSSigner refused a key wrapped in ParametersWithRandom, which is how BcContentSignerBuilder passes a key whenever setSecureRandom() has been called - so BcHssLmsContentSignerBuilder built a working signer until a random was set and then failed with \u0026quot;Incorrect Key Parameters\u0026quot;, and the two signers themselves raised ClassCastException on the same input. All three now unwrap it, as the promoted ML-DSA and SLH-DSA signers already did. The random is accepted and not used: LMS derives its message randomiser C from the key's seed and the one-time index, so it is deterministic and cannot repeat while q does not. Note SP 800-208 sec. 6.1 asks for C to come from an approved random bit generator, which this implementation does not do; that is unchanged here, and a supplied random is now ignored rather than refused.\u003c/li\u003e\n\u003cli\u003eLMS signature verification did not apply two of the checks RFC 8554 sec. 5.4.2 requires before a signature is processed. Step 2g refuses a signature whose LMS typecode is not the one from the public key, and without it the path computation took its height and tree digest from the parameter set the signature named rather than the key's, so a signature claiming a height-25 parameter set drove a 25-level computation against a height-5 key. Step 2i refuses a leaf number q outside the tree, and without it an out-of-range q flowed into the node arithmetic and was left for the candidate-root comparison to catch. Neither was a forgery - the domain separation between D_LEAF and D_INTR and the final comparison saw to that - but both are attacker-chosen work the specification says to refuse up front. Both are now checked, and a signature failing either is still reported as not verifying rather than thrown out of Signature.verify(). The catch around the signature decode in LMSSigner and HSSSigner has also been narrowed to the decode itself, as the corresponding SPI was corrected to do for github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2408\"\u003e#2408\u003c/a\u003e: past the parse the engine reports an inconsistent signature by returning false rather than by throwing, so the wider catch caught nothing while standing ready to turn a future internal error into a quiet false.\u003c/li\u003e\n\u003cli\u003eThe LMS and HSS key parameter classes now apply at construction the checks their decoders apply, so a key built directly cannot be one the decoder would refuse. LMSPrivateKeyParameters accepted an identifier of any length although the decoder reads exactly 16 bytes - such a key encoded but could not be read back - and left q, maxQ and the seed length unchecked; the seed is now required to be at least m bytes at decode as well, where a one-byte seed had been decoding silently and then deriving every one-time key from it. HSSPrivateKeyParameters checked neither its level count nor that it had been given a component key per level and a chaining signature per level below the root, and then indexed both lists, so a mismatch surfaced as IndexOutOfBoundsException - or, where a level happened to match, as a null chaining signature that only failed at signing time; the level is now checked after the reset that fills it in, since a null is legitimate on the way in. LMSPrivateKeyParameters.getInstance(byte[], byte[]) adopted the public key supplied beside the private one without comparing them, so a mismatched public key was simply reported by getPublicKey(); it now cross-checks the identifier, both parameter sets and, where the tree cache already holds it, the root, as the HSS entry point does. The decoders also now report a bad version or seed length as IOException rather than IllegalStateException, so a caller can catch one type for a malformed key, and the package-private LM-OTS public key decoder no longer declares throws Exception or dereferences an unrecognised typecode. The deprecated org.bouncycastle.pqc.crypto.lms copies carry the decoder corrections.\u003c/li\u003e\n\u003cli\u003eIn the LMS JCE layer, LMSKeyGenParameterSpec.fromNames knew all twenty LMS parameter-set names but only four of the sixteen LM-OTS ones, so none of the SP 800-208 n24 or SHAKE sets could be named; all sixteen are now present. KeyPairGenerator.initialize(int, SecureRandom) reports InvalidParameterException, which is what the JCA specifies and which extends the IllegalArgumentException it raised before, so existing catches still match. BCLMSPrivateKey.getIndex now takes the exhaustion check and the index read under the key's own monitor rather than as two separate calls, and two unused fields have gone from LMSSignatureSpi. Note that the LMS Signature claims its one-time key at the first update() rather than at sign(), so a Signature that is initialised and updated and then abandoned spends an index without producing a signature - the safe direction for a one-time scheme, and now documented on the SPI.\u003c/li\u003e\n\u003cli\u003eEvery other key pair generator that refuses a key size did the same thing the LMS one did above. KeyPairGenerator.initialize(int, SecureRandom) is documented to raise InvalidParameterException when the key size is not one the generator supports, and thirty of them raised a bare IllegalArgumentException instead, so a caller following the JCA and catching the documented type saw an exception escaping rather than a refusal. The ML-DSA, ML-KEM, SLH-DSA, Classic McEliece, FrodoKEM, NTRU and composite signature and KEM generators in the BC provider, and every generator in BCPQC, now raise InvalidParameterException - NewHope included, where the value is a key size it will not take rather than a mode of initialisation it does not offer. InvalidParameterException extends IllegalArgumentException, so callers written against the old behaviour go on catching it unchanged. The two RSA generators are corrected as well, and differently: theirs is a key size below a floor rather than a mode of initialisation they do not offer, and the refusal is raised by the lightweight RSAKeyGenerationParameters, which cannot name a java.security exception at all, so the RSA KeyPairGeneratorSpi now translates it - keeping the message verbatim and the original exception as the cause, through a new SecurityExceptions.invalidParameterException factory, since InvalidParameterException has no constructor that takes one. Of the 304 KeyPairGenerator services the two providers register, 299 now refuse a nonsense key size the way the JCA defines it and five accept it as a strength they can work with, with none left raising a bare IllegalArgumentException; that is asserted as a sweep over both providers rather than per algorithm, so a generator added later is covered without the test being touched. The jdk1.3 provider overlays of the four generators that have one carry the same change, and the jdk1.3 SecurityExceptions overlay gains the new factory along with the invalidAlgorithmParameterException one it had been missing.\u003c/li\u003e\n\u003cli\u003eKeyPairGenerator.initialize(AlgorithmParameterSpec, SecureRandom) had the same shape of problem as the int overload above, and only 44 of the 304 services the two providers register reported an unusable spec as the InvalidAlgorithmParameterException that method declares. The twenty-three PQC generators that resolve a parameter set by name - cmce, frodokem, mldsa, mlkem, slhdsa, aimer, bike, faest, falcon, haetae, hqc, mayo, mqom, ntru, ntruplus, both ntruprime variants, qruov, saber, sdith, smaugt, snova and sqisign, 230 services between them - case-folded the name they got back from the spec without checking it, so a spec with no getName() method, and a null spec, produced a NullPointerException from inside the fold; their own \u0026quot;is this name one I know\u0026quot; branch, which does report the declared exception, was unreachable. The two composite generators, whose parameter set is fixed by the algorithm name so that null is the only spec they accept, refused every other one with IllegalArgumentException. RSA answered correctly for a spec of the wrong type but not for one of the right type carrying values its lightweight parameters will not take - an even public exponent, or a key size below the floor - which is now translated the same way the int overload's is. All 304 services now report the declared exception, with the composites still taking the null spec that is right for them; note that InvalidAlgorithmParameterException is a checked exception and not an IllegalArgumentException, so a caller that was catching what these threw before has to catch the declared type instead.\u003c/li\u003e\n\u003cli\u003eAn HSS private key claimed the two records of its position under two different monitors. The top-level index and the bottom component key's one-time index q are independent records of the same position - the decoder requires them to agree, see the entry below - but generateLMSContext incremented the index under the HSS key's own monitor, released it, and only then claimed q under the component key's. A getEncoded() issued in between saw the index advanced and q not, and produced an encoding this implementation's own decoder rejects; and two threads meeting at a bottom-tree boundary could both pass the exhaustion test, take consecutive top-level indices and claim the same q, after which one of them was refused with \u0026quot;ots private key exhausted\u0026quot; by a key still reporting usages remaining, a top-level index had been spent with no signature made, and the two records stayed one apart for the rest of the key's life in that process - so it could no longer be encoded, cloned or sharded, and getIndex() and getUsagesRemaining() misreported by one. No one-time key was reused: the component key's claim is itself atomic, and the divergence runs index ahead of leaves, so the effect was on the key's usability rather than on the signatures it had made. Both records are now claimed under the one monitor, and the component key is claimed before the index is incremented so that an exhausted one leaves both untouched. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the same correction.\u003c/li\u003e\n\u003cli\u003eTimeStampToken parsed the attacker-controlled TSTInfo content of a time-stamp token (org.bouncycastle.tsp.TimeStampToken, reached from TimeStampResponse(byte[]) and (InputStream)) inside a try that caught only CMSException, so a well-formed RFC 3161 TimeStampResp whose embedded token carried a malformed TSTInfo - a SEQUENCE with fewer elements than the five mandatory fields, a non-SEQUENCE, truncated DER, or an unknown context tag - let an IllegalArgumentException or a NoSuchElementException escape the constructor's declared throws TSPException, IOException contract. A token signed by no signers or by more than one raised a bare IllegalArgumentException from the same constructor, before that try, for the same reason. Both are now reported as TSPException, matching the package-private TimeStampResponse(DLSequence) constructor and the existing getSignedAttributes guard in the same method; the signer-count refusal is a TSPValidationException, as the neighbouring check on the content type already was. Related, and the cause of the NoSuchElementException: asn1.tsp.TSTInfo read its five mandatory fields off the sequence with no bound on how many elements were actually there, so a short SEQUENCE left the enumeration to run out rather than being refused, and an oversize one was accepted with its extra elements absorbed into the optional slots. Decode now requires the five to ten elements RFC 3161 sec. 2.4.2 gives the type, which is what the sibling Accuracy and ArchiveTimeStamp decoders already did, so the failure is the IllegalArgumentException that getInstance is expected to raise (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2415\"\u003e#2415\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eNeither the HSS nor the XMSS^MT private key decoder checked its declared index against the traversal state stored beside it, although the two are independent records of the same position in the key and so can be compared. For HSS the records are the top-level index and the component keys' one-time indices q; for XMSS^MT they are the global index and the per-layer BDS states. A stored key whose index had been rolled back while its state stayed advanced - a partial write, a restore from backup, a buggy storage layer - was therefore accepted, and it then signed a second message under a one-time key the key had already used, producing a signature that verified, so nothing anywhere surfaced the reuse. RFC 8554 sec. 1 and RFC 8391 sec. 1.1 both require each one-time key to be used exactly once, and this is the failure those requirements exist to prevent; the single-tree XMSS decoder has tied its BDS state to its index since that state was first validated, and this brings the two multi-tree schemes into line. HSS decode now requires the declared index to equal the position the component q values imply - a level above the last contributes (q - 1) leaves of the levels beneath it, since its q has already advanced past the subtree it signed - and XMSS^MT decode now requires each present layer's BDS index to equal the leaf index that layer derives from the global index, allowing the one position where a layer has moved into a new subtree and its state legitimately still carries the previous subtree's final index. A layer with no state yet is unaffected, since those are built lazily at signing time. Related, and the same shape of omission: an XMSS or XMSS^MT private key encoding carries the tree root twice - the key's own root field and the root node of the BDS state stored beside it, which for XMSS^MT is the top layer's - and the two were never compared either. A corrupted root was accepted and then poisoned every signature the key made, because the root is hashed into the message digest: the signature did not verify and nothing indicated why. Decode now requires the two copies to agree. The BDS node values themselves are not checkable the way the LMS tree cache above is - a BDS authentication path, stack, retain or keep node does not have its children stored alongside it, so recomputing one means building a subtree, which is the work the state exists to avoid. Both checks are integer comparisons over the levels of the key, too small to measure against the surrounding decode, and both were verified not to reject any legitimate key by walking every index a key can reach: the full key space of the two-level HSS and the h=4/d=2, h=6/d=2, h=6/d=3, h=9/d=3 and h=8/d=4 XMSS^MT parameter sets, plus a three-level HSS key across a subtree boundary and an HSS shard. Since those node values cannot be recomputed, the encoded state now carries a checksum over itself instead, with the owning key's public seed hashed in front of it. Any corruption of the stored state is refused at decode rather than being loaded and then producing signatures that silently do not verify, and because the public seed is bound in, a state transplanted between two keys of the same parameter set is refused too, even though it is internally consistent and arrives with its own matching root. The public seed is bound rather than the secret seed or the PRF key deliberately: the state's own root and index are inside the encoding and so are already covered, hashing secret material would make the stored checksum a commitment to it for no gain in detection, and the PRF key does not influence the state at all. \u003cstrong\u003eThis is an error-detecting code and not integrity protection\u003c/strong\u003e - anyone able to rewrite the stored key recomputes it, so it establishes that the state is unchanged since it was written, never that it was correct when written, and the allocation bounds on the encoding remain the guard against a crafted one. It costs one SHA-256 over the state, measured at 5 to 8 microseconds each way for the h=10 and h=16 parameter sets, and 32 bytes of encoding. The state encoding was added earlier in this same cycle and has not been released, so the checksum is simply part of it rather than a new version: a state written by a 1.86 beta is rejected, which is recovered from by re-exporting the key. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the HSS check as well (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2414\"\u003e#2414\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe S/MIME example smoke test in the misc module (org.bouncycastle.mail.smime.examples.test.AllTests) drove SendSignedAndEncryptedMail against smtp.gmail.com, and that example finishes with Transport.send() under JavaMail's default settings, which have no connect timeout. Where outbound port 25 is refused the failure was swallowed and the test passed; where it is silently dropped, as on many home networks, the connect blocked and ./gradlew build hung in :misc:test indefinitely with \u0026quot;0 tests completed\u0026quot;. The test now delivers to an SMTP stub on a loopback port, with connect / read / write timeouts as a backstop, and asserts the message arrived (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2407\"\u003e#2407\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation took the traditional component public key bytes it feeds the KEM combiner from the recipient key's own encoding, while decapsulation recomputes the point from the private key and so always produced an uncompressed one. Section 4 of draft-ietf-lamps-pq-composite-kem requires an EC component to be carried as an uncompressed point, but a component key that encodes itself compressed - a BC EC key whose point format has been set through org.bouncycastle.jce.interfaces.ECPointEncoder, or a key from a provider that preserves a compressed encoding - was passed through as it came. Both sides then combined a different tradPK and derived different shared secrets, with no error reported on either: encapsulation and decapsulation both succeeded and the recipient simply could not decrypt. The EC component is now normalised to an uncompressed point wherever the engine serialises one, which covers the ephemeral key that forms the ciphertext as well. X25519 and X448 components have a single encoding and were unaffected, as were EC keys left in their default (uncompressed) format, whose shared secrets are unchanged. CompositePublicKey.getEncoded() took its component bytes the same way, so such a key also encoded to a composite key other implementations reject and whose bytes changed across an encode / decode / encode round trip - 1238 bytes rather than 1270 for MLKEM768-ECDH-P256, and for the composite ML-DSA keys sharing that method, 2006 rather than 2038 for MLDSA65-ECDSA-P256. It now normalises the component the same way. This is a write-side change only: a composite key carrying a compressed EC component is still decoded, since the component key factories accept either form, and continues to verify signatures as before - it simply re-encodes in the normalised form. The shared normalisation is org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil.getUncompressedSubjectPublicKeyBytes.\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation threw a NullPointerException, wrapped in an IllegalStateException out of KeyGenerator.generateKey(), when the SecureRandom it was given was null - which javax.crypto.KEM.newEncapsulator() documents as a request for the provider's default, and which KeyGenerator.init(spec, null) passes straight through. The three RSA-OAEP composites draw the traditional shared secret from that random directly, so they were the ones affected; the ECDH and X25519 / X448 composites escaped only because their component KeyPairGenerators default a random of their own. CompositeMLKEMEngine now defaults one through CryptoServicesRegistrar.getSecureRandom() on first use, as the composite KEM Cipher's wrap path already did, and as the KEM generators corrected earlier in this cycle now do. Related, the engine now also clears the ML-KEM component's shared secret alongside the traditional one on both the encapsulate and decapsulate paths - the copy handed back by getEncoded() was left in the heap - as section 3.5 of draft-ietf-lamps-pq-composite-kem requires.\u003c/li\u003e\n\u003cli\u003eCompositePublicKey.getAlgorithm() and CompositePrivateKey.getAlgorithm() returned null for all twelve Composite ML-KEM (draft-ietf-lamps-pq-composite-kem) parameter sets. Both classes resolved the name through the composite signature index only, which holds the composite ML-DSA OIDs, so a composite KEM key pair - generated, parsed from a certificate, or read from PKCS#8 - reported no algorithm at all, and the standard JCA idiom of reconstructing a key with KeyFactory.getInstance(key.getAlgorithm()) raised a NullPointerException. The lookup now falls back to the composite KEM index, so the name returned is the one the provider registers the algorithm under (e.g. MLKEM768-X25519-SHA3-256), matching the composite ML-DSA behaviour. The same single-index assumption made the CompositePublicKey(SubjectPublicKeyInfo) and CompositePrivateKey(PrivateKeyInfo) constructors reject a composite KEM key with \u0026quot;unable to create CompositePublicKey from SubjectPublicKeyInfo\u0026quot;; they now dispatch to the composite KEM key factory for those OIDs. Keys obtained through KeyFactory or through BouncyCastleProvider.getPublicKey / getPrivateKey were unaffected and are unchanged (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2404\"\u003e#2404\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe org.bouncycastle.jcajce.spec.KEMKDFSpec constructor stored a null otherInfo as given, so getOtherInfo() returned null, and three of the KDF branches KdfUtil.makeKeyBytes dispatches to - KMAC-128, KMAC-256 and SHAKE-256 - read the otherInfo length without a guard and threw NullPointerException out of the KEM operation, where the KDF2, KDF3 and HKDF branches tolerate a null through KDFParameters / HKDFParameters. The Builder of every spec in the package already mapped null to empty, so no provider path reached it, but the constructor is protected on a public class and KdfUtil is documented for callers building their own KEM integration; the deprecated KEMParameterSpec passes a null itself and escaped only because it also pins the KDF to null. The constructor now stores empty for a null, so getOtherInfo() never returns null, and a null and an explicitly empty otherInfo derive the same key.\u003c/li\u003e\n\u003cli\u003eQR-UOV signature verification accepted a signature encoding that was not canonical, so the encoding of a signature was not unique even after the trailing-byte fix of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e. Each F_q element of the signature is stored in ceil(log2 q) bits, one more bit pattern than the field has elements: q itself is representable and is arithmetically congruent to zero, so an element written as q verified exactly as the same element written as zero would, and the bits padding the last element out to the byte boundary were never read at all. Every zero element of a signature therefore carried a second encoding, and for the q = 7 parameter sets roughly one element in seven is zero - a single qruov_5_q7_L10 signature measured 256 spare bits, so on the order of 2^256 distinct byte strings verified for the one message and key. Verification now rejects any element outside [0, q) and any set padding bit; a signature produced by this or by the reference implementation is unaffected, as the KAT vectors of every parameter set confirm. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSNOVA signature verification ignored four bits inside the signature for any parameter set whose solution is an odd number of GF(16) nibbles - the SNOVA_24_5_5, SNOVA_25_8_3, SNOVA_29_6_5 and SNOVA_66_15_3 families, sixteen of the forty-four parameter sets. The last byte of the encoded solution carries a single nibble and the signer leaves the top four bits zero, but the decoder did not read them, so sixteen distinct byte strings verified for one signature. This is the same non-unique encoding github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e closed for bytes following the signature, applied inside it; the verifier now requires those bits to be zero. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSnovaPrivateKeyParameters did not validate the length of the private key encoding handed to it - the only one of the five schemes of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e that did not - and SnovaParameters.getPrivateKeyLength() reported the expanded (\u0026quot;ESK\u0026quot;) length even for a parameter set whose private key is the seed pair. A private key encoding reaches this constructor straight from a PKCS#8 blob, so a wrong length went undetected: a seed-form key with extra bytes appended was accepted and signed under a different derived key, and a short expanded-form key sized the signer's decode buffer negatively, throwing NegativeArraySizeException out of generateSignature() rather than being reported at construction. Related, the signing retry loop could not terminate: the vinegar values are derived from a single-byte counter, so only 256 distinct linear systems can be tried, and an expanded-form private key that is not a real central map is singular for all of them - generateSignature() then span forever rather than failing. The length is now checked at construction, getPrivateKeyLength() reports the length that parameter set's private key actually has, and the retry loop gives up after its 256 attempts as MAYO's does.\u003c/li\u003e\n\u003cli\u003eMayoSigner and MayoKeyPairGenerator did not clear several buffers holding secret key material that the MAYO reference implementation explicitly clears. Signing left the secret oil space O, the expanded L = (P1 + P1^t) * O + P2, and the M / VPV / Ox intermediates of the central map in place, having gone to the trouble of clearing eleven other buffers; key generation left the expanded seed, whose tail is the encoded oil space, and the P1 * O + P2 half of P; and the row-echelon step left the packed echelon form of the secret linear system and its pivot rows. Separately, if all 256 attempts at solving for the signature had given a rank-deficient system, signing emitted a signature built from the failed attempt's state instead of reporting the failure the reference returns, and AIMerSigner.generateSignature returned an empty array on failure, which a caller would hand on as though it were a signature. Both now throw.\u003c/li\u003e\n\u003cli\u003eFive PQC signature schemes - MAYO, SNOVA, QR-UOV, SQIsign and AIMer - returned the NIST crypto_sign \u0026quot;sm\u0026quot; signed-message envelope from generateSignature() rather than the signature. That envelope is an artefact of the reference KAT harness, which records the message alongside the signature so a vector file can be self-contained; it is not part of any of the five specifications, and no other BC signer emits it (Falcon's KAT test rebuilds the equivalent envelope in the test, which is where it belongs). Two consequences followed, both reaching the JCA Signature services of every parameter set of the five schemes in BouncyCastlePQCProvider. First, since the message was appended to the signature, verification had to skip whatever followed the signature proper, and it did so by checking only that the buffer was long enough - so any number of trailing bytes could be added to a valid signature, or the appended message replaced with unrelated data, and it still verified. A signature encoding was therefore not unique: anyone holding one valid signature could produce unlimited distinct byte strings that all verified for the same message and key, which breaks any use that treats the signature bytes as an identifier, deduplicates on them, or records them as evidence. Second, the envelope propagated into everything built on the operator layer: because ContentSigner hands the signature straight into the structure being signed, every X.509 certificate, CRL, CMS SignedData and TLS CertificateVerify BC produced with one of these algorithms carried a verbatim copy of the signed data inside its own signature field - a self-signed MAYO-1 certificate came to 3567 bytes where the same certificate is now 2020 - which no other implementation can parse as a signature, and which in a detached CMS signature meant the \u0026quot;detached\u0026quot; signature carried the content. generateSignature() now returns the bare signature, and verifySignature() requires exactly the parameter set's signature length, so appended or truncated data is rejected rather than ignored. \u003cstrong\u003eThis is a behavioural change for signatures produced by an earlier release\u003c/strong\u003e - MAYO and SNOVA from 1.84, QR-UOV, SQIsign and AIMer from 1.85 - which are no longer accepted in the envelope form they were emitted in; the signature bytes themselves are unchanged, so a stored value can be recovered by taking the leading signature-length bytes, or for AIMer, whose envelope was message || signature rather than signature || message, the trailing ones. The KAT tests now rebuild the envelope before comparing against the vector files, which continue to record it. Note that AIMer's verification had already been made length-exact during this cycle (see the entry below relating to github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2401\"\u003e#2401\u003c/a\u003e), so of the five only its envelope remained (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe MLS implementation did not bind an X.509 credential to the LeafNode's signature_key. LeafNode.verify() checked a leaf's signature against the signature_key declared in the leaf itself, while the X.509 credential's certificate chain was stored but never parsed or checked, so the certificate's public key was never required to match signature_key (RFC 9420 sec. 5.3). A leaf could therefore carry one party's certificate while being signed by an unrelated key and still be accepted under that party's identity through KeyPackage.verify() and the Group leaf-validation path. LeafNode.verify() now requires the end-entity certificate's subject public key, in the cipher suite's signature encoding, to equal signature_key for an X.509 credential, and rejects the leaf otherwise - including an empty chain or a certificate whose key type does not match the cipher suite; certificate-chain and identity validation to a trust anchor remain the application's responsibility per RFC 9420 sec. 5.3.1. A public org.bouncycastle.mls.codec.Certificate(byte[]) constructor and a Credential.getCertificates() accessor are added so callers can build and inspect X.509 credentials. Basic credentials are unaffected.\u003c/li\u003e\n\u003cli\u003eThe SecureRandom supplied to org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder.setSecureRandom() did not drive the content IV / nonce for any algorithm other than RC2. EnvelopedDataHelper.generateParameters passed the caller's SecureRandom to the AlgorithmParameterGenerator only in the RC2_CBC branch; every other content-encryption algorithm - AES-CBC, AES-GCM, AES-CCM, Camellia, ARIA, SEED and the rest - reached pGen.generateParameters() on an uninitialised generator, so the IV / nonce was drawn from a default SecureRandom and setSecureRandom() was silently ignored (the builder's javadoc states that random is used for IV/nonce generation). The generator is now initialised with the supplied random on the general path as well, so a caller who provides a specific randomness source - for a controlled or FIPS-approved DRBG, say - has it honoured for the content IV / nonce. The session-key generation path was unaffected and already used the supplied random. Because the content IV / nonce now comes from the supplied SecureRandom, the org.bouncycastle.crypto.util JournalingSecureRandom / JournaledAlgorithm reproducible-encryption support records it in the transcript: a resumed session reproduces the IV / nonce by regenerating it from the replayed randomness - build the resuming encryptor from the content-algorithm OID - rather than by reusing the AlgorithmIdentifier captured from the first encryption, which no longer keeps the transcript aligned.\u003c/li\u003e\n\u003cli\u003eThe NTRU LPRime, NTRU+ and SMAUG-T KEM generators threw a NullPointerException when constructed with a null SecureRandom, where every other KEM generator - including NTRU LPRime's own SNTRU Prime counterpart in the same package - defaults one through CryptoServicesRegistrar.getSecureRandom(). This is reachable from the lightweight API directly, and from javax.crypto.KEM, whose newEncapsulator() documents a null random as a request for the provider's default.\u003c/li\u003e\n\u003cli\u003eFrodoKEMEngine kept a single SHAKE instance in a field, so an engine reached concurrently produced wrong results. It is reached that way through org.bouncycastle.crypto.kems.FrodoKEMExtractor, which holds one engine for its lifetime: two threads extracting through one extractor interleaved the digest's absorb and squeeze phases, yielding shared secrets that silently did not match the sender's, or an IllegalStateException of \u0026quot;attempt to absorb while squeezing\u0026quot; from inside extractSecret. The digest is now built per call, as CMCEEngine's already was, which makes an extractor safe to share. Encapsulation was unaffected, since FrodoKEMGenerator builds an engine per call. Results for any single-threaded use are unchanged - the reference KAT vectors are byte-identical.\u003c/li\u003e\n\u003cli\u003eThe BCJSSE provider carried the TLS 1.2 coupling between the supported_groups extension and ECDSA over into TLS 1.3: an ECDSA signature scheme was treated as usable - offered in the signature_algorithms and signature_algorithms_cert extensions, and eligible when selecting the local credentials - only while the corresponding curve was among the named groups enabled for key exchange, both per context (a group unavailable for key agreement disabled the scheme outright) and per connection (the curve had to be in the supported_groups list about to be sent). RFC 8446 sec. 4.2.7 scopes supported_groups to key exchange only, with signature algorithms negotiated independently (sec. 4.2.3), so this incorrect restriction in TLS 1.3 has been removed. Ed25519, Ed448 and the RSA schemes were unaffected (as well as typical deployments using a default configuration for named groups).\u003c/li\u003e\n\u003cli\u003eThe bcmail module descriptor did not declare its javax.mail/javax.activation dependences, so a modular (module-path) consumer of the jar hit IllegalAccessError/module-resolution failures when the S/MIME classes touched the mail API. The descriptor now requires them optionally (requires static) under all four module names those libraries are known by - the automatic names mail and activation carried by the javax.mail:mail / javax.activation:activation artifacts, and the explicit names java.mail and java.activation carried by the newer com.sun.mail / com.sun.activation ones - a hard requires on any one name would break users of the others (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2389\"\u003e#2389\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFour type-coercion helpers in the OER / IEEE 1609.2 (ITS) decoder tested the wrong type in the identity fast path that lets a getInstance() factory return an argument that is already of the target type. org.bouncycastle.oer.its.ieee1609dot2.basetypes.UINT32.getInstance and org.bouncycastle.oer.its.etsi102941.basetypes.Version.getInstance guarded on UINT8 - a sibling of UINT32 under UintBase, and unrelated to Version - so passing a UINT8 threw ClassCastException, while passing an actual UINT32 or Version missed the fast path and fell through to ASN1Integer.getInstance, which rejects them: neither factory accepted its own type. org.bouncycastle.oer.its.etsi103097.EtsiTs103097DataEncryptedUnicast.getInstance guarded on its sibling EtsiTs103097DataEncrypted and then cast to the unicast type, so an EtsiTs103097DataEncrypted threw ClassCastException. org.bouncycastle.oer.OEROptional.getObject(Class) called value.getClass().isInstance(type) with the arguments transposed, which is always false because the argument is a java.lang.Class, so the cast path was dead and every optional field was resolved reflectively, failing with IllegalStateException for a target type with no static getInstance. Each guard now names the type it returns, matching the sibling UINT8 / UINT16 / UINT64 and EtsiTs103097DataEncrypted factories (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2373\"\u003e#2373\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eDefaultAlgorithmNameFinder and DefaultSignatureNameFinder had no entries at all for the ShangMi algorithms, so an SM2 signature AlgorithmIdentifier that DefaultSignatureAlgorithmIdentifierFinder itself produces came back named only by its OID string - getAlgorithmName(GMObjectIdentifiers.sm2sign_with_sm3) returned \u0026quot;1.2.156.10197.1.501\u0026quot; and hasAlgorithmName returned false. Both finders now name sm2sign_with_sm3 as SM3WITHSM2 and sm2sign_with_sha256 as SHA256WITHSM2, and DefaultAlgorithmNameFinder additionally names the sm3 digest. All three resolve through the BC provider, as Signature and MessageDigest respectively. The remaining GM arc - the SM4 cipher modes, the sm2encrypt variants, and the SM1 / SM6 / SSF33 ciphers BC does not implement - is still unnamed (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2377\"\u003e#2377\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe RFC 4998 evidence-record classes compared the digest AlgorithmIdentifier named by a time-stamp authority with the one their own DigestCalculator uses, and did so with AlgorithmIdentifier.equals(), which compares the encodings. A TSA that names SHA-256 with an explicit NULL parameters field - DigiCert among them - therefore failed against BC's own calculator, which names it with the parameters absent, and ERSArchiveTimeStampGenerator.generateArchiveTimeStamp rejected the response with \u0026quot;time stamp imprint for wrong algorithm\u0026quot;. Both spellings name the same digest and RFC 5754 sec. 2 requires a receiver to accept either, while requiring that identifiers be generated with the parameters absent, which BC already does. The three affected comparisons - the two in ERSArchiveTimeStampGenerator and the digest check in ERSEvidenceRecord.renew - now use the new AlgorithmIdentifier.areEquivalent, which matches on the algorithm and treats an absent parameters field and NULL as the same, and the consistency check across an evidence record's archive time stamp chain uses it too. An identifier carrying an actual parameter structure is never equivalent to one carrying none (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2379\"\u003e#2379\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eEDIPartyName.toASN1Primitive emitted the nameAssigner and partyName DirectoryStrings without their context tags, so an EDIPartyName built through its public constructor could not be parsed back by EDIPartyName.getInstance, which correctly requires them. RFC 5280 sec. 4.2.1.6 tags both members [0] and [1], and those tags are explicit despite the module's IMPLICIT TAGS because DirectoryString is a CHOICE, which X.680 does not allow to be tagged implicitly - the decoder already had this right. The encoder now matches it. Note the type was added during the 1.85 cycle and GeneralName validates its ediPartyName alternative through it, so a GeneralName carrying an untagged ediPartyName - including one BC itself produced - is rejected where 1.84 passed it through unexamined; the untagged form is not read leniently (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2380\"\u003e#2380\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eRSASSA-PSS could not be used with a RIPEMD digest through the JCA API. Nothing registered the RIPEMD PSS signatures, so Signature.getInstance(\u0026quot;RIPEMD160WITHRSAANDMGF1\u0026quot;) raised NoSuchAlgorithmException, and the generic RSASSA-PSS route with an explicit PSSParameterSpec failed too: org.bouncycastle.jcajce.provider.util.DigestFactory.getDigest returned null for a RIPEMD name, and isSameDigest - an allow-list of the SHA families and MD5 - reported two identical RIPEMD names as different digests, so the spec was rejected with \u0026quot;digest algorithm for MGF should be the same as for PSS parameters\u0026quot;. isSameDigest now answers true for equal names whatever the digest, which also covers Whirlpool, SM3, GOST3411 and anything else outside that allow-list; DigestFactory recognises RIPEMD128, RIPEMD160 and RIPEMD256 by name and OID; the three PSS signatures are registered with MGF1 over the same digest and a salt of the digest length; and DefaultSignatureAlgorithmIdentifierFinder gains the matching RIPEMD*WITHRSAANDMGF1 entries with their RSASSA-PSS-params, so the operator/JcaContentSignerBuilder path works as well. Note BC continues to require the PSS hash and the MGF1 hash to be the same, which RFC 8017 does not itself demand (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2381\"\u003e#2381\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe opt-in key-size validation on CMS key-transport recipients (org.bouncycastle.cms.jcajce.JceKeyTransRecipient.setKeySizeValidation(true)) never ran for a message using RFC 9709 CEK derivation (id-alg-cek-hkdf-sha256): the branch that should have selected the actual content-encryption algorithm carried in the KDF AlgorithmIdentifier's parameters compared the encrypted-key byte array against the id-alg-cek-hkdf-sha256 object identifier - a comparison that is always false - so the check fell through to a key-size lookup on the outer KDF OID, which has no registered key size, and silently checked nothing. A key-transport EnvelopedData/AuthEnvelopedData whose transported (and HKDF-derived) content-encryption key did not match the key size of the advertised content-encryption algorithm was therefore accepted even with validation enabled. The recipient now dispatches on the content-encryption AlgorithmIdentifier's algorithm OID, so key-size validation of RFC 9709 messages checks the recovered key against the inner content-encryption algorithm. Messages with a matching key size, non-HKDF messages, and recipients that do not enable validation are unaffected.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003eSee full diff in \u003ca href=\"https://github.com/bcgit/bc-java/commits\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark` from 0.29.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/blockquote\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/blockquote\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/42b4fb7adfe288ef13e9e27ab20aff7e91b0ab9d\"\u003e\u003ccode\u003e42b4fb7\u003c/code\u003e\u003c/a\u003e Prepare CHANGELOG for version 0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/b76e09d7a8362abb5f04e1d6b91dbd6da279a6fc\"\u003e\u003ccode\u003eb76e09d\u003c/code\u003e\u003c/a\u003e Limit how deep inline nodes may nest by default (100)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/49f65cb5cbec93cff713179990307145198e7061\"\u003e\u003ccode\u003e49f65cb\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing deeply nested emphasis\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/610f84b83e68c381e8f784ae4d044c80e1948b67\"\u003e\u003ccode\u003e610f84b\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological autolink email addresses\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/9f1d73897a56cbd74c39347af351a473e70297e1\"\u003e\u003ccode\u003e9f1d738\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological HTML block attributes\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/e13297e849995fdd582a85841067bff1d9c35ee5\"\u003e\u003ccode\u003ee13297e\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing pathological backticks\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/89d1bd3fa1524e8217ed61db5e8116c82434470f\"\u003e\u003ccode\u003e89d1bd3\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing with lots of \u003ccode\u003e\u0026lt;\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/commonmark/commonmark-java/compare/commonmark-parent-0.29.0...commonmark-parent-0.30.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark-ext-autolink` from 0.29.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark-ext-autolink's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing patho...\n\n_Description has been truncated_","html_url":"https://github.com/GabOnezio/Sophia/pull/13","url":"https://dependabot.ecosyste.ms/api/v1/hosts/GitHub/repositories/GabOnezio%2FSophia/issues/13","packages_url":"https://dependabot.ecosyste.ms/api/v1/issues/13/packages"},{"uuid":"5404482044","node_id":"PR_kwDOTknthM8AAAABC5NZ1A","number":38,"state":"closed","title":"build(deps): bump the android-deps group across 1 directory with 24 updates","user":"dependabot[bot]","labels":["dependencies","java"],"assignees":[],"locked":false,"comments_count":1,"pull_request":true,"closed_at":"2026-09-11T20:36:33.000Z","author_association":null,"state_reason":null,"created_at":"2026-09-09T20:37:26.000Z","updated_at":"2026-09-11T20:36:35.000Z","time_to_close":172747,"merged_at":null,"merged_by":null,"closed_by":null,"dependency_metadata":{"prefix":"build(deps): bump","group_name":"android-deps","update_count":24,"packages":[{"name":"gradle-wrapper","old_version":"9.6.1","new_version":"9.7.1","repository_url":"https://github.com/gradle/gradle"},{"name":"androidx.appcompat:appcompat","old_version":"1.7.1","new_version":"1.8.0"},{"name":"androidx.wear.protolayout:protolayout","old_version":"1.4.1","new_version":"1.4.2"},{"name":"androidx.wear.protolayout:protolayout-material3","old_version":"1.4.1","new_version":"1.4.2"},{"name":"androidx.wear.tiles:tiles","old_version":"1.6.1","new_version":"1.6.2"},{"name":"org.bouncycastle:bcprov-jdk18on","old_version":"1.85","new_version":"1.85.2","repository_url":"https://github.com/bcgit/bc-java"},{"name":"org.commonmark:commonmark","old_version":"0.29.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-autolink","old_version":"0.29.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-strikethrough","old_version":"0.29.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-tables","old_version":"0.29.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-task-list-items","old_version":"0.29.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"io.coil-kt.coil3:coil-compose","old_version":"3.5.0","new_version":"3.6.2","repository_url":"https://github.com/coil-kt/coil"},{"name":"io.coil-kt.coil3:coil-svg","old_version":"3.5.0","new_version":"3.6.2","repository_url":"https://github.com/coil-kt/coil"},{"name":"org.junit.vintage:junit-vintage-engine","old_version":"6.1.2","new_version":"6.1.3","repository_url":"https://github.com/junit-team/junit-framework"},{"name":"io.kotest:kotest-assertions-core-jvm","old_version":"6.2.3","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"io.kotest:kotest-runner-junit5-jvm","old_version":"6.2.3","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"com.squareup.okhttp3:mockwebserver","old_version":"5.4.0","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.squareup.okhttp3:okhttp","old_version":"5.4.0","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.android.application","old_version":"9.3.1","new_version":"9.4.0"},{"name":"com.android.library","old_version":"9.3.1","new_version":"9.4.0"},{"name":"com.android.test","old_version":"9.3.1","new_version":"9.4.0"},{"name":"org.jetbrains.kotlin.plugin.compose","old_version":"2.4.10","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"},{"name":"org.jetbrains.kotlin.plugin.serialization","old_version":"2.4.10","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"},{"name":"com.google.devtools.ksp","old_version":"2.3.10","new_version":"2.3.11","repository_url":"https://github.com/google/ksp"}],"path":null,"ecosystem":"maven"},"body":"Bumps the android-deps group with 24 updates in the /apps/android directory:\n\n| Package | From | To |\n| --- | --- | --- |\n| [gradle-wrapper](https://github.com/gradle/gradle) | `9.6.1` | `9.7.1` |\n| androidx.appcompat:appcompat | `1.7.1` | `1.8.0` |\n| androidx.wear.protolayout:protolayout | `1.4.1` | `1.4.2` |\n| androidx.wear.protolayout:protolayout-material3 | `1.4.1` | `1.4.2` |\n| androidx.wear.tiles:tiles | `1.6.1` | `1.6.2` |\n| [org.bouncycastle:bcprov-jdk18on](https://github.com/bcgit/bc-java) | `1.85` | `1.85.2` |\n| [org.commonmark:commonmark](https://github.com/commonmark/commonmark-java) | `0.29.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-autolink](https://github.com/commonmark/commonmark-java) | `0.29.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-strikethrough](https://github.com/commonmark/commonmark-java) | `0.29.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-tables](https://github.com/commonmark/commonmark-java) | `0.29.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-task-list-items](https://github.com/commonmark/commonmark-java) | `0.29.0` | `0.30.0` |\n| [io.coil-kt.coil3:coil-compose](https://github.com/coil-kt/coil) | `3.5.0` | `3.6.2` |\n| [io.coil-kt.coil3:coil-svg](https://github.com/coil-kt/coil) | `3.5.0` | `3.6.2` |\n| [org.junit.vintage:junit-vintage-engine](https://github.com/junit-team/junit-framework) | `6.1.2` | `6.1.3` |\n| [io.kotest:kotest-assertions-core-jvm](https://github.com/kotest/kotest) | `6.2.3` | `6.2.4` |\n| [io.kotest:kotest-runner-junit5-jvm](https://github.com/kotest/kotest) | `6.2.3` | `6.2.4` |\n| [com.squareup.okhttp3:mockwebserver](https://github.com/lysine-dev/okhttp) | `5.4.0` | `5.5.0` |\n| [com.squareup.okhttp3:okhttp](https://github.com/lysine-dev/okhttp) | `5.4.0` | `5.5.0` |\n| com.android.application | `9.3.1` | `9.4.0` |\n| com.android.library | `9.3.1` | `9.4.0` |\n| com.android.test | `9.3.1` | `9.4.0` |\n| [org.jetbrains.kotlin.plugin.compose](https://github.com/JetBrains/kotlin) | `2.4.10` | `2.4.20` |\n| [org.jetbrains.kotlin.plugin.serialization](https://github.com/JetBrains/kotlin) | `2.4.10` | `2.4.20` |\n| [com.google.devtools.ksp](https://github.com/google/ksp) | `2.3.10` | `2.3.11` |\n\n\nUpdates `gradle-wrapper` from 9.6.1 to 9.7.1\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/gradle/gradle/releases\"\u003egradle-wrapper's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e9.7.1\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.1.\u003c/p\u003e\n\u003cp\u003eThis is a patch release for 9.7.0. We recommend using 9.7.1 instead of 9.7.0.\u003c/p\u003e\n\u003cp\u003eHere are the highlights of 9.7.0 release:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIsolated Projects graduates to incubating\u003c/li\u003e\n\u003cli\u003eBroader Configuration Cache compatibility\u003c/li\u003e\n\u003cli\u003eResilient Sync helps you fix broken builds\u003c/li\u003e\n\u003cli\u003eMore source locations in problem reports\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003ca href=\"https://docs.gradle.org/9.7.1/release-notes.html\"\u003eRead the Release Notes\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eWe would like to thank the following community members for their contributions to this release of Gradle:\n\u003ca href=\"https://github.com/aSemy\"\u003eAdam\u003c/a\u003e,\n\u003ca href=\"https://github.com/Gautam-aman\"\u003eAman Gautam\u003c/a\u003e,\n\u003ca href=\"https://github.com/YukiCodepth\"\u003eAman Kumar\u003c/a\u003e,\n\u003ca href=\"https://github.com/adubrouski\"\u003eAnton Dubrouski\u003c/a\u003e,\n\u003ca href=\"https://github.com/liutikas\"\u003eAurimas\u003c/a\u003e,\n\u003ca href=\"https://github.com/gbhavya07\"\u003egbhavya07\u003c/a\u003e,\n\u003ca href=\"https://github.com/joshfriend\"\u003eJosh Friend\u003c/a\u003e,\n\u003ca href=\"https://github.com/nicklauslittle-gov\"\u003enicklauslittle-gov\u003c/a\u003e,\n\u003ca href=\"https://github.com/psoni674\"\u003ePragati\u003c/a\u003e,\n\u003ca href=\"https://github.com/Project516\"\u003eproject516\u003c/a\u003e,\n\u003ca href=\"https://github.com/Uomocapra\"\u003eQin Mi\u003c/a\u003e,\n\u003ca href=\"https://github.com/rkdfx\"\u003eRavi\u003c/a\u003e,\n\u003ca href=\"https://github.com/sk-reddy17\"\u003esk-reddy17\u003c/a\u003e,\n\u003ca href=\"https://github.com/Suvrat1629\"\u003eSuvrat Acharya\u003c/a\u003e,\n\u003ca href=\"https://github.com/ShreckYe\"\u003eYongshun Ye\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eUpgrade instructions\u003c/h2\u003e\n\u003cp\u003eSwitch your build to use Gradle 9.7.1 by updating your wrapper:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e./gradlew :wrapper --gradle-version=9.7.1 \u0026amp;\u0026amp; ./gradlew :wrapper\r\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eSee the Gradle \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/upgrading_version_9.html\"\u003e9.x upgrade guide\u003c/a\u003e to learn about deprecations, breaking changes and other considerations when upgrading.\u003c/p\u003e\n\u003cp\u003eFor Java, Groovy, Kotlin and Android compatibility, see the \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/compatibility.html\"\u003efull compatibility notes\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eReporting problems\u003c/h2\u003e\n\u003cp\u003eIf you find a problem with this release, please file a bug on \u003ca href=\"https://github.com/gradle/gradle/issues\"\u003eGitHub Issues\u003c/a\u003e adhering to our issue guidelines.\nIf you're not sure you're encountering a bug, please use the \u003ca href=\"https://discuss.gradle.org/c/help-discuss\"\u003eforum\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eWe hope you will build happiness with Gradle, and we look forward to your feedback via \u003ca href=\"https://twitter.com/gradle\"\u003eTwitter\u003c/a\u003e or on \u003ca href=\"https://github.com/gradle\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003e9.7.0\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.0.\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/92f0512e7f06d84621afba191f75e265363890cf\"\u003e\u003ccode\u003e92f0512\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38892\"\u003e#38892\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/820ee75a99a179bbffa41bcedc6477b685fabb9f\"\u003e\u003ccode\u003e820ee75\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/82c23f9bd2a89b4cc644e1f90a28a8668feb3dee\"\u003e\u003ccode\u003e82c23f9\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering problem in KTS (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38878\"\u003e#38878\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/ef11a7268fe8cc8d6ab849ec911aa11220180553\"\u003e\u003ccode\u003eef11a72\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering issue\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/bb0d8a974a71b1003efea41e4046e98855cd5ff8\"\u003e\u003ccode\u003ebb0d8a9\u003c/code\u003e\u003c/a\u003e Make relevant tests polyglot (run for multiple DSLs)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/336e129d7f95c03486acafc97abf59734acfed48\"\u003e\u003ccode\u003e336e129\u003c/code\u003e\u003c/a\u003e Update signing configuration (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38874\"\u003e#38874\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/4bdf0da2dad9884d089a6062a45ea7183e7d735d\"\u003e\u003ccode\u003e4bdf0da\u003c/code\u003e\u003c/a\u003e Update signing configuration\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/cd9b92c1b82856248cf1dc58b50378238bec7b52\"\u003e\u003ccode\u003ecd9b92c\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38839\"\u003e#38839\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/5f4e381964897ad8d6b99e5a7c77f26dba3259fb\"\u003e\u003ccode\u003e5f4e381\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/1e08ab551367aeb5fb48b26e72807e1d2b27c939\"\u003e\u003ccode\u003e1e08ab5\u003c/code\u003e\u003c/a\u003e Keep type-use annotations in extracted ABI classes (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38810\"\u003e#38810\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/gradle/gradle/compare/v9.6.1...v9.7.1\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `androidx.appcompat:appcompat` from 1.7.1 to 1.8.0\n\nUpdates `androidx.wear.protolayout:protolayout` from 1.4.1 to 1.4.2\n\nUpdates `androidx.wear.protolayout:protolayout-material3` from 1.4.1 to 1.4.2\n\nUpdates `androidx.wear.protolayout:protolayout-material3` from 1.4.1 to 1.4.2\n\nUpdates `androidx.wear.tiles:tiles` from 1.6.1 to 1.6.2\n\nUpdates `org.bouncycastle:bcprov-jdk18on` from 1.85 to 1.85.2\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.md\"\u003eorg.bouncycastle:bcprov-jdk18on's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch1\u003eBouncy Castle Crypto Package - Release Notes\u003c/h1\u003e\n\u003ch2\u003e1.0 Introduction\u003c/h2\u003e\n\u003cp\u003eThe Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. The package is organised so that it contains a light-weight API suitable for use in any environment (including the J2ME) with the additional infrastructure to conform the algorithms to the JCE framework.\u003c/p\u003e\n\u003ch2\u003e2.0 Release History\u003c/h2\u003e\n\u003cp\u003e\u003c!-- raw HTML omitted --\u003e\u003c!-- raw HTML omitted --\u003e\u003c/p\u003e\n\u003ch3\u003e2.1.1 Version\u003c/h3\u003e\n\u003cp\u003eRelease: 1.86\u003cbr /\u003e\nDate: 2026, TBD\u003c/p\u003e\n\u003ch3\u003e2.1.2 Defects Fixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) let a subkey inherit the primary key's Key Flags when its own Subkey Binding signature carried no Key Flags subpacket, which made the two capability decisions taken for one subkey disagree. OpenPGPCertificate.OpenPGPComponentKey.isSigningKey() reads the effective flags, which fell back to the primary key's direct-key or primary user ID self-signature, so a subkey bound with no flags of its own counted as signing-capable; verifyEmbeddedPrimaryKeyBinding reads the binding signature's own flags, found no signing capability there, and so skipped the embedded Primary Key Binding (cross-certification) signature that RFC 9580 sec. 5.2.1.8 and sec. 10.1.3 require of a subkey that can issue signatures. A data signature made by such a subkey was therefore attributed to the certificate and reported valid by OpenPGPSignature.OpenPGPDocumentSignature.isValid() with the cross-certification requirement never applied, where GnuPG refuses the same certificate and message as not cross-certified. An attacker holding a third party's public signing subkey - which is public material - could bind it to their own primary key with a Subkey Binding signature they are able to make, carrying no Key Flags and no embedded Primary Key Binding signature, which they cannot make without the subkey's private key, and have that party's genuine signatures verify as valid under the attacker's own identity: misattribution of a real signature rather than a forgery of a new one, since the signature still has to be one the subkey actually made. Key Flags are a statement about the key the carrying signature refers to (RFC 9580 sec. 5.2.3.29), so a subkey no longer inherits them from the certificate-wide signatures of the primary key: a Subkey Binding signature that omits the subpacket now leaves the subkey with no capabilities rather than the primary's, which makes the flags the cross-certification check consults the same flags every other decision consults. Preferences and the other subpackets a direct-key signature carries are inherited as before, and the primary key itself - whose flags legitimately come from its direct-key or user ID self-signature - is unaffected. The low-level PGPSignature / PGPPublicKeyRing API performs no binding checks by design and is unchanged.\u003c/li\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) used a version 6 key that carried no valid Direct Key signature, falling back to the primary user ID binding as it correctly does for a version 4 key. RFC 9580 sec. 5.2.3.10 requires the opposite: \u0026quot;An implementation MUST ensure that a valid Direct Key signature is present before using a version 6 key. This prevents certain attacks where an adversary strips a self-signature specifying a Key Expiration Time or certain preferences.\u0026quot; The certificate grammar says the same structurally, the Direct Key signature being mandatory in the version 6 structure of sec. 10.1.1 and optional in the version 4 one of sec. 10.1.3. Because a version 6 certificate carries its key expiration, features and algorithm preferences on the Direct Key signature - the convention the RFC recommends and the one OpenPGPKeyGenerator follows, its user ID certification carrying no expiration at all - removing that single signature packet from a published certificate silently dropped the expiration along with the preferences and features: OpenPGPCertificate.getSignatureChainFor fell back to the user ID binding, the primary key was still reported bound, and getEncryptionKeys() and getSigningKeys() went on returning the subkeys of a key whose owner had set it to expire. The primary key fingerprint is unchanged by the removal, so a relying party pinning the key by fingerprint still treats it as the same key, and no private key or hash collision is involved; the natural moment for the strip is the key refresh that RFC 9580 names as the reason to refetch a key at all - to learn about changes in expiration, features, preferences and revocation - which is exactly the update it defeats. This is a downgrade rather than a forgery, nothing being attributed to a key that did not authorise it, and the concerning direction is encryption, to a key meant to have been retired. OpenPGPCertificate.isBoundBy now requires a valid Direct Key self-signature on a version 6 primary key before any component of the certificate - the primary key, its subkeys or its identities - is treated as bound, so a version 6 certificate stripped of it offers no keys at all rather than an unexpiring set. Version 4 certificates are unaffected: there the key expiration legitimately lives on the user ID self-signature and the fallback is correct, so it stays. The revocation-only version 6 certificate of sec. 10.1.2, which legitimately carries no Direct Key signature, is unaffected as well - its key was already refused as revoked, and reading the revocation does not go through the binding check.\u003c/li\u003e\n\u003cli\u003eThe lightweight LMSSigner and HSSSigner refused a key wrapped in ParametersWithRandom, which is how BcContentSignerBuilder passes a key whenever setSecureRandom() has been called - so BcHssLmsContentSignerBuilder built a working signer until a random was set and then failed with \u0026quot;Incorrect Key Parameters\u0026quot;, and the two signers themselves raised ClassCastException on the same input. All three now unwrap it, as the promoted ML-DSA and SLH-DSA signers already did. The random is accepted and not used: LMS derives its message randomiser C from the key's seed and the one-time index, so it is deterministic and cannot repeat while q does not. Note SP 800-208 sec. 6.1 asks for C to come from an approved random bit generator, which this implementation does not do; that is unchanged here, and a supplied random is now ignored rather than refused.\u003c/li\u003e\n\u003cli\u003eLMS signature verification did not apply two of the checks RFC 8554 sec. 5.4.2 requires before a signature is processed. Step 2g refuses a signature whose LMS typecode is not the one from the public key, and without it the path computation took its height and tree digest from the parameter set the signature named rather than the key's, so a signature claiming a height-25 parameter set drove a 25-level computation against a height-5 key. Step 2i refuses a leaf number q outside the tree, and without it an out-of-range q flowed into the node arithmetic and was left for the candidate-root comparison to catch. Neither was a forgery - the domain separation between D_LEAF and D_INTR and the final comparison saw to that - but both are attacker-chosen work the specification says to refuse up front. Both are now checked, and a signature failing either is still reported as not verifying rather than thrown out of Signature.verify(). The catch around the signature decode in LMSSigner and HSSSigner has also been narrowed to the decode itself, as the corresponding SPI was corrected to do for github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2408\"\u003e#2408\u003c/a\u003e: past the parse the engine reports an inconsistent signature by returning false rather than by throwing, so the wider catch caught nothing while standing ready to turn a future internal error into a quiet false.\u003c/li\u003e\n\u003cli\u003eThe LMS and HSS key parameter classes now apply at construction the checks their decoders apply, so a key built directly cannot be one the decoder would refuse. LMSPrivateKeyParameters accepted an identifier of any length although the decoder reads exactly 16 bytes - such a key encoded but could not be read back - and left q, maxQ and the seed length unchecked; the seed is now required to be at least m bytes at decode as well, where a one-byte seed had been decoding silently and then deriving every one-time key from it. HSSPrivateKeyParameters checked neither its level count nor that it had been given a component key per level and a chaining signature per level below the root, and then indexed both lists, so a mismatch surfaced as IndexOutOfBoundsException - or, where a level happened to match, as a null chaining signature that only failed at signing time; the level is now checked after the reset that fills it in, since a null is legitimate on the way in. LMSPrivateKeyParameters.getInstance(byte[], byte[]) adopted the public key supplied beside the private one without comparing them, so a mismatched public key was simply reported by getPublicKey(); it now cross-checks the identifier, both parameter sets and, where the tree cache already holds it, the root, as the HSS entry point does. The decoders also now report a bad version or seed length as IOException rather than IllegalStateException, so a caller can catch one type for a malformed key, and the package-private LM-OTS public key decoder no longer declares throws Exception or dereferences an unrecognised typecode. The deprecated org.bouncycastle.pqc.crypto.lms copies carry the decoder corrections.\u003c/li\u003e\n\u003cli\u003eIn the LMS JCE layer, LMSKeyGenParameterSpec.fromNames knew all twenty LMS parameter-set names but only four of the sixteen LM-OTS ones, so none of the SP 800-208 n24 or SHAKE sets could be named; all sixteen are now present. KeyPairGenerator.initialize(int, SecureRandom) reports InvalidParameterException, which is what the JCA specifies and which extends the IllegalArgumentException it raised before, so existing catches still match. BCLMSPrivateKey.getIndex now takes the exhaustion check and the index read under the key's own monitor rather than as two separate calls, and two unused fields have gone from LMSSignatureSpi. Note that the LMS Signature claims its one-time key at the first update() rather than at sign(), so a Signature that is initialised and updated and then abandoned spends an index without producing a signature - the safe direction for a one-time scheme, and now documented on the SPI.\u003c/li\u003e\n\u003cli\u003eEvery other key pair generator that refuses a key size did the same thing the LMS one did above. KeyPairGenerator.initialize(int, SecureRandom) is documented to raise InvalidParameterException when the key size is not one the generator supports, and thirty of them raised a bare IllegalArgumentException instead, so a caller following the JCA and catching the documented type saw an exception escaping rather than a refusal. The ML-DSA, ML-KEM, SLH-DSA, Classic McEliece, FrodoKEM, NTRU and composite signature and KEM generators in the BC provider, and every generator in BCPQC, now raise InvalidParameterException - NewHope included, where the value is a key size it will not take rather than a mode of initialisation it does not offer. InvalidParameterException extends IllegalArgumentException, so callers written against the old behaviour go on catching it unchanged. The two RSA generators are corrected as well, and differently: theirs is a key size below a floor rather than a mode of initialisation they do not offer, and the refusal is raised by the lightweight RSAKeyGenerationParameters, which cannot name a java.security exception at all, so the RSA KeyPairGeneratorSpi now translates it - keeping the message verbatim and the original exception as the cause, through a new SecurityExceptions.invalidParameterException factory, since InvalidParameterException has no constructor that takes one. Of the 304 KeyPairGenerator services the two providers register, 299 now refuse a nonsense key size the way the JCA defines it and five accept it as a strength they can work with, with none left raising a bare IllegalArgumentException; that is asserted as a sweep over both providers rather than per algorithm, so a generator added later is covered without the test being touched. The jdk1.3 provider overlays of the four generators that have one carry the same change, and the jdk1.3 SecurityExceptions overlay gains the new factory along with the invalidAlgorithmParameterException one it had been missing.\u003c/li\u003e\n\u003cli\u003eKeyPairGenerator.initialize(AlgorithmParameterSpec, SecureRandom) had the same shape of problem as the int overload above, and only 44 of the 304 services the two providers register reported an unusable spec as the InvalidAlgorithmParameterException that method declares. The twenty-three PQC generators that resolve a parameter set by name - cmce, frodokem, mldsa, mlkem, slhdsa, aimer, bike, faest, falcon, haetae, hqc, mayo, mqom, ntru, ntruplus, both ntruprime variants, qruov, saber, sdith, smaugt, snova and sqisign, 230 services between them - case-folded the name they got back from the spec without checking it, so a spec with no getName() method, and a null spec, produced a NullPointerException from inside the fold; their own \u0026quot;is this name one I know\u0026quot; branch, which does report the declared exception, was unreachable. The two composite generators, whose parameter set is fixed by the algorithm name so that null is the only spec they accept, refused every other one with IllegalArgumentException. RSA answered correctly for a spec of the wrong type but not for one of the right type carrying values its lightweight parameters will not take - an even public exponent, or a key size below the floor - which is now translated the same way the int overload's is. All 304 services now report the declared exception, with the composites still taking the null spec that is right for them; note that InvalidAlgorithmParameterException is a checked exception and not an IllegalArgumentException, so a caller that was catching what these threw before has to catch the declared type instead.\u003c/li\u003e\n\u003cli\u003eAn HSS private key claimed the two records of its position under two different monitors. The top-level index and the bottom component key's one-time index q are independent records of the same position - the decoder requires them to agree, see the entry below - but generateLMSContext incremented the index under the HSS key's own monitor, released it, and only then claimed q under the component key's. A getEncoded() issued in between saw the index advanced and q not, and produced an encoding this implementation's own decoder rejects; and two threads meeting at a bottom-tree boundary could both pass the exhaustion test, take consecutive top-level indices and claim the same q, after which one of them was refused with \u0026quot;ots private key exhausted\u0026quot; by a key still reporting usages remaining, a top-level index had been spent with no signature made, and the two records stayed one apart for the rest of the key's life in that process - so it could no longer be encoded, cloned or sharded, and getIndex() and getUsagesRemaining() misreported by one. No one-time key was reused: the component key's claim is itself atomic, and the divergence runs index ahead of leaves, so the effect was on the key's usability rather than on the signatures it had made. Both records are now claimed under the one monitor, and the component key is claimed before the index is incremented so that an exhausted one leaves both untouched. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the same correction.\u003c/li\u003e\n\u003cli\u003eTimeStampToken parsed the attacker-controlled TSTInfo content of a time-stamp token (org.bouncycastle.tsp.TimeStampToken, reached from TimeStampResponse(byte[]) and (InputStream)) inside a try that caught only CMSException, so a well-formed RFC 3161 TimeStampResp whose embedded token carried a malformed TSTInfo - a SEQUENCE with fewer elements than the five mandatory fields, a non-SEQUENCE, truncated DER, or an unknown context tag - let an IllegalArgumentException or a NoSuchElementException escape the constructor's declared throws TSPException, IOException contract. A token signed by no signers or by more than one raised a bare IllegalArgumentException from the same constructor, before that try, for the same reason. Both are now reported as TSPException, matching the package-private TimeStampResponse(DLSequence) constructor and the existing getSignedAttributes guard in the same method; the signer-count refusal is a TSPValidationException, as the neighbouring check on the content type already was. Related, and the cause of the NoSuchElementException: asn1.tsp.TSTInfo read its five mandatory fields off the sequence with no bound on how many elements were actually there, so a short SEQUENCE left the enumeration to run out rather than being refused, and an oversize one was accepted with its extra elements absorbed into the optional slots. Decode now requires the five to ten elements RFC 3161 sec. 2.4.2 gives the type, which is what the sibling Accuracy and ArchiveTimeStamp decoders already did, so the failure is the IllegalArgumentException that getInstance is expected to raise (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2415\"\u003e#2415\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eNeither the HSS nor the XMSS^MT private key decoder checked its declared index against the traversal state stored beside it, although the two are independent records of the same position in the key and so can be compared. For HSS the records are the top-level index and the component keys' one-time indices q; for XMSS^MT they are the global index and the per-layer BDS states. A stored key whose index had been rolled back while its state stayed advanced - a partial write, a restore from backup, a buggy storage layer - was therefore accepted, and it then signed a second message under a one-time key the key had already used, producing a signature that verified, so nothing anywhere surfaced the reuse. RFC 8554 sec. 1 and RFC 8391 sec. 1.1 both require each one-time key to be used exactly once, and this is the failure those requirements exist to prevent; the single-tree XMSS decoder has tied its BDS state to its index since that state was first validated, and this brings the two multi-tree schemes into line. HSS decode now requires the declared index to equal the position the component q values imply - a level above the last contributes (q - 1) leaves of the levels beneath it, since its q has already advanced past the subtree it signed - and XMSS^MT decode now requires each present layer's BDS index to equal the leaf index that layer derives from the global index, allowing the one position where a layer has moved into a new subtree and its state legitimately still carries the previous subtree's final index. A layer with no state yet is unaffected, since those are built lazily at signing time. Related, and the same shape of omission: an XMSS or XMSS^MT private key encoding carries the tree root twice - the key's own root field and the root node of the BDS state stored beside it, which for XMSS^MT is the top layer's - and the two were never compared either. A corrupted root was accepted and then poisoned every signature the key made, because the root is hashed into the message digest: the signature did not verify and nothing indicated why. Decode now requires the two copies to agree. The BDS node values themselves are not checkable the way the LMS tree cache above is - a BDS authentication path, stack, retain or keep node does not have its children stored alongside it, so recomputing one means building a subtree, which is the work the state exists to avoid. Both checks are integer comparisons over the levels of the key, too small to measure against the surrounding decode, and both were verified not to reject any legitimate key by walking every index a key can reach: the full key space of the two-level HSS and the h=4/d=2, h=6/d=2, h=6/d=3, h=9/d=3 and h=8/d=4 XMSS^MT parameter sets, plus a three-level HSS key across a subtree boundary and an HSS shard. Since those node values cannot be recomputed, the encoded state now carries a checksum over itself instead, with the owning key's public seed hashed in front of it. Any corruption of the stored state is refused at decode rather than being loaded and then producing signatures that silently do not verify, and because the public seed is bound in, a state transplanted between two keys of the same parameter set is refused too, even though it is internally consistent and arrives with its own matching root. The public seed is bound rather than the secret seed or the PRF key deliberately: the state's own root and index are inside the encoding and so are already covered, hashing secret material would make the stored checksum a commitment to it for no gain in detection, and the PRF key does not influence the state at all. \u003cstrong\u003eThis is an error-detecting code and not integrity protection\u003c/strong\u003e - anyone able to rewrite the stored key recomputes it, so it establishes that the state is unchanged since it was written, never that it was correct when written, and the allocation bounds on the encoding remain the guard against a crafted one. It costs one SHA-256 over the state, measured at 5 to 8 microseconds each way for the h=10 and h=16 parameter sets, and 32 bytes of encoding. The state encoding was added earlier in this same cycle and has not been released, so the checksum is simply part of it rather than a new version: a state written by a 1.86 beta is rejected, which is recovered from by re-exporting the key. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the HSS check as well (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2414\"\u003e#2414\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe S/MIME example smoke test in the misc module (org.bouncycastle.mail.smime.examples.test.AllTests) drove SendSignedAndEncryptedMail against smtp.gmail.com, and that example finishes with Transport.send() under JavaMail's default settings, which have no connect timeout. Where outbound port 25 is refused the failure was swallowed and the test passed; where it is silently dropped, as on many home networks, the connect blocked and ./gradlew build hung in :misc:test indefinitely with \u0026quot;0 tests completed\u0026quot;. The test now delivers to an SMTP stub on a loopback port, with connect / read / write timeouts as a backstop, and asserts the message arrived (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2407\"\u003e#2407\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation took the traditional component public key bytes it feeds the KEM combiner from the recipient key's own encoding, while decapsulation recomputes the point from the private key and so always produced an uncompressed one. Section 4 of draft-ietf-lamps-pq-composite-kem requires an EC component to be carried as an uncompressed point, but a component key that encodes itself compressed - a BC EC key whose point format has been set through org.bouncycastle.jce.interfaces.ECPointEncoder, or a key from a provider that preserves a compressed encoding - was passed through as it came. Both sides then combined a different tradPK and derived different shared secrets, with no error reported on either: encapsulation and decapsulation both succeeded and the recipient simply could not decrypt. The EC component is now normalised to an uncompressed point wherever the engine serialises one, which covers the ephemeral key that forms the ciphertext as well. X25519 and X448 components have a single encoding and were unaffected, as were EC keys left in their default (uncompressed) format, whose shared secrets are unchanged. CompositePublicKey.getEncoded() took its component bytes the same way, so such a key also encoded to a composite key other implementations reject and whose bytes changed across an encode / decode / encode round trip - 1238 bytes rather than 1270 for MLKEM768-ECDH-P256, and for the composite ML-DSA keys sharing that method, 2006 rather than 2038 for MLDSA65-ECDSA-P256. It now normalises the component the same way. This is a write-side change only: a composite key carrying a compressed EC component is still decoded, since the component key factories accept either form, and continues to verify signatures as before - it simply re-encodes in the normalised form. The shared normalisation is org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil.getUncompressedSubjectPublicKeyBytes.\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation threw a NullPointerException, wrapped in an IllegalStateException out of KeyGenerator.generateKey(), when the SecureRandom it was given was null - which javax.crypto.KEM.newEncapsulator() documents as a request for the provider's default, and which KeyGenerator.init(spec, null) passes straight through. The three RSA-OAEP composites draw the traditional shared secret from that random directly, so they were the ones affected; the ECDH and X25519 / X448 composites escaped only because their component KeyPairGenerators default a random of their own. CompositeMLKEMEngine now defaults one through CryptoServicesRegistrar.getSecureRandom() on first use, as the composite KEM Cipher's wrap path already did, and as the KEM generators corrected earlier in this cycle now do. Related, the engine now also clears the ML-KEM component's shared secret alongside the traditional one on both the encapsulate and decapsulate paths - the copy handed back by getEncoded() was left in the heap - as section 3.5 of draft-ietf-lamps-pq-composite-kem requires.\u003c/li\u003e\n\u003cli\u003eCompositePublicKey.getAlgorithm() and CompositePrivateKey.getAlgorithm() returned null for all twelve Composite ML-KEM (draft-ietf-lamps-pq-composite-kem) parameter sets. Both classes resolved the name through the composite signature index only, which holds the composite ML-DSA OIDs, so a composite KEM key pair - generated, parsed from a certificate, or read from PKCS#8 - reported no algorithm at all, and the standard JCA idiom of reconstructing a key with KeyFactory.getInstance(key.getAlgorithm()) raised a NullPointerException. The lookup now falls back to the composite KEM index, so the name returned is the one the provider registers the algorithm under (e.g. MLKEM768-X25519-SHA3-256), matching the composite ML-DSA behaviour. The same single-index assumption made the CompositePublicKey(SubjectPublicKeyInfo) and CompositePrivateKey(PrivateKeyInfo) constructors reject a composite KEM key with \u0026quot;unable to create CompositePublicKey from SubjectPublicKeyInfo\u0026quot;; they now dispatch to the composite KEM key factory for those OIDs. Keys obtained through KeyFactory or through BouncyCastleProvider.getPublicKey / getPrivateKey were unaffected and are unchanged (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2404\"\u003e#2404\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe org.bouncycastle.jcajce.spec.KEMKDFSpec constructor stored a null otherInfo as given, so getOtherInfo() returned null, and three of the KDF branches KdfUtil.makeKeyBytes dispatches to - KMAC-128, KMAC-256 and SHAKE-256 - read the otherInfo length without a guard and threw NullPointerException out of the KEM operation, where the KDF2, KDF3 and HKDF branches tolerate a null through KDFParameters / HKDFParameters. The Builder of every spec in the package already mapped null to empty, so no provider path reached it, but the constructor is protected on a public class and KdfUtil is documented for callers building their own KEM integration; the deprecated KEMParameterSpec passes a null itself and escaped only because it also pins the KDF to null. The constructor now stores empty for a null, so getOtherInfo() never returns null, and a null and an explicitly empty otherInfo derive the same key.\u003c/li\u003e\n\u003cli\u003eQR-UOV signature verification accepted a signature encoding that was not canonical, so the encoding of a signature was not unique even after the trailing-byte fix of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e. Each F_q element of the signature is stored in ceil(log2 q) bits, one more bit pattern than the field has elements: q itself is representable and is arithmetically congruent to zero, so an element written as q verified exactly as the same element written as zero would, and the bits padding the last element out to the byte boundary were never read at all. Every zero element of a signature therefore carried a second encoding, and for the q = 7 parameter sets roughly one element in seven is zero - a single qruov_5_q7_L10 signature measured 256 spare bits, so on the order of 2^256 distinct byte strings verified for the one message and key. Verification now rejects any element outside [0, q) and any set padding bit; a signature produced by this or by the reference implementation is unaffected, as the KAT vectors of every parameter set confirm. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSNOVA signature verification ignored four bits inside the signature for any parameter set whose solution is an odd number of GF(16) nibbles - the SNOVA_24_5_5, SNOVA_25_8_3, SNOVA_29_6_5 and SNOVA_66_15_3 families, sixteen of the forty-four parameter sets. The last byte of the encoded solution carries a single nibble and the signer leaves the top four bits zero, but the decoder did not read them, so sixteen distinct byte strings verified for one signature. This is the same non-unique encoding github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e closed for bytes following the signature, applied inside it; the verifier now requires those bits to be zero. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSnovaPrivateKeyParameters did not validate the length of the private key encoding handed to it - the only one of the five schemes of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e that did not - and SnovaParameters.getPrivateKeyLength() reported the expanded (\u0026quot;ESK\u0026quot;) length even for a parameter set whose private key is the seed pair. A private key encoding reaches this constructor straight from a PKCS#8 blob, so a wrong length went undetected: a seed-form key with extra bytes appended was accepted and signed under a different derived key, and a short expanded-form key sized the signer's decode buffer negatively, throwing NegativeArraySizeException out of generateSignature() rather than being reported at construction. Related, the signing retry loop could not terminate: the vinegar values are derived from a single-byte counter, so only 256 distinct linear systems can be tried, and an expanded-form private key that is not a real central map is singular for all of them - generateSignature() then span forever rather than failing. The length is now checked at construction, getPrivateKeyLength() reports the length that parameter set's private key actually has, and the retry loop gives up after its 256 attempts as MAYO's does.\u003c/li\u003e\n\u003cli\u003eMayoSigner and MayoKeyPairGenerator did not clear several buffers holding secret key material that the MAYO reference implementation explicitly clears. Signing left the secret oil space O, the expanded L = (P1 + P1^t) * O + P2, and the M / VPV / Ox intermediates of the central map in place, having gone to the trouble of clearing eleven other buffers; key generation left the expanded seed, whose tail is the encoded oil space, and the P1 * O + P2 half of P; and the row-echelon step left the packed echelon form of the secret linear system and its pivot rows. Separately, if all 256 attempts at solving for the signature had given a rank-deficient system, signing emitted a signature built from the failed attempt's state instead of reporting the failure the reference returns, and AIMerSigner.generateSignature returned an empty array on failure, which a caller would hand on as though it were a signature. Both now throw.\u003c/li\u003e\n\u003cli\u003eFive PQC signature schemes - MAYO, SNOVA, QR-UOV, SQIsign and AIMer - returned the NIST crypto_sign \u0026quot;sm\u0026quot; signed-message envelope from generateSignature() rather than the signature. That envelope is an artefact of the reference KAT harness, which records the message alongside the signature so a vector file can be self-contained; it is not part of any of the five specifications, and no other BC signer emits it (Falcon's KAT test rebuilds the equivalent envelope in the test, which is where it belongs). Two consequences followed, both reaching the JCA Signature services of every parameter set of the five schemes in BouncyCastlePQCProvider. First, since the message was appended to the signature, verification had to skip whatever followed the signature proper, and it did so by checking only that the buffer was long enough - so any number of trailing bytes could be added to a valid signature, or the appended message replaced with unrelated data, and it still verified. A signature encoding was therefore not unique: anyone holding one valid signature could produce unlimited distinct byte strings that all verified for the same message and key, which breaks any use that treats the signature bytes as an identifier, deduplicates on them, or records them as evidence. Second, the envelope propagated into everything built on the operator layer: because ContentSigner hands the signature straight into the structure being signed, every X.509 certificate, CRL, CMS SignedData and TLS CertificateVerify BC produced with one of these algorithms carried a verbatim copy of the signed data inside its own signature field - a self-signed MAYO-1 certificate came to 3567 bytes where the same certificate is now 2020 - which no other implementation can parse as a signature, and which in a detached CMS signature meant the \u0026quot;detached\u0026quot; signature carried the content. generateSignature() now returns the bare signature, and verifySignature() requires exactly the parameter set's signature length, so appended or truncated data is rejected rather than ignored. \u003cstrong\u003eThis is a behavioural change for signatures produced by an earlier release\u003c/strong\u003e - MAYO and SNOVA from 1.84, QR-UOV, SQIsign and AIMer from 1.85 - which are no longer accepted in the envelope form they were emitted in; the signature bytes themselves are unchanged, so a stored value can be recovered by taking the leading signature-length bytes, or for AIMer, whose envelope was message || signature rather than signature || message, the trailing ones. The KAT tests now rebuild the envelope before comparing against the vector files, which continue to record it. Note that AIMer's verification had already been made length-exact during this cycle (see the entry below relating to github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2401\"\u003e#2401\u003c/a\u003e), so of the five only its envelope remained (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe MLS implementation did not bind an X.509 credential to the LeafNode's signature_key. LeafNode.verify() checked a leaf's signature against the signature_key declared in the leaf itself, while the X.509 credential's certificate chain was stored but never parsed or checked, so the certificate's public key was never required to match signature_key (RFC 9420 sec. 5.3). A leaf could therefore carry one party's certificate while being signed by an unrelated key and still be accepted under that party's identity through KeyPackage.verify() and the Group leaf-validation path. LeafNode.verify() now requires the end-entity certificate's subject public key, in the cipher suite's signature encoding, to equal signature_key for an X.509 credential, and rejects the leaf otherwise - including an empty chain or a certificate whose key type does not match the cipher suite; certificate-chain and identity validation to a trust anchor remain the application's responsibility per RFC 9420 sec. 5.3.1. A public org.bouncycastle.mls.codec.Certificate(byte[]) constructor and a Credential.getCertificates() accessor are added so callers can build and inspect X.509 credentials. Basic credentials are unaffected.\u003c/li\u003e\n\u003cli\u003eThe SecureRandom supplied to org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder.setSecureRandom() did not drive the content IV / nonce for any algorithm other than RC2. EnvelopedDataHelper.generateParameters passed the caller's SecureRandom to the AlgorithmParameterGenerator only in the RC2_CBC branch; every other content-encryption algorithm - AES-CBC, AES-GCM, AES-CCM, Camellia, ARIA, SEED and the rest - reached pGen.generateParameters() on an uninitialised generator, so the IV / nonce was drawn from a default SecureRandom and setSecureRandom() was silently ignored (the builder's javadoc states that random is used for IV/nonce generation). The generator is now initialised with the supplied random on the general path as well, so a caller who provides a specific randomness source - for a controlled or FIPS-approved DRBG, say - has it honoured for the content IV / nonce. The session-key generation path was unaffected and already used the supplied random. Because the content IV / nonce now comes from the supplied SecureRandom, the org.bouncycastle.crypto.util JournalingSecureRandom / JournaledAlgorithm reproducible-encryption support records it in the transcript: a resumed session reproduces the IV / nonce by regenerating it from the replayed randomness - build the resuming encryptor from the content-algorithm OID - rather than by reusing the AlgorithmIdentifier captured from the first encryption, which no longer keeps the transcript aligned.\u003c/li\u003e\n\u003cli\u003eThe NTRU LPRime, NTRU+ and SMAUG-T KEM generators threw a NullPointerException when constructed with a null SecureRandom, where every other KEM generator - including NTRU LPRime's own SNTRU Prime counterpart in the same package - defaults one through CryptoServicesRegistrar.getSecureRandom(). This is reachable from the lightweight API directly, and from javax.crypto.KEM, whose newEncapsulator() documents a null random as a request for the provider's default.\u003c/li\u003e\n\u003cli\u003eFrodoKEMEngine kept a single SHAKE instance in a field, so an engine reached concurrently produced wrong results. It is reached that way through org.bouncycastle.crypto.kems.FrodoKEMExtractor, which holds one engine for its lifetime: two threads extracting through one extractor interleaved the digest's absorb and squeeze phases, yielding shared secrets that silently did not match the sender's, or an IllegalStateException of \u0026quot;attempt to absorb while squeezing\u0026quot; from inside extractSecret. The digest is now built per call, as CMCEEngine's already was, which makes an extractor safe to share. Encapsulation was unaffected, since FrodoKEMGenerator builds an engine per call. Results for any single-threaded use are unchanged - the reference KAT vectors are byte-identical.\u003c/li\u003e\n\u003cli\u003eThe BCJSSE provider carried the TLS 1.2 coupling between the supported_groups extension and ECDSA over into TLS 1.3: an ECDSA signature scheme was treated as usable - offered in the signature_algorithms and signature_algorithms_cert extensions, and eligible when selecting the local credentials - only while the corresponding curve was among the named groups enabled for key exchange, both per context (a group unavailable for key agreement disabled the scheme outright) and per connection (the curve had to be in the supported_groups list about to be sent). RFC 8446 sec. 4.2.7 scopes supported_groups to key exchange only, with signature algorithms negotiated independently (sec. 4.2.3), so this incorrect restriction in TLS 1.3 has been removed. Ed25519, Ed448 and the RSA schemes were unaffected (as well as typical deployments using a default configuration for named groups).\u003c/li\u003e\n\u003cli\u003eThe bcmail module descriptor did not declare its javax.mail/javax.activation dependences, so a modular (module-path) consumer of the jar hit IllegalAccessError/module-resolution failures when the S/MIME classes touched the mail API. The descriptor now requires them optionally (requires static) under all four module names those libraries are known by - the automatic names mail and activation carried by the javax.mail:mail / javax.activation:activation artifacts, and the explicit names java.mail and java.activation carried by the newer com.sun.mail / com.sun.activation ones - a hard requires on any one name would break users of the others (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2389\"\u003e#2389\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFour type-coercion helpers in the OER / IEEE 1609.2 (ITS) decoder tested the wrong type in the identity fast path that lets a getInstance() factory return an argument that is already of the target type. org.bouncycastle.oer.its.ieee1609dot2.basetypes.UINT32.getInstance and org.bouncycastle.oer.its.etsi102941.basetypes.Version.getInstance guarded on UINT8 - a sibling of UINT32 under UintBase, and unrelated to Version - so passing a UINT8 threw ClassCastException, while passing an actual UINT32 or Version missed the fast path and fell through to ASN1Integer.getInstance, which rejects them: neither factory accepted its own type. org.bouncycastle.oer.its.etsi103097.EtsiTs103097DataEncryptedUnicast.getInstance guarded on its sibling EtsiTs103097DataEncrypted and then cast to the unicast type, so an EtsiTs103097DataEncrypted threw ClassCastException. org.bouncycastle.oer.OEROptional.getObject(Class) called value.getClass().isInstance(type) with the arguments transposed, which is always false because the argument is a java.lang.Class, so the cast path was dead and every optional field was resolved reflectively, failing with IllegalStateException for a target type with no static getInstance. Each guard now names the type it returns, matching the sibling UINT8 / UINT16 / UINT64 and EtsiTs103097DataEncrypted factories (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2373\"\u003e#2373\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eDefaultAlgorithmNameFinder and DefaultSignatureNameFinder had no entries at all for the ShangMi algorithms, so an SM2 signature AlgorithmIdentifier that DefaultSignatureAlgorithmIdentifierFinder itself produces came back named only by its OID string - getAlgorithmName(GMObjectIdentifiers.sm2sign_with_sm3) returned \u0026quot;1.2.156.10197.1.501\u0026quot; and hasAlgorithmName returned false. Both finders now name sm2sign_with_sm3 as SM3WITHSM2 and sm2sign_with_sha256 as SHA256WITHSM2, and DefaultAlgorithmNameFinder additionally names the sm3 digest. All three resolve through the BC provider, as Signature and MessageDigest respectively. The remaining GM arc - the SM4 cipher modes, the sm2encrypt variants, and the SM1 / SM6 / SSF33 ciphers BC does not implement - is still unnamed (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2377\"\u003e#2377\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe RFC 4998 evidence-record classes compared the digest AlgorithmIdentifier named by a time-stamp authority with the one their own DigestCalculator uses, and did so with AlgorithmIdentifier.equals(), which compares the encodings. A TSA that names SHA-256 with an explicit NULL parameters field - DigiCert among them - therefore failed against BC's own calculator, which names it with the parameters absent, and ERSArchiveTimeStampGenerator.generateArchiveTimeStamp rejected the response with \u0026quot;time stamp imprint for wrong algorithm\u0026quot;. Both spellings name the same digest and RFC 5754 sec. 2 requires a receiver to accept either, while requiring that identifiers be generated with the parameters absent, which BC already does. The three affected comparisons - the two in ERSArchiveTimeStampGenerator and the digest check in ERSEvidenceRecord.renew - now use the new AlgorithmIdentifier.areEquivalent, which matches on the algorithm and treats an absent parameters field and NULL as the same, and the consistency check across an evidence record's archive time stamp chain uses it too. An identifier carrying an actual parameter structure is never equivalent to one carrying none (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2379\"\u003e#2379\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eEDIPartyName.toASN1Primitive emitted the nameAssigner and partyName DirectoryStrings without their context tags, so an EDIPartyName built through its public constructor could not be parsed back by EDIPartyName.getInstance, which correctly requires them. RFC 5280 sec. 4.2.1.6 tags both members [0] and [1], and those tags are explicit despite the module's IMPLICIT TAGS because DirectoryString is a CHOICE, which X.680 does not allow to be tagged implicitly - the decoder already had this right. The encoder now matches it. Note the type was added during the 1.85 cycle and GeneralName validates its ediPartyName alternative through it, so a GeneralName carrying an untagged ediPartyName - including one BC itself produced - is rejected where 1.84 passed it through unexamined; the untagged form is not read leniently (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2380\"\u003e#2380\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eRSASSA-PSS could not be used with a RIPEMD digest through the JCA API. Nothing registered the RIPEMD PSS signatures, so Signature.getInstance(\u0026quot;RIPEMD160WITHRSAANDMGF1\u0026quot;) raised NoSuchAlgorithmException, and the generic RSASSA-PSS route with an explicit PSSParameterSpec failed too: org.bouncycastle.jcajce.provider.util.DigestFactory.getDigest returned null for a RIPEMD name, and isSameDigest - an allow-list of the SHA families and MD5 - reported two identical RIPEMD names as different digests, so the spec was rejected with \u0026quot;digest algorithm for MGF should be the same as for PSS parameters\u0026quot;. isSameDigest now answers true for equal names whatever the digest, which also covers Whirlpool, SM3, GOST3411 and anything else outside that allow-list; DigestFactory recognises RIPEMD128, RIPEMD160 and RIPEMD256 by name and OID; the three PSS signatures are registered with MGF1 over the same digest and a salt of the digest length; and DefaultSignatureAlgorithmIdentifierFinder gains the matching RIPEMD*WITHRSAANDMGF1 entries with their RSASSA-PSS-params, so the operator/JcaContentSignerBuilder path works as well. Note BC continues to require the PSS hash and the MGF1 hash to be the same, which RFC 8017 does not itself demand (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2381\"\u003e#2381\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe opt-in key-size validation on CMS key-transport recipients (org.bouncycastle.cms.jcajce.JceKeyTransRecipient.setKeySizeValidation(true)) never ran for a message using RFC 9709 CEK derivation (id-alg-cek-hkdf-sha256): the branch that should have selected the actual content-encryption algorithm carried in the KDF AlgorithmIdentifier's parameters compared the encrypted-key byte array against the id-alg-cek-hkdf-sha256 object identifier - a comparison that is always false - so the check fell through to a key-size lookup on the outer KDF OID, which has no registered key size, and silently checked nothing. A key-transport EnvelopedData/AuthEnvelopedData whose transported (and HKDF-derived) content-encryption key did not match the key size of the advertised content-encryption algorithm was therefore accepted even with validation enabled. The recipient now dispatches on the content-encryption AlgorithmIdentifier's algorithm OID, so key-size validation of RFC 9709 messages checks the recovered key against the inner content-encryption algorithm. Messages with a matching key size, non-HKDF messages, and recipients that do not enable validation are unaffected.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003eSee full diff in \u003ca href=\"https://github.com/bcgit/bc-java/commits\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark` from 0.29.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/blockquote\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/blockquote\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/42b4fb7adfe288ef13e9e27ab20aff7e91b0ab9d\"\u003e\u003ccode\u003e42b4fb7\u003c/code\u003e\u003c/a\u003e Prepare CHANGELOG for version 0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/b76e09d7a8362abb5f04e1d6b91dbd6da279a6fc\"\u003e\u003ccode\u003eb76e09d\u003c/code\u003e\u003c/a\u003e Limit how deep inline nodes may nest by default (100)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/49f65cb5cbec93cff713179990307145198e7061\"\u003e\u003ccode\u003e49f65cb\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing deeply nested emphasis\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/610f84b83e68c381e8f784ae4d044c80e1948b67\"\u003e\u003ccode\u003e610f84b\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological autolink email addresses\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/9f1d73897a56cbd74c39347af351a473e70297e1\"\u003e\u003ccode\u003e9f1d738\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological HTML block attributes\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/e13297e849995fdd582a85841067bff1d9c35ee5\"\u003e\u003ccode\u003ee13297e\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing pathological backticks\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/89d1bd3fa1524e8217ed61db5e8116c82434470f\"\u003e\u003ccode\u003e89d1bd3\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing with lots of \u003ccode\u003e\u0026lt;\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/commonmark/commonmark-java/compare/commonmark-parent-0.29.0...commonmark-parent-0.30.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark-ext-autolink` from 0.29.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark-ext-autolink's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003cc...\n\n_Description has been truncated_","html_url":"https://github.com/Ben-Jianming/openclaw-pqc/pull/38","url":"https://dependabot.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ben-Jianming%2Fopenclaw-pqc/issues/38","packages_url":"https://dependabot.ecosyste.ms/api/v1/issues/38/packages"},{"uuid":"5404069327","node_id":"PR_kwDOTDTeds8AAAABC44JkA","number":31,"state":"closed","title":"build(deps): bump the android-deps group across 1 directory with 17 updates","user":"dependabot[bot]","labels":["dependencies","java"],"assignees":[],"locked":false,"comments_count":3,"pull_request":true,"closed_at":"2026-09-11T19:46:19.000Z","author_association":null,"state_reason":null,"created_at":"2026-09-09T19:52:52.000Z","updated_at":"2026-09-11T19:46:19.000Z","time_to_close":172407,"merged_at":null,"merged_by":null,"closed_by":null,"dependency_metadata":{"prefix":"build(deps): bump","group_name":"android-deps","update_count":17,"packages":[{"name":"gradle-wrapper","old_version":"9.5.1","new_version":"9.7.1","repository_url":"https://github.com/gradle/gradle"},{"name":"androidx.core:core-ktx","old_version":"1.18.0","new_version":"1.19.0"},{"name":"org.bouncycastle:bcprov-jdk18on","old_version":"1.84","new_version":"1.85.2","repository_url":"https://github.com/bcgit/bc-java"},{"name":"org.commonmark:commonmark","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-autolink","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-strikethrough","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-tables","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-task-list-items","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.junit.vintage:junit-vintage-engine","old_version":"6.1.0","new_version":"6.1.3","repository_url":"https://github.com/junit-team/junit-framework"},{"name":"io.kotest:kotest-assertions-core-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"io.kotest:kotest-runner-junit5-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"com.squareup.okhttp3:mockwebserver","old_version":"5.3.2","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.squareup.okhttp3:okhttp","old_version":"5.3.2","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.android.application","old_version":"9.2.1","new_version":"9.4.0"},{"name":"com.android.test","old_version":"9.2.1","new_version":"9.4.0"},{"name":"org.jetbrains.kotlin.plugin.compose","old_version":"2.4.0","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"},{"name":"org.jetbrains.kotlin.plugin.serialization","old_version":"2.4.0","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"}],"path":null,"ecosystem":"maven"},"body":"Bumps the android-deps group with 17 updates in the /apps/android directory:\n\n| Package | From | To |\n| --- | --- | --- |\n| [gradle-wrapper](https://github.com/gradle/gradle) | `9.5.1` | `9.7.1` |\n| androidx.core:core-ktx | `1.18.0` | `1.19.0` |\n| [org.bouncycastle:bcprov-jdk18on](https://github.com/bcgit/bc-java) | `1.84` | `1.85.2` |\n| [org.commonmark:commonmark](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-autolink](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-strikethrough](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-tables](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-task-list-items](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.junit.vintage:junit-vintage-engine](https://github.com/junit-team/junit-framework) | `6.1.0` | `6.1.3` |\n| [io.kotest:kotest-assertions-core-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [io.kotest:kotest-runner-junit5-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [com.squareup.okhttp3:mockwebserver](https://github.com/lysine-dev/okhttp) | `5.3.2` | `5.5.0` |\n| [com.squareup.okhttp3:okhttp](https://github.com/lysine-dev/okhttp) | `5.3.2` | `5.5.0` |\n| com.android.application | `9.2.1` | `9.4.0` |\n| com.android.test | `9.2.1` | `9.4.0` |\n| [org.jetbrains.kotlin.plugin.compose](https://github.com/JetBrains/kotlin) | `2.4.0` | `2.4.20` |\n| [org.jetbrains.kotlin.plugin.serialization](https://github.com/JetBrains/kotlin) | `2.4.0` | `2.4.20` |\n\n\nUpdates `gradle-wrapper` from 9.5.1 to 9.7.1\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/gradle/gradle/releases\"\u003egradle-wrapper's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e9.7.1\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.1.\u003c/p\u003e\n\u003cp\u003eThis is a patch release for 9.7.0. We recommend using 9.7.1 instead of 9.7.0.\u003c/p\u003e\n\u003cp\u003eHere are the highlights of 9.7.0 release:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIsolated Projects graduates to incubating\u003c/li\u003e\n\u003cli\u003eBroader Configuration Cache compatibility\u003c/li\u003e\n\u003cli\u003eResilient Sync helps you fix broken builds\u003c/li\u003e\n\u003cli\u003eMore source locations in problem reports\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003ca href=\"https://docs.gradle.org/9.7.1/release-notes.html\"\u003eRead the Release Notes\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eWe would like to thank the following community members for their contributions to this release of Gradle:\n\u003ca href=\"https://github.com/aSemy\"\u003eAdam\u003c/a\u003e,\n\u003ca href=\"https://github.com/Gautam-aman\"\u003eAman Gautam\u003c/a\u003e,\n\u003ca href=\"https://github.com/YukiCodepth\"\u003eAman Kumar\u003c/a\u003e,\n\u003ca href=\"https://github.com/adubrouski\"\u003eAnton Dubrouski\u003c/a\u003e,\n\u003ca href=\"https://github.com/liutikas\"\u003eAurimas\u003c/a\u003e,\n\u003ca href=\"https://github.com/gbhavya07\"\u003egbhavya07\u003c/a\u003e,\n\u003ca href=\"https://github.com/joshfriend\"\u003eJosh Friend\u003c/a\u003e,\n\u003ca href=\"https://github.com/nicklauslittle-gov\"\u003enicklauslittle-gov\u003c/a\u003e,\n\u003ca href=\"https://github.com/psoni674\"\u003ePragati\u003c/a\u003e,\n\u003ca href=\"https://github.com/Project516\"\u003eproject516\u003c/a\u003e,\n\u003ca href=\"https://github.com/Uomocapra\"\u003eQin Mi\u003c/a\u003e,\n\u003ca href=\"https://github.com/rkdfx\"\u003eRavi\u003c/a\u003e,\n\u003ca href=\"https://github.com/sk-reddy17\"\u003esk-reddy17\u003c/a\u003e,\n\u003ca href=\"https://github.com/Suvrat1629\"\u003eSuvrat Acharya\u003c/a\u003e,\n\u003ca href=\"https://github.com/ShreckYe\"\u003eYongshun Ye\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eUpgrade instructions\u003c/h2\u003e\n\u003cp\u003eSwitch your build to use Gradle 9.7.1 by updating your wrapper:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e./gradlew :wrapper --gradle-version=9.7.1 \u0026amp;\u0026amp; ./gradlew :wrapper\r\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eSee the Gradle \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/upgrading_version_9.html\"\u003e9.x upgrade guide\u003c/a\u003e to learn about deprecations, breaking changes and other considerations when upgrading.\u003c/p\u003e\n\u003cp\u003eFor Java, Groovy, Kotlin and Android compatibility, see the \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/compatibility.html\"\u003efull compatibility notes\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eReporting problems\u003c/h2\u003e\n\u003cp\u003eIf you find a problem with this release, please file a bug on \u003ca href=\"https://github.com/gradle/gradle/issues\"\u003eGitHub Issues\u003c/a\u003e adhering to our issue guidelines.\nIf you're not sure you're encountering a bug, please use the \u003ca href=\"https://discuss.gradle.org/c/help-discuss\"\u003eforum\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eWe hope you will build happiness with Gradle, and we look forward to your feedback via \u003ca href=\"https://twitter.com/gradle\"\u003eTwitter\u003c/a\u003e or on \u003ca href=\"https://github.com/gradle\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003e9.7.0\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.0.\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/92f0512e7f06d84621afba191f75e265363890cf\"\u003e\u003ccode\u003e92f0512\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38892\"\u003e#38892\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/820ee75a99a179bbffa41bcedc6477b685fabb9f\"\u003e\u003ccode\u003e820ee75\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/82c23f9bd2a89b4cc644e1f90a28a8668feb3dee\"\u003e\u003ccode\u003e82c23f9\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering problem in KTS (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38878\"\u003e#38878\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/ef11a7268fe8cc8d6ab849ec911aa11220180553\"\u003e\u003ccode\u003eef11a72\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering issue\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/bb0d8a974a71b1003efea41e4046e98855cd5ff8\"\u003e\u003ccode\u003ebb0d8a9\u003c/code\u003e\u003c/a\u003e Make relevant tests polyglot (run for multiple DSLs)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/336e129d7f95c03486acafc97abf59734acfed48\"\u003e\u003ccode\u003e336e129\u003c/code\u003e\u003c/a\u003e Update signing configuration (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38874\"\u003e#38874\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/4bdf0da2dad9884d089a6062a45ea7183e7d735d\"\u003e\u003ccode\u003e4bdf0da\u003c/code\u003e\u003c/a\u003e Update signing configuration\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/cd9b92c1b82856248cf1dc58b50378238bec7b52\"\u003e\u003ccode\u003ecd9b92c\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38839\"\u003e#38839\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/5f4e381964897ad8d6b99e5a7c77f26dba3259fb\"\u003e\u003ccode\u003e5f4e381\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/1e08ab551367aeb5fb48b26e72807e1d2b27c939\"\u003e\u003ccode\u003e1e08ab5\u003c/code\u003e\u003c/a\u003e Keep type-use annotations in extracted ABI classes (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38810\"\u003e#38810\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/gradle/gradle/compare/v9.5.1...v9.7.1\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `androidx.core:core-ktx` from 1.18.0 to 1.19.0\n\nUpdates `org.bouncycastle:bcprov-jdk18on` from 1.84 to 1.85.2\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.md\"\u003eorg.bouncycastle:bcprov-jdk18on's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch1\u003eBouncy Castle Crypto Package - Release Notes\u003c/h1\u003e\n\u003ch2\u003e1.0 Introduction\u003c/h2\u003e\n\u003cp\u003eThe Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. The package is organised so that it contains a light-weight API suitable for use in any environment (including the J2ME) with the additional infrastructure to conform the algorithms to the JCE framework.\u003c/p\u003e\n\u003ch2\u003e2.0 Release History\u003c/h2\u003e\n\u003cp\u003e\u003c!-- raw HTML omitted --\u003e\u003c!-- raw HTML omitted --\u003e\u003c/p\u003e\n\u003ch3\u003e2.1.1 Version\u003c/h3\u003e\n\u003cp\u003eRelease: 1.86\u003cbr /\u003e\nDate: 2026, TBD\u003c/p\u003e\n\u003ch3\u003e2.1.2 Defects Fixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) let a subkey inherit the primary key's Key Flags when its own Subkey Binding signature carried no Key Flags subpacket, which made the two capability decisions taken for one subkey disagree. OpenPGPCertificate.OpenPGPComponentKey.isSigningKey() reads the effective flags, which fell back to the primary key's direct-key or primary user ID self-signature, so a subkey bound with no flags of its own counted as signing-capable; verifyEmbeddedPrimaryKeyBinding reads the binding signature's own flags, found no signing capability there, and so skipped the embedded Primary Key Binding (cross-certification) signature that RFC 9580 sec. 5.2.1.8 and sec. 10.1.3 require of a subkey that can issue signatures. A data signature made by such a subkey was therefore attributed to the certificate and reported valid by OpenPGPSignature.OpenPGPDocumentSignature.isValid() with the cross-certification requirement never applied, where GnuPG refuses the same certificate and message as not cross-certified. An attacker holding a third party's public signing subkey - which is public material - could bind it to their own primary key with a Subkey Binding signature they are able to make, carrying no Key Flags and no embedded Primary Key Binding signature, which they cannot make without the subkey's private key, and have that party's genuine signatures verify as valid under the attacker's own identity: misattribution of a real signature rather than a forgery of a new one, since the signature still has to be one the subkey actually made. Key Flags are a statement about the key the carrying signature refers to (RFC 9580 sec. 5.2.3.29), so a subkey no longer inherits them from the certificate-wide signatures of the primary key: a Subkey Binding signature that omits the subpacket now leaves the subkey with no capabilities rather than the primary's, which makes the flags the cross-certification check consults the same flags every other decision consults. Preferences and the other subpackets a direct-key signature carries are inherited as before, and the primary key itself - whose flags legitimately come from its direct-key or user ID self-signature - is unaffected. The low-level PGPSignature / PGPPublicKeyRing API performs no binding checks by design and is unchanged.\u003c/li\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) used a version 6 key that carried no valid Direct Key signature, falling back to the primary user ID binding as it correctly does for a version 4 key. RFC 9580 sec. 5.2.3.10 requires the opposite: \u0026quot;An implementation MUST ensure that a valid Direct Key signature is present before using a version 6 key. This prevents certain attacks where an adversary strips a self-signature specifying a Key Expiration Time or certain preferences.\u0026quot; The certificate grammar says the same structurally, the Direct Key signature being mandatory in the version 6 structure of sec. 10.1.1 and optional in the version 4 one of sec. 10.1.3. Because a version 6 certificate carries its key expiration, features and algorithm preferences on the Direct Key signature - the convention the RFC recommends and the one OpenPGPKeyGenerator follows, its user ID certification carrying no expiration at all - removing that single signature packet from a published certificate silently dropped the expiration along with the preferences and features: OpenPGPCertificate.getSignatureChainFor fell back to the user ID binding, the primary key was still reported bound, and getEncryptionKeys() and getSigningKeys() went on returning the subkeys of a key whose owner had set it to expire. The primary key fingerprint is unchanged by the removal, so a relying party pinning the key by fingerprint still treats it as the same key, and no private key or hash collision is involved; the natural moment for the strip is the key refresh that RFC 9580 names as the reason to refetch a key at all - to learn about changes in expiration, features, preferences and revocation - which is exactly the update it defeats. This is a downgrade rather than a forgery, nothing being attributed to a key that did not authorise it, and the concerning direction is encryption, to a key meant to have been retired. OpenPGPCertificate.isBoundBy now requires a valid Direct Key self-signature on a version 6 primary key before any component of the certificate - the primary key, its subkeys or its identities - is treated as bound, so a version 6 certificate stripped of it offers no keys at all rather than an unexpiring set. Version 4 certificates are unaffected: there the key expiration legitimately lives on the user ID self-signature and the fallback is correct, so it stays. The revocation-only version 6 certificate of sec. 10.1.2, which legitimately carries no Direct Key signature, is unaffected as well - its key was already refused as revoked, and reading the revocation does not go through the binding check.\u003c/li\u003e\n\u003cli\u003eThe lightweight LMSSigner and HSSSigner refused a key wrapped in ParametersWithRandom, which is how BcContentSignerBuilder passes a key whenever setSecureRandom() has been called - so BcHssLmsContentSignerBuilder built a working signer until a random was set and then failed with \u0026quot;Incorrect Key Parameters\u0026quot;, and the two signers themselves raised ClassCastException on the same input. All three now unwrap it, as the promoted ML-DSA and SLH-DSA signers already did. The random is accepted and not used: LMS derives its message randomiser C from the key's seed and the one-time index, so it is deterministic and cannot repeat while q does not. Note SP 800-208 sec. 6.1 asks for C to come from an approved random bit generator, which this implementation does not do; that is unchanged here, and a supplied random is now ignored rather than refused.\u003c/li\u003e\n\u003cli\u003eLMS signature verification did not apply two of the checks RFC 8554 sec. 5.4.2 requires before a signature is processed. Step 2g refuses a signature whose LMS typecode is not the one from the public key, and without it the path computation took its height and tree digest from the parameter set the signature named rather than the key's, so a signature claiming a height-25 parameter set drove a 25-level computation against a height-5 key. Step 2i refuses a leaf number q outside the tree, and without it an out-of-range q flowed into the node arithmetic and was left for the candidate-root comparison to catch. Neither was a forgery - the domain separation between D_LEAF and D_INTR and the final comparison saw to that - but both are attacker-chosen work the specification says to refuse up front. Both are now checked, and a signature failing either is still reported as not verifying rather than thrown out of Signature.verify(). The catch around the signature decode in LMSSigner and HSSSigner has also been narrowed to the decode itself, as the corresponding SPI was corrected to do for github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2408\"\u003e#2408\u003c/a\u003e: past the parse the engine reports an inconsistent signature by returning false rather than by throwing, so the wider catch caught nothing while standing ready to turn a future internal error into a quiet false.\u003c/li\u003e\n\u003cli\u003eThe LMS and HSS key parameter classes now apply at construction the checks their decoders apply, so a key built directly cannot be one the decoder would refuse. LMSPrivateKeyParameters accepted an identifier of any length although the decoder reads exactly 16 bytes - such a key encoded but could not be read back - and left q, maxQ and the seed length unchecked; the seed is now required to be at least m bytes at decode as well, where a one-byte seed had been decoding silently and then deriving every one-time key from it. HSSPrivateKeyParameters checked neither its level count nor that it had been given a component key per level and a chaining signature per level below the root, and then indexed both lists, so a mismatch surfaced as IndexOutOfBoundsException - or, where a level happened to match, as a null chaining signature that only failed at signing time; the level is now checked after the reset that fills it in, since a null is legitimate on the way in. LMSPrivateKeyParameters.getInstance(byte[], byte[]) adopted the public key supplied beside the private one without comparing them, so a mismatched public key was simply reported by getPublicKey(); it now cross-checks the identifier, both parameter sets and, where the tree cache already holds it, the root, as the HSS entry point does. The decoders also now report a bad version or seed length as IOException rather than IllegalStateException, so a caller can catch one type for a malformed key, and the package-private LM-OTS public key decoder no longer declares throws Exception or dereferences an unrecognised typecode. The deprecated org.bouncycastle.pqc.crypto.lms copies carry the decoder corrections.\u003c/li\u003e\n\u003cli\u003eIn the LMS JCE layer, LMSKeyGenParameterSpec.fromNames knew all twenty LMS parameter-set names but only four of the sixteen LM-OTS ones, so none of the SP 800-208 n24 or SHAKE sets could be named; all sixteen are now present. KeyPairGenerator.initialize(int, SecureRandom) reports InvalidParameterException, which is what the JCA specifies and which extends the IllegalArgumentException it raised before, so existing catches still match. BCLMSPrivateKey.getIndex now takes the exhaustion check and the index read under the key's own monitor rather than as two separate calls, and two unused fields have gone from LMSSignatureSpi. Note that the LMS Signature claims its one-time key at the first update() rather than at sign(), so a Signature that is initialised and updated and then abandoned spends an index without producing a signature - the safe direction for a one-time scheme, and now documented on the SPI.\u003c/li\u003e\n\u003cli\u003eEvery other key pair generator that refuses a key size did the same thing the LMS one did above. KeyPairGenerator.initialize(int, SecureRandom) is documented to raise InvalidParameterException when the key size is not one the generator supports, and thirty of them raised a bare IllegalArgumentException instead, so a caller following the JCA and catching the documented type saw an exception escaping rather than a refusal. The ML-DSA, ML-KEM, SLH-DSA, Classic McEliece, FrodoKEM, NTRU and composite signature and KEM generators in the BC provider, and every generator in BCPQC, now raise InvalidParameterException - NewHope included, where the value is a key size it will not take rather than a mode of initialisation it does not offer. InvalidParameterException extends IllegalArgumentException, so callers written against the old behaviour go on catching it unchanged. The two RSA generators are corrected as well, and differently: theirs is a key size below a floor rather than a mode of initialisation they do not offer, and the refusal is raised by the lightweight RSAKeyGenerationParameters, which cannot name a java.security exception at all, so the RSA KeyPairGeneratorSpi now translates it - keeping the message verbatim and the original exception as the cause, through a new SecurityExceptions.invalidParameterException factory, since InvalidParameterException has no constructor that takes one. Of the 304 KeyPairGenerator services the two providers register, 299 now refuse a nonsense key size the way the JCA defines it and five accept it as a strength they can work with, with none left raising a bare IllegalArgumentException; that is asserted as a sweep over both providers rather than per algorithm, so a generator added later is covered without the test being touched. The jdk1.3 provider overlays of the four generators that have one carry the same change, and the jdk1.3 SecurityExceptions overlay gains the new factory along with the invalidAlgorithmParameterException one it had been missing.\u003c/li\u003e\n\u003cli\u003eKeyPairGenerator.initialize(AlgorithmParameterSpec, SecureRandom) had the same shape of problem as the int overload above, and only 44 of the 304 services the two providers register reported an unusable spec as the InvalidAlgorithmParameterException that method declares. The twenty-three PQC generators that resolve a parameter set by name - cmce, frodokem, mldsa, mlkem, slhdsa, aimer, bike, faest, falcon, haetae, hqc, mayo, mqom, ntru, ntruplus, both ntruprime variants, qruov, saber, sdith, smaugt, snova and sqisign, 230 services between them - case-folded the name they got back from the spec without checking it, so a spec with no getName() method, and a null spec, produced a NullPointerException from inside the fold; their own \u0026quot;is this name one I know\u0026quot; branch, which does report the declared exception, was unreachable. The two composite generators, whose parameter set is fixed by the algorithm name so that null is the only spec they accept, refused every other one with IllegalArgumentException. RSA answered correctly for a spec of the wrong type but not for one of the right type carrying values its lightweight parameters will not take - an even public exponent, or a key size below the floor - which is now translated the same way the int overload's is. All 304 services now report the declared exception, with the composites still taking the null spec that is right for them; note that InvalidAlgorithmParameterException is a checked exception and not an IllegalArgumentException, so a caller that was catching what these threw before has to catch the declared type instead.\u003c/li\u003e\n\u003cli\u003eAn HSS private key claimed the two records of its position under two different monitors. The top-level index and the bottom component key's one-time index q are independent records of the same position - the decoder requires them to agree, see the entry below - but generateLMSContext incremented the index under the HSS key's own monitor, released it, and only then claimed q under the component key's. A getEncoded() issued in between saw the index advanced and q not, and produced an encoding this implementation's own decoder rejects; and two threads meeting at a bottom-tree boundary could both pass the exhaustion test, take consecutive top-level indices and claim the same q, after which one of them was refused with \u0026quot;ots private key exhausted\u0026quot; by a key still reporting usages remaining, a top-level index had been spent with no signature made, and the two records stayed one apart for the rest of the key's life in that process - so it could no longer be encoded, cloned or sharded, and getIndex() and getUsagesRemaining() misreported by one. No one-time key was reused: the component key's claim is itself atomic, and the divergence runs index ahead of leaves, so the effect was on the key's usability rather than on the signatures it had made. Both records are now claimed under the one monitor, and the component key is claimed before the index is incremented so that an exhausted one leaves both untouched. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the same correction.\u003c/li\u003e\n\u003cli\u003eTimeStampToken parsed the attacker-controlled TSTInfo content of a time-stamp token (org.bouncycastle.tsp.TimeStampToken, reached from TimeStampResponse(byte[]) and (InputStream)) inside a try that caught only CMSException, so a well-formed RFC 3161 TimeStampResp whose embedded token carried a malformed TSTInfo - a SEQUENCE with fewer elements than the five mandatory fields, a non-SEQUENCE, truncated DER, or an unknown context tag - let an IllegalArgumentException or a NoSuchElementException escape the constructor's declared throws TSPException, IOException contract. A token signed by no signers or by more than one raised a bare IllegalArgumentException from the same constructor, before that try, for the same reason. Both are now reported as TSPException, matching the package-private TimeStampResponse(DLSequence) constructor and the existing getSignedAttributes guard in the same method; the signer-count refusal is a TSPValidationException, as the neighbouring check on the content type already was. Related, and the cause of the NoSuchElementException: asn1.tsp.TSTInfo read its five mandatory fields off the sequence with no bound on how many elements were actually there, so a short SEQUENCE left the enumeration to run out rather than being refused, and an oversize one was accepted with its extra elements absorbed into the optional slots. Decode now requires the five to ten elements RFC 3161 sec. 2.4.2 gives the type, which is what the sibling Accuracy and ArchiveTimeStamp decoders already did, so the failure is the IllegalArgumentException that getInstance is expected to raise (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2415\"\u003e#2415\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eNeither the HSS nor the XMSS^MT private key decoder checked its declared index against the traversal state stored beside it, although the two are independent records of the same position in the key and so can be compared. For HSS the records are the top-level index and the component keys' one-time indices q; for XMSS^MT they are the global index and the per-layer BDS states. A stored key whose index had been rolled back while its state stayed advanced - a partial write, a restore from backup, a buggy storage layer - was therefore accepted, and it then signed a second message under a one-time key the key had already used, producing a signature that verified, so nothing anywhere surfaced the reuse. RFC 8554 sec. 1 and RFC 8391 sec. 1.1 both require each one-time key to be used exactly once, and this is the failure those requirements exist to prevent; the single-tree XMSS decoder has tied its BDS state to its index since that state was first validated, and this brings the two multi-tree schemes into line. HSS decode now requires the declared index to equal the position the component q values imply - a level above the last contributes (q - 1) leaves of the levels beneath it, since its q has already advanced past the subtree it signed - and XMSS^MT decode now requires each present layer's BDS index to equal the leaf index that layer derives from the global index, allowing the one position where a layer has moved into a new subtree and its state legitimately still carries the previous subtree's final index. A layer with no state yet is unaffected, since those are built lazily at signing time. Related, and the same shape of omission: an XMSS or XMSS^MT private key encoding carries the tree root twice - the key's own root field and the root node of the BDS state stored beside it, which for XMSS^MT is the top layer's - and the two were never compared either. A corrupted root was accepted and then poisoned every signature the key made, because the root is hashed into the message digest: the signature did not verify and nothing indicated why. Decode now requires the two copies to agree. The BDS node values themselves are not checkable the way the LMS tree cache above is - a BDS authentication path, stack, retain or keep node does not have its children stored alongside it, so recomputing one means building a subtree, which is the work the state exists to avoid. Both checks are integer comparisons over the levels of the key, too small to measure against the surrounding decode, and both were verified not to reject any legitimate key by walking every index a key can reach: the full key space of the two-level HSS and the h=4/d=2, h=6/d=2, h=6/d=3, h=9/d=3 and h=8/d=4 XMSS^MT parameter sets, plus a three-level HSS key across a subtree boundary and an HSS shard. Since those node values cannot be recomputed, the encoded state now carries a checksum over itself instead, with the owning key's public seed hashed in front of it. Any corruption of the stored state is refused at decode rather than being loaded and then producing signatures that silently do not verify, and because the public seed is bound in, a state transplanted between two keys of the same parameter set is refused too, even though it is internally consistent and arrives with its own matching root. The public seed is bound rather than the secret seed or the PRF key deliberately: the state's own root and index are inside the encoding and so are already covered, hashing secret material would make the stored checksum a commitment to it for no gain in detection, and the PRF key does not influence the state at all. \u003cstrong\u003eThis is an error-detecting code and not integrity protection\u003c/strong\u003e - anyone able to rewrite the stored key recomputes it, so it establishes that the state is unchanged since it was written, never that it was correct when written, and the allocation bounds on the encoding remain the guard against a crafted one. It costs one SHA-256 over the state, measured at 5 to 8 microseconds each way for the h=10 and h=16 parameter sets, and 32 bytes of encoding. The state encoding was added earlier in this same cycle and has not been released, so the checksum is simply part of it rather than a new version: a state written by a 1.86 beta is rejected, which is recovered from by re-exporting the key. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the HSS check as well (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2414\"\u003e#2414\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe S/MIME example smoke test in the misc module (org.bouncycastle.mail.smime.examples.test.AllTests) drove SendSignedAndEncryptedMail against smtp.gmail.com, and that example finishes with Transport.send() under JavaMail's default settings, which have no connect timeout. Where outbound port 25 is refused the failure was swallowed and the test passed; where it is silently dropped, as on many home networks, the connect blocked and ./gradlew build hung in :misc:test indefinitely with \u0026quot;0 tests completed\u0026quot;. The test now delivers to an SMTP stub on a loopback port, with connect / read / write timeouts as a backstop, and asserts the message arrived (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2407\"\u003e#2407\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation took the traditional component public key bytes it feeds the KEM combiner from the recipient key's own encoding, while decapsulation recomputes the point from the private key and so always produced an uncompressed one. Section 4 of draft-ietf-lamps-pq-composite-kem requires an EC component to be carried as an uncompressed point, but a component key that encodes itself compressed - a BC EC key whose point format has been set through org.bouncycastle.jce.interfaces.ECPointEncoder, or a key from a provider that preserves a compressed encoding - was passed through as it came. Both sides then combined a different tradPK and derived different shared secrets, with no error reported on either: encapsulation and decapsulation both succeeded and the recipient simply could not decrypt. The EC component is now normalised to an uncompressed point wherever the engine serialises one, which covers the ephemeral key that forms the ciphertext as well. X25519 and X448 components have a single encoding and were unaffected, as were EC keys left in their default (uncompressed) format, whose shared secrets are unchanged. CompositePublicKey.getEncoded() took its component bytes the same way, so such a key also encoded to a composite key other implementations reject and whose bytes changed across an encode / decode / encode round trip - 1238 bytes rather than 1270 for MLKEM768-ECDH-P256, and for the composite ML-DSA keys sharing that method, 2006 rather than 2038 for MLDSA65-ECDSA-P256. It now normalises the component the same way. This is a write-side change only: a composite key carrying a compressed EC component is still decoded, since the component key factories accept either form, and continues to verify signatures as before - it simply re-encodes in the normalised form. The shared normalisation is org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil.getUncompressedSubjectPublicKeyBytes.\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation threw a NullPointerException, wrapped in an IllegalStateException out of KeyGenerator.generateKey(), when the SecureRandom it was given was null - which javax.crypto.KEM.newEncapsulator() documents as a request for the provider's default, and which KeyGenerator.init(spec, null) passes straight through. The three RSA-OAEP composites draw the traditional shared secret from that random directly, so they were the ones affected; the ECDH and X25519 / X448 composites escaped only because their component KeyPairGenerators default a random of their own. CompositeMLKEMEngine now defaults one through CryptoServicesRegistrar.getSecureRandom() on first use, as the composite KEM Cipher's wrap path already did, and as the KEM generators corrected earlier in this cycle now do. Related, the engine now also clears the ML-KEM component's shared secret alongside the traditional one on both the encapsulate and decapsulate paths - the copy handed back by getEncoded() was left in the heap - as section 3.5 of draft-ietf-lamps-pq-composite-kem requires.\u003c/li\u003e\n\u003cli\u003eCompositePublicKey.getAlgorithm() and CompositePrivateKey.getAlgorithm() returned null for all twelve Composite ML-KEM (draft-ietf-lamps-pq-composite-kem) parameter sets. Both classes resolved the name through the composite signature index only, which holds the composite ML-DSA OIDs, so a composite KEM key pair - generated, parsed from a certificate, or read from PKCS#8 - reported no algorithm at all, and the standard JCA idiom of reconstructing a key with KeyFactory.getInstance(key.getAlgorithm()) raised a NullPointerException. The lookup now falls back to the composite KEM index, so the name returned is the one the provider registers the algorithm under (e.g. MLKEM768-X25519-SHA3-256), matching the composite ML-DSA behaviour. The same single-index assumption made the CompositePublicKey(SubjectPublicKeyInfo) and CompositePrivateKey(PrivateKeyInfo) constructors reject a composite KEM key with \u0026quot;unable to create CompositePublicKey from SubjectPublicKeyInfo\u0026quot;; they now dispatch to the composite KEM key factory for those OIDs. Keys obtained through KeyFactory or through BouncyCastleProvider.getPublicKey / getPrivateKey were unaffected and are unchanged (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2404\"\u003e#2404\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe org.bouncycastle.jcajce.spec.KEMKDFSpec constructor stored a null otherInfo as given, so getOtherInfo() returned null, and three of the KDF branches KdfUtil.makeKeyBytes dispatches to - KMAC-128, KMAC-256 and SHAKE-256 - read the otherInfo length without a guard and threw NullPointerException out of the KEM operation, where the KDF2, KDF3 and HKDF branches tolerate a null through KDFParameters / HKDFParameters. The Builder of every spec in the package already mapped null to empty, so no provider path reached it, but the constructor is protected on a public class and KdfUtil is documented for callers building their own KEM integration; the deprecated KEMParameterSpec passes a null itself and escaped only because it also pins the KDF to null. The constructor now stores empty for a null, so getOtherInfo() never returns null, and a null and an explicitly empty otherInfo derive the same key.\u003c/li\u003e\n\u003cli\u003eQR-UOV signature verification accepted a signature encoding that was not canonical, so the encoding of a signature was not unique even after the trailing-byte fix of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e. Each F_q element of the signature is stored in ceil(log2 q) bits, one more bit pattern than the field has elements: q itself is representable and is arithmetically congruent to zero, so an element written as q verified exactly as the same element written as zero would, and the bits padding the last element out to the byte boundary were never read at all. Every zero element of a signature therefore carried a second encoding, and for the q = 7 parameter sets roughly one element in seven is zero - a single qruov_5_q7_L10 signature measured 256 spare bits, so on the order of 2^256 distinct byte strings verified for the one message and key. Verification now rejects any element outside [0, q) and any set padding bit; a signature produced by this or by the reference implementation is unaffected, as the KAT vectors of every parameter set confirm. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSNOVA signature verification ignored four bits inside the signature for any parameter set whose solution is an odd number of GF(16) nibbles - the SNOVA_24_5_5, SNOVA_25_8_3, SNOVA_29_6_5 and SNOVA_66_15_3 families, sixteen of the forty-four parameter sets. The last byte of the encoded solution carries a single nibble and the signer leaves the top four bits zero, but the decoder did not read them, so sixteen distinct byte strings verified for one signature. This is the same non-unique encoding github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e closed for bytes following the signature, applied inside it; the verifier now requires those bits to be zero. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSnovaPrivateKeyParameters did not validate the length of the private key encoding handed to it - the only one of the five schemes of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e that did not - and SnovaParameters.getPrivateKeyLength() reported the expanded (\u0026quot;ESK\u0026quot;) length even for a parameter set whose private key is the seed pair. A private key encoding reaches this constructor straight from a PKCS#8 blob, so a wrong length went undetected: a seed-form key with extra bytes appended was accepted and signed under a different derived key, and a short expanded-form key sized the signer's decode buffer negatively, throwing NegativeArraySizeException out of generateSignature() rather than being reported at construction. Related, the signing retry loop could not terminate: the vinegar values are derived from a single-byte counter, so only 256 distinct linear systems can be tried, and an expanded-form private key that is not a real central map is singular for all of them - generateSignature() then span forever rather than failing. The length is now checked at construction, getPrivateKeyLength() reports the length that parameter set's private key actually has, and the retry loop gives up after its 256 attempts as MAYO's does.\u003c/li\u003e\n\u003cli\u003eMayoSigner and MayoKeyPairGenerator did not clear several buffers holding secret key material that the MAYO reference implementation explicitly clears. Signing left the secret oil space O, the expanded L = (P1 + P1^t) * O + P2, and the M / VPV / Ox intermediates of the central map in place, having gone to the trouble of clearing eleven other buffers; key generation left the expanded seed, whose tail is the encoded oil space, and the P1 * O + P2 half of P; and the row-echelon step left the packed echelon form of the secret linear system and its pivot rows. Separately, if all 256 attempts at solving for the signature had given a rank-deficient system, signing emitted a signature built from the failed attempt's state instead of reporting the failure the reference returns, and AIMerSigner.generateSignature returned an empty array on failure, which a caller would hand on as though it were a signature. Both now throw.\u003c/li\u003e\n\u003cli\u003eFive PQC signature schemes - MAYO, SNOVA, QR-UOV, SQIsign and AIMer - returned the NIST crypto_sign \u0026quot;sm\u0026quot; signed-message envelope from generateSignature() rather than the signature. That envelope is an artefact of the reference KAT harness, which records the message alongside the signature so a vector file can be self-contained; it is not part of any of the five specifications, and no other BC signer emits it (Falcon's KAT test rebuilds the equivalent envelope in the test, which is where it belongs). Two consequences followed, both reaching the JCA Signature services of every parameter set of the five schemes in BouncyCastlePQCProvider. First, since the message was appended to the signature, verification had to skip whatever followed the signature proper, and it did so by checking only that the buffer was long enough - so any number of trailing bytes could be added to a valid signature, or the appended message replaced with unrelated data, and it still verified. A signature encoding was therefore not unique: anyone holding one valid signature could produce unlimited distinct byte strings that all verified for the same message and key, which breaks any use that treats the signature bytes as an identifier, deduplicates on them, or records them as evidence. Second, the envelope propagated into everything built on the operator layer: because ContentSigner hands the signature straight into the structure being signed, every X.509 certificate, CRL, CMS SignedData and TLS CertificateVerify BC produced with one of these algorithms carried a verbatim copy of the signed data inside its own signature field - a self-signed MAYO-1 certificate came to 3567 bytes where the same certificate is now 2020 - which no other implementation can parse as a signature, and which in a detached CMS signature meant the \u0026quot;detached\u0026quot; signature carried the content. generateSignature() now returns the bare signature, and verifySignature() requires exactly the parameter set's signature length, so appended or truncated data is rejected rather than ignored. \u003cstrong\u003eThis is a behavioural change for signatures produced by an earlier release\u003c/strong\u003e - MAYO and SNOVA from 1.84, QR-UOV, SQIsign and AIMer from 1.85 - which are no longer accepted in the envelope form they were emitted in; the signature bytes themselves are unchanged, so a stored value can be recovered by taking the leading signature-length bytes, or for AIMer, whose envelope was message || signature rather than signature || message, the trailing ones. The KAT tests now rebuild the envelope before comparing against the vector files, which continue to record it. Note that AIMer's verification had already been made length-exact during this cycle (see the entry below relating to github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2401\"\u003e#2401\u003c/a\u003e), so of the five only its envelope remained (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe MLS implementation did not bind an X.509 credential to the LeafNode's signature_key. LeafNode.verify() checked a leaf's signature against the signature_key declared in the leaf itself, while the X.509 credential's certificate chain was stored but never parsed or checked, so the certificate's public key was never required to match signature_key (RFC 9420 sec. 5.3). A leaf could therefore carry one party's certificate while being signed by an unrelated key and still be accepted under that party's identity through KeyPackage.verify() and the Group leaf-validation path. LeafNode.verify() now requires the end-entity certificate's subject public key, in the cipher suite's signature encoding, to equal signature_key for an X.509 credential, and rejects the leaf otherwise - including an empty chain or a certificate whose key type does not match the cipher suite; certificate-chain and identity validation to a trust anchor remain the application's responsibility per RFC 9420 sec. 5.3.1. A public org.bouncycastle.mls.codec.Certificate(byte[]) constructor and a Credential.getCertificates() accessor are added so callers can build and inspect X.509 credentials. Basic credentials are unaffected.\u003c/li\u003e\n\u003cli\u003eThe SecureRandom supplied to org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder.setSecureRandom() did not drive the content IV / nonce for any algorithm other than RC2. EnvelopedDataHelper.generateParameters passed the caller's SecureRandom to the AlgorithmParameterGenerator only in the RC2_CBC branch; every other content-encryption algorithm - AES-CBC, AES-GCM, AES-CCM, Camellia, ARIA, SEED and the rest - reached pGen.generateParameters() on an uninitialised generator, so the IV / nonce was drawn from a default SecureRandom and setSecureRandom() was silently ignored (the builder's javadoc states that random is used for IV/nonce generation). The generator is now initialised with the supplied random on the general path as well, so a caller who provides a specific randomness source - for a controlled or FIPS-approved DRBG, say - has it honoured for the content IV / nonce. The session-key generation path was unaffected and already used the supplied random. Because the content IV / nonce now comes from the supplied SecureRandom, the org.bouncycastle.crypto.util JournalingSecureRandom / JournaledAlgorithm reproducible-encryption support records it in the transcript: a resumed session reproduces the IV / nonce by regenerating it from the replayed randomness - build the resuming encryptor from the content-algorithm OID - rather than by reusing the AlgorithmIdentifier captured from the first encryption, which no longer keeps the transcript aligned.\u003c/li\u003e\n\u003cli\u003eThe NTRU LPRime, NTRU+ and SMAUG-T KEM generators threw a NullPointerException when constructed with a null SecureRandom, where every other KEM generator - including NTRU LPRime's own SNTRU Prime counterpart in the same package - defaults one through CryptoServicesRegistrar.getSecureRandom(). This is reachable from the lightweight API directly, and from javax.crypto.KEM, whose newEncapsulator() documents a null random as a request for the provider's default.\u003c/li\u003e\n\u003cli\u003eFrodoKEMEngine kept a single SHAKE instance in a field, so an engine reached concurrently produced wrong results. It is reached that way through org.bouncycastle.crypto.kems.FrodoKEMExtractor, which holds one engine for its lifetime: two threads extracting through one extractor interleaved the digest's absorb and squeeze phases, yielding shared secrets that silently did not match the sender's, or an IllegalStateException of \u0026quot;attempt to absorb while squeezing\u0026quot; from inside extractSecret. The digest is now built per call, as CMCEEngine's already was, which makes an extractor safe to share. Encapsulation was unaffected, since FrodoKEMGenerator builds an engine per call. Results for any single-threaded use are unchanged - the reference KAT vectors are byte-identical.\u003c/li\u003e\n\u003cli\u003eThe BCJSSE provider carried the TLS 1.2 coupling between the supported_groups extension and ECDSA over into TLS 1.3: an ECDSA signature scheme was treated as usable - offered in the signature_algorithms and signature_algorithms_cert extensions, and eligible when selecting the local credentials - only while the corresponding curve was among the named groups enabled for key exchange, both per context (a group unavailable for key agreement disabled the scheme outright) and per connection (the curve had to be in the supported_groups list about to be sent). RFC 8446 sec. 4.2.7 scopes supported_groups to key exchange only, with signature algorithms negotiated independently (sec. 4.2.3), so this incorrect restriction in TLS 1.3 has been removed. Ed25519, Ed448 and the RSA schemes were unaffected (as well as typical deployments using a default configuration for named groups).\u003c/li\u003e\n\u003cli\u003eThe bcmail module descriptor did not declare its javax.mail/javax.activation dependences, so a modular (module-path) consumer of the jar hit IllegalAccessError/module-resolution failures when the S/MIME classes touched the mail API. The descriptor now requires them optionally (requires static) under all four module names those libraries are known by - the automatic names mail and activation carried by the javax.mail:mail / javax.activation:activation artifacts, and the explicit names java.mail and java.activation carried by the newer com.sun.mail / com.sun.activation ones - a hard requires on any one name would break users of the others (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2389\"\u003e#2389\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFour type-coercion helpers in the OER / IEEE 1609.2 (ITS) decoder tested the wrong type in the identity fast path that lets a getInstance() factory return an argument that is already of the target type. org.bouncycastle.oer.its.ieee1609dot2.basetypes.UINT32.getInstance and org.bouncycastle.oer.its.etsi102941.basetypes.Version.getInstance guarded on UINT8 - a sibling of UINT32 under UintBase, and unrelated to Version - so passing a UINT8 threw ClassCastException, while passing an actual UINT32 or Version missed the fast path and fell through to ASN1Integer.getInstance, which rejects them: neither factory accepted its own type. org.bouncycastle.oer.its.etsi103097.EtsiTs103097DataEncryptedUnicast.getInstance guarded on its sibling EtsiTs103097DataEncrypted and then cast to the unicast type, so an EtsiTs103097DataEncrypted threw ClassCastException. org.bouncycastle.oer.OEROptional.getObject(Class) called value.getClass().isInstance(type) with the arguments transposed, which is always false because the argument is a java.lang.Class, so the cast path was dead and every optional field was resolved reflectively, failing with IllegalStateException for a target type with no static getInstance. Each guard now names the type it returns, matching the sibling UINT8 / UINT16 / UINT64 and EtsiTs103097DataEncrypted factories (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2373\"\u003e#2373\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eDefaultAlgorithmNameFinder and DefaultSignatureNameFinder had no entries at all for the ShangMi algorithms, so an SM2 signature AlgorithmIdentifier that DefaultSignatureAlgorithmIdentifierFinder itself produces came back named only by its OID string - getAlgorithmName(GMObjectIdentifiers.sm2sign_with_sm3) returned \u0026quot;1.2.156.10197.1.501\u0026quot; and hasAlgorithmName returned false. Both finders now name sm2sign_with_sm3 as SM3WITHSM2 and sm2sign_with_sha256 as SHA256WITHSM2, and DefaultAlgorithmNameFinder additionally names the sm3 digest. All three resolve through the BC provider, as Signature and MessageDigest respectively. The remaining GM arc - the SM4 cipher modes, the sm2encrypt variants, and the SM1 / SM6 / SSF33 ciphers BC does not implement - is still unnamed (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2377\"\u003e#2377\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe RFC 4998 evidence-record classes compared the digest AlgorithmIdentifier named by a time-stamp authority with the one their own DigestCalculator uses, and did so with AlgorithmIdentifier.equals(), which compares the encodings. A TSA that names SHA-256 with an explicit NULL parameters field - DigiCert among them - therefore failed against BC's own calculator, which names it with the parameters absent, and ERSArchiveTimeStampGenerator.generateArchiveTimeStamp rejected the response with \u0026quot;time stamp imprint for wrong algorithm\u0026quot;. Both spellings name the same digest and RFC 5754 sec. 2 requires a receiver to accept either, while requiring that identifiers be generated with the parameters absent, which BC already does. The three affected comparisons - the two in ERSArchiveTimeStampGenerator and the digest check in ERSEvidenceRecord.renew - now use the new AlgorithmIdentifier.areEquivalent, which matches on the algorithm and treats an absent parameters field and NULL as the same, and the consistency check across an evidence record's archive time stamp chain uses it too. An identifier carrying an actual parameter structure is never equivalent to one carrying none (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2379\"\u003e#2379\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eEDIPartyName.toASN1Primitive emitted the nameAssigner and partyName DirectoryStrings without their context tags, so an EDIPartyName built through its public constructor could not be parsed back by EDIPartyName.getInstance, which correctly requires them. RFC 5280 sec. 4.2.1.6 tags both members [0] and [1], and those tags are explicit despite the module's IMPLICIT TAGS because DirectoryString is a CHOICE, which X.680 does not allow to be tagged implicitly - the decoder already had this right. The encoder now matches it. Note the type was added during the 1.85 cycle and GeneralName validates its ediPartyName alternative through it, so a GeneralName carrying an untagged ediPartyName - including one BC itself produced - is rejected where 1.84 passed it through unexamined; the untagged form is not read leniently (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2380\"\u003e#2380\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eRSASSA-PSS could not be used with a RIPEMD digest through the JCA API. Nothing registered the RIPEMD PSS signatures, so Signature.getInstance(\u0026quot;RIPEMD160WITHRSAANDMGF1\u0026quot;) raised NoSuchAlgorithmException, and the generic RSASSA-PSS route with an explicit PSSParameterSpec failed too: org.bouncycastle.jcajce.provider.util.DigestFactory.getDigest returned null for a RIPEMD name, and isSameDigest - an allow-list of the SHA families and MD5 - reported two identical RIPEMD names as different digests, so the spec was rejected with \u0026quot;digest algorithm for MGF should be the same as for PSS parameters\u0026quot;. isSameDigest now answers true for equal names whatever the digest, which also covers Whirlpool, SM3, GOST3411 and anything else outside that allow-list; DigestFactory recognises RIPEMD128, RIPEMD160 and RIPEMD256 by name and OID; the three PSS signatures are registered with MGF1 over the same digest and a salt of the digest length; and DefaultSignatureAlgorithmIdentifierFinder gains the matching RIPEMD*WITHRSAANDMGF1 entries with their RSASSA-PSS-params, so the operator/JcaContentSignerBuilder path works as well. Note BC continues to require the PSS hash and the MGF1 hash to be the same, which RFC 8017 does not itself demand (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2381\"\u003e#2381\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe opt-in key-size validation on CMS key-transport recipients (org.bouncycastle.cms.jcajce.JceKeyTransRecipient.setKeySizeValidation(true)) never ran for a message using RFC 9709 CEK derivation (id-alg-cek-hkdf-sha256): the branch that should have selected the actual content-encryption algorithm carried in the KDF AlgorithmIdentifier's parameters compared the encrypted-key byte array against the id-alg-cek-hkdf-sha256 object identifier - a comparison that is always false - so the check fell through to a key-size lookup on the outer KDF OID, which has no registered key size, and silently checked nothing. A key-transport EnvelopedData/AuthEnvelopedData whose transported (and HKDF-derived) content-encryption key did not match the key size of the advertised content-encryption algorithm was therefore accepted even with validation enabled. The recipient now dispatches on the content-encryption AlgorithmIdentifier's algorithm OID, so key-size validation of RFC 9709 messages checks the recovered key against the inner content-encryption algorithm. Messages with a matching key size, non-HKDF messages, and recipients that do not enable validation are unaffected.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003eSee full diff in \u003ca href=\"https://github.com/bcgit/bc-java/commits\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003ecommonmark-java 0.29.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e[0.29.0] - 2026-06-20\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/42b4fb7adfe288ef13e9e27ab20aff7e91b0ab9d\"\u003e\u003ccode\u003e42b4fb7\u003c/code\u003e\u003c/a\u003e Prepare CHANGELOG for version 0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/b76e09d7a8362abb5f04e1d6b91dbd6da279a6fc\"\u003e\u003ccode\u003eb76e09d\u003c/code\u003e\u003c/a\u003e Limit how deep inline nodes may nest by default (100)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/49f65cb5cbec93cff713179990307145198e7061\"\u003e\u003ccode\u003e49f65cb\u003c/code\u003e\u003c/a\u003e Fix StackOverflowEr...\n\n_Description has been truncated_","html_url":"https://github.com/ifabrish/openclaw-ifabrish-/pull/31","url":"https://dependabot.ecosyste.ms/api/v1/hosts/GitHub/repositories/ifabrish%2Fopenclaw-ifabrish-/issues/31","packages_url":"https://dependabot.ecosyste.ms/api/v1/issues/31/packages"},{"uuid":"5403922362","node_id":"PR_kwDOTB6pPc8AAAABC4wjig","number":31,"state":"closed","title":"chore(deps): bump the android-deps group across 1 directory with 16 updates","user":"dependabot[bot]","labels":["dependencies","java"],"assignees":[],"locked":false,"comments_count":1,"pull_request":true,"closed_at":"2026-09-11T19:35:06.000Z","author_association":null,"state_reason":null,"created_at":"2026-09-09T19:37:22.000Z","updated_at":"2026-09-11T19:35:08.000Z","time_to_close":172664,"merged_at":null,"merged_by":null,"closed_by":null,"dependency_metadata":{"prefix":"chore(deps): bump","group_name":"android-deps","update_count":16,"packages":[{"name":"gradle-wrapper","old_version":"9.5.1","new_version":"9.7.1","repository_url":"https://github.com/gradle/gradle"},{"name":"org.bouncycastle:bcprov-jdk18on","old_version":"1.84","new_version":"1.85.2","repository_url":"https://github.com/bcgit/bc-java"},{"name":"org.commonmark:commonmark","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-autolink","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-strikethrough","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-tables","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-task-list-items","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.junit.vintage:junit-vintage-engine","old_version":"6.1.0","new_version":"6.1.3","repository_url":"https://github.com/junit-team/junit-framework"},{"name":"io.kotest:kotest-assertions-core-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"io.kotest:kotest-runner-junit5-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"com.squareup.okhttp3:mockwebserver","old_version":"5.3.2","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.squareup.okhttp3:okhttp","old_version":"5.3.2","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.android.application","old_version":"9.2.1","new_version":"9.4.0"},{"name":"com.android.test","old_version":"9.2.1","new_version":"9.4.0"},{"name":"org.jetbrains.kotlin.plugin.compose","old_version":"2.4.0","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"},{"name":"org.jetbrains.kotlin.plugin.serialization","old_version":"2.4.0","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"}],"path":null,"ecosystem":"maven"},"body":"Bumps the android-deps group with 16 updates in the /apps/android directory:\n\n| Package | From | To |\n| --- | --- | --- |\n| [gradle-wrapper](https://github.com/gradle/gradle) | `9.5.1` | `9.7.1` |\n| [org.bouncycastle:bcprov-jdk18on](https://github.com/bcgit/bc-java) | `1.84` | `1.85.2` |\n| [org.commonmark:commonmark](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-autolink](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-strikethrough](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-tables](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-task-list-items](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.junit.vintage:junit-vintage-engine](https://github.com/junit-team/junit-framework) | `6.1.0` | `6.1.3` |\n| [io.kotest:kotest-assertions-core-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [io.kotest:kotest-runner-junit5-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [com.squareup.okhttp3:mockwebserver](https://github.com/lysine-dev/okhttp) | `5.3.2` | `5.5.0` |\n| [com.squareup.okhttp3:okhttp](https://github.com/lysine-dev/okhttp) | `5.3.2` | `5.5.0` |\n| com.android.application | `9.2.1` | `9.4.0` |\n| com.android.test | `9.2.1` | `9.4.0` |\n| [org.jetbrains.kotlin.plugin.compose](https://github.com/JetBrains/kotlin) | `2.4.0` | `2.4.20` |\n| [org.jetbrains.kotlin.plugin.serialization](https://github.com/JetBrains/kotlin) | `2.4.0` | `2.4.20` |\n\n\nUpdates `gradle-wrapper` from 9.5.1 to 9.7.1\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/gradle/gradle/releases\"\u003egradle-wrapper's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e9.7.1\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.1.\u003c/p\u003e\n\u003cp\u003eThis is a patch release for 9.7.0. We recommend using 9.7.1 instead of 9.7.0.\u003c/p\u003e\n\u003cp\u003eHere are the highlights of 9.7.0 release:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIsolated Projects graduates to incubating\u003c/li\u003e\n\u003cli\u003eBroader Configuration Cache compatibility\u003c/li\u003e\n\u003cli\u003eResilient Sync helps you fix broken builds\u003c/li\u003e\n\u003cli\u003eMore source locations in problem reports\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003ca href=\"https://docs.gradle.org/9.7.1/release-notes.html\"\u003eRead the Release Notes\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eWe would like to thank the following community members for their contributions to this release of Gradle:\n\u003ca href=\"https://github.com/aSemy\"\u003eAdam\u003c/a\u003e,\n\u003ca href=\"https://github.com/Gautam-aman\"\u003eAman Gautam\u003c/a\u003e,\n\u003ca href=\"https://github.com/YukiCodepth\"\u003eAman Kumar\u003c/a\u003e,\n\u003ca href=\"https://github.com/adubrouski\"\u003eAnton Dubrouski\u003c/a\u003e,\n\u003ca href=\"https://github.com/liutikas\"\u003eAurimas\u003c/a\u003e,\n\u003ca href=\"https://github.com/gbhavya07\"\u003egbhavya07\u003c/a\u003e,\n\u003ca href=\"https://github.com/joshfriend\"\u003eJosh Friend\u003c/a\u003e,\n\u003ca href=\"https://github.com/nicklauslittle-gov\"\u003enicklauslittle-gov\u003c/a\u003e,\n\u003ca href=\"https://github.com/psoni674\"\u003ePragati\u003c/a\u003e,\n\u003ca href=\"https://github.com/Project516\"\u003eproject516\u003c/a\u003e,\n\u003ca href=\"https://github.com/Uomocapra\"\u003eQin Mi\u003c/a\u003e,\n\u003ca href=\"https://github.com/rkdfx\"\u003eRavi\u003c/a\u003e,\n\u003ca href=\"https://github.com/sk-reddy17\"\u003esk-reddy17\u003c/a\u003e,\n\u003ca href=\"https://github.com/Suvrat1629\"\u003eSuvrat Acharya\u003c/a\u003e,\n\u003ca href=\"https://github.com/ShreckYe\"\u003eYongshun Ye\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eUpgrade instructions\u003c/h2\u003e\n\u003cp\u003eSwitch your build to use Gradle 9.7.1 by updating your wrapper:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e./gradlew :wrapper --gradle-version=9.7.1 \u0026amp;\u0026amp; ./gradlew :wrapper\r\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eSee the Gradle \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/upgrading_version_9.html\"\u003e9.x upgrade guide\u003c/a\u003e to learn about deprecations, breaking changes and other considerations when upgrading.\u003c/p\u003e\n\u003cp\u003eFor Java, Groovy, Kotlin and Android compatibility, see the \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/compatibility.html\"\u003efull compatibility notes\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eReporting problems\u003c/h2\u003e\n\u003cp\u003eIf you find a problem with this release, please file a bug on \u003ca href=\"https://github.com/gradle/gradle/issues\"\u003eGitHub Issues\u003c/a\u003e adhering to our issue guidelines.\nIf you're not sure you're encountering a bug, please use the \u003ca href=\"https://discuss.gradle.org/c/help-discuss\"\u003eforum\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eWe hope you will build happiness with Gradle, and we look forward to your feedback via \u003ca href=\"https://twitter.com/gradle\"\u003eTwitter\u003c/a\u003e or on \u003ca href=\"https://github.com/gradle\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003e9.7.0\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.0.\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/92f0512e7f06d84621afba191f75e265363890cf\"\u003e\u003ccode\u003e92f0512\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38892\"\u003e#38892\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/820ee75a99a179bbffa41bcedc6477b685fabb9f\"\u003e\u003ccode\u003e820ee75\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/82c23f9bd2a89b4cc644e1f90a28a8668feb3dee\"\u003e\u003ccode\u003e82c23f9\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering problem in KTS (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38878\"\u003e#38878\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/ef11a7268fe8cc8d6ab849ec911aa11220180553\"\u003e\u003ccode\u003eef11a72\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering issue\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/bb0d8a974a71b1003efea41e4046e98855cd5ff8\"\u003e\u003ccode\u003ebb0d8a9\u003c/code\u003e\u003c/a\u003e Make relevant tests polyglot (run for multiple DSLs)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/336e129d7f95c03486acafc97abf59734acfed48\"\u003e\u003ccode\u003e336e129\u003c/code\u003e\u003c/a\u003e Update signing configuration (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38874\"\u003e#38874\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/4bdf0da2dad9884d089a6062a45ea7183e7d735d\"\u003e\u003ccode\u003e4bdf0da\u003c/code\u003e\u003c/a\u003e Update signing configuration\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/cd9b92c1b82856248cf1dc58b50378238bec7b52\"\u003e\u003ccode\u003ecd9b92c\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38839\"\u003e#38839\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/5f4e381964897ad8d6b99e5a7c77f26dba3259fb\"\u003e\u003ccode\u003e5f4e381\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/1e08ab551367aeb5fb48b26e72807e1d2b27c939\"\u003e\u003ccode\u003e1e08ab5\u003c/code\u003e\u003c/a\u003e Keep type-use annotations in extracted ABI classes (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38810\"\u003e#38810\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/gradle/gradle/compare/v9.5.1...v9.7.1\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.bouncycastle:bcprov-jdk18on` from 1.84 to 1.85.2\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.md\"\u003eorg.bouncycastle:bcprov-jdk18on's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch1\u003eBouncy Castle Crypto Package - Release Notes\u003c/h1\u003e\n\u003ch2\u003e1.0 Introduction\u003c/h2\u003e\n\u003cp\u003eThe Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. The package is organised so that it contains a light-weight API suitable for use in any environment (including the J2ME) with the additional infrastructure to conform the algorithms to the JCE framework.\u003c/p\u003e\n\u003ch2\u003e2.0 Release History\u003c/h2\u003e\n\u003cp\u003e\u003c!-- raw HTML omitted --\u003e\u003c!-- raw HTML omitted --\u003e\u003c/p\u003e\n\u003ch3\u003e2.1.1 Version\u003c/h3\u003e\n\u003cp\u003eRelease: 1.86\u003cbr /\u003e\nDate: 2026, TBD\u003c/p\u003e\n\u003ch3\u003e2.1.2 Defects Fixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) let a subkey inherit the primary key's Key Flags when its own Subkey Binding signature carried no Key Flags subpacket, which made the two capability decisions taken for one subkey disagree. OpenPGPCertificate.OpenPGPComponentKey.isSigningKey() reads the effective flags, which fell back to the primary key's direct-key or primary user ID self-signature, so a subkey bound with no flags of its own counted as signing-capable; verifyEmbeddedPrimaryKeyBinding reads the binding signature's own flags, found no signing capability there, and so skipped the embedded Primary Key Binding (cross-certification) signature that RFC 9580 sec. 5.2.1.8 and sec. 10.1.3 require of a subkey that can issue signatures. A data signature made by such a subkey was therefore attributed to the certificate and reported valid by OpenPGPSignature.OpenPGPDocumentSignature.isValid() with the cross-certification requirement never applied, where GnuPG refuses the same certificate and message as not cross-certified. An attacker holding a third party's public signing subkey - which is public material - could bind it to their own primary key with a Subkey Binding signature they are able to make, carrying no Key Flags and no embedded Primary Key Binding signature, which they cannot make without the subkey's private key, and have that party's genuine signatures verify as valid under the attacker's own identity: misattribution of a real signature rather than a forgery of a new one, since the signature still has to be one the subkey actually made. Key Flags are a statement about the key the carrying signature refers to (RFC 9580 sec. 5.2.3.29), so a subkey no longer inherits them from the certificate-wide signatures of the primary key: a Subkey Binding signature that omits the subpacket now leaves the subkey with no capabilities rather than the primary's, which makes the flags the cross-certification check consults the same flags every other decision consults. Preferences and the other subpackets a direct-key signature carries are inherited as before, and the primary key itself - whose flags legitimately come from its direct-key or user ID self-signature - is unaffected. The low-level PGPSignature / PGPPublicKeyRing API performs no binding checks by design and is unchanged.\u003c/li\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) used a version 6 key that carried no valid Direct Key signature, falling back to the primary user ID binding as it correctly does for a version 4 key. RFC 9580 sec. 5.2.3.10 requires the opposite: \u0026quot;An implementation MUST ensure that a valid Direct Key signature is present before using a version 6 key. This prevents certain attacks where an adversary strips a self-signature specifying a Key Expiration Time or certain preferences.\u0026quot; The certificate grammar says the same structurally, the Direct Key signature being mandatory in the version 6 structure of sec. 10.1.1 and optional in the version 4 one of sec. 10.1.3. Because a version 6 certificate carries its key expiration, features and algorithm preferences on the Direct Key signature - the convention the RFC recommends and the one OpenPGPKeyGenerator follows, its user ID certification carrying no expiration at all - removing that single signature packet from a published certificate silently dropped the expiration along with the preferences and features: OpenPGPCertificate.getSignatureChainFor fell back to the user ID binding, the primary key was still reported bound, and getEncryptionKeys() and getSigningKeys() went on returning the subkeys of a key whose owner had set it to expire. The primary key fingerprint is unchanged by the removal, so a relying party pinning the key by fingerprint still treats it as the same key, and no private key or hash collision is involved; the natural moment for the strip is the key refresh that RFC 9580 names as the reason to refetch a key at all - to learn about changes in expiration, features, preferences and revocation - which is exactly the update it defeats. This is a downgrade rather than a forgery, nothing being attributed to a key that did not authorise it, and the concerning direction is encryption, to a key meant to have been retired. OpenPGPCertificate.isBoundBy now requires a valid Direct Key self-signature on a version 6 primary key before any component of the certificate - the primary key, its subkeys or its identities - is treated as bound, so a version 6 certificate stripped of it offers no keys at all rather than an unexpiring set. Version 4 certificates are unaffected: there the key expiration legitimately lives on the user ID self-signature and the fallback is correct, so it stays. The revocation-only version 6 certificate of sec. 10.1.2, which legitimately carries no Direct Key signature, is unaffected as well - its key was already refused as revoked, and reading the revocation does not go through the binding check.\u003c/li\u003e\n\u003cli\u003eThe lightweight LMSSigner and HSSSigner refused a key wrapped in ParametersWithRandom, which is how BcContentSignerBuilder passes a key whenever setSecureRandom() has been called - so BcHssLmsContentSignerBuilder built a working signer until a random was set and then failed with \u0026quot;Incorrect Key Parameters\u0026quot;, and the two signers themselves raised ClassCastException on the same input. All three now unwrap it, as the promoted ML-DSA and SLH-DSA signers already did. The random is accepted and not used: LMS derives its message randomiser C from the key's seed and the one-time index, so it is deterministic and cannot repeat while q does not. Note SP 800-208 sec. 6.1 asks for C to come from an approved random bit generator, which this implementation does not do; that is unchanged here, and a supplied random is now ignored rather than refused.\u003c/li\u003e\n\u003cli\u003eLMS signature verification did not apply two of the checks RFC 8554 sec. 5.4.2 requires before a signature is processed. Step 2g refuses a signature whose LMS typecode is not the one from the public key, and without it the path computation took its height and tree digest from the parameter set the signature named rather than the key's, so a signature claiming a height-25 parameter set drove a 25-level computation against a height-5 key. Step 2i refuses a leaf number q outside the tree, and without it an out-of-range q flowed into the node arithmetic and was left for the candidate-root comparison to catch. Neither was a forgery - the domain separation between D_LEAF and D_INTR and the final comparison saw to that - but both are attacker-chosen work the specification says to refuse up front. Both are now checked, and a signature failing either is still reported as not verifying rather than thrown out of Signature.verify(). The catch around the signature decode in LMSSigner and HSSSigner has also been narrowed to the decode itself, as the corresponding SPI was corrected to do for github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2408\"\u003e#2408\u003c/a\u003e: past the parse the engine reports an inconsistent signature by returning false rather than by throwing, so the wider catch caught nothing while standing ready to turn a future internal error into a quiet false.\u003c/li\u003e\n\u003cli\u003eThe LMS and HSS key parameter classes now apply at construction the checks their decoders apply, so a key built directly cannot be one the decoder would refuse. LMSPrivateKeyParameters accepted an identifier of any length although the decoder reads exactly 16 bytes - such a key encoded but could not be read back - and left q, maxQ and the seed length unchecked; the seed is now required to be at least m bytes at decode as well, where a one-byte seed had been decoding silently and then deriving every one-time key from it. HSSPrivateKeyParameters checked neither its level count nor that it had been given a component key per level and a chaining signature per level below the root, and then indexed both lists, so a mismatch surfaced as IndexOutOfBoundsException - or, where a level happened to match, as a null chaining signature that only failed at signing time; the level is now checked after the reset that fills it in, since a null is legitimate on the way in. LMSPrivateKeyParameters.getInstance(byte[], byte[]) adopted the public key supplied beside the private one without comparing them, so a mismatched public key was simply reported by getPublicKey(); it now cross-checks the identifier, both parameter sets and, where the tree cache already holds it, the root, as the HSS entry point does. The decoders also now report a bad version or seed length as IOException rather than IllegalStateException, so a caller can catch one type for a malformed key, and the package-private LM-OTS public key decoder no longer declares throws Exception or dereferences an unrecognised typecode. The deprecated org.bouncycastle.pqc.crypto.lms copies carry the decoder corrections.\u003c/li\u003e\n\u003cli\u003eIn the LMS JCE layer, LMSKeyGenParameterSpec.fromNames knew all twenty LMS parameter-set names but only four of the sixteen LM-OTS ones, so none of the SP 800-208 n24 or SHAKE sets could be named; all sixteen are now present. KeyPairGenerator.initialize(int, SecureRandom) reports InvalidParameterException, which is what the JCA specifies and which extends the IllegalArgumentException it raised before, so existing catches still match. BCLMSPrivateKey.getIndex now takes the exhaustion check and the index read under the key's own monitor rather than as two separate calls, and two unused fields have gone from LMSSignatureSpi. Note that the LMS Signature claims its one-time key at the first update() rather than at sign(), so a Signature that is initialised and updated and then abandoned spends an index without producing a signature - the safe direction for a one-time scheme, and now documented on the SPI.\u003c/li\u003e\n\u003cli\u003eEvery other key pair generator that refuses a key size did the same thing the LMS one did above. KeyPairGenerator.initialize(int, SecureRandom) is documented to raise InvalidParameterException when the key size is not one the generator supports, and thirty of them raised a bare IllegalArgumentException instead, so a caller following the JCA and catching the documented type saw an exception escaping rather than a refusal. The ML-DSA, ML-KEM, SLH-DSA, Classic McEliece, FrodoKEM, NTRU and composite signature and KEM generators in the BC provider, and every generator in BCPQC, now raise InvalidParameterException - NewHope included, where the value is a key size it will not take rather than a mode of initialisation it does not offer. InvalidParameterException extends IllegalArgumentException, so callers written against the old behaviour go on catching it unchanged. The two RSA generators are corrected as well, and differently: theirs is a key size below a floor rather than a mode of initialisation they do not offer, and the refusal is raised by the lightweight RSAKeyGenerationParameters, which cannot name a java.security exception at all, so the RSA KeyPairGeneratorSpi now translates it - keeping the message verbatim and the original exception as the cause, through a new SecurityExceptions.invalidParameterException factory, since InvalidParameterException has no constructor that takes one. Of the 304 KeyPairGenerator services the two providers register, 299 now refuse a nonsense key size the way the JCA defines it and five accept it as a strength they can work with, with none left raising a bare IllegalArgumentException; that is asserted as a sweep over both providers rather than per algorithm, so a generator added later is covered without the test being touched. The jdk1.3 provider overlays of the four generators that have one carry the same change, and the jdk1.3 SecurityExceptions overlay gains the new factory along with the invalidAlgorithmParameterException one it had been missing.\u003c/li\u003e\n\u003cli\u003eKeyPairGenerator.initialize(AlgorithmParameterSpec, SecureRandom) had the same shape of problem as the int overload above, and only 44 of the 304 services the two providers register reported an unusable spec as the InvalidAlgorithmParameterException that method declares. The twenty-three PQC generators that resolve a parameter set by name - cmce, frodokem, mldsa, mlkem, slhdsa, aimer, bike, faest, falcon, haetae, hqc, mayo, mqom, ntru, ntruplus, both ntruprime variants, qruov, saber, sdith, smaugt, snova and sqisign, 230 services between them - case-folded the name they got back from the spec without checking it, so a spec with no getName() method, and a null spec, produced a NullPointerException from inside the fold; their own \u0026quot;is this name one I know\u0026quot; branch, which does report the declared exception, was unreachable. The two composite generators, whose parameter set is fixed by the algorithm name so that null is the only spec they accept, refused every other one with IllegalArgumentException. RSA answered correctly for a spec of the wrong type but not for one of the right type carrying values its lightweight parameters will not take - an even public exponent, or a key size below the floor - which is now translated the same way the int overload's is. All 304 services now report the declared exception, with the composites still taking the null spec that is right for them; note that InvalidAlgorithmParameterException is a checked exception and not an IllegalArgumentException, so a caller that was catching what these threw before has to catch the declared type instead.\u003c/li\u003e\n\u003cli\u003eAn HSS private key claimed the two records of its position under two different monitors. The top-level index and the bottom component key's one-time index q are independent records of the same position - the decoder requires them to agree, see the entry below - but generateLMSContext incremented the index under the HSS key's own monitor, released it, and only then claimed q under the component key's. A getEncoded() issued in between saw the index advanced and q not, and produced an encoding this implementation's own decoder rejects; and two threads meeting at a bottom-tree boundary could both pass the exhaustion test, take consecutive top-level indices and claim the same q, after which one of them was refused with \u0026quot;ots private key exhausted\u0026quot; by a key still reporting usages remaining, a top-level index had been spent with no signature made, and the two records stayed one apart for the rest of the key's life in that process - so it could no longer be encoded, cloned or sharded, and getIndex() and getUsagesRemaining() misreported by one. No one-time key was reused: the component key's claim is itself atomic, and the divergence runs index ahead of leaves, so the effect was on the key's usability rather than on the signatures it had made. Both records are now claimed under the one monitor, and the component key is claimed before the index is incremented so that an exhausted one leaves both untouched. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the same correction.\u003c/li\u003e\n\u003cli\u003eTimeStampToken parsed the attacker-controlled TSTInfo content of a time-stamp token (org.bouncycastle.tsp.TimeStampToken, reached from TimeStampResponse(byte[]) and (InputStream)) inside a try that caught only CMSException, so a well-formed RFC 3161 TimeStampResp whose embedded token carried a malformed TSTInfo - a SEQUENCE with fewer elements than the five mandatory fields, a non-SEQUENCE, truncated DER, or an unknown context tag - let an IllegalArgumentException or a NoSuchElementException escape the constructor's declared throws TSPException, IOException contract. A token signed by no signers or by more than one raised a bare IllegalArgumentException from the same constructor, before that try, for the same reason. Both are now reported as TSPException, matching the package-private TimeStampResponse(DLSequence) constructor and the existing getSignedAttributes guard in the same method; the signer-count refusal is a TSPValidationException, as the neighbouring check on the content type already was. Related, and the cause of the NoSuchElementException: asn1.tsp.TSTInfo read its five mandatory fields off the sequence with no bound on how many elements were actually there, so a short SEQUENCE left the enumeration to run out rather than being refused, and an oversize one was accepted with its extra elements absorbed into the optional slots. Decode now requires the five to ten elements RFC 3161 sec. 2.4.2 gives the type, which is what the sibling Accuracy and ArchiveTimeStamp decoders already did, so the failure is the IllegalArgumentException that getInstance is expected to raise (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2415\"\u003e#2415\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eNeither the HSS nor the XMSS^MT private key decoder checked its declared index against the traversal state stored beside it, although the two are independent records of the same position in the key and so can be compared. For HSS the records are the top-level index and the component keys' one-time indices q; for XMSS^MT they are the global index and the per-layer BDS states. A stored key whose index had been rolled back while its state stayed advanced - a partial write, a restore from backup, a buggy storage layer - was therefore accepted, and it then signed a second message under a one-time key the key had already used, producing a signature that verified, so nothing anywhere surfaced the reuse. RFC 8554 sec. 1 and RFC 8391 sec. 1.1 both require each one-time key to be used exactly once, and this is the failure those requirements exist to prevent; the single-tree XMSS decoder has tied its BDS state to its index since that state was first validated, and this brings the two multi-tree schemes into line. HSS decode now requires the declared index to equal the position the component q values imply - a level above the last contributes (q - 1) leaves of the levels beneath it, since its q has already advanced past the subtree it signed - and XMSS^MT decode now requires each present layer's BDS index to equal the leaf index that layer derives from the global index, allowing the one position where a layer has moved into a new subtree and its state legitimately still carries the previous subtree's final index. A layer with no state yet is unaffected, since those are built lazily at signing time. Related, and the same shape of omission: an XMSS or XMSS^MT private key encoding carries the tree root twice - the key's own root field and the root node of the BDS state stored beside it, which for XMSS^MT is the top layer's - and the two were never compared either. A corrupted root was accepted and then poisoned every signature the key made, because the root is hashed into the message digest: the signature did not verify and nothing indicated why. Decode now requires the two copies to agree. The BDS node values themselves are not checkable the way the LMS tree cache above is - a BDS authentication path, stack, retain or keep node does not have its children stored alongside it, so recomputing one means building a subtree, which is the work the state exists to avoid. Both checks are integer comparisons over the levels of the key, too small to measure against the surrounding decode, and both were verified not to reject any legitimate key by walking every index a key can reach: the full key space of the two-level HSS and the h=4/d=2, h=6/d=2, h=6/d=3, h=9/d=3 and h=8/d=4 XMSS^MT parameter sets, plus a three-level HSS key across a subtree boundary and an HSS shard. Since those node values cannot be recomputed, the encoded state now carries a checksum over itself instead, with the owning key's public seed hashed in front of it. Any corruption of the stored state is refused at decode rather than being loaded and then producing signatures that silently do not verify, and because the public seed is bound in, a state transplanted between two keys of the same parameter set is refused too, even though it is internally consistent and arrives with its own matching root. The public seed is bound rather than the secret seed or the PRF key deliberately: the state's own root and index are inside the encoding and so are already covered, hashing secret material would make the stored checksum a commitment to it for no gain in detection, and the PRF key does not influence the state at all. \u003cstrong\u003eThis is an error-detecting code and not integrity protection\u003c/strong\u003e - anyone able to rewrite the stored key recomputes it, so it establishes that the state is unchanged since it was written, never that it was correct when written, and the allocation bounds on the encoding remain the guard against a crafted one. It costs one SHA-256 over the state, measured at 5 to 8 microseconds each way for the h=10 and h=16 parameter sets, and 32 bytes of encoding. The state encoding was added earlier in this same cycle and has not been released, so the checksum is simply part of it rather than a new version: a state written by a 1.86 beta is rejected, which is recovered from by re-exporting the key. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the HSS check as well (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2414\"\u003e#2414\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe S/MIME example smoke test in the misc module (org.bouncycastle.mail.smime.examples.test.AllTests) drove SendSignedAndEncryptedMail against smtp.gmail.com, and that example finishes with Transport.send() under JavaMail's default settings, which have no connect timeout. Where outbound port 25 is refused the failure was swallowed and the test passed; where it is silently dropped, as on many home networks, the connect blocked and ./gradlew build hung in :misc:test indefinitely with \u0026quot;0 tests completed\u0026quot;. The test now delivers to an SMTP stub on a loopback port, with connect / read / write timeouts as a backstop, and asserts the message arrived (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2407\"\u003e#2407\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation took the traditional component public key bytes it feeds the KEM combiner from the recipient key's own encoding, while decapsulation recomputes the point from the private key and so always produced an uncompressed one. Section 4 of draft-ietf-lamps-pq-composite-kem requires an EC component to be carried as an uncompressed point, but a component key that encodes itself compressed - a BC EC key whose point format has been set through org.bouncycastle.jce.interfaces.ECPointEncoder, or a key from a provider that preserves a compressed encoding - was passed through as it came. Both sides then combined a different tradPK and derived different shared secrets, with no error reported on either: encapsulation and decapsulation both succeeded and the recipient simply could not decrypt. The EC component is now normalised to an uncompressed point wherever the engine serialises one, which covers the ephemeral key that forms the ciphertext as well. X25519 and X448 components have a single encoding and were unaffected, as were EC keys left in their default (uncompressed) format, whose shared secrets are unchanged. CompositePublicKey.getEncoded() took its component bytes the same way, so such a key also encoded to a composite key other implementations reject and whose bytes changed across an encode / decode / encode round trip - 1238 bytes rather than 1270 for MLKEM768-ECDH-P256, and for the composite ML-DSA keys sharing that method, 2006 rather than 2038 for MLDSA65-ECDSA-P256. It now normalises the component the same way. This is a write-side change only: a composite key carrying a compressed EC component is still decoded, since the component key factories accept either form, and continues to verify signatures as before - it simply re-encodes in the normalised form. The shared normalisation is org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil.getUncompressedSubjectPublicKeyBytes.\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation threw a NullPointerException, wrapped in an IllegalStateException out of KeyGenerator.generateKey(), when the SecureRandom it was given was null - which javax.crypto.KEM.newEncapsulator() documents as a request for the provider's default, and which KeyGenerator.init(spec, null) passes straight through. The three RSA-OAEP composites draw the traditional shared secret from that random directly, so they were the ones affected; the ECDH and X25519 / X448 composites escaped only because their component KeyPairGenerators default a random of their own. CompositeMLKEMEngine now defaults one through CryptoServicesRegistrar.getSecureRandom() on first use, as the composite KEM Cipher's wrap path already did, and as the KEM generators corrected earlier in this cycle now do. Related, the engine now also clears the ML-KEM component's shared secret alongside the traditional one on both the encapsulate and decapsulate paths - the copy handed back by getEncoded() was left in the heap - as section 3.5 of draft-ietf-lamps-pq-composite-kem requires.\u003c/li\u003e\n\u003cli\u003eCompositePublicKey.getAlgorithm() and CompositePrivateKey.getAlgorithm() returned null for all twelve Composite ML-KEM (draft-ietf-lamps-pq-composite-kem) parameter sets. Both classes resolved the name through the composite signature index only, which holds the composite ML-DSA OIDs, so a composite KEM key pair - generated, parsed from a certificate, or read from PKCS#8 - reported no algorithm at all, and the standard JCA idiom of reconstructing a key with KeyFactory.getInstance(key.getAlgorithm()) raised a NullPointerException. The lookup now falls back to the composite KEM index, so the name returned is the one the provider registers the algorithm under (e.g. MLKEM768-X25519-SHA3-256), matching the composite ML-DSA behaviour. The same single-index assumption made the CompositePublicKey(SubjectPublicKeyInfo) and CompositePrivateKey(PrivateKeyInfo) constructors reject a composite KEM key with \u0026quot;unable to create CompositePublicKey from SubjectPublicKeyInfo\u0026quot;; they now dispatch to the composite KEM key factory for those OIDs. Keys obtained through KeyFactory or through BouncyCastleProvider.getPublicKey / getPrivateKey were unaffected and are unchanged (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2404\"\u003e#2404\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe org.bouncycastle.jcajce.spec.KEMKDFSpec constructor stored a null otherInfo as given, so getOtherInfo() returned null, and three of the KDF branches KdfUtil.makeKeyBytes dispatches to - KMAC-128, KMAC-256 and SHAKE-256 - read the otherInfo length without a guard and threw NullPointerException out of the KEM operation, where the KDF2, KDF3 and HKDF branches tolerate a null through KDFParameters / HKDFParameters. The Builder of every spec in the package already mapped null to empty, so no provider path reached it, but the constructor is protected on a public class and KdfUtil is documented for callers building their own KEM integration; the deprecated KEMParameterSpec passes a null itself and escaped only because it also pins the KDF to null. The constructor now stores empty for a null, so getOtherInfo() never returns null, and a null and an explicitly empty otherInfo derive the same key.\u003c/li\u003e\n\u003cli\u003eQR-UOV signature verification accepted a signature encoding that was not canonical, so the encoding of a signature was not unique even after the trailing-byte fix of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e. Each F_q element of the signature is stored in ceil(log2 q) bits, one more bit pattern than the field has elements: q itself is representable and is arithmetically congruent to zero, so an element written as q verified exactly as the same element written as zero would, and the bits padding the last element out to the byte boundary were never read at all. Every zero element of a signature therefore carried a second encoding, and for the q = 7 parameter sets roughly one element in seven is zero - a single qruov_5_q7_L10 signature measured 256 spare bits, so on the order of 2^256 distinct byte strings verified for the one message and key. Verification now rejects any element outside [0, q) and any set padding bit; a signature produced by this or by the reference implementation is unaffected, as the KAT vectors of every parameter set confirm. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSNOVA signature verification ignored four bits inside the signature for any parameter set whose solution is an odd number of GF(16) nibbles - the SNOVA_24_5_5, SNOVA_25_8_3, SNOVA_29_6_5 and SNOVA_66_15_3 families, sixteen of the forty-four parameter sets. The last byte of the encoded solution carries a single nibble and the signer leaves the top four bits zero, but the decoder did not read them, so sixteen distinct byte strings verified for one signature. This is the same non-unique encoding github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e closed for bytes following the signature, applied inside it; the verifier now requires those bits to be zero. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSnovaPrivateKeyParameters did not validate the length of the private key encoding handed to it - the only one of the five schemes of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e that did not - and SnovaParameters.getPrivateKeyLength() reported the expanded (\u0026quot;ESK\u0026quot;) length even for a parameter set whose private key is the seed pair. A private key encoding reaches this constructor straight from a PKCS#8 blob, so a wrong length went undetected: a seed-form key with extra bytes appended was accepted and signed under a different derived key, and a short expanded-form key sized the signer's decode buffer negatively, throwing NegativeArraySizeException out of generateSignature() rather than being reported at construction. Related, the signing retry loop could not terminate: the vinegar values are derived from a single-byte counter, so only 256 distinct linear systems can be tried, and an expanded-form private key that is not a real central map is singular for all of them - generateSignature() then span forever rather than failing. The length is now checked at construction, getPrivateKeyLength() reports the length that parameter set's private key actually has, and the retry loop gives up after its 256 attempts as MAYO's does.\u003c/li\u003e\n\u003cli\u003eMayoSigner and MayoKeyPairGenerator did not clear several buffers holding secret key material that the MAYO reference implementation explicitly clears. Signing left the secret oil space O, the expanded L = (P1 + P1^t) * O + P2, and the M / VPV / Ox intermediates of the central map in place, having gone to the trouble of clearing eleven other buffers; key generation left the expanded seed, whose tail is the encoded oil space, and the P1 * O + P2 half of P; and the row-echelon step left the packed echelon form of the secret linear system and its pivot rows. Separately, if all 256 attempts at solving for the signature had given a rank-deficient system, signing emitted a signature built from the failed attempt's state instead of reporting the failure the reference returns, and AIMerSigner.generateSignature returned an empty array on failure, which a caller would hand on as though it were a signature. Both now throw.\u003c/li\u003e\n\u003cli\u003eFive PQC signature schemes - MAYO, SNOVA, QR-UOV, SQIsign and AIMer - returned the NIST crypto_sign \u0026quot;sm\u0026quot; signed-message envelope from generateSignature() rather than the signature. That envelope is an artefact of the reference KAT harness, which records the message alongside the signature so a vector file can be self-contained; it is not part of any of the five specifications, and no other BC signer emits it (Falcon's KAT test rebuilds the equivalent envelope in the test, which is where it belongs). Two consequences followed, both reaching the JCA Signature services of every parameter set of the five schemes in BouncyCastlePQCProvider. First, since the message was appended to the signature, verification had to skip whatever followed the signature proper, and it did so by checking only that the buffer was long enough - so any number of trailing bytes could be added to a valid signature, or the appended message replaced with unrelated data, and it still verified. A signature encoding was therefore not unique: anyone holding one valid signature could produce unlimited distinct byte strings that all verified for the same message and key, which breaks any use that treats the signature bytes as an identifier, deduplicates on them, or records them as evidence. Second, the envelope propagated into everything built on the operator layer: because ContentSigner hands the signature straight into the structure being signed, every X.509 certificate, CRL, CMS SignedData and TLS CertificateVerify BC produced with one of these algorithms carried a verbatim copy of the signed data inside its own signature field - a self-signed MAYO-1 certificate came to 3567 bytes where the same certificate is now 2020 - which no other implementation can parse as a signature, and which in a detached CMS signature meant the \u0026quot;detached\u0026quot; signature carried the content. generateSignature() now returns the bare signature, and verifySignature() requires exactly the parameter set's signature length, so appended or truncated data is rejected rather than ignored. \u003cstrong\u003eThis is a behavioural change for signatures produced by an earlier release\u003c/strong\u003e - MAYO and SNOVA from 1.84, QR-UOV, SQIsign and AIMer from 1.85 - which are no longer accepted in the envelope form they were emitted in; the signature bytes themselves are unchanged, so a stored value can be recovered by taking the leading signature-length bytes, or for AIMer, whose envelope was message || signature rather than signature || message, the trailing ones. The KAT tests now rebuild the envelope before comparing against the vector files, which continue to record it. Note that AIMer's verification had already been made length-exact during this cycle (see the entry below relating to github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2401\"\u003e#2401\u003c/a\u003e), so of the five only its envelope remained (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe MLS implementation did not bind an X.509 credential to the LeafNode's signature_key. LeafNode.verify() checked a leaf's signature against the signature_key declared in the leaf itself, while the X.509 credential's certificate chain was stored but never parsed or checked, so the certificate's public key was never required to match signature_key (RFC 9420 sec. 5.3). A leaf could therefore carry one party's certificate while being signed by an unrelated key and still be accepted under that party's identity through KeyPackage.verify() and the Group leaf-validation path. LeafNode.verify() now requires the end-entity certificate's subject public key, in the cipher suite's signature encoding, to equal signature_key for an X.509 credential, and rejects the leaf otherwise - including an empty chain or a certificate whose key type does not match the cipher suite; certificate-chain and identity validation to a trust anchor remain the application's responsibility per RFC 9420 sec. 5.3.1. A public org.bouncycastle.mls.codec.Certificate(byte[]) constructor and a Credential.getCertificates() accessor are added so callers can build and inspect X.509 credentials. Basic credentials are unaffected.\u003c/li\u003e\n\u003cli\u003eThe SecureRandom supplied to org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder.setSecureRandom() did not drive the content IV / nonce for any algorithm other than RC2. EnvelopedDataHelper.generateParameters passed the caller's SecureRandom to the AlgorithmParameterGenerator only in the RC2_CBC branch; every other content-encryption algorithm - AES-CBC, AES-GCM, AES-CCM, Camellia, ARIA, SEED and the rest - reached pGen.generateParameters() on an uninitialised generator, so the IV / nonce was drawn from a default SecureRandom and setSecureRandom() was silently ignored (the builder's javadoc states that random is used for IV/nonce generation). The generator is now initialised with the supplied random on the general path as well, so a caller who provides a specific randomness source - for a controlled or FIPS-approved DRBG, say - has it honoured for the content IV / nonce. The session-key generation path was unaffected and already used the supplied random. Because the content IV / nonce now comes from the supplied SecureRandom, the org.bouncycastle.crypto.util JournalingSecureRandom / JournaledAlgorithm reproducible-encryption support records it in the transcript: a resumed session reproduces the IV / nonce by regenerating it from the replayed randomness - build the resuming encryptor from the content-algorithm OID - rather than by reusing the AlgorithmIdentifier captured from the first encryption, which no longer keeps the transcript aligned.\u003c/li\u003e\n\u003cli\u003eThe NTRU LPRime, NTRU+ and SMAUG-T KEM generators threw a NullPointerException when constructed with a null SecureRandom, where every other KEM generator - including NTRU LPRime's own SNTRU Prime counterpart in the same package - defaults one through CryptoServicesRegistrar.getSecureRandom(). This is reachable from the lightweight API directly, and from javax.crypto.KEM, whose newEncapsulator() documents a null random as a request for the provider's default.\u003c/li\u003e\n\u003cli\u003eFrodoKEMEngine kept a single SHAKE instance in a field, so an engine reached concurrently produced wrong results. It is reached that way through org.bouncycastle.crypto.kems.FrodoKEMExtractor, which holds one engine for its lifetime: two threads extracting through one extractor interleaved the digest's absorb and squeeze phases, yielding shared secrets that silently did not match the sender's, or an IllegalStateException of \u0026quot;attempt to absorb while squeezing\u0026quot; from inside extractSecret. The digest is now built per call, as CMCEEngine's already was, which makes an extractor safe to share. Encapsulation was unaffected, since FrodoKEMGenerator builds an engine per call. Results for any single-threaded use are unchanged - the reference KAT vectors are byte-identical.\u003c/li\u003e\n\u003cli\u003eThe BCJSSE provider carried the TLS 1.2 coupling between the supported_groups extension and ECDSA over into TLS 1.3: an ECDSA signature scheme was treated as usable - offered in the signature_algorithms and signature_algorithms_cert extensions, and eligible when selecting the local credentials - only while the corresponding curve was among the named groups enabled for key exchange, both per context (a group unavailable for key agreement disabled the scheme outright) and per connection (the curve had to be in the supported_groups list about to be sent). RFC 8446 sec. 4.2.7 scopes supported_groups to key exchange only, with signature algorithms negotiated independently (sec. 4.2.3), so this incorrect restriction in TLS 1.3 has been removed. Ed25519, Ed448 and the RSA schemes were unaffected (as well as typical deployments using a default configuration for named groups).\u003c/li\u003e\n\u003cli\u003eThe bcmail module descriptor did not declare its javax.mail/javax.activation dependences, so a modular (module-path) consumer of the jar hit IllegalAccessError/module-resolution failures when the S/MIME classes touched the mail API. The descriptor now requires them optionally (requires static) under all four module names those libraries are known by - the automatic names mail and activation carried by the javax.mail:mail / javax.activation:activation artifacts, and the explicit names java.mail and java.activation carried by the newer com.sun.mail / com.sun.activation ones - a hard requires on any one name would break users of the others (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2389\"\u003e#2389\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFour type-coercion helpers in the OER / IEEE 1609.2 (ITS) decoder tested the wrong type in the identity fast path that lets a getInstance() factory return an argument that is already of the target type. org.bouncycastle.oer.its.ieee1609dot2.basetypes.UINT32.getInstance and org.bouncycastle.oer.its.etsi102941.basetypes.Version.getInstance guarded on UINT8 - a sibling of UINT32 under UintBase, and unrelated to Version - so passing a UINT8 threw ClassCastException, while passing an actual UINT32 or Version missed the fast path and fell through to ASN1Integer.getInstance, which rejects them: neither factory accepted its own type. org.bouncycastle.oer.its.etsi103097.EtsiTs103097DataEncryptedUnicast.getInstance guarded on its sibling EtsiTs103097DataEncrypted and then cast to the unicast type, so an EtsiTs103097DataEncrypted threw ClassCastException. org.bouncycastle.oer.OEROptional.getObject(Class) called value.getClass().isInstance(type) with the arguments transposed, which is always false because the argument is a java.lang.Class, so the cast path was dead and every optional field was resolved reflectively, failing with IllegalStateException for a target type with no static getInstance. Each guard now names the type it returns, matching the sibling UINT8 / UINT16 / UINT64 and EtsiTs103097DataEncrypted factories (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2373\"\u003e#2373\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eDefaultAlgorithmNameFinder and DefaultSignatureNameFinder had no entries at all for the ShangMi algorithms, so an SM2 signature AlgorithmIdentifier that DefaultSignatureAlgorithmIdentifierFinder itself produces came back named only by its OID string - getAlgorithmName(GMObjectIdentifiers.sm2sign_with_sm3) returned \u0026quot;1.2.156.10197.1.501\u0026quot; and hasAlgorithmName returned false. Both finders now name sm2sign_with_sm3 as SM3WITHSM2 and sm2sign_with_sha256 as SHA256WITHSM2, and DefaultAlgorithmNameFinder additionally names the sm3 digest. All three resolve through the BC provider, as Signature and MessageDigest respectively. The remaining GM arc - the SM4 cipher modes, the sm2encrypt variants, and the SM1 / SM6 / SSF33 ciphers BC does not implement - is still unnamed (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2377\"\u003e#2377\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe RFC 4998 evidence-record classes compared the digest AlgorithmIdentifier named by a time-stamp authority with the one their own DigestCalculator uses, and did so with AlgorithmIdentifier.equals(), which compares the encodings. A TSA that names SHA-256 with an explicit NULL parameters field - DigiCert among them - therefore failed against BC's own calculator, which names it with the parameters absent, and ERSArchiveTimeStampGenerator.generateArchiveTimeStamp rejected the response with \u0026quot;time stamp imprint for wrong algorithm\u0026quot;. Both spellings name the same digest and RFC 5754 sec. 2 requires a receiver to accept either, while requiring that identifiers be generated with the parameters absent, which BC already does. The three affected comparisons - the two in ERSArchiveTimeStampGenerator and the digest check in ERSEvidenceRecord.renew - now use the new AlgorithmIdentifier.areEquivalent, which matches on the algorithm and treats an absent parameters field and NULL as the same, and the consistency check across an evidence record's archive time stamp chain uses it too. An identifier carrying an actual parameter structure is never equivalent to one carrying none (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2379\"\u003e#2379\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eEDIPartyName.toASN1Primitive emitted the nameAssigner and partyName DirectoryStrings without their context tags, so an EDIPartyName built through its public constructor could not be parsed back by EDIPartyName.getInstance, which correctly requires them. RFC 5280 sec. 4.2.1.6 tags both members [0] and [1], and those tags are explicit despite the module's IMPLICIT TAGS because DirectoryString is a CHOICE, which X.680 does not allow to be tagged implicitly - the decoder already had this right. The encoder now matches it. Note the type was added during the 1.85 cycle and GeneralName validates its ediPartyName alternative through it, so a GeneralName carrying an untagged ediPartyName - including one BC itself produced - is rejected where 1.84 passed it through unexamined; the untagged form is not read leniently (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2380\"\u003e#2380\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eRSASSA-PSS could not be used with a RIPEMD digest through the JCA API. Nothing registered the RIPEMD PSS signatures, so Signature.getInstance(\u0026quot;RIPEMD160WITHRSAANDMGF1\u0026quot;) raised NoSuchAlgorithmException, and the generic RSASSA-PSS route with an explicit PSSParameterSpec failed too: org.bouncycastle.jcajce.provider.util.DigestFactory.getDigest returned null for a RIPEMD name, and isSameDigest - an allow-list of the SHA families and MD5 - reported two identical RIPEMD names as different digests, so the spec was rejected with \u0026quot;digest algorithm for MGF should be the same as for PSS parameters\u0026quot;. isSameDigest now answers true for equal names whatever the digest, which also covers Whirlpool, SM3, GOST3411 and anything else outside that allow-list; DigestFactory recognises RIPEMD128, RIPEMD160 and RIPEMD256 by name and OID; the three PSS signatures are registered with MGF1 over the same digest and a salt of the digest length; and DefaultSignatureAlgorithmIdentifierFinder gains the matching RIPEMD*WITHRSAANDMGF1 entries with their RSASSA-PSS-params, so the operator/JcaContentSignerBuilder path works as well. Note BC continues to require the PSS hash and the MGF1 hash to be the same, which RFC 8017 does not itself demand (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2381\"\u003e#2381\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe opt-in key-size validation on CMS key-transport recipients (org.bouncycastle.cms.jcajce.JceKeyTransRecipient.setKeySizeValidation(true)) never ran for a message using RFC 9709 CEK derivation (id-alg-cek-hkdf-sha256): the branch that should have selected the actual content-encryption algorithm carried in the KDF AlgorithmIdentifier's parameters compared the encrypted-key byte array against the id-alg-cek-hkdf-sha256 object identifier - a comparison that is always false - so the check fell through to a key-size lookup on the outer KDF OID, which has no registered key size, and silently checked nothing. A key-transport EnvelopedData/AuthEnvelopedData whose transported (and HKDF-derived) content-encryption key did not match the key size of the advertised content-encryption algorithm was therefore accepted even with validation enabled. The recipient now dispatches on the content-encryption AlgorithmIdentifier's algorithm OID, so key-size validation of RFC 9709 messages checks the recovered key against the inner content-encryption algorithm. Messages with a matching key size, non-HKDF messages, and recipients that do not enable validation are unaffected.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003eSee full diff in \u003ca href=\"https://github.com/bcgit/bc-java/commits\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003ecommonmark-java 0.29.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e[0.29.0] - 2026-06-20\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/42b4fb7adfe288ef13e9e27ab20aff7e91b0ab9d\"\u003e\u003ccode\u003e42b4fb7\u003c/code\u003e\u003c/a\u003e Prepare CHANGELOG for version 0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/b76e09d7a8362abb5f04e1d6b91dbd6da279a6fc\"\u003e\u003ccode\u003eb76e09d\u003c/code\u003e\u003c/a\u003e Limit how deep inline nodes may nest by default (100)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/49f65cb5cbec93cff713179990307145198e7061\"\u003e\u003ccode\u003e49f65cb\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing deeply nested emphasis\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/c...\n\n_Description has been truncated_","html_url":"https://github.com/zetavue/openclaw-talk-transcript-persistence/pull/31","url":"https://dependabot.ecosyste.ms/api/v1/hosts/GitHub/repositories/zetavue%2Fopenclaw-talk-transcript-persistence/issues/31","packages_url":"https://dependabot.ecosyste.ms/api/v1/issues/31/packages"},{"uuid":"5403641597","node_id":"PR_kwDOTDg46M8AAAABC4h51A","number":30,"state":"closed","title":"build(deps): bump the android-deps group across 1 directory with 17 updates","user":"dependabot[bot]","labels":["dependencies","java"],"assignees":[],"locked":false,"comments_count":1,"pull_request":true,"closed_at":"2026-09-11T19:05:27.000Z","author_association":null,"state_reason":null,"created_at":"2026-09-09T19:08:50.000Z","updated_at":"2026-09-11T19:05:28.000Z","time_to_close":172597,"merged_at":null,"merged_by":null,"closed_by":null,"dependency_metadata":{"prefix":"build(deps): bump","group_name":"android-deps","update_count":17,"packages":[{"name":"gradle-wrapper","old_version":"9.5.1","new_version":"9.7.1","repository_url":"https://github.com/gradle/gradle"},{"name":"androidx.core:core-ktx","old_version":"1.18.0","new_version":"1.19.0"},{"name":"org.bouncycastle:bcprov-jdk18on","old_version":"1.84","new_version":"1.85.2","repository_url":"https://github.com/bcgit/bc-java"},{"name":"org.commonmark:commonmark","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-autolink","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-strikethrough","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-tables","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-task-list-items","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.junit.vintage:junit-vintage-engine","old_version":"6.1.0","new_version":"6.1.3","repository_url":"https://github.com/junit-team/junit-framework"},{"name":"io.kotest:kotest-assertions-core-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"io.kotest:kotest-runner-junit5-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"com.squareup.okhttp3:mockwebserver","old_version":"5.3.2","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.squareup.okhttp3:okhttp","old_version":"5.3.2","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.android.application","old_version":"9.2.1","new_version":"9.4.0"},{"name":"com.android.test","old_version":"9.2.1","new_version":"9.4.0"},{"name":"org.jetbrains.kotlin.plugin.compose","old_version":"2.4.0","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"},{"name":"org.jetbrains.kotlin.plugin.serialization","old_version":"2.4.0","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"}],"path":null,"ecosystem":"maven"},"body":"Bumps the android-deps group with 17 updates in the /apps/android directory:\n\n| Package | From | To |\n| --- | --- | --- |\n| [gradle-wrapper](https://github.com/gradle/gradle) | `9.5.1` | `9.7.1` |\n| androidx.core:core-ktx | `1.18.0` | `1.19.0` |\n| [org.bouncycastle:bcprov-jdk18on](https://github.com/bcgit/bc-java) | `1.84` | `1.85.2` |\n| [org.commonmark:commonmark](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-autolink](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-strikethrough](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-tables](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-task-list-items](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.junit.vintage:junit-vintage-engine](https://github.com/junit-team/junit-framework) | `6.1.0` | `6.1.3` |\n| [io.kotest:kotest-assertions-core-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [io.kotest:kotest-runner-junit5-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [com.squareup.okhttp3:mockwebserver](https://github.com/lysine-dev/okhttp) | `5.3.2` | `5.5.0` |\n| [com.squareup.okhttp3:okhttp](https://github.com/lysine-dev/okhttp) | `5.3.2` | `5.5.0` |\n| com.android.application | `9.2.1` | `9.4.0` |\n| com.android.test | `9.2.1` | `9.4.0` |\n| [org.jetbrains.kotlin.plugin.compose](https://github.com/JetBrains/kotlin) | `2.4.0` | `2.4.20` |\n| [org.jetbrains.kotlin.plugin.serialization](https://github.com/JetBrains/kotlin) | `2.4.0` | `2.4.20` |\n\n\nUpdates `gradle-wrapper` from 9.5.1 to 9.7.1\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/gradle/gradle/releases\"\u003egradle-wrapper's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e9.7.1\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.1.\u003c/p\u003e\n\u003cp\u003eThis is a patch release for 9.7.0. We recommend using 9.7.1 instead of 9.7.0.\u003c/p\u003e\n\u003cp\u003eHere are the highlights of 9.7.0 release:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIsolated Projects graduates to incubating\u003c/li\u003e\n\u003cli\u003eBroader Configuration Cache compatibility\u003c/li\u003e\n\u003cli\u003eResilient Sync helps you fix broken builds\u003c/li\u003e\n\u003cli\u003eMore source locations in problem reports\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003ca href=\"https://docs.gradle.org/9.7.1/release-notes.html\"\u003eRead the Release Notes\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eWe would like to thank the following community members for their contributions to this release of Gradle:\n\u003ca href=\"https://github.com/aSemy\"\u003eAdam\u003c/a\u003e,\n\u003ca href=\"https://github.com/Gautam-aman\"\u003eAman Gautam\u003c/a\u003e,\n\u003ca href=\"https://github.com/YukiCodepth\"\u003eAman Kumar\u003c/a\u003e,\n\u003ca href=\"https://github.com/adubrouski\"\u003eAnton Dubrouski\u003c/a\u003e,\n\u003ca href=\"https://github.com/liutikas\"\u003eAurimas\u003c/a\u003e,\n\u003ca href=\"https://github.com/gbhavya07\"\u003egbhavya07\u003c/a\u003e,\n\u003ca href=\"https://github.com/joshfriend\"\u003eJosh Friend\u003c/a\u003e,\n\u003ca href=\"https://github.com/nicklauslittle-gov\"\u003enicklauslittle-gov\u003c/a\u003e,\n\u003ca href=\"https://github.com/psoni674\"\u003ePragati\u003c/a\u003e,\n\u003ca href=\"https://github.com/Project516\"\u003eproject516\u003c/a\u003e,\n\u003ca href=\"https://github.com/Uomocapra\"\u003eQin Mi\u003c/a\u003e,\n\u003ca href=\"https://github.com/rkdfx\"\u003eRavi\u003c/a\u003e,\n\u003ca href=\"https://github.com/sk-reddy17\"\u003esk-reddy17\u003c/a\u003e,\n\u003ca href=\"https://github.com/Suvrat1629\"\u003eSuvrat Acharya\u003c/a\u003e,\n\u003ca href=\"https://github.com/ShreckYe\"\u003eYongshun Ye\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eUpgrade instructions\u003c/h2\u003e\n\u003cp\u003eSwitch your build to use Gradle 9.7.1 by updating your wrapper:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e./gradlew :wrapper --gradle-version=9.7.1 \u0026amp;\u0026amp; ./gradlew :wrapper\r\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eSee the Gradle \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/upgrading_version_9.html\"\u003e9.x upgrade guide\u003c/a\u003e to learn about deprecations, breaking changes and other considerations when upgrading.\u003c/p\u003e\n\u003cp\u003eFor Java, Groovy, Kotlin and Android compatibility, see the \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/compatibility.html\"\u003efull compatibility notes\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eReporting problems\u003c/h2\u003e\n\u003cp\u003eIf you find a problem with this release, please file a bug on \u003ca href=\"https://github.com/gradle/gradle/issues\"\u003eGitHub Issues\u003c/a\u003e adhering to our issue guidelines.\nIf you're not sure you're encountering a bug, please use the \u003ca href=\"https://discuss.gradle.org/c/help-discuss\"\u003eforum\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eWe hope you will build happiness with Gradle, and we look forward to your feedback via \u003ca href=\"https://twitter.com/gradle\"\u003eTwitter\u003c/a\u003e or on \u003ca href=\"https://github.com/gradle\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003e9.7.0\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.0.\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/92f0512e7f06d84621afba191f75e265363890cf\"\u003e\u003ccode\u003e92f0512\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38892\"\u003e#38892\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/820ee75a99a179bbffa41bcedc6477b685fabb9f\"\u003e\u003ccode\u003e820ee75\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/82c23f9bd2a89b4cc644e1f90a28a8668feb3dee\"\u003e\u003ccode\u003e82c23f9\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering problem in KTS (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38878\"\u003e#38878\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/ef11a7268fe8cc8d6ab849ec911aa11220180553\"\u003e\u003ccode\u003eef11a72\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering issue\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/bb0d8a974a71b1003efea41e4046e98855cd5ff8\"\u003e\u003ccode\u003ebb0d8a9\u003c/code\u003e\u003c/a\u003e Make relevant tests polyglot (run for multiple DSLs)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/336e129d7f95c03486acafc97abf59734acfed48\"\u003e\u003ccode\u003e336e129\u003c/code\u003e\u003c/a\u003e Update signing configuration (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38874\"\u003e#38874\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/4bdf0da2dad9884d089a6062a45ea7183e7d735d\"\u003e\u003ccode\u003e4bdf0da\u003c/code\u003e\u003c/a\u003e Update signing configuration\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/cd9b92c1b82856248cf1dc58b50378238bec7b52\"\u003e\u003ccode\u003ecd9b92c\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38839\"\u003e#38839\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/5f4e381964897ad8d6b99e5a7c77f26dba3259fb\"\u003e\u003ccode\u003e5f4e381\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/1e08ab551367aeb5fb48b26e72807e1d2b27c939\"\u003e\u003ccode\u003e1e08ab5\u003c/code\u003e\u003c/a\u003e Keep type-use annotations in extracted ABI classes (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38810\"\u003e#38810\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/gradle/gradle/compare/v9.5.1...v9.7.1\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `androidx.core:core-ktx` from 1.18.0 to 1.19.0\n\nUpdates `org.bouncycastle:bcprov-jdk18on` from 1.84 to 1.85.2\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.md\"\u003eorg.bouncycastle:bcprov-jdk18on's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch1\u003eBouncy Castle Crypto Package - Release Notes\u003c/h1\u003e\n\u003ch2\u003e1.0 Introduction\u003c/h2\u003e\n\u003cp\u003eThe Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. The package is organised so that it contains a light-weight API suitable for use in any environment (including the J2ME) with the additional infrastructure to conform the algorithms to the JCE framework.\u003c/p\u003e\n\u003ch2\u003e2.0 Release History\u003c/h2\u003e\n\u003cp\u003e\u003c!-- raw HTML omitted --\u003e\u003c!-- raw HTML omitted --\u003e\u003c/p\u003e\n\u003ch3\u003e2.1.1 Version\u003c/h3\u003e\n\u003cp\u003eRelease: 1.86\u003cbr /\u003e\nDate: 2026, TBD\u003c/p\u003e\n\u003ch3\u003e2.1.2 Defects Fixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) let a subkey inherit the primary key's Key Flags when its own Subkey Binding signature carried no Key Flags subpacket, which made the two capability decisions taken for one subkey disagree. OpenPGPCertificate.OpenPGPComponentKey.isSigningKey() reads the effective flags, which fell back to the primary key's direct-key or primary user ID self-signature, so a subkey bound with no flags of its own counted as signing-capable; verifyEmbeddedPrimaryKeyBinding reads the binding signature's own flags, found no signing capability there, and so skipped the embedded Primary Key Binding (cross-certification) signature that RFC 9580 sec. 5.2.1.8 and sec. 10.1.3 require of a subkey that can issue signatures. A data signature made by such a subkey was therefore attributed to the certificate and reported valid by OpenPGPSignature.OpenPGPDocumentSignature.isValid() with the cross-certification requirement never applied, where GnuPG refuses the same certificate and message as not cross-certified. An attacker holding a third party's public signing subkey - which is public material - could bind it to their own primary key with a Subkey Binding signature they are able to make, carrying no Key Flags and no embedded Primary Key Binding signature, which they cannot make without the subkey's private key, and have that party's genuine signatures verify as valid under the attacker's own identity: misattribution of a real signature rather than a forgery of a new one, since the signature still has to be one the subkey actually made. Key Flags are a statement about the key the carrying signature refers to (RFC 9580 sec. 5.2.3.29), so a subkey no longer inherits them from the certificate-wide signatures of the primary key: a Subkey Binding signature that omits the subpacket now leaves the subkey with no capabilities rather than the primary's, which makes the flags the cross-certification check consults the same flags every other decision consults. Preferences and the other subpackets a direct-key signature carries are inherited as before, and the primary key itself - whose flags legitimately come from its direct-key or user ID self-signature - is unaffected. The low-level PGPSignature / PGPPublicKeyRing API performs no binding checks by design and is unchanged.\u003c/li\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) used a version 6 key that carried no valid Direct Key signature, falling back to the primary user ID binding as it correctly does for a version 4 key. RFC 9580 sec. 5.2.3.10 requires the opposite: \u0026quot;An implementation MUST ensure that a valid Direct Key signature is present before using a version 6 key. This prevents certain attacks where an adversary strips a self-signature specifying a Key Expiration Time or certain preferences.\u0026quot; The certificate grammar says the same structurally, the Direct Key signature being mandatory in the version 6 structure of sec. 10.1.1 and optional in the version 4 one of sec. 10.1.3. Because a version 6 certificate carries its key expiration, features and algorithm preferences on the Direct Key signature - the convention the RFC recommends and the one OpenPGPKeyGenerator follows, its user ID certification carrying no expiration at all - removing that single signature packet from a published certificate silently dropped the expiration along with the preferences and features: OpenPGPCertificate.getSignatureChainFor fell back to the user ID binding, the primary key was still reported bound, and getEncryptionKeys() and getSigningKeys() went on returning the subkeys of a key whose owner had set it to expire. The primary key fingerprint is unchanged by the removal, so a relying party pinning the key by fingerprint still treats it as the same key, and no private key or hash collision is involved; the natural moment for the strip is the key refresh that RFC 9580 names as the reason to refetch a key at all - to learn about changes in expiration, features, preferences and revocation - which is exactly the update it defeats. This is a downgrade rather than a forgery, nothing being attributed to a key that did not authorise it, and the concerning direction is encryption, to a key meant to have been retired. OpenPGPCertificate.isBoundBy now requires a valid Direct Key self-signature on a version 6 primary key before any component of the certificate - the primary key, its subkeys or its identities - is treated as bound, so a version 6 certificate stripped of it offers no keys at all rather than an unexpiring set. Version 4 certificates are unaffected: there the key expiration legitimately lives on the user ID self-signature and the fallback is correct, so it stays. The revocation-only version 6 certificate of sec. 10.1.2, which legitimately carries no Direct Key signature, is unaffected as well - its key was already refused as revoked, and reading the revocation does not go through the binding check.\u003c/li\u003e\n\u003cli\u003eThe lightweight LMSSigner and HSSSigner refused a key wrapped in ParametersWithRandom, which is how BcContentSignerBuilder passes a key whenever setSecureRandom() has been called - so BcHssLmsContentSignerBuilder built a working signer until a random was set and then failed with \u0026quot;Incorrect Key Parameters\u0026quot;, and the two signers themselves raised ClassCastException on the same input. All three now unwrap it, as the promoted ML-DSA and SLH-DSA signers already did. The random is accepted and not used: LMS derives its message randomiser C from the key's seed and the one-time index, so it is deterministic and cannot repeat while q does not. Note SP 800-208 sec. 6.1 asks for C to come from an approved random bit generator, which this implementation does not do; that is unchanged here, and a supplied random is now ignored rather than refused.\u003c/li\u003e\n\u003cli\u003eLMS signature verification did not apply two of the checks RFC 8554 sec. 5.4.2 requires before a signature is processed. Step 2g refuses a signature whose LMS typecode is not the one from the public key, and without it the path computation took its height and tree digest from the parameter set the signature named rather than the key's, so a signature claiming a height-25 parameter set drove a 25-level computation against a height-5 key. Step 2i refuses a leaf number q outside the tree, and without it an out-of-range q flowed into the node arithmetic and was left for the candidate-root comparison to catch. Neither was a forgery - the domain separation between D_LEAF and D_INTR and the final comparison saw to that - but both are attacker-chosen work the specification says to refuse up front. Both are now checked, and a signature failing either is still reported as not verifying rather than thrown out of Signature.verify(). The catch around the signature decode in LMSSigner and HSSSigner has also been narrowed to the decode itself, as the corresponding SPI was corrected to do for github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2408\"\u003e#2408\u003c/a\u003e: past the parse the engine reports an inconsistent signature by returning false rather than by throwing, so the wider catch caught nothing while standing ready to turn a future internal error into a quiet false.\u003c/li\u003e\n\u003cli\u003eThe LMS and HSS key parameter classes now apply at construction the checks their decoders apply, so a key built directly cannot be one the decoder would refuse. LMSPrivateKeyParameters accepted an identifier of any length although the decoder reads exactly 16 bytes - such a key encoded but could not be read back - and left q, maxQ and the seed length unchecked; the seed is now required to be at least m bytes at decode as well, where a one-byte seed had been decoding silently and then deriving every one-time key from it. HSSPrivateKeyParameters checked neither its level count nor that it had been given a component key per level and a chaining signature per level below the root, and then indexed both lists, so a mismatch surfaced as IndexOutOfBoundsException - or, where a level happened to match, as a null chaining signature that only failed at signing time; the level is now checked after the reset that fills it in, since a null is legitimate on the way in. LMSPrivateKeyParameters.getInstance(byte[], byte[]) adopted the public key supplied beside the private one without comparing them, so a mismatched public key was simply reported by getPublicKey(); it now cross-checks the identifier, both parameter sets and, where the tree cache already holds it, the root, as the HSS entry point does. The decoders also now report a bad version or seed length as IOException rather than IllegalStateException, so a caller can catch one type for a malformed key, and the package-private LM-OTS public key decoder no longer declares throws Exception or dereferences an unrecognised typecode. The deprecated org.bouncycastle.pqc.crypto.lms copies carry the decoder corrections.\u003c/li\u003e\n\u003cli\u003eIn the LMS JCE layer, LMSKeyGenParameterSpec.fromNames knew all twenty LMS parameter-set names but only four of the sixteen LM-OTS ones, so none of the SP 800-208 n24 or SHAKE sets could be named; all sixteen are now present. KeyPairGenerator.initialize(int, SecureRandom) reports InvalidParameterException, which is what the JCA specifies and which extends the IllegalArgumentException it raised before, so existing catches still match. BCLMSPrivateKey.getIndex now takes the exhaustion check and the index read under the key's own monitor rather than as two separate calls, and two unused fields have gone from LMSSignatureSpi. Note that the LMS Signature claims its one-time key at the first update() rather than at sign(), so a Signature that is initialised and updated and then abandoned spends an index without producing a signature - the safe direction for a one-time scheme, and now documented on the SPI.\u003c/li\u003e\n\u003cli\u003eEvery other key pair generator that refuses a key size did the same thing the LMS one did above. KeyPairGenerator.initialize(int, SecureRandom) is documented to raise InvalidParameterException when the key size is not one the generator supports, and thirty of them raised a bare IllegalArgumentException instead, so a caller following the JCA and catching the documented type saw an exception escaping rather than a refusal. The ML-DSA, ML-KEM, SLH-DSA, Classic McEliece, FrodoKEM, NTRU and composite signature and KEM generators in the BC provider, and every generator in BCPQC, now raise InvalidParameterException - NewHope included, where the value is a key size it will not take rather than a mode of initialisation it does not offer. InvalidParameterException extends IllegalArgumentException, so callers written against the old behaviour go on catching it unchanged. The two RSA generators are corrected as well, and differently: theirs is a key size below a floor rather than a mode of initialisation they do not offer, and the refusal is raised by the lightweight RSAKeyGenerationParameters, which cannot name a java.security exception at all, so the RSA KeyPairGeneratorSpi now translates it - keeping the message verbatim and the original exception as the cause, through a new SecurityExceptions.invalidParameterException factory, since InvalidParameterException has no constructor that takes one. Of the 304 KeyPairGenerator services the two providers register, 299 now refuse a nonsense key size the way the JCA defines it and five accept it as a strength they can work with, with none left raising a bare IllegalArgumentException; that is asserted as a sweep over both providers rather than per algorithm, so a generator added later is covered without the test being touched. The jdk1.3 provider overlays of the four generators that have one carry the same change, and the jdk1.3 SecurityExceptions overlay gains the new factory along with the invalidAlgorithmParameterException one it had been missing.\u003c/li\u003e\n\u003cli\u003eKeyPairGenerator.initialize(AlgorithmParameterSpec, SecureRandom) had the same shape of problem as the int overload above, and only 44 of the 304 services the two providers register reported an unusable spec as the InvalidAlgorithmParameterException that method declares. The twenty-three PQC generators that resolve a parameter set by name - cmce, frodokem, mldsa, mlkem, slhdsa, aimer, bike, faest, falcon, haetae, hqc, mayo, mqom, ntru, ntruplus, both ntruprime variants, qruov, saber, sdith, smaugt, snova and sqisign, 230 services between them - case-folded the name they got back from the spec without checking it, so a spec with no getName() method, and a null spec, produced a NullPointerException from inside the fold; their own \u0026quot;is this name one I know\u0026quot; branch, which does report the declared exception, was unreachable. The two composite generators, whose parameter set is fixed by the algorithm name so that null is the only spec they accept, refused every other one with IllegalArgumentException. RSA answered correctly for a spec of the wrong type but not for one of the right type carrying values its lightweight parameters will not take - an even public exponent, or a key size below the floor - which is now translated the same way the int overload's is. All 304 services now report the declared exception, with the composites still taking the null spec that is right for them; note that InvalidAlgorithmParameterException is a checked exception and not an IllegalArgumentException, so a caller that was catching what these threw before has to catch the declared type instead.\u003c/li\u003e\n\u003cli\u003eAn HSS private key claimed the two records of its position under two different monitors. The top-level index and the bottom component key's one-time index q are independent records of the same position - the decoder requires them to agree, see the entry below - but generateLMSContext incremented the index under the HSS key's own monitor, released it, and only then claimed q under the component key's. A getEncoded() issued in between saw the index advanced and q not, and produced an encoding this implementation's own decoder rejects; and two threads meeting at a bottom-tree boundary could both pass the exhaustion test, take consecutive top-level indices and claim the same q, after which one of them was refused with \u0026quot;ots private key exhausted\u0026quot; by a key still reporting usages remaining, a top-level index had been spent with no signature made, and the two records stayed one apart for the rest of the key's life in that process - so it could no longer be encoded, cloned or sharded, and getIndex() and getUsagesRemaining() misreported by one. No one-time key was reused: the component key's claim is itself atomic, and the divergence runs index ahead of leaves, so the effect was on the key's usability rather than on the signatures it had made. Both records are now claimed under the one monitor, and the component key is claimed before the index is incremented so that an exhausted one leaves both untouched. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the same correction.\u003c/li\u003e\n\u003cli\u003eTimeStampToken parsed the attacker-controlled TSTInfo content of a time-stamp token (org.bouncycastle.tsp.TimeStampToken, reached from TimeStampResponse(byte[]) and (InputStream)) inside a try that caught only CMSException, so a well-formed RFC 3161 TimeStampResp whose embedded token carried a malformed TSTInfo - a SEQUENCE with fewer elements than the five mandatory fields, a non-SEQUENCE, truncated DER, or an unknown context tag - let an IllegalArgumentException or a NoSuchElementException escape the constructor's declared throws TSPException, IOException contract. A token signed by no signers or by more than one raised a bare IllegalArgumentException from the same constructor, before that try, for the same reason. Both are now reported as TSPException, matching the package-private TimeStampResponse(DLSequence) constructor and the existing getSignedAttributes guard in the same method; the signer-count refusal is a TSPValidationException, as the neighbouring check on the content type already was. Related, and the cause of the NoSuchElementException: asn1.tsp.TSTInfo read its five mandatory fields off the sequence with no bound on how many elements were actually there, so a short SEQUENCE left the enumeration to run out rather than being refused, and an oversize one was accepted with its extra elements absorbed into the optional slots. Decode now requires the five to ten elements RFC 3161 sec. 2.4.2 gives the type, which is what the sibling Accuracy and ArchiveTimeStamp decoders already did, so the failure is the IllegalArgumentException that getInstance is expected to raise (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2415\"\u003e#2415\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eNeither the HSS nor the XMSS^MT private key decoder checked its declared index against the traversal state stored beside it, although the two are independent records of the same position in the key and so can be compared. For HSS the records are the top-level index and the component keys' one-time indices q; for XMSS^MT they are the global index and the per-layer BDS states. A stored key whose index had been rolled back while its state stayed advanced - a partial write, a restore from backup, a buggy storage layer - was therefore accepted, and it then signed a second message under a one-time key the key had already used, producing a signature that verified, so nothing anywhere surfaced the reuse. RFC 8554 sec. 1 and RFC 8391 sec. 1.1 both require each one-time key to be used exactly once, and this is the failure those requirements exist to prevent; the single-tree XMSS decoder has tied its BDS state to its index since that state was first validated, and this brings the two multi-tree schemes into line. HSS decode now requires the declared index to equal the position the component q values imply - a level above the last contributes (q - 1) leaves of the levels beneath it, since its q has already advanced past the subtree it signed - and XMSS^MT decode now requires each present layer's BDS index to equal the leaf index that layer derives from the global index, allowing the one position where a layer has moved into a new subtree and its state legitimately still carries the previous subtree's final index. A layer with no state yet is unaffected, since those are built lazily at signing time. Related, and the same shape of omission: an XMSS or XMSS^MT private key encoding carries the tree root twice - the key's own root field and the root node of the BDS state stored beside it, which for XMSS^MT is the top layer's - and the two were never compared either. A corrupted root was accepted and then poisoned every signature the key made, because the root is hashed into the message digest: the signature did not verify and nothing indicated why. Decode now requires the two copies to agree. The BDS node values themselves are not checkable the way the LMS tree cache above is - a BDS authentication path, stack, retain or keep node does not have its children stored alongside it, so recomputing one means building a subtree, which is the work the state exists to avoid. Both checks are integer comparisons over the levels of the key, too small to measure against the surrounding decode, and both were verified not to reject any legitimate key by walking every index a key can reach: the full key space of the two-level HSS and the h=4/d=2, h=6/d=2, h=6/d=3, h=9/d=3 and h=8/d=4 XMSS^MT parameter sets, plus a three-level HSS key across a subtree boundary and an HSS shard. Since those node values cannot be recomputed, the encoded state now carries a checksum over itself instead, with the owning key's public seed hashed in front of it. Any corruption of the stored state is refused at decode rather than being loaded and then producing signatures that silently do not verify, and because the public seed is bound in, a state transplanted between two keys of the same parameter set is refused too, even though it is internally consistent and arrives with its own matching root. The public seed is bound rather than the secret seed or the PRF key deliberately: the state's own root and index are inside the encoding and so are already covered, hashing secret material would make the stored checksum a commitment to it for no gain in detection, and the PRF key does not influence the state at all. \u003cstrong\u003eThis is an error-detecting code and not integrity protection\u003c/strong\u003e - anyone able to rewrite the stored key recomputes it, so it establishes that the state is unchanged since it was written, never that it was correct when written, and the allocation bounds on the encoding remain the guard against a crafted one. It costs one SHA-256 over the state, measured at 5 to 8 microseconds each way for the h=10 and h=16 parameter sets, and 32 bytes of encoding. The state encoding was added earlier in this same cycle and has not been released, so the checksum is simply part of it rather than a new version: a state written by a 1.86 beta is rejected, which is recovered from by re-exporting the key. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the HSS check as well (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2414\"\u003e#2414\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe S/MIME example smoke test in the misc module (org.bouncycastle.mail.smime.examples.test.AllTests) drove SendSignedAndEncryptedMail against smtp.gmail.com, and that example finishes with Transport.send() under JavaMail's default settings, which have no connect timeout. Where outbound port 25 is refused the failure was swallowed and the test passed; where it is silently dropped, as on many home networks, the connect blocked and ./gradlew build hung in :misc:test indefinitely with \u0026quot;0 tests completed\u0026quot;. The test now delivers to an SMTP stub on a loopback port, with connect / read / write timeouts as a backstop, and asserts the message arrived (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2407\"\u003e#2407\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation took the traditional component public key bytes it feeds the KEM combiner from the recipient key's own encoding, while decapsulation recomputes the point from the private key and so always produced an uncompressed one. Section 4 of draft-ietf-lamps-pq-composite-kem requires an EC component to be carried as an uncompressed point, but a component key that encodes itself compressed - a BC EC key whose point format has been set through org.bouncycastle.jce.interfaces.ECPointEncoder, or a key from a provider that preserves a compressed encoding - was passed through as it came. Both sides then combined a different tradPK and derived different shared secrets, with no error reported on either: encapsulation and decapsulation both succeeded and the recipient simply could not decrypt. The EC component is now normalised to an uncompressed point wherever the engine serialises one, which covers the ephemeral key that forms the ciphertext as well. X25519 and X448 components have a single encoding and were unaffected, as were EC keys left in their default (uncompressed) format, whose shared secrets are unchanged. CompositePublicKey.getEncoded() took its component bytes the same way, so such a key also encoded to a composite key other implementations reject and whose bytes changed across an encode / decode / encode round trip - 1238 bytes rather than 1270 for MLKEM768-ECDH-P256, and for the composite ML-DSA keys sharing that method, 2006 rather than 2038 for MLDSA65-ECDSA-P256. It now normalises the component the same way. This is a write-side change only: a composite key carrying a compressed EC component is still decoded, since the component key factories accept either form, and continues to verify signatures as before - it simply re-encodes in the normalised form. The shared normalisation is org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil.getUncompressedSubjectPublicKeyBytes.\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation threw a NullPointerException, wrapped in an IllegalStateException out of KeyGenerator.generateKey(), when the SecureRandom it was given was null - which javax.crypto.KEM.newEncapsulator() documents as a request for the provider's default, and which KeyGenerator.init(spec, null) passes straight through. The three RSA-OAEP composites draw the traditional shared secret from that random directly, so they were the ones affected; the ECDH and X25519 / X448 composites escaped only because their component KeyPairGenerators default a random of their own. CompositeMLKEMEngine now defaults one through CryptoServicesRegistrar.getSecureRandom() on first use, as the composite KEM Cipher's wrap path already did, and as the KEM generators corrected earlier in this cycle now do. Related, the engine now also clears the ML-KEM component's shared secret alongside the traditional one on both the encapsulate and decapsulate paths - the copy handed back by getEncoded() was left in the heap - as section 3.5 of draft-ietf-lamps-pq-composite-kem requires.\u003c/li\u003e\n\u003cli\u003eCompositePublicKey.getAlgorithm() and CompositePrivateKey.getAlgorithm() returned null for all twelve Composite ML-KEM (draft-ietf-lamps-pq-composite-kem) parameter sets. Both classes resolved the name through the composite signature index only, which holds the composite ML-DSA OIDs, so a composite KEM key pair - generated, parsed from a certificate, or read from PKCS#8 - reported no algorithm at all, and the standard JCA idiom of reconstructing a key with KeyFactory.getInstance(key.getAlgorithm()) raised a NullPointerException. The lookup now falls back to the composite KEM index, so the name returned is the one the provider registers the algorithm under (e.g. MLKEM768-X25519-SHA3-256), matching the composite ML-DSA behaviour. The same single-index assumption made the CompositePublicKey(SubjectPublicKeyInfo) and CompositePrivateKey(PrivateKeyInfo) constructors reject a composite KEM key with \u0026quot;unable to create CompositePublicKey from SubjectPublicKeyInfo\u0026quot;; they now dispatch to the composite KEM key factory for those OIDs. Keys obtained through KeyFactory or through BouncyCastleProvider.getPublicKey / getPrivateKey were unaffected and are unchanged (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2404\"\u003e#2404\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe org.bouncycastle.jcajce.spec.KEMKDFSpec constructor stored a null otherInfo as given, so getOtherInfo() returned null, and three of the KDF branches KdfUtil.makeKeyBytes dispatches to - KMAC-128, KMAC-256 and SHAKE-256 - read the otherInfo length without a guard and threw NullPointerException out of the KEM operation, where the KDF2, KDF3 and HKDF branches tolerate a null through KDFParameters / HKDFParameters. The Builder of every spec in the package already mapped null to empty, so no provider path reached it, but the constructor is protected on a public class and KdfUtil is documented for callers building their own KEM integration; the deprecated KEMParameterSpec passes a null itself and escaped only because it also pins the KDF to null. The constructor now stores empty for a null, so getOtherInfo() never returns null, and a null and an explicitly empty otherInfo derive the same key.\u003c/li\u003e\n\u003cli\u003eQR-UOV signature verification accepted a signature encoding that was not canonical, so the encoding of a signature was not unique even after the trailing-byte fix of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e. Each F_q element of the signature is stored in ceil(log2 q) bits, one more bit pattern than the field has elements: q itself is representable and is arithmetically congruent to zero, so an element written as q verified exactly as the same element written as zero would, and the bits padding the last element out to the byte boundary were never read at all. Every zero element of a signature therefore carried a second encoding, and for the q = 7 parameter sets roughly one element in seven is zero - a single qruov_5_q7_L10 signature measured 256 spare bits, so on the order of 2^256 distinct byte strings verified for the one message and key. Verification now rejects any element outside [0, q) and any set padding bit; a signature produced by this or by the reference implementation is unaffected, as the KAT vectors of every parameter set confirm. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSNOVA signature verification ignored four bits inside the signature for any parameter set whose solution is an odd number of GF(16) nibbles - the SNOVA_24_5_5, SNOVA_25_8_3, SNOVA_29_6_5 and SNOVA_66_15_3 families, sixteen of the forty-four parameter sets. The last byte of the encoded solution carries a single nibble and the signer leaves the top four bits zero, but the decoder did not read them, so sixteen distinct byte strings verified for one signature. This is the same non-unique encoding github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e closed for bytes following the signature, applied inside it; the verifier now requires those bits to be zero. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSnovaPrivateKeyParameters did not validate the length of the private key encoding handed to it - the only one of the five schemes of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e that did not - and SnovaParameters.getPrivateKeyLength() reported the expanded (\u0026quot;ESK\u0026quot;) length even for a parameter set whose private key is the seed pair. A private key encoding reaches this constructor straight from a PKCS#8 blob, so a wrong length went undetected: a seed-form key with extra bytes appended was accepted and signed under a different derived key, and a short expanded-form key sized the signer's decode buffer negatively, throwing NegativeArraySizeException out of generateSignature() rather than being reported at construction. Related, the signing retry loop could not terminate: the vinegar values are derived from a single-byte counter, so only 256 distinct linear systems can be tried, and an expanded-form private key that is not a real central map is singular for all of them - generateSignature() then span forever rather than failing. The length is now checked at construction, getPrivateKeyLength() reports the length that parameter set's private key actually has, and the retry loop gives up after its 256 attempts as MAYO's does.\u003c/li\u003e\n\u003cli\u003eMayoSigner and MayoKeyPairGenerator did not clear several buffers holding secret key material that the MAYO reference implementation explicitly clears. Signing left the secret oil space O, the expanded L = (P1 + P1^t) * O + P2, and the M / VPV / Ox intermediates of the central map in place, having gone to the trouble of clearing eleven other buffers; key generation left the expanded seed, whose tail is the encoded oil space, and the P1 * O + P2 half of P; and the row-echelon step left the packed echelon form of the secret linear system and its pivot rows. Separately, if all 256 attempts at solving for the signature had given a rank-deficient system, signing emitted a signature built from the failed attempt's state instead of reporting the failure the reference returns, and AIMerSigner.generateSignature returned an empty array on failure, which a caller would hand on as though it were a signature. Both now throw.\u003c/li\u003e\n\u003cli\u003eFive PQC signature schemes - MAYO, SNOVA, QR-UOV, SQIsign and AIMer - returned the NIST crypto_sign \u0026quot;sm\u0026quot; signed-message envelope from generateSignature() rather than the signature. That envelope is an artefact of the reference KAT harness, which records the message alongside the signature so a vector file can be self-contained; it is not part of any of the five specifications, and no other BC signer emits it (Falcon's KAT test rebuilds the equivalent envelope in the test, which is where it belongs). Two consequences followed, both reaching the JCA Signature services of every parameter set of the five schemes in BouncyCastlePQCProvider. First, since the message was appended to the signature, verification had to skip whatever followed the signature proper, and it did so by checking only that the buffer was long enough - so any number of trailing bytes could be added to a valid signature, or the appended message replaced with unrelated data, and it still verified. A signature encoding was therefore not unique: anyone holding one valid signature could produce unlimited distinct byte strings that all verified for the same message and key, which breaks any use that treats the signature bytes as an identifier, deduplicates on them, or records them as evidence. Second, the envelope propagated into everything built on the operator layer: because ContentSigner hands the signature straight into the structure being signed, every X.509 certificate, CRL, CMS SignedData and TLS CertificateVerify BC produced with one of these algorithms carried a verbatim copy of the signed data inside its own signature field - a self-signed MAYO-1 certificate came to 3567 bytes where the same certificate is now 2020 - which no other implementation can parse as a signature, and which in a detached CMS signature meant the \u0026quot;detached\u0026quot; signature carried the content. generateSignature() now returns the bare signature, and verifySignature() requires exactly the parameter set's signature length, so appended or truncated data is rejected rather than ignored. \u003cstrong\u003eThis is a behavioural change for signatures produced by an earlier release\u003c/strong\u003e - MAYO and SNOVA from 1.84, QR-UOV, SQIsign and AIMer from 1.85 - which are no longer accepted in the envelope form they were emitted in; the signature bytes themselves are unchanged, so a stored value can be recovered by taking the leading signature-length bytes, or for AIMer, whose envelope was message || signature rather than signature || message, the trailing ones. The KAT tests now rebuild the envelope before comparing against the vector files, which continue to record it. Note that AIMer's verification had already been made length-exact during this cycle (see the entry below relating to github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2401\"\u003e#2401\u003c/a\u003e), so of the five only its envelope remained (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe MLS implementation did not bind an X.509 credential to the LeafNode's signature_key. LeafNode.verify() checked a leaf's signature against the signature_key declared in the leaf itself, while the X.509 credential's certificate chain was stored but never parsed or checked, so the certificate's public key was never required to match signature_key (RFC 9420 sec. 5.3). A leaf could therefore carry one party's certificate while being signed by an unrelated key and still be accepted under that party's identity through KeyPackage.verify() and the Group leaf-validation path. LeafNode.verify() now requires the end-entity certificate's subject public key, in the cipher suite's signature encoding, to equal signature_key for an X.509 credential, and rejects the leaf otherwise - including an empty chain or a certificate whose key type does not match the cipher suite; certificate-chain and identity validation to a trust anchor remain the application's responsibility per RFC 9420 sec. 5.3.1. A public org.bouncycastle.mls.codec.Certificate(byte[]) constructor and a Credential.getCertificates() accessor are added so callers can build and inspect X.509 credentials. Basic credentials are unaffected.\u003c/li\u003e\n\u003cli\u003eThe SecureRandom supplied to org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder.setSecureRandom() did not drive the content IV / nonce for any algorithm other than RC2. EnvelopedDataHelper.generateParameters passed the caller's SecureRandom to the AlgorithmParameterGenerator only in the RC2_CBC branch; every other content-encryption algorithm - AES-CBC, AES-GCM, AES-CCM, Camellia, ARIA, SEED and the rest - reached pGen.generateParameters() on an uninitialised generator, so the IV / nonce was drawn from a default SecureRandom and setSecureRandom() was silently ignored (the builder's javadoc states that random is used for IV/nonce generation). The generator is now initialised with the supplied random on the general path as well, so a caller who provides a specific randomness source - for a controlled or FIPS-approved DRBG, say - has it honoured for the content IV / nonce. The session-key generation path was unaffected and already used the supplied random. Because the content IV / nonce now comes from the supplied SecureRandom, the org.bouncycastle.crypto.util JournalingSecureRandom / JournaledAlgorithm reproducible-encryption support records it in the transcript: a resumed session reproduces the IV / nonce by regenerating it from the replayed randomness - build the resuming encryptor from the content-algorithm OID - rather than by reusing the AlgorithmIdentifier captured from the first encryption, which no longer keeps the transcript aligned.\u003c/li\u003e\n\u003cli\u003eThe NTRU LPRime, NTRU+ and SMAUG-T KEM generators threw a NullPointerException when constructed with a null SecureRandom, where every other KEM generator - including NTRU LPRime's own SNTRU Prime counterpart in the same package - defaults one through CryptoServicesRegistrar.getSecureRandom(). This is reachable from the lightweight API directly, and from javax.crypto.KEM, whose newEncapsulator() documents a null random as a request for the provider's default.\u003c/li\u003e\n\u003cli\u003eFrodoKEMEngine kept a single SHAKE instance in a field, so an engine reached concurrently produced wrong results. It is reached that way through org.bouncycastle.crypto.kems.FrodoKEMExtractor, which holds one engine for its lifetime: two threads extracting through one extractor interleaved the digest's absorb and squeeze phases, yielding shared secrets that silently did not match the sender's, or an IllegalStateException of \u0026quot;attempt to absorb while squeezing\u0026quot; from inside extractSecret. The digest is now built per call, as CMCEEngine's already was, which makes an extractor safe to share. Encapsulation was unaffected, since FrodoKEMGenerator builds an engine per call. Results for any single-threaded use are unchanged - the reference KAT vectors are byte-identical.\u003c/li\u003e\n\u003cli\u003eThe BCJSSE provider carried the TLS 1.2 coupling between the supported_groups extension and ECDSA over into TLS 1.3: an ECDSA signature scheme was treated as usable - offered in the signature_algorithms and signature_algorithms_cert extensions, and eligible when selecting the local credentials - only while the corresponding curve was among the named groups enabled for key exchange, both per context (a group unavailable for key agreement disabled the scheme outright) and per connection (the curve had to be in the supported_groups list about to be sent). RFC 8446 sec. 4.2.7 scopes supported_groups to key exchange only, with signature algorithms negotiated independently (sec. 4.2.3), so this incorrect restriction in TLS 1.3 has been removed. Ed25519, Ed448 and the RSA schemes were unaffected (as well as typical deployments using a default configuration for named groups).\u003c/li\u003e\n\u003cli\u003eThe bcmail module descriptor did not declare its javax.mail/javax.activation dependences, so a modular (module-path) consumer of the jar hit IllegalAccessError/module-resolution failures when the S/MIME classes touched the mail API. The descriptor now requires them optionally (requires static) under all four module names those libraries are known by - the automatic names mail and activation carried by the javax.mail:mail / javax.activation:activation artifacts, and the explicit names java.mail and java.activation carried by the newer com.sun.mail / com.sun.activation ones - a hard requires on any one name would break users of the others (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2389\"\u003e#2389\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFour type-coercion helpers in the OER / IEEE 1609.2 (ITS) decoder tested the wrong type in the identity fast path that lets a getInstance() factory return an argument that is already of the target type. org.bouncycastle.oer.its.ieee1609dot2.basetypes.UINT32.getInstance and org.bouncycastle.oer.its.etsi102941.basetypes.Version.getInstance guarded on UINT8 - a sibling of UINT32 under UintBase, and unrelated to Version - so passing a UINT8 threw ClassCastException, while passing an actual UINT32 or Version missed the fast path and fell through to ASN1Integer.getInstance, which rejects them: neither factory accepted its own type. org.bouncycastle.oer.its.etsi103097.EtsiTs103097DataEncryptedUnicast.getInstance guarded on its sibling EtsiTs103097DataEncrypted and then cast to the unicast type, so an EtsiTs103097DataEncrypted threw ClassCastException. org.bouncycastle.oer.OEROptional.getObject(Class) called value.getClass().isInstance(type) with the arguments transposed, which is always false because the argument is a java.lang.Class, so the cast path was dead and every optional field was resolved reflectively, failing with IllegalStateException for a target type with no static getInstance. Each guard now names the type it returns, matching the sibling UINT8 / UINT16 / UINT64 and EtsiTs103097DataEncrypted factories (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2373\"\u003e#2373\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eDefaultAlgorithmNameFinder and DefaultSignatureNameFinder had no entries at all for the ShangMi algorithms, so an SM2 signature AlgorithmIdentifier that DefaultSignatureAlgorithmIdentifierFinder itself produces came back named only by its OID string - getAlgorithmName(GMObjectIdentifiers.sm2sign_with_sm3) returned \u0026quot;1.2.156.10197.1.501\u0026quot; and hasAlgorithmName returned false. Both finders now name sm2sign_with_sm3 as SM3WITHSM2 and sm2sign_with_sha256 as SHA256WITHSM2, and DefaultAlgorithmNameFinder additionally names the sm3 digest. All three resolve through the BC provider, as Signature and MessageDigest respectively. The remaining GM arc - the SM4 cipher modes, the sm2encrypt variants, and the SM1 / SM6 / SSF33 ciphers BC does not implement - is still unnamed (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2377\"\u003e#2377\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe RFC 4998 evidence-record classes compared the digest AlgorithmIdentifier named by a time-stamp authority with the one their own DigestCalculator uses, and did so with AlgorithmIdentifier.equals(), which compares the encodings. A TSA that names SHA-256 with an explicit NULL parameters field - DigiCert among them - therefore failed against BC's own calculator, which names it with the parameters absent, and ERSArchiveTimeStampGenerator.generateArchiveTimeStamp rejected the response with \u0026quot;time stamp imprint for wrong algorithm\u0026quot;. Both spellings name the same digest and RFC 5754 sec. 2 requires a receiver to accept either, while requiring that identifiers be generated with the parameters absent, which BC already does. The three affected comparisons - the two in ERSArchiveTimeStampGenerator and the digest check in ERSEvidenceRecord.renew - now use the new AlgorithmIdentifier.areEquivalent, which matches on the algorithm and treats an absent parameters field and NULL as the same, and the consistency check across an evidence record's archive time stamp chain uses it too. An identifier carrying an actual parameter structure is never equivalent to one carrying none (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2379\"\u003e#2379\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eEDIPartyName.toASN1Primitive emitted the nameAssigner and partyName DirectoryStrings without their context tags, so an EDIPartyName built through its public constructor could not be parsed back by EDIPartyName.getInstance, which correctly requires them. RFC 5280 sec. 4.2.1.6 tags both members [0] and [1], and those tags are explicit despite the module's IMPLICIT TAGS because DirectoryString is a CHOICE, which X.680 does not allow to be tagged implicitly - the decoder already had this right. The encoder now matches it. Note the type was added during the 1.85 cycle and GeneralName validates its ediPartyName alternative through it, so a GeneralName carrying an untagged ediPartyName - including one BC itself produced - is rejected where 1.84 passed it through unexamined; the untagged form is not read leniently (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2380\"\u003e#2380\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eRSASSA-PSS could not be used with a RIPEMD digest through the JCA API. Nothing registered the RIPEMD PSS signatures, so Signature.getInstance(\u0026quot;RIPEMD160WITHRSAANDMGF1\u0026quot;) raised NoSuchAlgorithmException, and the generic RSASSA-PSS route with an explicit PSSParameterSpec failed too: org.bouncycastle.jcajce.provider.util.DigestFactory.getDigest returned null for a RIPEMD name, and isSameDigest - an allow-list of the SHA families and MD5 - reported two identical RIPEMD names as different digests, so the spec was rejected with \u0026quot;digest algorithm for MGF should be the same as for PSS parameters\u0026quot;. isSameDigest now answers true for equal names whatever the digest, which also covers Whirlpool, SM3, GOST3411 and anything else outside that allow-list; DigestFactory recognises RIPEMD128, RIPEMD160 and RIPEMD256 by name and OID; the three PSS signatures are registered with MGF1 over the same digest and a salt of the digest length; and DefaultSignatureAlgorithmIdentifierFinder gains the matching RIPEMD*WITHRSAANDMGF1 entries with their RSASSA-PSS-params, so the operator/JcaContentSignerBuilder path works as well. Note BC continues to require the PSS hash and the MGF1 hash to be the same, which RFC 8017 does not itself demand (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2381\"\u003e#2381\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe opt-in key-size validation on CMS key-transport recipients (org.bouncycastle.cms.jcajce.JceKeyTransRecipient.setKeySizeValidation(true)) never ran for a message using RFC 9709 CEK derivation (id-alg-cek-hkdf-sha256): the branch that should have selected the actual content-encryption algorithm carried in the KDF AlgorithmIdentifier's parameters compared the encrypted-key byte array against the id-alg-cek-hkdf-sha256 object identifier - a comparison that is always false - so the check fell through to a key-size lookup on the outer KDF OID, which has no registered key size, and silently checked nothing. A key-transport EnvelopedData/AuthEnvelopedData whose transported (and HKDF-derived) content-encryption key did not match the key size of the advertised content-encryption algorithm was therefore accepted even with validation enabled. The recipient now dispatches on the content-encryption AlgorithmIdentifier's algorithm OID, so key-size validation of RFC 9709 messages checks the recovered key against the inner content-encryption algorithm. Messages with a matching key size, non-HKDF messages, and recipients that do not enable validation are unaffected.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003eSee full diff in \u003ca href=\"https://github.com/bcgit/bc-java/commits\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003ecommonmark-java 0.29.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e[0.29.0] - 2026-06-20\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/42b4fb7adfe288ef13e9e27ab20aff7e91b0ab9d\"\u003e\u003ccode\u003e42b4fb7\u003c/code\u003e\u003c/a\u003e Prepare CHANGELOG for version 0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/b76e09d7a8362abb5f04e1d6b91dbd6da279a6fc\"\u003e\u003ccode\u003eb76e09d\u003c/code\u003e\u003c/a\u003e Limit how deep inline nodes may nest by default (100)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/49f65cb5cbec93cff713179990307145198e7061\"\u003e\u003ccode\u003e49f65cb\u003c/code\u003e\u003c/a\u003e Fix StackOverflowEr...\n\n_Description has been truncated_","html_url":"https://github.com/SpaceX-mit/openclaw-handbook/pull/30","url":"https://dependabot.ecosyste.ms/api/v1/hosts/GitHub/repositories/SpaceX-mit%2Fopenclaw-handbook/issues/30","packages_url":"https://dependabot.ecosyste.ms/api/v1/issues/30/packages"},{"uuid":"5403242676","node_id":"PR_kwDOS-Nvx88AAAABC4NQFQ","number":42,"state":"closed","title":"chore(deps): bump the android-deps group across 1 directory with 21 updates","user":"dependabot[bot]","labels":["dependencies","java"],"assignees":[],"locked":false,"comments_count":1,"pull_request":true,"closed_at":"2026-09-11T18:25:43.000Z","author_association":null,"state_reason":null,"created_at":"2026-09-09T18:27:01.000Z","updated_at":"2026-09-11T18:25:44.000Z","time_to_close":172722,"merged_at":null,"merged_by":null,"closed_by":null,"dependency_metadata":{"prefix":"chore(deps): bump","group_name":"android-deps","update_count":21,"packages":[{"name":"gradle-wrapper","old_version":"9.4.1","new_version":"9.7.1","repository_url":"https://github.com/gradle/gradle"},{"name":"androidx.core:core-ktx","old_version":"1.18.0","new_version":"1.19.0"},{"name":"org.bouncycastle:bcprov-jdk18on","old_version":"1.84","new_version":"1.85.2","repository_url":"https://github.com/bcgit/bc-java"},{"name":"org.commonmark:commonmark","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-autolink","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-strikethrough","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-tables","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-task-list-items","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"dnsjava:dnsjava","old_version":"3.6.4","new_version":"3.6.5","repository_url":"https://github.com/dnsjava/dnsjava"},{"name":"org.junit.vintage:junit-vintage-engine","old_version":"6.0.3","new_version":"6.1.3","repository_url":"https://github.com/junit-team/junit-framework"},{"name":"io.kotest:kotest-assertions-core-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"io.kotest:kotest-runner-junit5-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"org.jetbrains.kotlinx:kotlinx-coroutines-android","old_version":"1.10.2","new_version":"1.11.0","repository_url":"https://github.com/Kotlin/kotlinx.coroutines"},{"name":"org.jetbrains.kotlinx:kotlinx-coroutines-test","old_version":"1.10.2","new_version":"1.11.0","repository_url":"https://github.com/Kotlin/kotlinx.coroutines"},{"name":"com.google.android.material:material","old_version":"1.13.0","new_version":"1.14.0","repository_url":"https://github.com/material-components/material-components-android"},{"name":"com.squareup.okhttp3:mockwebserver","old_version":"5.3.2","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.squareup.okhttp3:okhttp","old_version":"5.3.2","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.android.application","old_version":"9.2.0","new_version":"9.4.0"},{"name":"com.android.test","old_version":"9.2.0","new_version":"9.4.0"},{"name":"org.jetbrains.kotlin.plugin.compose","old_version":"2.3.21","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"},{"name":"org.jetbrains.kotlin.plugin.serialization","old_version":"2.3.21","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"}],"path":null,"ecosystem":"maven"},"body":"Bumps the android-deps group with 21 updates in the /apps/android directory:\n\n| Package | From | To |\n| --- | --- | --- |\n| [gradle-wrapper](https://github.com/gradle/gradle) | `9.4.1` | `9.7.1` |\n| androidx.core:core-ktx | `1.18.0` | `1.19.0` |\n| [org.bouncycastle:bcprov-jdk18on](https://github.com/bcgit/bc-java) | `1.84` | `1.85.2` |\n| [org.commonmark:commonmark](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-autolink](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-strikethrough](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-tables](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-task-list-items](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [dnsjava:dnsjava](https://github.com/dnsjava/dnsjava) | `3.6.4` | `3.6.5` |\n| [org.junit.vintage:junit-vintage-engine](https://github.com/junit-team/junit-framework) | `6.0.3` | `6.1.3` |\n| [io.kotest:kotest-assertions-core-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [io.kotest:kotest-runner-junit5-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [org.jetbrains.kotlinx:kotlinx-coroutines-android](https://github.com/Kotlin/kotlinx.coroutines) | `1.10.2` | `1.11.0` |\n| [org.jetbrains.kotlinx:kotlinx-coroutines-test](https://github.com/Kotlin/kotlinx.coroutines) | `1.10.2` | `1.11.0` |\n| [com.google.android.material:material](https://github.com/material-components/material-components-android) | `1.13.0` | `1.14.0` |\n| [com.squareup.okhttp3:mockwebserver](https://github.com/lysine-dev/okhttp) | `5.3.2` | `5.5.0` |\n| [com.squareup.okhttp3:okhttp](https://github.com/lysine-dev/okhttp) | `5.3.2` | `5.5.0` |\n| com.android.application | `9.2.0` | `9.4.0` |\n| com.android.test | `9.2.0` | `9.4.0` |\n| [org.jetbrains.kotlin.plugin.compose](https://github.com/JetBrains/kotlin) | `2.3.21` | `2.4.20` |\n| [org.jetbrains.kotlin.plugin.serialization](https://github.com/JetBrains/kotlin) | `2.3.21` | `2.4.20` |\n\n\nUpdates `gradle-wrapper` from 9.4.1 to 9.7.1\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/gradle/gradle/releases\"\u003egradle-wrapper's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e9.7.1\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.1.\u003c/p\u003e\n\u003cp\u003eThis is a patch release for 9.7.0. We recommend using 9.7.1 instead of 9.7.0.\u003c/p\u003e\n\u003cp\u003eHere are the highlights of 9.7.0 release:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIsolated Projects graduates to incubating\u003c/li\u003e\n\u003cli\u003eBroader Configuration Cache compatibility\u003c/li\u003e\n\u003cli\u003eResilient Sync helps you fix broken builds\u003c/li\u003e\n\u003cli\u003eMore source locations in problem reports\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003ca href=\"https://docs.gradle.org/9.7.1/release-notes.html\"\u003eRead the Release Notes\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eWe would like to thank the following community members for their contributions to this release of Gradle:\n\u003ca href=\"https://github.com/aSemy\"\u003eAdam\u003c/a\u003e,\n\u003ca href=\"https://github.com/Gautam-aman\"\u003eAman Gautam\u003c/a\u003e,\n\u003ca href=\"https://github.com/YukiCodepth\"\u003eAman Kumar\u003c/a\u003e,\n\u003ca href=\"https://github.com/adubrouski\"\u003eAnton Dubrouski\u003c/a\u003e,\n\u003ca href=\"https://github.com/liutikas\"\u003eAurimas\u003c/a\u003e,\n\u003ca href=\"https://github.com/gbhavya07\"\u003egbhavya07\u003c/a\u003e,\n\u003ca href=\"https://github.com/joshfriend\"\u003eJosh Friend\u003c/a\u003e,\n\u003ca href=\"https://github.com/nicklauslittle-gov\"\u003enicklauslittle-gov\u003c/a\u003e,\n\u003ca href=\"https://github.com/psoni674\"\u003ePragati\u003c/a\u003e,\n\u003ca href=\"https://github.com/Project516\"\u003eproject516\u003c/a\u003e,\n\u003ca href=\"https://github.com/Uomocapra\"\u003eQin Mi\u003c/a\u003e,\n\u003ca href=\"https://github.com/rkdfx\"\u003eRavi\u003c/a\u003e,\n\u003ca href=\"https://github.com/sk-reddy17\"\u003esk-reddy17\u003c/a\u003e,\n\u003ca href=\"https://github.com/Suvrat1629\"\u003eSuvrat Acharya\u003c/a\u003e,\n\u003ca href=\"https://github.com/ShreckYe\"\u003eYongshun Ye\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eUpgrade instructions\u003c/h2\u003e\n\u003cp\u003eSwitch your build to use Gradle 9.7.1 by updating your wrapper:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e./gradlew :wrapper --gradle-version=9.7.1 \u0026amp;\u0026amp; ./gradlew :wrapper\r\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eSee the Gradle \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/upgrading_version_9.html\"\u003e9.x upgrade guide\u003c/a\u003e to learn about deprecations, breaking changes and other considerations when upgrading.\u003c/p\u003e\n\u003cp\u003eFor Java, Groovy, Kotlin and Android compatibility, see the \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/compatibility.html\"\u003efull compatibility notes\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eReporting problems\u003c/h2\u003e\n\u003cp\u003eIf you find a problem with this release, please file a bug on \u003ca href=\"https://github.com/gradle/gradle/issues\"\u003eGitHub Issues\u003c/a\u003e adhering to our issue guidelines.\nIf you're not sure you're encountering a bug, please use the \u003ca href=\"https://discuss.gradle.org/c/help-discuss\"\u003eforum\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eWe hope you will build happiness with Gradle, and we look forward to your feedback via \u003ca href=\"https://twitter.com/gradle\"\u003eTwitter\u003c/a\u003e or on \u003ca href=\"https://github.com/gradle\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003e9.7.0\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.0.\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/92f0512e7f06d84621afba191f75e265363890cf\"\u003e\u003ccode\u003e92f0512\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38892\"\u003e#38892\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/820ee75a99a179bbffa41bcedc6477b685fabb9f\"\u003e\u003ccode\u003e820ee75\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/82c23f9bd2a89b4cc644e1f90a28a8668feb3dee\"\u003e\u003ccode\u003e82c23f9\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering problem in KTS (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38878\"\u003e#38878\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/ef11a7268fe8cc8d6ab849ec911aa11220180553\"\u003e\u003ccode\u003eef11a72\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering issue\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/bb0d8a974a71b1003efea41e4046e98855cd5ff8\"\u003e\u003ccode\u003ebb0d8a9\u003c/code\u003e\u003c/a\u003e Make relevant tests polyglot (run for multiple DSLs)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/336e129d7f95c03486acafc97abf59734acfed48\"\u003e\u003ccode\u003e336e129\u003c/code\u003e\u003c/a\u003e Update signing configuration (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38874\"\u003e#38874\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/4bdf0da2dad9884d089a6062a45ea7183e7d735d\"\u003e\u003ccode\u003e4bdf0da\u003c/code\u003e\u003c/a\u003e Update signing configuration\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/cd9b92c1b82856248cf1dc58b50378238bec7b52\"\u003e\u003ccode\u003ecd9b92c\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38839\"\u003e#38839\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/5f4e381964897ad8d6b99e5a7c77f26dba3259fb\"\u003e\u003ccode\u003e5f4e381\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/1e08ab551367aeb5fb48b26e72807e1d2b27c939\"\u003e\u003ccode\u003e1e08ab5\u003c/code\u003e\u003c/a\u003e Keep type-use annotations in extracted ABI classes (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38810\"\u003e#38810\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/gradle/gradle/compare/v9.4.1...v9.7.1\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `androidx.core:core-ktx` from 1.18.0 to 1.19.0\n\nUpdates `org.bouncycastle:bcprov-jdk18on` from 1.84 to 1.85.2\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.md\"\u003eorg.bouncycastle:bcprov-jdk18on's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch1\u003eBouncy Castle Crypto Package - Release Notes\u003c/h1\u003e\n\u003ch2\u003e1.0 Introduction\u003c/h2\u003e\n\u003cp\u003eThe Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. The package is organised so that it contains a light-weight API suitable for use in any environment (including the J2ME) with the additional infrastructure to conform the algorithms to the JCE framework.\u003c/p\u003e\n\u003ch2\u003e2.0 Release History\u003c/h2\u003e\n\u003cp\u003e\u003c!-- raw HTML omitted --\u003e\u003c!-- raw HTML omitted --\u003e\u003c/p\u003e\n\u003ch3\u003e2.1.1 Version\u003c/h3\u003e\n\u003cp\u003eRelease: 1.86\u003cbr /\u003e\nDate: 2026, TBD\u003c/p\u003e\n\u003ch3\u003e2.1.2 Defects Fixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) let a subkey inherit the primary key's Key Flags when its own Subkey Binding signature carried no Key Flags subpacket, which made the two capability decisions taken for one subkey disagree. OpenPGPCertificate.OpenPGPComponentKey.isSigningKey() reads the effective flags, which fell back to the primary key's direct-key or primary user ID self-signature, so a subkey bound with no flags of its own counted as signing-capable; verifyEmbeddedPrimaryKeyBinding reads the binding signature's own flags, found no signing capability there, and so skipped the embedded Primary Key Binding (cross-certification) signature that RFC 9580 sec. 5.2.1.8 and sec. 10.1.3 require of a subkey that can issue signatures. A data signature made by such a subkey was therefore attributed to the certificate and reported valid by OpenPGPSignature.OpenPGPDocumentSignature.isValid() with the cross-certification requirement never applied, where GnuPG refuses the same certificate and message as not cross-certified. An attacker holding a third party's public signing subkey - which is public material - could bind it to their own primary key with a Subkey Binding signature they are able to make, carrying no Key Flags and no embedded Primary Key Binding signature, which they cannot make without the subkey's private key, and have that party's genuine signatures verify as valid under the attacker's own identity: misattribution of a real signature rather than a forgery of a new one, since the signature still has to be one the subkey actually made. Key Flags are a statement about the key the carrying signature refers to (RFC 9580 sec. 5.2.3.29), so a subkey no longer inherits them from the certificate-wide signatures of the primary key: a Subkey Binding signature that omits the subpacket now leaves the subkey with no capabilities rather than the primary's, which makes the flags the cross-certification check consults the same flags every other decision consults. Preferences and the other subpackets a direct-key signature carries are inherited as before, and the primary key itself - whose flags legitimately come from its direct-key or user ID self-signature - is unaffected. The low-level PGPSignature / PGPPublicKeyRing API performs no binding checks by design and is unchanged.\u003c/li\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) used a version 6 key that carried no valid Direct Key signature, falling back to the primary user ID binding as it correctly does for a version 4 key. RFC 9580 sec. 5.2.3.10 requires the opposite: \u0026quot;An implementation MUST ensure that a valid Direct Key signature is present before using a version 6 key. This prevents certain attacks where an adversary strips a self-signature specifying a Key Expiration Time or certain preferences.\u0026quot; The certificate grammar says the same structurally, the Direct Key signature being mandatory in the version 6 structure of sec. 10.1.1 and optional in the version 4 one of sec. 10.1.3. Because a version 6 certificate carries its key expiration, features and algorithm preferences on the Direct Key signature - the convention the RFC recommends and the one OpenPGPKeyGenerator follows, its user ID certification carrying no expiration at all - removing that single signature packet from a published certificate silently dropped the expiration along with the preferences and features: OpenPGPCertificate.getSignatureChainFor fell back to the user ID binding, the primary key was still reported bound, and getEncryptionKeys() and getSigningKeys() went on returning the subkeys of a key whose owner had set it to expire. The primary key fingerprint is unchanged by the removal, so a relying party pinning the key by fingerprint still treats it as the same key, and no private key or hash collision is involved; the natural moment for the strip is the key refresh that RFC 9580 names as the reason to refetch a key at all - to learn about changes in expiration, features, preferences and revocation - which is exactly the update it defeats. This is a downgrade rather than a forgery, nothing being attributed to a key that did not authorise it, and the concerning direction is encryption, to a key meant to have been retired. OpenPGPCertificate.isBoundBy now requires a valid Direct Key self-signature on a version 6 primary key before any component of the certificate - the primary key, its subkeys or its identities - is treated as bound, so a version 6 certificate stripped of it offers no keys at all rather than an unexpiring set. Version 4 certificates are unaffected: there the key expiration legitimately lives on the user ID self-signature and the fallback is correct, so it stays. The revocation-only version 6 certificate of sec. 10.1.2, which legitimately carries no Direct Key signature, is unaffected as well - its key was already refused as revoked, and reading the revocation does not go through the binding check.\u003c/li\u003e\n\u003cli\u003eThe lightweight LMSSigner and HSSSigner refused a key wrapped in ParametersWithRandom, which is how BcContentSignerBuilder passes a key whenever setSecureRandom() has been called - so BcHssLmsContentSignerBuilder built a working signer until a random was set and then failed with \u0026quot;Incorrect Key Parameters\u0026quot;, and the two signers themselves raised ClassCastException on the same input. All three now unwrap it, as the promoted ML-DSA and SLH-DSA signers already did. The random is accepted and not used: LMS derives its message randomiser C from the key's seed and the one-time index, so it is deterministic and cannot repeat while q does not. Note SP 800-208 sec. 6.1 asks for C to come from an approved random bit generator, which this implementation does not do; that is unchanged here, and a supplied random is now ignored rather than refused.\u003c/li\u003e\n\u003cli\u003eLMS signature verification did not apply two of the checks RFC 8554 sec. 5.4.2 requires before a signature is processed. Step 2g refuses a signature whose LMS typecode is not the one from the public key, and without it the path computation took its height and tree digest from the parameter set the signature named rather than the key's, so a signature claiming a height-25 parameter set drove a 25-level computation against a height-5 key. Step 2i refuses a leaf number q outside the tree, and without it an out-of-range q flowed into the node arithmetic and was left for the candidate-root comparison to catch. Neither was a forgery - the domain separation between D_LEAF and D_INTR and the final comparison saw to that - but both are attacker-chosen work the specification says to refuse up front. Both are now checked, and a signature failing either is still reported as not verifying rather than thrown out of Signature.verify(). The catch around the signature decode in LMSSigner and HSSSigner has also been narrowed to the decode itself, as the corresponding SPI was corrected to do for github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2408\"\u003e#2408\u003c/a\u003e: past the parse the engine reports an inconsistent signature by returning false rather than by throwing, so the wider catch caught nothing while standing ready to turn a future internal error into a quiet false.\u003c/li\u003e\n\u003cli\u003eThe LMS and HSS key parameter classes now apply at construction the checks their decoders apply, so a key built directly cannot be one the decoder would refuse. LMSPrivateKeyParameters accepted an identifier of any length although the decoder reads exactly 16 bytes - such a key encoded but could not be read back - and left q, maxQ and the seed length unchecked; the seed is now required to be at least m bytes at decode as well, where a one-byte seed had been decoding silently and then deriving every one-time key from it. HSSPrivateKeyParameters checked neither its level count nor that it had been given a component key per level and a chaining signature per level below the root, and then indexed both lists, so a mismatch surfaced as IndexOutOfBoundsException - or, where a level happened to match, as a null chaining signature that only failed at signing time; the level is now checked after the reset that fills it in, since a null is legitimate on the way in. LMSPrivateKeyParameters.getInstance(byte[], byte[]) adopted the public key supplied beside the private one without comparing them, so a mismatched public key was simply reported by getPublicKey(); it now cross-checks the identifier, both parameter sets and, where the tree cache already holds it, the root, as the HSS entry point does. The decoders also now report a bad version or seed length as IOException rather than IllegalStateException, so a caller can catch one type for a malformed key, and the package-private LM-OTS public key decoder no longer declares throws Exception or dereferences an unrecognised typecode. The deprecated org.bouncycastle.pqc.crypto.lms copies carry the decoder corrections.\u003c/li\u003e\n\u003cli\u003eIn the LMS JCE layer, LMSKeyGenParameterSpec.fromNames knew all twenty LMS parameter-set names but only four of the sixteen LM-OTS ones, so none of the SP 800-208 n24 or SHAKE sets could be named; all sixteen are now present. KeyPairGenerator.initialize(int, SecureRandom) reports InvalidParameterException, which is what the JCA specifies and which extends the IllegalArgumentException it raised before, so existing catches still match. BCLMSPrivateKey.getIndex now takes the exhaustion check and the index read under the key's own monitor rather than as two separate calls, and two unused fields have gone from LMSSignatureSpi. Note that the LMS Signature claims its one-time key at the first update() rather than at sign(), so a Signature that is initialised and updated and then abandoned spends an index without producing a signature - the safe direction for a one-time scheme, and now documented on the SPI.\u003c/li\u003e\n\u003cli\u003eEvery other key pair generator that refuses a key size did the same thing the LMS one did above. KeyPairGenerator.initialize(int, SecureRandom) is documented to raise InvalidParameterException when the key size is not one the generator supports, and thirty of them raised a bare IllegalArgumentException instead, so a caller following the JCA and catching the documented type saw an exception escaping rather than a refusal. The ML-DSA, ML-KEM, SLH-DSA, Classic McEliece, FrodoKEM, NTRU and composite signature and KEM generators in the BC provider, and every generator in BCPQC, now raise InvalidParameterException - NewHope included, where the value is a key size it will not take rather than a mode of initialisation it does not offer. InvalidParameterException extends IllegalArgumentException, so callers written against the old behaviour go on catching it unchanged. The two RSA generators are corrected as well, and differently: theirs is a key size below a floor rather than a mode of initialisation they do not offer, and the refusal is raised by the lightweight RSAKeyGenerationParameters, which cannot name a java.security exception at all, so the RSA KeyPairGeneratorSpi now translates it - keeping the message verbatim and the original exception as the cause, through a new SecurityExceptions.invalidParameterException factory, since InvalidParameterException has no constructor that takes one. Of the 304 KeyPairGenerator services the two providers register, 299 now refuse a nonsense key size the way the JCA defines it and five accept it as a strength they can work with, with none left raising a bare IllegalArgumentException; that is asserted as a sweep over both providers rather than per algorithm, so a generator added later is covered without the test being touched. The jdk1.3 provider overlays of the four generators that have one carry the same change, and the jdk1.3 SecurityExceptions overlay gains the new factory along with the invalidAlgorithmParameterException one it had been missing.\u003c/li\u003e\n\u003cli\u003eKeyPairGenerator.initialize(AlgorithmParameterSpec, SecureRandom) had the same shape of problem as the int overload above, and only 44 of the 304 services the two providers register reported an unusable spec as the InvalidAlgorithmParameterException that method declares. The twenty-three PQC generators that resolve a parameter set by name - cmce, frodokem, mldsa, mlkem, slhdsa, aimer, bike, faest, falcon, haetae, hqc, mayo, mqom, ntru, ntruplus, both ntruprime variants, qruov, saber, sdith, smaugt, snova and sqisign, 230 services between them - case-folded the name they got back from the spec without checking it, so a spec with no getName() method, and a null spec, produced a NullPointerException from inside the fold; their own \u0026quot;is this name one I know\u0026quot; branch, which does report the declared exception, was unreachable. The two composite generators, whose parameter set is fixed by the algorithm name so that null is the only spec they accept, refused every other one with IllegalArgumentException. RSA answered correctly for a spec of the wrong type but not for one of the right type carrying values its lightweight parameters will not take - an even public exponent, or a key size below the floor - which is now translated the same way the int overload's is. All 304 services now report the declared exception, with the composites still taking the null spec that is right for them; note that InvalidAlgorithmParameterException is a checked exception and not an IllegalArgumentException, so a caller that was catching what these threw before has to catch the declared type instead.\u003c/li\u003e\n\u003cli\u003eAn HSS private key claimed the two records of its position under two different monitors. The top-level index and the bottom component key's one-time index q are independent records of the same position - the decoder requires them to agree, see the entry below - but generateLMSContext incremented the index under the HSS key's own monitor, released it, and only then claimed q under the component key's. A getEncoded() issued in between saw the index advanced and q not, and produced an encoding this implementation's own decoder rejects; and two threads meeting at a bottom-tree boundary could both pass the exhaustion test, take consecutive top-level indices and claim the same q, after which one of them was refused with \u0026quot;ots private key exhausted\u0026quot; by a key still reporting usages remaining, a top-level index had been spent with no signature made, and the two records stayed one apart for the rest of the key's life in that process - so it could no longer be encoded, cloned or sharded, and getIndex() and getUsagesRemaining() misreported by one. No one-time key was reused: the component key's claim is itself atomic, and the divergence runs index ahead of leaves, so the effect was on the key's usability rather than on the signatures it had made. Both records are now claimed under the one monitor, and the component key is claimed before the index is incremented so that an exhausted one leaves both untouched. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the same correction.\u003c/li\u003e\n\u003cli\u003eTimeStampToken parsed the attacker-controlled TSTInfo content of a time-stamp token (org.bouncycastle.tsp.TimeStampToken, reached from TimeStampResponse(byte[]) and (InputStream)) inside a try that caught only CMSException, so a well-formed RFC 3161 TimeStampResp whose embedded token carried a malformed TSTInfo - a SEQUENCE with fewer elements than the five mandatory fields, a non-SEQUENCE, truncated DER, or an unknown context tag - let an IllegalArgumentException or a NoSuchElementException escape the constructor's declared throws TSPException, IOException contract. A token signed by no signers or by more than one raised a bare IllegalArgumentException from the same constructor, before that try, for the same reason. Both are now reported as TSPException, matching the package-private TimeStampResponse(DLSequence) constructor and the existing getSignedAttributes guard in the same method; the signer-count refusal is a TSPValidationException, as the neighbouring check on the content type already was. Related, and the cause of the NoSuchElementException: asn1.tsp.TSTInfo read its five mandatory fields off the sequence with no bound on how many elements were actually there, so a short SEQUENCE left the enumeration to run out rather than being refused, and an oversize one was accepted with its extra elements absorbed into the optional slots. Decode now requires the five to ten elements RFC 3161 sec. 2.4.2 gives the type, which is what the sibling Accuracy and ArchiveTimeStamp decoders already did, so the failure is the IllegalArgumentException that getInstance is expected to raise (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2415\"\u003e#2415\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eNeither the HSS nor the XMSS^MT private key decoder checked its declared index against the traversal state stored beside it, although the two are independent records of the same position in the key and so can be compared. For HSS the records are the top-level index and the component keys' one-time indices q; for XMSS^MT they are the global index and the per-layer BDS states. A stored key whose index had been rolled back while its state stayed advanced - a partial write, a restore from backup, a buggy storage layer - was therefore accepted, and it then signed a second message under a one-time key the key had already used, producing a signature that verified, so nothing anywhere surfaced the reuse. RFC 8554 sec. 1 and RFC 8391 sec. 1.1 both require each one-time key to be used exactly once, and this is the failure those requirements exist to prevent; the single-tree XMSS decoder has tied its BDS state to its index since that state was first validated, and this brings the two multi-tree schemes into line. HSS decode now requires the declared index to equal the position the component q values imply - a level above the last contributes (q - 1) leaves of the levels beneath it, since its q has already advanced past the subtree it signed - and XMSS^MT decode now requires each present layer's BDS index to equal the leaf index that layer derives from the global index, allowing the one position where a layer has moved into a new subtree and its state legitimately still carries the previous subtree's final index. A layer with no state yet is unaffected, since those are built lazily at signing time. Related, and the same shape of omission: an XMSS or XMSS^MT private key encoding carries the tree root twice - the key's own root field and the root node of the BDS state stored beside it, which for XMSS^MT is the top layer's - and the two were never compared either. A corrupted root was accepted and then poisoned every signature the key made, because the root is hashed into the message digest: the signature did not verify and nothing indicated why. Decode now requires the two copies to agree. The BDS node values themselves are not checkable the way the LMS tree cache above is - a BDS authentication path, stack, retain or keep node does not have its children stored alongside it, so recomputing one means building a subtree, which is the work the state exists to avoid. Both checks are integer comparisons over the levels of the key, too small to measure against the surrounding decode, and both were verified not to reject any legitimate key by walking every index a key can reach: the full key space of the two-level HSS and the h=4/d=2, h=6/d=2, h=6/d=3, h=9/d=3 and h=8/d=4 XMSS^MT parameter sets, plus a three-level HSS key across a subtree boundary and an HSS shard. Since those node values cannot be recomputed, the encoded state now carries a checksum over itself instead, with the owning key's public seed hashed in front of it. Any corruption of the stored state is refused at decode rather than being loaded and then producing signatures that silently do not verify, and because the public seed is bound in, a state transplanted between two keys of the same parameter set is refused too, even though it is internally consistent and arrives with its own matching root. The public seed is bound rather than the secret seed or the PRF key deliberately: the state's own root and index are inside the encoding and so are already covered, hashing secret material would make the stored checksum a commitment to it for no gain in detection, and the PRF key does not influence the state at all. \u003cstrong\u003eThis is an error-detecting code and not integrity protection\u003c/strong\u003e - anyone able to rewrite the stored key recomputes it, so it establishes that the state is unchanged since it was written, never that it was correct when written, and the allocation bounds on the encoding remain the guard against a crafted one. It costs one SHA-256 over the state, measured at 5 to 8 microseconds each way for the h=10 and h=16 parameter sets, and 32 bytes of encoding. The state encoding was added earlier in this same cycle and has not been released, so the checksum is simply part of it rather than a new version: a state written by a 1.86 beta is rejected, which is recovered from by re-exporting the key. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the HSS check as well (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2414\"\u003e#2414\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe S/MIME example smoke test in the misc module (org.bouncycastle.mail.smime.examples.test.AllTests) drove SendSignedAndEncryptedMail against smtp.gmail.com, and that example finishes with Transport.send() under JavaMail's default settings, which have no connect timeout. Where outbound port 25 is refused the failure was swallowed and the test passed; where it is silently dropped, as on many home networks, the connect blocked and ./gradlew build hung in :misc:test indefinitely with \u0026quot;0 tests completed\u0026quot;. The test now delivers to an SMTP stub on a loopback port, with connect / read / write timeouts as a backstop, and asserts the message arrived (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2407\"\u003e#2407\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation took the traditional component public key bytes it feeds the KEM combiner from the recipient key's own encoding, while decapsulation recomputes the point from the private key and so always produced an uncompressed one. Section 4 of draft-ietf-lamps-pq-composite-kem requires an EC component to be carried as an uncompressed point, but a component key that encodes itself compressed - a BC EC key whose point format has been set through org.bouncycastle.jce.interfaces.ECPointEncoder, or a key from a provider that preserves a compressed encoding - was passed through as it came. Both sides then combined a different tradPK and derived different shared secrets, with no error reported on either: encapsulation and decapsulation both succeeded and the recipient simply could not decrypt. The EC component is now normalised to an uncompressed point wherever the engine serialises one, which covers the ephemeral key that forms the ciphertext as well. X25519 and X448 components have a single encoding and were unaffected, as were EC keys left in their default (uncompressed) format, whose shared secrets are unchanged. CompositePublicKey.getEncoded() took its component bytes the same way, so such a key also encoded to a composite key other implementations reject and whose bytes changed across an encode / decode / encode round trip - 1238 bytes rather than 1270 for MLKEM768-ECDH-P256, and for the composite ML-DSA keys sharing that method, 2006 rather than 2038 for MLDSA65-ECDSA-P256. It now normalises the component the same way. This is a write-side change only: a composite key carrying a compressed EC component is still decoded, since the component key factories accept either form, and continues to verify signatures as before - it simply re-encodes in the normalised form. The shared normalisation is org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil.getUncompressedSubjectPublicKeyBytes.\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation threw a NullPointerException, wrapped in an IllegalStateException out of KeyGenerator.generateKey(), when the SecureRandom it was given was null - which javax.crypto.KEM.newEncapsulator() documents as a request for the provider's default, and which KeyGenerator.init(spec, null) passes straight through. The three RSA-OAEP composites draw the traditional shared secret from that random directly, so they were the ones affected; the ECDH and X25519 / X448 composites escaped only because their component KeyPairGenerators default a random of their own. CompositeMLKEMEngine now defaults one through CryptoServicesRegistrar.getSecureRandom() on first use, as the composite KEM Cipher's wrap path already did, and as the KEM generators corrected earlier in this cycle now do. Related, the engine now also clears the ML-KEM component's shared secret alongside the traditional one on both the encapsulate and decapsulate paths - the copy handed back by getEncoded() was left in the heap - as section 3.5 of draft-ietf-lamps-pq-composite-kem requires.\u003c/li\u003e\n\u003cli\u003eCompositePublicKey.getAlgorithm() and CompositePrivateKey.getAlgorithm() returned null for all twelve Composite ML-KEM (draft-ietf-lamps-pq-composite-kem) parameter sets. Both classes resolved the name through the composite signature index only, which holds the composite ML-DSA OIDs, so a composite KEM key pair - generated, parsed from a certificate, or read from PKCS#8 - reported no algorithm at all, and the standard JCA idiom of reconstructing a key with KeyFactory.getInstance(key.getAlgorithm()) raised a NullPointerException. The lookup now falls back to the composite KEM index, so the name returned is the one the provider registers the algorithm under (e.g. MLKEM768-X25519-SHA3-256), matching the composite ML-DSA behaviour. The same single-index assumption made the CompositePublicKey(SubjectPublicKeyInfo) and CompositePrivateKey(PrivateKeyInfo) constructors reject a composite KEM key with \u0026quot;unable to create CompositePublicKey from SubjectPublicKeyInfo\u0026quot;; they now dispatch to the composite KEM key factory for those OIDs. Keys obtained through KeyFactory or through BouncyCastleProvider.getPublicKey / getPrivateKey were unaffected and are unchanged (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2404\"\u003e#2404\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe org.bouncycastle.jcajce.spec.KEMKDFSpec constructor stored a null otherInfo as given, so getOtherInfo() returned null, and three of the KDF branches KdfUtil.makeKeyBytes dispatches to - KMAC-128, KMAC-256 and SHAKE-256 - read the otherInfo length without a guard and threw NullPointerException out of the KEM operation, where the KDF2, KDF3 and HKDF branches tolerate a null through KDFParameters / HKDFParameters. The Builder of every spec in the package already mapped null to empty, so no provider path reached it, but the constructor is protected on a public class and KdfUtil is documented for callers building their own KEM integration; the deprecated KEMParameterSpec passes a null itself and escaped only because it also pins the KDF to null. The constructor now stores empty for a null, so getOtherInfo() never returns null, and a null and an explicitly empty otherInfo derive the same key.\u003c/li\u003e\n\u003cli\u003eQR-UOV signature verification accepted a signature encoding that was not canonical, so the encoding of a signature was not unique even after the trailing-byte fix of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e. Each F_q element of the signature is stored in ceil(log2 q) bits, one more bit pattern than the field has elements: q itself is representable and is arithmetically congruent to zero, so an element written as q verified exactly as the same element written as zero would, and the bits padding the last element out to the byte boundary were never read at all. Every zero element of a signature therefore carried a second encoding, and for the q = 7 parameter sets roughly one element in seven is zero - a single qruov_5_q7_L10 signature measured 256 spare bits, so on the order of 2^256 distinct byte strings verified for the one message and key. Verification now rejects any element outside [0, q) and any set padding bit; a signature produced by this or by the reference implementation is unaffected, as the KAT vectors of every parameter set confirm. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSNOVA signature verification ignored four bits inside the signature for any parameter set whose solution is an odd number of GF(16) nibbles - the SNOVA_24_5_5, SNOVA_25_8_3, SNOVA_29_6_5 and SNOVA_66_15_3 families, sixteen of the forty-four parameter sets. The last byte of the encoded solution carries a single nibble and the signer leaves the top four bits zero, but the decoder did not read them, so sixteen distinct byte strings verified for one signature. This is the same non-unique encoding github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e closed for bytes following the signature, applied inside it; the verifier now requires those bits to be zero. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSnovaPrivateKeyParameters did not validate the length of the private key encoding handed to it - the only one of the five schemes of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e that did not - and SnovaParameters.getPrivateKeyLength() reported the expanded (\u0026quot;ESK\u0026quot;) length even for a parameter set whose private key is the seed pair. A private key encoding reaches this constructor straight from a PKCS#8 blob, so a wrong length went undetected: a seed-form key with extra bytes appended was accepted and signed under a different derived key, and a short expanded-form key sized the signer's decode buffer negatively, throwing NegativeArraySizeException out of generateSignature() rather than being reported at construction. Related, the signing retry loop could not terminate: the vinegar values are derived from a single-byte counter, so only 256 distinct linear systems can be tried, and an expanded-form private key that is not a real central map is singular for all of them - generateSignature() then span forever rather than failing. The length is now checked at construction, getPrivateKeyLength() reports the length that parameter set's private key actually has, and the retry loop gives up after its 256 attempts as MAYO's does.\u003c/li\u003e\n\u003cli\u003eMayoSigner and MayoKeyPairGenerator did not clear several buffers holding secret key material that the MAYO reference implementation explicitly clears. Signing left the secret oil space O, the expanded L = (P1 + P1^t) * O + P2, and the M / VPV / Ox intermediates of the central map in place, having gone to the trouble of clearing eleven other buffers; key generation left the expanded seed, whose tail is the encoded oil space, and the P1 * O + P2 half of P; and the row-echelon step left the packed echelon form of the secret linear system and its pivot rows. Separately, if all 256 attempts at solving for the signature had given a rank-deficient system, signing emitted a signature built from the failed attempt's state instead of reporting the failure the reference returns, and AIMerSigner.generateSignature returned an empty array on failure, which a caller would hand on as though it were a signature. Both now throw.\u003c/li\u003e\n\u003cli\u003eFive PQC signature schemes - MAYO, SNOVA, QR-UOV, SQIsign and AIMer - returned the NIST crypto_sign \u0026quot;sm\u0026quot; signed-message envelope from generateSignature() rather than the signature. That envelope is an artefact of the reference KAT harness, which records the message alongside the signature so a vector file can be self-contained; it is not part of any of the five specifications, and no other BC signer emits it (Falcon's KAT test rebuilds the equivalent envelope in the test, which is where it belongs). Two consequences followed, both reaching the JCA Signature services of every parameter set of the five schemes in BouncyCastlePQCProvider. First, since the message was appended to the signature, verification had to skip whatever followed the signature proper, and it did so by checking only that the buffer was long enough - so any number of trailing bytes could be added to a valid signature, or the appended message replaced with unrelated data, and it still verified. A signature encoding was therefore not unique: anyone holding one valid signature could produce unlimited distinct byte strings that all verified for the same message and key, which breaks any use that treats the signature bytes as an identifier, deduplicates on them, or records them as evidence. Second, the envelope propagated into everything built on the operator layer: because ContentSigner hands the signature straight into the structure being signed, every X.509 certificate, CRL, CMS SignedData and TLS CertificateVerify BC produced with one of these algorithms carried a verbatim copy of the signed data inside its own signature field - a self-signed MAYO-1 certificate came to 3567 bytes where the same certificate is now 2020 - which no other implementation can parse as a signature, and which in a detached CMS signature meant the \u0026quot;detached\u0026quot; signature carried the content. generateSignature() now returns the bare signature, and verifySignature() requires exactly the parameter set's signature length, so appended or truncated data is rejected rather than ignored. \u003cstrong\u003eThis is a behavioural change for signatures produced by an earlier release\u003c/strong\u003e - MAYO and SNOVA from 1.84, QR-UOV, SQIsign and AIMer from 1.85 - which are no longer accepted in the envelope form they were emitted in; the signature bytes themselves are unchanged, so a stored value can be recovered by taking the leading signature-length bytes, or for AIMer, whose envelope was message || signature rather than signature || message, the trailing ones. The KAT tests now rebuild the envelope before comparing against the vector files, which continue to record it. Note that AIMer's verification had already been made length-exact during this cycle (see the entry below relating to github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2401\"\u003e#2401\u003c/a\u003e), so of the five only its envelope remained (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe MLS implementation did not bind an X.509 credential to the LeafNode's signature_key. LeafNode.verify() checked a leaf's signature against the signature_key declared in the leaf itself, while the X.509 credential's certificate chain was stored but never parsed or checked, so the certificate's public key was never required to match signature_key (RFC 9420 sec. 5.3). A leaf could therefore carry one party's certificate while being signed by an unrelated key and still be accepted under that party's identity through KeyPackage.verify() and the Group leaf-validation path. LeafNode.verify() now requires the end-entity certificate's subject public key, in the cipher suite's signature encoding, to equal signature_key for an X.509 credential, and rejects the leaf otherwise - including an empty chain or a certificate whose key type does not match the cipher suite; certificate-chain and identity validation to a trust anchor remain the application's responsibility per RFC 9420 sec. 5.3.1. A public org.bouncycastle.mls.codec.Certificate(byte[]) constructor and a Credential.getCertificates() accessor are added so callers can build and inspect X.509 credentials. Basic credentials are unaffected.\u003c/li\u003e\n\u003cli\u003eThe SecureRandom supplied to org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder.setSecureRandom() did not drive the content IV / nonce for any algorithm other than RC2. EnvelopedDataHelper.generateParameters passed the caller's SecureRandom to the AlgorithmParameterGenerator only in the RC2_CBC branch; every other content-encryption algorithm - AES-CBC, AES-GCM, AES-CCM, Camellia, ARIA, SEED and the rest - reached pGen.generateParameters() on an uninitialised generator, so the IV / nonce was drawn from a default SecureRandom and setSecureRandom() was silently ignored (the builder's javadoc states that random is used for IV/nonce generation). The generator is now initialised with the supplied random on the general path as well, so a caller who provides a specific randomness source - for a controlled or FIPS-approved DRBG, say - has it honoured for the content IV / nonce. The session-key generation path was unaffected and already used the supplied random. Because the content IV / nonce now comes from the supplied SecureRandom, the org.bouncycastle.crypto.util JournalingSecureRandom / JournaledAlgorithm reproducible-encryption support records it in the transcript: a resumed session reproduces the IV / nonce by regenerating it from the replayed randomness - build the resuming encryptor from the content-algorithm OID - rather than by reusing the AlgorithmIdentifier captured from the first encryption, which no longer keeps the transcript aligned.\u003c/li\u003e\n\u003cli\u003eThe NTRU LPRime, NTRU+ and SMAUG-T KEM generators threw a NullPointerException when constructed with a null SecureRandom, where every other KEM generator - including NTRU LPRime's own SNTRU Prime counterpart in the same package - defaults one through CryptoServicesRegistrar.getSecureRandom(). This is reachable from the lightweight API directly, and from javax.crypto.KEM, whose newEncapsulator() documents a null random as a request for the provider's default.\u003c/li\u003e\n\u003cli\u003eFrodoKEMEngine kept a single SHAKE instance in a field, so an engine reached concurrently produced wrong results. It is reached that way through org.bouncycastle.crypto.kems.FrodoKEMExtractor, which holds one engine for its lifetime: two threads extracting through one extractor interleaved the digest's absorb and squeeze phases, yielding shared secrets that silently did not match the sender's, or an IllegalStateException of \u0026quot;attempt to absorb while squeezing\u0026quot; from inside extractSecret. The digest is now built per call, as CMCEEngine's already was, which makes an extractor safe to share. Encapsulation was unaffected, since FrodoKEMGenerator builds an engine per call. Results for any single-threaded use are unchanged - the reference KAT vectors are byte-identical.\u003c/li\u003e\n\u003cli\u003eThe BCJSSE provider carried the TLS 1.2 coupling between the supported_groups extension and ECDSA over into TLS 1.3: an ECDSA signature scheme was treated as usable - offered in the signature_algorithms and signature_algorithms_cert extensions, and eligible when selecting the local credentials - only while the corresponding curve was among the named groups enabled for key exchange, both per context (a group unavailable for key agreement disabled the scheme outright) and per connection (the curve had to be in the supported_groups list about to be sent). RFC 8446 sec. 4.2.7 scopes supported_groups to key exchange only, with signature algorithms negotiated independently (sec. 4.2.3), so this incorrect restriction in TLS 1.3 has been removed. Ed25519, Ed448 and the RSA schemes were unaffected (as well as typical deployments using a default configuration for named groups).\u003c/li\u003e\n\u003cli\u003eThe bcmail module descriptor did not declare its javax.mail/javax.activation dependences, so a modular (module-path) consumer of the jar hit IllegalAccessError/module-resolution failures when the S/MIME classes touched the mail API. The descriptor now requires them optionally (requires static) under all four module names those libraries are known by - the automatic names mail and activation carried by the javax.mail:mail / javax.activation:activation artifacts, and the explicit names java.mail and java.activation carried by the newer com.sun.mail / com.sun.activation ones - a hard requires on any one name would break users of the others (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2389\"\u003e#2389\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFour type-coercion helpers in the OER / IEEE 1609.2 (ITS) decoder tested the wrong type in the identity fast path that lets a getInstance() factory return an argument that is already of the target type. org.bouncycastle.oer.its.ieee1609dot2.basetypes.UINT32.getInstance and org.bouncycastle.oer.its.etsi102941.basetypes.Version.getInstance guarded on UINT8 - a sibling of UINT32 under UintBase, and unrelated to Version - so passing a UINT8 threw ClassCastException, while passing an actual UINT32 or Version missed the fast path and fell through to ASN1Integer.getInstance, which rejects them: neither factory accepted its own type. org.bouncycastle.oer.its.etsi103097.EtsiTs103097DataEncryptedUnicast.getInstance guarded on its sibling EtsiTs103097DataEncrypted and then cast to the unicast type, so an EtsiTs103097DataEncrypted threw ClassCastException. org.bouncycastle.oer.OEROptional.getObject(Class) called value.getClass().isInstance(type) with the arguments transposed, which is always false because the argument is a java.lang.Class, so the cast path was dead and every optional field was resolved reflectively, failing with IllegalStateException for a target type with no static getInstance. Each guard now names the type it returns, matching the sibling UINT8 / UINT16 / UINT64 and EtsiTs103097DataEncrypted factories (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2373\"\u003e#2373\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eDefaultAlgorithmNameFinder and DefaultSignatureNameFinder had no entries at all for the ShangMi algorithms, so an SM2 signature AlgorithmIdentifier that DefaultSignatureAlgorithmIdentifierFinder itself produces came back named only by its OID string - getAlgorithmName(GMObjectIdentifiers.sm2sign_with_sm3) returned \u0026quot;1.2.156.10197.1.501\u0026quot; and hasAlgorithmName returned false. Both finders now name sm2sign_with_sm3 as SM3WITHSM2 and sm2sign_with_sha256 as SHA256WITHSM2, and DefaultAlgorithmNameFinder additionally names the sm3 digest. All three resolve through the BC provider, as Signature and MessageDigest respectively. The remaining GM arc - the SM4 cipher modes, the sm2encrypt variants, and the SM1 / SM6 / SSF33 ciphers BC does not implement - is still unnamed (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2377\"\u003e#2377\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe RFC 4998 evidence-record classes compared the digest AlgorithmIdentifier named by a time-stamp authority with the one their own DigestCalculator uses, and did so with AlgorithmIdentifier.equals(), which compares the encodings. A TSA that names SHA-256 with an explicit NULL parameters field - DigiCert among them - therefore failed against BC's own calculator, which names it with the parameters absent, and ERSArchiveTimeStampGenerator.generateArchiveTimeStamp rejected the response with \u0026quot;time stamp imprint for wrong algorithm\u0026quot;. Both spellings name the same digest and RFC 5754 sec. 2 requires a receiver to accept either, while requiring that identifiers be generated with the parameters absent, which BC already does. The three affected comparisons - the two in ERSArchiveTimeStampGenerator and the digest check in ERSEvidenceRecord.renew - now use the new AlgorithmIdentifier.areEquivalent, which matches on the algorithm and treats an absent parameters field and NULL as the same, and the consistency check across an evidence record's archive time stamp chain uses it too. An identifier carrying an actual parameter structure is never equivalent to one carrying none (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2379\"\u003e#2379\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eEDIPartyName.toASN1Primitive emitted the nameAssigner and partyName DirectoryStrings without their context tags, so an EDIPartyName built through its public constructor could not be parsed back by EDIPartyName.getInstance, which correctly requires them. RFC 5280 sec. 4.2.1.6 tags both members [0] and [1], and those tags are explicit despite the module's IMPLICIT TAGS because DirectoryString is a CHOICE, which X.680 does not allow to be tagged implicitly - the decoder already had this right. The encoder now matches it. Note the type was added during the 1.85 cycle and GeneralName validates its ediPartyName alternative through it, so a GeneralName carrying an untagged ediPartyName - including one BC itself produced - is rejected where 1.84 passed it through unexamined; the untagged form is not read leniently (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2380\"\u003e#2380\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eRSASSA-PSS could not be used with a RIPEMD digest through the JCA API. Nothing registered the RIPEMD PSS signatures, so Signature.getInstance(\u0026quot;RIPEMD160WITHRSAANDMGF1\u0026quot;) raised NoSuchAlgorithmException, and the generic RSASSA-PSS route with an explicit PSSParameterSpec failed too: org.bouncycastle.jcajce.provider.util.DigestFactory.getDigest returned null for a RIPEMD name, and isSameDigest - an allow-list of the SHA families and MD5 - reported two identical RIPEMD names as different digests, so the spec was rejected with \u0026quot;digest algorithm for MGF should be the same as for PSS parameters\u0026quot;. isSameDigest now answers true for equal names whatever the digest, which also covers Whirlpool, SM3, GOST3411 and anything else outside that allow-list; DigestFactory recognises RIPEMD128, RIPEMD160 and RIPEMD256 by name and OID; the three PSS signatures are registered with MGF1 over the same digest and a salt of the digest length; and DefaultSignatureAlgorithmIdentifierFinder gains the matching RIPEMD*WITHRSAANDMGF1 entries with their RSASSA-PSS-params, so the operator/JcaContentSignerBuilder path works as well. Note BC continues to require the PSS hash and the MGF1 hash to be the same, which RFC 8017 does not itself demand (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2381\"\u003e#2381\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe opt-in key-size validation on CMS key-transport recipients (org.bouncycastle.cms.jcajce.JceKeyTransRecipient.setKeySizeValidation(true)) never ran for a message using RFC 9709 CEK derivation (id-alg-cek-hkdf-sha256): the branch that should have selected the actual content-encryption algorithm carried in the KDF AlgorithmIdentifier's parameters compared the encrypted-key byte array against the id-alg-cek-hkdf-sha256 object identifier - a comparison that is always false - so the check fell through to a key-size lookup on the outer KDF OID, which has no registered key size, and silently checked nothing. A key-transport EnvelopedData/AuthEnvelopedData whose transported (and HKDF-derived) content-encryption key did not match the key size of the advertised content-encryption algorithm was therefore accepted even with validation enabled. The recipient now dispatches on the content-encryption AlgorithmIdentifier's algorithm OID, so key-size validation of RFC 9709 messages checks the recovered key against the inner content-encryption algorithm. Messages with a matching key size, non-HKDF messages, and recipients that do not enable validation are unaffected.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003eSee full diff in \u003ca href=\"https://github.com/bcgit/bc-java/commits\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003ecommonmark-java 0.29.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e[0.29.0] - 2026-06-20\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/comm...\n\n_Description has been truncated_","html_url":"https://github.com/wangqianCAI/OBI/pull/42","url":"https://dependabot.ecosyste.ms/api/v1/hosts/GitHub/repositories/wangqianCAI%2FOBI/issues/42","packages_url":"https://dependabot.ecosyste.ms/api/v1/issues/42/packages"},{"uuid":"5400378360","node_id":"PR_kwDOUSwqdc8AAAABC150hg","number":5,"state":"closed","title":"Bump the android group in /android with 15 updates","user":"dependabot[bot]","labels":["dependencies","java"],"assignees":[],"locked":false,"comments_count":2,"pull_request":true,"closed_at":"2026-09-09T14:06:39.000Z","author_association":null,"state_reason":null,"created_at":"2026-09-09T13:55:10.000Z","updated_at":"2026-09-09T14:06:50.000Z","time_to_close":689,"merged_at":null,"merged_by":null,"closed_by":null,"dependency_metadata":{"prefix":"Bump","group_name":"android","update_count":15,"packages":[{"name":"gradle-wrapper","old_version":"8.11.1","new_version":"9.7.1","repository_url":"https://github.com/gradle/gradle"},{"name":"androidx.core:core-ktx","old_version":"1.15.0","new_version":"1.19.0"},{"name":"androidx.appcompat:appcompat","old_version":"1.7.0","new_version":"1.8.0"},{"name":"androidx.compose:compose-bom","old_version":"2024.12.01","new_version":"2026.08.00"},{"name":"androidx.navigation:navigation-compose","old_version":"2.8.5","new_version":"2.10.0"},{"name":"com.squareup.okhttp3:okhttp","old_version":"4.12.0","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.squareup.okhttp3:mockwebserver","old_version":"4.12.0","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"org.jetbrains.kotlinx:kotlinx-serialization-json","old_version":"1.7.3","new_version":"1.11.0","repository_url":"https://github.com/Kotlin/kotlinx.serialization"},{"name":"androidx.biometric:biometric","old_version":"1.2.0-alpha05","new_version":"1.4.0-alpha07"},{"name":"org.jetbrains.kotlinx:kotlinx-coroutines-android","old_version":"1.9.0","new_version":"1.11.0","repository_url":"https://github.com/Kotlin/kotlinx.coroutines"},{"name":"org.jetbrains.kotlinx:kotlinx-coroutines-test","old_version":"1.9.0","new_version":"1.11.0","repository_url":"https://github.com/Kotlin/kotlinx.coroutines"},{"name":"com.android.application","old_version":"8.7.3","new_version":"9.4.0"},{"name":"org.jetbrains.kotlin.android","old_version":"2.0.21","new_version":"2.4.10","repository_url":"https://github.com/JetBrains/kotlin"},{"name":"org.jetbrains.kotlin.plugin.compose","old_version":"2.0.21","new_version":"2.4.10","repository_url":"https://github.com/JetBrains/kotlin"},{"name":"org.jetbrains.kotlin.plugin.serialization","old_version":"2.0.21","new_version":"2.4.10","repository_url":"https://github.com/JetBrains/kotlin"}],"path":"/android","ecosystem":"maven"},"body":"Bumps the android group in /android with 15 updates:\n\n| Package | From | To |\n| --- | --- | --- |\n| [gradle-wrapper](https://github.com/gradle/gradle) | `8.11.1` | `9.7.1` |\n| androidx.core:core-ktx | `1.15.0` | `1.19.0` |\n| androidx.appcompat:appcompat | `1.7.0` | `1.8.0` |\n| androidx.compose:compose-bom | `2024.12.01` | `2026.08.00` |\n| androidx.navigation:navigation-compose | `2.8.5` | `2.10.0` |\n| [com.squareup.okhttp3:okhttp](https://github.com/lysine-dev/okhttp) | `4.12.0` | `5.5.0` |\n| [com.squareup.okhttp3:mockwebserver](https://github.com/lysine-dev/okhttp) | `4.12.0` | `5.5.0` |\n| [org.jetbrains.kotlinx:kotlinx-serialization-json](https://github.com/Kotlin/kotlinx.serialization) | `1.7.3` | `1.11.0` |\n| androidx.biometric:biometric | `1.2.0-alpha05` | `1.4.0-alpha07` |\n| [org.jetbrains.kotlinx:kotlinx-coroutines-android](https://github.com/Kotlin/kotlinx.coroutines) | `1.9.0` | `1.11.0` |\n| [org.jetbrains.kotlinx:kotlinx-coroutines-test](https://github.com/Kotlin/kotlinx.coroutines) | `1.9.0` | `1.11.0` |\n| com.android.application | `8.7.3` | `9.4.0` |\n| [org.jetbrains.kotlin.android](https://github.com/JetBrains/kotlin) | `2.0.21` | `2.4.10` |\n| [org.jetbrains.kotlin.plugin.compose](https://github.com/JetBrains/kotlin) | `2.0.21` | `2.4.10` |\n| [org.jetbrains.kotlin.plugin.serialization](https://github.com/JetBrains/kotlin) | `2.0.21` | `2.4.10` |\n\nUpdates `gradle-wrapper` from 8.11.1 to 9.7.1\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/gradle/gradle/releases\"\u003egradle-wrapper's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e9.7.1\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.1.\u003c/p\u003e\n\u003cp\u003eThis is a patch release for 9.7.0. We recommend using 9.7.1 instead of 9.7.0.\u003c/p\u003e\n\u003cp\u003eHere are the highlights of 9.7.0 release:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIsolated Projects graduates to incubating\u003c/li\u003e\n\u003cli\u003eBroader Configuration Cache compatibility\u003c/li\u003e\n\u003cli\u003eResilient Sync helps you fix broken builds\u003c/li\u003e\n\u003cli\u003eMore source locations in problem reports\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003ca href=\"https://docs.gradle.org/9.7.1/release-notes.html\"\u003eRead the Release Notes\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eWe would like to thank the following community members for their contributions to this release of Gradle:\n\u003ca href=\"https://github.com/aSemy\"\u003eAdam\u003c/a\u003e,\n\u003ca href=\"https://github.com/Gautam-aman\"\u003eAman Gautam\u003c/a\u003e,\n\u003ca href=\"https://github.com/YukiCodepth\"\u003eAman Kumar\u003c/a\u003e,\n\u003ca href=\"https://github.com/adubrouski\"\u003eAnton Dubrouski\u003c/a\u003e,\n\u003ca href=\"https://github.com/liutikas\"\u003eAurimas\u003c/a\u003e,\n\u003ca href=\"https://github.com/gbhavya07\"\u003egbhavya07\u003c/a\u003e,\n\u003ca href=\"https://github.com/joshfriend\"\u003eJosh Friend\u003c/a\u003e,\n\u003ca href=\"https://github.com/nicklauslittle-gov\"\u003enicklauslittle-gov\u003c/a\u003e,\n\u003ca href=\"https://github.com/psoni674\"\u003ePragati\u003c/a\u003e,\n\u003ca href=\"https://github.com/Project516\"\u003eproject516\u003c/a\u003e,\n\u003ca href=\"https://github.com/Uomocapra\"\u003eQin Mi\u003c/a\u003e,\n\u003ca href=\"https://github.com/rkdfx\"\u003eRavi\u003c/a\u003e,\n\u003ca href=\"https://github.com/sk-reddy17\"\u003esk-reddy17\u003c/a\u003e,\n\u003ca href=\"https://github.com/Suvrat1629\"\u003eSuvrat Acharya\u003c/a\u003e,\n\u003ca href=\"https://github.com/ShreckYe\"\u003eYongshun Ye\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eUpgrade instructions\u003c/h2\u003e\n\u003cp\u003eSwitch your build to use Gradle 9.7.1 by updating your wrapper:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e./gradlew :wrapper --gradle-version=9.7.1 \u0026amp;\u0026amp; ./gradlew :wrapper\r\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eSee the Gradle \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/upgrading_version_9.html\"\u003e9.x upgrade guide\u003c/a\u003e to learn about deprecations, breaking changes and other considerations when upgrading.\u003c/p\u003e\n\u003cp\u003eFor Java, Groovy, Kotlin and Android compatibility, see the \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/compatibility.html\"\u003efull compatibility notes\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eReporting problems\u003c/h2\u003e\n\u003cp\u003eIf you find a problem with this release, please file a bug on \u003ca href=\"https://github.com/gradle/gradle/issues\"\u003eGitHub Issues\u003c/a\u003e adhering to our issue guidelines.\nIf you're not sure you're encountering a bug, please use the \u003ca href=\"https://discuss.gradle.org/c/help-discuss\"\u003eforum\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eWe hope you will build happiness with Gradle, and we look forward to your feedback via \u003ca href=\"https://twitter.com/gradle\"\u003eTwitter\u003c/a\u003e or on \u003ca href=\"https://github.com/gradle\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003e9.7.0\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.0.\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/92f0512e7f06d84621afba191f75e265363890cf\"\u003e\u003ccode\u003e92f0512\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38892\"\u003e#38892\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/820ee75a99a179bbffa41bcedc6477b685fabb9f\"\u003e\u003ccode\u003e820ee75\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/82c23f9bd2a89b4cc644e1f90a28a8668feb3dee\"\u003e\u003ccode\u003e82c23f9\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering problem in KTS (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38878\"\u003e#38878\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/ef11a7268fe8cc8d6ab849ec911aa11220180553\"\u003e\u003ccode\u003eef11a72\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering issue\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/bb0d8a974a71b1003efea41e4046e98855cd5ff8\"\u003e\u003ccode\u003ebb0d8a9\u003c/code\u003e\u003c/a\u003e Make relevant tests polyglot (run for multiple DSLs)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/336e129d7f95c03486acafc97abf59734acfed48\"\u003e\u003ccode\u003e336e129\u003c/code\u003e\u003c/a\u003e Update signing configuration (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38874\"\u003e#38874\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/4bdf0da2dad9884d089a6062a45ea7183e7d735d\"\u003e\u003ccode\u003e4bdf0da\u003c/code\u003e\u003c/a\u003e Update signing configuration\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/cd9b92c1b82856248cf1dc58b50378238bec7b52\"\u003e\u003ccode\u003ecd9b92c\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38839\"\u003e#38839\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/5f4e381964897ad8d6b99e5a7c77f26dba3259fb\"\u003e\u003ccode\u003e5f4e381\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/1e08ab551367aeb5fb48b26e72807e1d2b27c939\"\u003e\u003ccode\u003e1e08ab5\u003c/code\u003e\u003c/a\u003e Keep type-use annotations in extracted ABI classes (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38810\"\u003e#38810\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/gradle/gradle/compare/v8.11.1...v9.7.1\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `androidx.core:core-ktx` from 1.15.0 to 1.19.0\n\nUpdates `androidx.appcompat:appcompat` from 1.7.0 to 1.8.0\n\nUpdates `androidx.compose:compose-bom` from 2024.12.01 to 2026.08.00\n\nUpdates `androidx.navigation:navigation-compose` from 2.8.5 to 2.10.0\n\nUpdates `com.squareup.okhttp3:okhttp` from 4.12.0 to 5.5.0\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/lysine-dev/okhttp/blob/main/CHANGELOG.md\"\u003ecom.squareup.okhttp3:okhttp's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003eVersion 5.5.0\u003c/h2\u003e\n\u003cp\u003e\u003cem\u003e2026-08-16\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003eThis release introduces \u003cstrong\u003eopt-in\u003c/strong\u003e support for [Encrypted Client Hello (ECH)]. This new feature\nimproves user privacy by encrypting domain names in transit. With regular TLS, your coffee shop’s\nWi-Fi router can see that you’re visiting \u003cem\u003ewikipedia.com\u003c/em\u003e, but it cannot see which page you’re\nlooking at. With ECH, the router observes only the IP address. This additional privacy is most\neffective on sites hosted by big CDNs because the IP address doesn’t imply a particular website.\u003c/p\u003e\n\u003cp\u003eThis requires ECH support in the platform’s TLS stack. Today this is only Android 17 (API 37,\nreleased June 2026). When other TLS stacks add ECH support, we'll integrate them.\u003c/p\u003e\n\u003cp\u003eECH took a lot of work to implement because the encryption keys are published over DNS in the\n[HTTPS resource record], and we needed to write new code to fetch these records. This release\nincludes a major update to OkHttp’s DNS API: it now supports multiple resource record types (not\njust IP addresses!), asynchronous streaming results, and in-memory caching.\u003c/p\u003e\n\u003cp\u003eTo opt in, you can use \u003ccode\u003eDnsOverHttps\u003c/code\u003e:\u003c/p\u003e\n\u003cpre lang=\"kotlin\"\u003e\u003ccode\u003e// DnsOverHttps itself uses OkHttpClient. Build both clients upon the\n// same bootstrap client so they share a connection pool and dispatcher.\nval bootstrapClient = OkHttpClient()\n\u003cp\u003e// This sample uses Cloudflare's 1.1.1.1 DnsOverHttps service.\nval client = bootstrapClient.newBuilder()\n.dns(DnsOverHttps.Builder()\n.client(bootstrapClient)\n.url(\u0026quot;\u003ca href=\"https://1.1.1.1/dns-query\u0026amp;quot;.toHttpUrl()\"\u003ehttps://1.1.1.1/dns-query\u0026amp;quot;.toHttpUrl()\u003c/a\u003e)\n.build())\n.build()\n\u003c/code\u003e\u003c/pre\u003e\u003c/p\u003e\n\u003cp\u003eYou could also opt in with our new \u003ccode\u003eAndroidDns\u003c/code\u003e API. Unfortunately, the privacy benefits of ECH are\nthwarted because its DNS queries are not encrypted by default.\u003c/p\u003e\n\u003cpre lang=\"kotlin\"\u003e\u003ccode\u003e// AndroidDns fetches the HTTPS DNS resource records necessary for ECH.\nval client = OkHttpClient.Builder()\n  .dns(AndroidDns())\n  .build()\n\u003c/code\u003e\u003c/pre\u003e\n\u003cul\u003e\n\u003cli\u003eNew: OkHttp artifacts are now signed with our [new signing key]. This project and three sibling\nprojects ([Retrofit], [Okio], and [SQLDelight]) recently joined [the Commonhaus Foundation].\u003c/li\u003e\n\u003cli\u003eFix: MockWebServer’s \u003ccode\u003e@StartStop\u003c/code\u003e annotation now supports \u003ccode\u003e@Nested\u003c/code\u003e JUnit 5 tests.\u003c/li\u003e\n\u003cli\u003eFix: Our default TLS hostname verifier now reject hosts that fail IP canonicalization.\u003c/li\u003e\n\u003cli\u003eFix: Closing a multipart part's sink no longer closes the entire request body.\u003c/li\u003e\n\u003cli\u003eFix: Flush HTTP/1 request bodies before detaching the timeout. We had a bug where timeouts\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/a94bdf152084d11acecd44dcd09ffef203f4f0aa\"\u003e\u003ccode\u003ea94bdf1\u003c/code\u003e\u003c/a\u003e Prepare for release 5.5.0.\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/ecc3b05adfe6b2607b8ec251562c2cccf7c1923a\"\u003e\u003ccode\u003eecc3b05\u003c/code\u003e\u003c/a\u003e Use a fixed size for DoH request body (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9687\"\u003e#9687\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/9926082660dfa6f1cc848c6f465cf5ccb998e415\"\u003e\u003ccode\u003e9926082\u003c/code\u003e\u003c/a\u003e Revert \u0026quot;Use a fixed size for DoH request body\u0026quot; (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9686\"\u003e#9686\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/0070c2e7b4c162ee03abf1c88fd94083e94697f4\"\u003e\u003ccode\u003e0070c2e\u003c/code\u003e\u003c/a\u003e Use a fixed size for DoH request body\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/15764539c69842dad607462f102a2507223dbfe7\"\u003e\u003ccode\u003e1576453\u003c/code\u003e\u003c/a\u003e Order ServiceMetadata records per the spec (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9683\"\u003e#9683\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/fb582e976a9a82d691342a4d57b3c72208ce416c\"\u003e\u003ccode\u003efb582e9\u003c/code\u003e\u003c/a\u003e Flip wiring of Dns.SYSTEM (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9682\"\u003e#9682\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/4e884abb1a207c321acffb070c476acb4b89fa3f\"\u003e\u003ccode\u003e4e884ab\u003c/code\u003e\u003c/a\u003e retryOnConnectionFailure doesn't impact ECH retries (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9681\"\u003e#9681\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/0433cee8131b63fa2c0634fa2f9b3a01f9a8b1f3\"\u003e\u003ccode\u003e0433cee\u003c/code\u003e\u003c/a\u003e Only one contributing.md doc (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9678\"\u003e#9678\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/a2cf5aa9f8711dabe514871e9dc4a9336a0e403f\"\u003e\u003ccode\u003ea2cf5aa\u003c/code\u003e\u003c/a\u003e Don't recover after an ECH public_name fails to verify (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9680\"\u003e#9680\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/5410de9760bce8719129c3d08eb19e5bace75f6e\"\u003e\u003ccode\u003e5410de9\u003c/code\u003e\u003c/a\u003e Test ECH + HTTP proxy (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9671\"\u003e#9671\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/lysine-dev/okhttp/compare/parent-4.12.0...parent-5.5.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `com.squareup.okhttp3:mockwebserver` from 4.12.0 to 5.5.0\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/lysine-dev/okhttp/blob/main/CHANGELOG.md\"\u003ecom.squareup.okhttp3:mockwebserver's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003eVersion 5.5.0\u003c/h2\u003e\n\u003cp\u003e\u003cem\u003e2026-08-16\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003eThis release introduces \u003cstrong\u003eopt-in\u003c/strong\u003e support for [Encrypted Client Hello (ECH)]. This new feature\nimproves user privacy by encrypting domain names in transit. With regular TLS, your coffee shop’s\nWi-Fi router can see that you’re visiting \u003cem\u003ewikipedia.com\u003c/em\u003e, but it cannot see which page you’re\nlooking at. With ECH, the router observes only the IP address. This additional privacy is most\neffective on sites hosted by big CDNs because the IP address doesn’t imply a particular website.\u003c/p\u003e\n\u003cp\u003eThis requires ECH support in the platform’s TLS stack. Today this is only Android 17 (API 37,\nreleased June 2026). When other TLS stacks add ECH support, we'll integrate them.\u003c/p\u003e\n\u003cp\u003eECH took a lot of work to implement because the encryption keys are published over DNS in the\n[HTTPS resource record], and we needed to write new code to fetch these records. This release\nincludes a major update to OkHttp’s DNS API: it now supports multiple resource record types (not\njust IP addresses!), asynchronous streaming results, and in-memory caching.\u003c/p\u003e\n\u003cp\u003eTo opt in, you can use \u003ccode\u003eDnsOverHttps\u003c/code\u003e:\u003c/p\u003e\n\u003cpre lang=\"kotlin\"\u003e\u003ccode\u003e// DnsOverHttps itself uses OkHttpClient. Build both clients upon the\n// same bootstrap client so they share a connection pool and dispatcher.\nval bootstrapClient = OkHttpClient()\n\u003cp\u003e// This sample uses Cloudflare's 1.1.1.1 DnsOverHttps service.\nval client = bootstrapClient.newBuilder()\n.dns(DnsOverHttps.Builder()\n.client(bootstrapClient)\n.url(\u0026quot;\u003ca href=\"https://1.1.1.1/dns-query\u0026amp;quot;.toHttpUrl()\"\u003ehttps://1.1.1.1/dns-query\u0026amp;quot;.toHttpUrl()\u003c/a\u003e)\n.build())\n.build()\n\u003c/code\u003e\u003c/pre\u003e\u003c/p\u003e\n\u003cp\u003eYou could also opt in with our new \u003ccode\u003eAndroidDns\u003c/code\u003e API. Unfortunately, the privacy benefits of ECH are\nthwarted because its DNS queries are not encrypted by default.\u003c/p\u003e\n\u003cpre lang=\"kotlin\"\u003e\u003ccode\u003e// AndroidDns fetches the HTTPS DNS resource records necessary for ECH.\nval client = OkHttpClient.Builder()\n  .dns(AndroidDns())\n  .build()\n\u003c/code\u003e\u003c/pre\u003e\n\u003cul\u003e\n\u003cli\u003eNew: OkHttp artifacts are now signed with our [new signing key]. This project and three sibling\nprojects ([Retrofit], [Okio], and [SQLDelight]) recently joined [the Commonhaus Foundation].\u003c/li\u003e\n\u003cli\u003eFix: MockWebServer’s \u003ccode\u003e@StartStop\u003c/code\u003e annotation now supports \u003ccode\u003e@Nested\u003c/code\u003e JUnit 5 tests.\u003c/li\u003e\n\u003cli\u003eFix: Our default TLS hostname verifier now reject hosts that fail IP canonicalization.\u003c/li\u003e\n\u003cli\u003eFix: Closing a multipart part's sink no longer closes the entire request body.\u003c/li\u003e\n\u003cli\u003eFix: Flush HTTP/1 request bodies before detaching the timeout. We had a bug where timeouts\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/a94bdf152084d11acecd44dcd09ffef203f4f0aa\"\u003e\u003ccode\u003ea94bdf1\u003c/code\u003e\u003c/a\u003e Prepare for release 5.5.0.\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/ecc3b05adfe6b2607b8ec251562c2cccf7c1923a\"\u003e\u003ccode\u003eecc3b05\u003c/code\u003e\u003c/a\u003e Use a fixed size for DoH request body (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9687\"\u003e#9687\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/9926082660dfa6f1cc848c6f465cf5ccb998e415\"\u003e\u003ccode\u003e9926082\u003c/code\u003e\u003c/a\u003e Revert \u0026quot;Use a fixed size for DoH request body\u0026quot; (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9686\"\u003e#9686\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/0070c2e7b4c162ee03abf1c88fd94083e94697f4\"\u003e\u003ccode\u003e0070c2e\u003c/code\u003e\u003c/a\u003e Use a fixed size for DoH request body\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/15764539c69842dad607462f102a2507223dbfe7\"\u003e\u003ccode\u003e1576453\u003c/code\u003e\u003c/a\u003e Order ServiceMetadata records per the spec (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9683\"\u003e#9683\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/fb582e976a9a82d691342a4d57b3c72208ce416c\"\u003e\u003ccode\u003efb582e9\u003c/code\u003e\u003c/a\u003e Flip wiring of Dns.SYSTEM (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9682\"\u003e#9682\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/4e884abb1a207c321acffb070c476acb4b89fa3f\"\u003e\u003ccode\u003e4e884ab\u003c/code\u003e\u003c/a\u003e retryOnConnectionFailure doesn't impact ECH retries (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9681\"\u003e#9681\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/0433cee8131b63fa2c0634fa2f9b3a01f9a8b1f3\"\u003e\u003ccode\u003e0433cee\u003c/code\u003e\u003c/a\u003e Only one contributing.md doc (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9678\"\u003e#9678\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/a2cf5aa9f8711dabe514871e9dc4a9336a0e403f\"\u003e\u003ccode\u003ea2cf5aa\u003c/code\u003e\u003c/a\u003e Don't recover after an ECH public_name fails to verify (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9680\"\u003e#9680\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/5410de9760bce8719129c3d08eb19e5bace75f6e\"\u003e\u003ccode\u003e5410de9\u003c/code\u003e\u003c/a\u003e Test ECH + HTTP proxy (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9671\"\u003e#9671\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/lysine-dev/okhttp/compare/parent-4.12.0...parent-5.5.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `com.squareup.okhttp3:mockwebserver` from 4.12.0 to 5.5.0\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/lysine-dev/okhttp/blob/main/CHANGELOG.md\"\u003ecom.squareup.okhttp3:mockwebserver's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003eVersion 5.5.0\u003c/h2\u003e\n\u003cp\u003e\u003cem\u003e2026-08-16\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003eThis release introduces \u003cstrong\u003eopt-in\u003c/strong\u003e support for [Encrypted Client Hello (ECH)]. This new feature\nimproves user privacy by encrypting domain names in transit. With regular TLS, your coffee shop’s\nWi-Fi router can see that you’re visiting \u003cem\u003ewikipedia.com\u003c/em\u003e, but it cannot see which page you’re\nlooking at. With ECH, the router observes only the IP address. This additional privacy is most\neffective on sites hosted by big CDNs because the IP address doesn’t imply a particular website.\u003c/p\u003e\n\u003cp\u003eThis requires ECH support in the platform’s TLS stack. Today this is only Android 17 (API 37,\nreleased June 2026). When other TLS stacks add ECH support, we'll integrate them.\u003c/p\u003e\n\u003cp\u003eECH took a lot of work to implement because the encryption keys are published over DNS in the\n[HTTPS resource record], and we needed to write new code to fetch these records. This release\nincludes a major update to OkHttp’s DNS API: it now supports multiple resource record types (not\njust IP addresses!), asynchronous streaming results, and in-memory caching.\u003c/p\u003e\n\u003cp\u003eTo opt in, you can use \u003ccode\u003eDnsOverHttps\u003c/code\u003e:\u003c/p\u003e\n\u003cpre lang=\"kotlin\"\u003e\u003ccode\u003e// DnsOverHttps itself uses OkHttpClient. Build both clients upon the\n// same bootstrap client so they share a connection pool and dispatcher.\nval bootstrapClient = OkHttpClient()\n\u003cp\u003e// This sample uses Cloudflare's 1.1.1.1 DnsOverHttps service.\nval client = bootstrapClient.newBuilder()\n.dns(DnsOverHttps.Builder()\n.client(bootstrapClient)\n.url(\u0026quot;\u003ca href=\"https://1.1.1.1/dns-query\u0026amp;quot;.toHttpUrl()\"\u003ehttps://1.1.1.1/dns-query\u0026amp;quot;.toHttpUrl()\u003c/a\u003e)\n.build())\n.build()\n\u003c/code\u003e\u003c/pre\u003e\u003c/p\u003e\n\u003cp\u003eYou could also opt in with our new \u003ccode\u003eAndroidDns\u003c/code\u003e API. Unfortunately, the privacy benefits of ECH are\nthwarted because its DNS queries are not encrypted by default.\u003c/p\u003e\n\u003cpre lang=\"kotlin\"\u003e\u003ccode\u003e// AndroidDns fetches the HTTPS DNS resource records necessary for ECH.\nval client = OkHttpClient.Builder()\n  .dns(AndroidDns())\n  .build()\n\u003c/code\u003e\u003c/pre\u003e\n\u003cul\u003e\n\u003cli\u003eNew: OkHttp artifacts are now signed with our [new signing key]. This project and three sibling\nprojects ([Retrofit], [Okio], and [SQLDelight]) recently joined [the Commonhaus Foundation].\u003c/li\u003e\n\u003cli\u003eFix: MockWebServer’s \u003ccode\u003e@StartStop\u003c/code\u003e annotation now supports \u003ccode\u003e@Nested\u003c/code\u003e JUnit 5 tests.\u003c/li\u003e\n\u003cli\u003eFix: Our default TLS hostname verifier now reject hosts that fail IP canonicalization.\u003c/li\u003e\n\u003cli\u003eFix: Closing a multipart part's sink no longer closes the entire request body.\u003c/li\u003e\n\u003cli\u003eFix: Flush HTTP/1 request bodies before detaching the timeout. We had a bug where timeouts\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/a94bdf152084d11acecd44dcd09ffef203f4f0aa\"\u003e\u003ccode\u003ea94bdf1\u003c/code\u003e\u003c/a\u003e Prepare for release 5.5.0.\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/ecc3b05adfe6b2607b8ec251562c2cccf7c1923a\"\u003e\u003ccode\u003eecc3b05\u003c/code\u003e\u003c/a\u003e Use a fixed size for DoH request body (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9687\"\u003e#9687\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/9926082660dfa6f1cc848c6f465cf5ccb998e415\"\u003e\u003ccode\u003e9926082\u003c/code\u003e\u003c/a\u003e Revert \u0026quot;Use a fixed size for DoH request body\u0026quot; (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9686\"\u003e#9686\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/0070c2e7b4c162ee03abf1c88fd94083e94697f4\"\u003e\u003ccode\u003e0070c2e\u003c/code\u003e\u003c/a\u003e Use a fixed size for DoH request body\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/15764539c69842dad607462f102a2507223dbfe7\"\u003e\u003ccode\u003e1576453\u003c/code\u003e\u003c/a\u003e Order ServiceMetadata records per the spec (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9683\"\u003e#9683\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/fb582e976a9a82d691342a4d57b3c72208ce416c\"\u003e\u003ccode\u003efb582e9\u003c/code\u003e\u003c/a\u003e Flip wiring of Dns.SYSTEM (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9682\"\u003e#9682\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/4e884abb1a207c321acffb070c476acb4b89fa3f\"\u003e\u003ccode\u003e4e884ab\u003c/code\u003e\u003c/a\u003e retryOnConnectionFailure doesn't impact ECH retries (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9681\"\u003e#9681\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/0433cee8131b63fa2c0634fa2f9b3a01f9a8b1f3\"\u003e\u003ccode\u003e0433cee\u003c/code\u003e\u003c/a\u003e Only one contributing.md doc (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9678\"\u003e#9678\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/a2cf5aa9f8711dabe514871e9dc4a9336a0e403f\"\u003e\u003ccode\u003ea2cf5aa\u003c/code\u003e\u003c/a\u003e Don't recover after an ECH public_name fails to verify (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9680\"\u003e#9680\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/5410de9760bce8719129c3d08eb19e5bace75f6e\"\u003e\u003ccode\u003e5410de9\u003c/code\u003e\u003c/a\u003e Test ECH + HTTP proxy (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9671\"\u003e#9671\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/lysine-dev/okhttp/compare/parent-4.12.0...parent-5.5.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.jetbrains.kotlinx:kotlinx-serialization-json` from 1.7.3 to 1.11.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/Kotlin/kotlinx.serialization/releases\"\u003eorg.jetbrains.kotlinx:kotlinx-serialization-json's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e1.11.0\u003c/h2\u003e\n\u003cp\u003eThis release is based on Kotlin 2.3.20 and provides a new Json exceptions API and some bugfixes and improvements.\u003c/p\u003e\n\u003ch2\u003eExpose Json exceptions structure\u003c/h2\u003e\n\u003cp\u003eTo make working with exceptions easier and providing proper error codes in e.g., REST APIs,\nclasses \u003ccode\u003eJsonException\u003c/code\u003e, \u003ccode\u003eJsonDecodingException\u003c/code\u003e, and \u003ccode\u003eJsonEncodingException\u003c/code\u003e are now public.\nThey have relevant public properties, such as \u003ccode\u003eshortMessage\u003c/code\u003e, \u003ccode\u003epath\u003c/code\u003e, \u003ccode\u003eoffset\u003c/code\u003e, and others.\nThis API is currently experimental, and we're going to improve it further in the subsequent releases.\nSee the linked issues for the details: \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/1930\"\u003e#1930\u003c/a\u003e, \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/1877\"\u003e#1877\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eAbility to hide user input from exception messages for security/privacy reasons.\u003c/h2\u003e\n\u003cp\u003eHistorically, exception messages in kotlinx.serialization often included the input Json itself for debuggability reason.\nSuch behavior may pose additional challenges for logging, analytics, and other systems, since\na system is not always allowed to store user data due to privacy/security reasons, which imposes additional sanitation logic.\nTo address this issue, a new property \u003ccode\u003eexceptionsWithDebugInfo\u003c/code\u003e is added to \u003ccode\u003eJsonConfiguration\u003c/code\u003e.\nDisable it to hide user input from exception messages.\nIMPORTANT: This behavior will be enabled by default when this property becomes stable.\nSee \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/2590\"\u003e#2590\u003c/a\u003e for more details.\u003c/p\u003e\n\u003ch2\u003eBugfixes and improvements\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eCBOR: Relax value range check when decoding numbers (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/3167\"\u003e#3167\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eUse a specialized writeDecimalLong method for IO stream integrations in Json (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/3152\"\u003e#3152\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e1.10.0\u003c/h2\u003e\n\u003cp\u003eThis release is based on Kotlin 2.3.0 and contains all of the changes from 1.10.0-RC.\nThe only additional change is a fix for ProtoBuf packing of Kotlin unsigned types (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/3079\"\u003e#3079\u003c/a\u003e).\nBig thanks to \u003ca href=\"https://github.com/KosmX\"\u003eKosmX\u003c/a\u003e for contributing the fix.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eFor your convenience, the changelog for 1.10.0-RC is duplicated below:\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch2\u003eStabilization of APIs\u003c/h2\u003e\n\u003cp\u003ekotlinx-serialization 1.10 and subsequent releases will be focused on stabilization of existing APIs.\nThe following APIs and configuration options are no longer experimental because they're widely used without any known major issues:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003eJson\u003c/code\u003e configuration options: \u003ccode\u003edecodeEnumsCaseInsensitive\u003c/code\u003e, \u003ccode\u003eallowTrailingComma\u003c/code\u003e, \u003ccode\u003eallowComments\u003c/code\u003e, and \u003ccode\u003eprettyPrintIndent\u003c/code\u003e. (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/3100\"\u003e#3100\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e@EncodeDefault\u003c/code\u003e annotation and its modes. (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/3106\"\u003e#3106\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eJsonUnquotedLiteral\u003c/code\u003e constructor function (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/2900\"\u003e#2900\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eJsonPrimitive\u003c/code\u003e constructor function overloads that accept unsigned types. (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/3117\"\u003e#3117\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eJSON DSL functions on \u003ccode\u003eJsonElement\u003c/code\u003e with \u003ccode\u003eNothing?\u003c/code\u003e overloads. (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/3117\"\u003e#3117\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003eReadiness for return value checker\u003c/h2\u003e\n\u003cp\u003eKotlin 2.3.0 \u003ca href=\"https://kotlinlang.org/docs/whatsnew23.html#unused-return-value-checker\"\u003eintroduces a new feature\u003c/a\u003e aimed at helping you to catch bugs related to the accidentally ignored return value of the function.\nkotlinx-serialization 1.10.0-RC code is fully marked for this feature, meaning that you can get warnings for unused function calls like \u003ccode\u003eJson.encodeToString(...)\u003c/code\u003e. To get the warnings, the feature has to be enabled in your project as \u003ca href=\"https://kotlinlang.org/docs/unused-return-value-checker.html#configure-the-unused-return-value-checker\"\u003edescribed here\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003ePolymorphism improvements\u003c/h2\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/Kotlin/kotlinx.serialization/blob/master/CHANGELOG.md\"\u003eorg.jetbrains.kotlinx:kotlinx-serialization-json's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch1\u003e1.11.0 / 2026-04-10\u003c/h1\u003e\n\u003cp\u003eThis release is based on Kotlin 2.3.20 and provides new Json exceptions API and some bugfixes and improvements.\u003c/p\u003e\n\u003ch2\u003eExpose Json exceptions structure\u003c/h2\u003e\n\u003cp\u003eTo make working with exceptions easier and providing proper error codes in e.g., REST APIs,\nclasses \u003ccode\u003eJsonException\u003c/code\u003e, \u003ccode\u003eJsonDecodingException\u003c/code\u003e, and \u003ccode\u003eJsonEncodingException\u003c/code\u003e are now public.\nThey have relevant public properties, such as \u003ccode\u003eshortMessage\u003c/code\u003e, \u003ccode\u003epath\u003c/code\u003e, \u003ccode\u003eoffset\u003c/code\u003e, and others.\nThis API is currently experimental, and we're going to improve it further in the subsequent releases.\nSee the linked issues for the details: \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/1930\"\u003e#1930\u003c/a\u003e, \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/1877\"\u003e#1877\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eAbility to hide user input from exception messages for security/privacy reasons.\u003c/h2\u003e\n\u003cp\u003eHistorically, exception messages in kotlinx.serialization often included the input Json itself for debuggability reason.\nSuch behavior may pose additional challenges for logging, analytics, and other systems, since\na system is not always allowed to store user data due to privacy/security reasons, which imposes additional sanitation logic.\nTo address this issue, a new property \u003ccode\u003eexceptionsWithDebugInfo\u003c/code\u003e is added to \u003ccode\u003eJsonConfiguration\u003c/code\u003e.\nDisable it to hide user input from exception messages.\nIMPORTANT: This behavior will be enabled by default when this property becomes stable.\nSee \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/2590\"\u003e#2590\u003c/a\u003e for more details.\u003c/p\u003e\n\u003ch2\u003eBugfixes and improvements\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eCBOR: Relax value range check when decoding numbers (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/3167\"\u003e#3167\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eUse a specialized writeDecimalLong method for IO stream integrations in Json (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/3152\"\u003e#3152\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1\u003e1.10.0 / 2026-01-21\u003c/h1\u003e\n\u003cp\u003eThis release is based on Kotlin 2.3.0 and contains all of the changes from 1.10.0-RC.\nThe only additional change is a fix for ProtoBuf packing of Kotlin unsigned types (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/3079\"\u003e#3079\u003c/a\u003e).\nBig thanks to \u003ca href=\"https://github.com/KosmX\"\u003eKosmX\u003c/a\u003e for contributing the fix.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eFor your convenience, the changelog for 1.10.0-RC is duplicated below:\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch2\u003eStabilization of APIs\u003c/h2\u003e\n\u003cp\u003ekotlinx-serialization 1.10 and subsequent releases will be focused on stabilization of existing APIs.\nThe following APIs and configuration options are no longer experimental because they're widely used without any known major issues:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003eJson\u003c/code\u003e configuration options: \u003ccode\u003edecodeEnumsCaseInsensitive\u003c/code\u003e, \u003ccode\u003eallowTrailingComma\u003c/code\u003e, \u003ccode\u003eallowComments\u003c/code\u003e, and \u003ccode\u003eprettyPrintIndent\u003c/code\u003e. (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/3100\"\u003e#3100\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e@EncodeDefault\u003c/code\u003e annotation and its modes. (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/3106\"\u003e#3106\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eJsonUnquotedLiteral\u003c/code\u003e constructor function (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/2900\"\u003e#2900\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eJsonPrimitive\u003c/code\u003e constructor function overloads that accept unsigned types. (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/3117\"\u003e#3117\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eJSON DSL functions on \u003ccode\u003eJsonElement\u003c/code\u003e with \u003ccode\u003eNothing?\u003c/code\u003e overloads. (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/3117\"\u003e#3117\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003eReadiness for return value checker\u003c/h2\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.serialization/commit/6956af2e6073347c7832c3c5b374fa3b5a345956\"\u003e\u003ccode\u003e6956af2\u003c/code\u003e\u003c/a\u003e Prepare 1.11 release\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.serialization/commit/390d84c68a19cbf7fa453dec22a333648bde49b4\"\u003e\u003ccode\u003e390d84c\u003c/code\u003e\u003c/a\u003e Merge remote-tracking branch 'origin/master' into dev\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.serialization/commit/431fe2dc0a144300b33038820d24fc30302c8abc\"\u003e\u003ccode\u003e431fe2d\u003c/code\u003e\u003c/a\u003e Use local repo for publishing (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/3171\"\u003e#3171\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.serialization/commit/05c12b60a6717b99053fb82e1f94d2f859727374\"\u003e\u003ccode\u003e05c12b6\u003c/code\u003e\u003c/a\u003e Add usage attribute to \u0026quot;testRepositories\u0026quot; configuration\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.serialization/commit/a4e1f082ef2e72caa139b474c05657de6015da20\"\u003e\u003ccode\u003ea4e1f08\u003c/code\u003e\u003c/a\u003e Bump Kover version to 0.9.8 release (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/3174\"\u003e#3174\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.serialization/commit/304e858ccc7066854637d86ab80056f5f2bcc094\"\u003e\u003ccode\u003e304e858\u003c/code\u003e\u003c/a\u003e Expose Json exceptions structure (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/3145\"\u003e#3145\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.serialization/commit/4a0338ef5093d765138151bc30282e909ca459e4\"\u003e\u003ccode\u003e4a0338e\u003c/code\u003e\u003c/a\u003e Included G Play SDK verification file for core-jvm (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/3169\"\u003e#3169\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.serialization/commit/421f64c74f0ea6d4a3cdc8dd483505366e3f6c8f\"\u003e\u003ccode\u003e421f64c\u003c/code\u003e\u003c/a\u003e CBOR: Relax value range check when decoding numbers (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/3167\"\u003e#3167\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.serialization/commit/85a4f126ec491c77e2b3686cc22c1bae27a20783\"\u003e\u003ccode\u003e85a4f12\u003c/code\u003e\u003c/a\u003e KT-84955: mark apple x64 tagets as deprecated error\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.serialization/commit/bd38b0e49bce38d1a55576e89856bc63990167ed\"\u003e\u003ccode\u003ebd38b0e\u003c/code\u003e\u003c/a\u003e Remove dead code\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/Kotlin/kotlinx.serialization/compare/v1.7.3...v1.11.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `androidx.biometric:biometric` from 1.2.0-alpha05 to 1.4.0-alpha07\n\nUpdates `org.jetbrains.kotlinx:kotlinx-coroutines-android` from 1.9.0 to 1.11.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/Kotlin/kotlinx.coroutines/releases\"\u003eorg.jetbrains.kotlinx:kotlinx-coroutines-android's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e1.11.0\u003c/h2\u003e\n\u003ch3\u003eVarious\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eKotlin was updated to 2.2.20 (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4545\"\u003e#4545\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eImproved the published jar files (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/3842\"\u003e#3842\u003c/a\u003e, \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4599\"\u003e#4599\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eVarious documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4433\"\u003e#4433\u003c/a\u003e, \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4596\"\u003e#4596\u003c/a\u003e).\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eBreaking changes and deprecations\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eMoved \u003ccode\u003ePromise\u003c/code\u003e-related functions from JS and Wasm/JS to the new \u003ccode\u003eweb\u003c/code\u003e target. On Wasm/JS, this is a breaking change. Before the change, \u003ccode\u003ePromise\u003c/code\u003e on Wasm/JS could work with arbitrary Kotlin types, but now, only \u003ccode\u003eJsAny\u003c/code\u003e subtypes are accepted (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4563\"\u003e#4563\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eChanged handling of coroutine exceptions that can't be propagated on JS and Wasm/JS. B\nefore, exceptions were logged, but now, they are reported to the JS runtime (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4451\"\u003e#4451\u003c/a\u003e, \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4631\"\u003e#4631\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eDeprecated using \u003ccode\u003eCoroutineDispatcher\u003c/code\u003e as the coroutine context key; now, \u003ccode\u003eContinuationInterceptor\u003c/code\u003e has to be used instead (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4333\"\u003e#4333\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdvanced the deprecation levels on \u003ccode\u003ekotlinx-coroutines-test\u003c/code\u003e APIs (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4604\"\u003e#4604\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdded lint functions that mark passing a \u003ccode\u003eJob\u003c/code\u003e to coroutine builders as deprecated (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4435\"\u003e#4435\u003c/a\u003e).\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eBug fixes and improvements\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eAdded a \u003ccode\u003ecallsInPlace(EXACTLY_ONCE)\u003c/code\u003e contract to \u003ccode\u003erunBlocking\u003c/code\u003e in code shared between JVM and Native (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4368\"\u003e#4368\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdded a \u003ccode\u003ecallsInPlace(EXACTLY_ONCE)\u003c/code\u003e contract to \u003ccode\u003esuspendCancellableCoroutine\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4574\"\u003e#4574\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFixed \u003ccode\u003eflowOn\u003c/code\u003e incorrectly handling \u003ccode\u003eThreadContextElement\u003c/code\u003e updates (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4403\"\u003e#4403\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFixed exceptions in user-supplied \u003ccode\u003eThread.UncaughtExceptionHandler\u003c/code\u003e instances causing the internal coroutines machinery to fail (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4516\"\u003e#4516\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFixed \u003ccode\u003eCoroutineDispatcher.asScheduler\u003c/code\u003e in the RxJava integration not cancelling outstanding work when a \u003ccode\u003eWorker\u003c/code\u003e gets cancelled, which led to memory leaks in some scenarios (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4615\"\u003e#4615\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFixed \u003ccode\u003eSharedFlow\u003c/code\u003e entering an invalid state when a subscriber and an emitter are cancelled simultaneously (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4583\"\u003e#4583\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFixed an R8 optimization leading to \u003ccode\u003eshareIn\u003c/code\u003e/\u003ccode\u003estateIn\u003c/code\u003e coroutines getting garbage-collected (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4646\"\u003e#4646\u003c/a\u003e). Thanks, \u003ca href=\"https://github.com/solevic\"\u003e\u003ccode\u003e@​solevic\u003c/code\u003e\u003c/a\u003e!\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eSmall additions\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eAdded \u003ccode\u003eCompletableDeferred.asDeferred\u003c/code\u003e for obtaining a read-only \u003ccode\u003eDeferred\u003c/code\u003e view (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4408\"\u003e#4408\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdded \u003ccode\u003eSharedFlow.asFlow\u003c/code\u003e for obtaining a \u003ccode\u003eFlow\u003c/code\u003e view with hidden hot flow semantics (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4530\"\u003e#4530\u003c/a\u003e). Thanks, \u003ca href=\"https://github.com/g000sha256\"\u003e\u003ccode\u003e@​g000sha256\u003c/code\u003e\u003c/a\u003e!\u003c/li\u003e\n\u003cli\u003eAdded a \u003ccode\u003eStateFlow.collectLatest\u003c/code\u003e overload returning \u003ccode\u003eNothing\u003c/code\u003e to assist with finding unreachable code (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4454\"\u003e#4454\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdded \u003ccode\u003eReceiveChannel.consumeTo\u003c/code\u003e for consuming a \u003ccode\u003eReceiveChannel\u003c/code\u003e into a \u003ccode\u003eMutableCollection\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4520\"\u003e#4520\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdded a \u003ccode\u003eStateFlow\u0026lt;T\u0026gt;.onSubscription\u003c/code\u003e overload returning a \u003ccode\u003eStateFlow\u0026lt;T\u0026gt;\u003c/code\u003e, similar to \u003ccode\u003eSharedFlow\u0026lt;T\u0026gt;.onSubscription\u003c/code\u003e returning \u003ccode\u003eSharedFlow\u0026lt;T\u0026gt;\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4275\"\u003e#4275\u003c/a\u003e). Thanks, \u003ca href=\"https://github.com/xit0c\"\u003e\u003ccode\u003e@​xit0c\u003c/code\u003e\u003c/a\u003e!\u003c/li\u003e\n\u003cli\u003eAdded terminal \u003ccode\u003eFlow\u003c/code\u003e operators for collecting a \u003ccode\u003eFlow\u003c/code\u003e to a \u003ccode\u003eMap\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/1541\"\u003e#1541\u003c/a\u003e).\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChangelog relative to version 1.11.0\u003c/h3\u003e\n\u003cp\u003eNo changes, only the version is increased.\u003c/p\u003e\n\u003ch2\u003e1.11.0-rc02\u003c/h2\u003e\n\u003cp\u003eRestored binary compatibility with 1.10.2 and older versions on Wasm/JS for usages of \u003ccode\u003ePromise\u003c/code\u003e-related functions (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4661\"\u003e#4661\u003c/a\u003e).\u003c/p\u003e\n\u003ch2\u003e1.11.0-rc01\u003c/h2\u003e\n\u003ch3\u003eVarious\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eKotlin was updated to 2.2.20 (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4545\"\u003e#4545\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eImproved the published jar files (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/3842\"\u003e#3842\u003c/a\u003e, \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4599\"\u003e#4599\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eVarious documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4433\"\u003e#4433\u003c/a\u003e, \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4596\"\u003e#4596\u003c/a\u003e).\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eBreaking changes and deprecations\u003c/h3\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/Kotlin/kotlinx.coroutines/blob/master/CHANGES.md\"\u003eorg.jetbrains.kotlinx:kotlinx-coroutines-android's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003eVersion 1.11.0\u003c/h2\u003e\n\u003ch3\u003eVarious\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eKotlin was updated to 2.2.20 (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4545\"\u003e#4545\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eImproved the published jar files (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/3842\"\u003e#3842\u003c/a\u003e, \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4599\"\u003e#4599\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eVarious documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4433\"\u003e#4433\u003c/a\u003e, \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4596\"\u003e#4596\u003c/a\u003e).\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eBreaking changes and deprecations\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eMoved \u003ccode\u003ePromise\u003c/code\u003e-related functions from JS and Wasm/JS to the new \u003ccode\u003eweb\u003c/code\u003e target. On Wasm/JS, this is a breaking change. Before the change, \u003ccode\u003ePromise\u003c/code\u003e on Wasm/JS could work with arbitrary Kotlin types, but now, only \u003ccode\u003eJsAny\u003c/code\u003e subtypes are accepted (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4563\"\u003e#4563\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eChanged handling of coroutine exceptions that can't be propagated on JS and Wasm/JS. Before, exceptions were logged, but now, they are reported to the JS runtime (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4451\"\u003e#4451\u003c/a\u003e, \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4631\"\u003e#4631\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eDeprecated using \u003ccode\u003eCoroutineDispatcher\u003c/code\u003e as the coroutine context key; now, \u003ccode\u003eContinuationInterceptor\u003c/code\u003e has to be used instead (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4333\"\u003e#4333\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdvanced the deprecation levels on \u003ccode\u003ekotlinx-coroutines-test\u003c/code\u003e APIs (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4604\"\u003e#4604\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdded lint functions that mark passing a \u003ccode\u003eJob\u003c/code\u003e to coroutine builders as deprecated (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4435\"\u003e#4435\u003c/a\u003e).\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eBug fixes and improvements\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eAdded a \u003ccode\u003ecallsInPlace(EXACTLY_ONCE)\u003c/code\u003e contract to \u003ccode\u003erunBlocking\u003c/code\u003e in code shared between JVM and Native (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4368\"\u003e#4368\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdded a \u003ccode\u003ecallsInPlace(EXACTLY_ONCE)\u003c/code\u003e contract to \u003ccode\u003esuspendCancellableCoroutine\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4574\"\u003e#4574\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFixed \u003ccode\u003eflowOn\u003c/code\u003e incorrectly handling \u003ccode\u003eThreadContextElement\u003c/code\u003e updates (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4403\"\u003e#4403\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFixed exceptions in user-supplied \u003ccode\u003eThread.UncaughtExceptionHandler\u003c/code\u003e instances causing the internal coroutines machinery to fail (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4516\"\u003e#4516\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFixed \u003ccode\u003eCoroutineDispatcher.asScheduler\u003c/code\u003e in the RxJava integration not cancelling outstanding work when a \u003ccode\u003eWorker\u003c/code\u003e gets cancelled, which led to memory leaks in some scenarios (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4615\"\u003e#4615\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFixed \u003ccode\u003eSharedFlow\u003c/code\u003e entering an invalid state when a subscriber and an emitter are cancelled simultaneously (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4583\"\u003e#4583\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFixed an R8 optimization leading to \u003ccode\u003eshareIn\u003c/code\u003e/\u003ccode\u003estateIn\u003c/code\u003e coroutines getting garbage-collected (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4646\"\u003e#4646\u003c/a\u003e). Thanks, \u003ca href=\"https://github.com/solevic\"\u003e\u003ccode\u003e@​solevic\u003c/code\u003e\u003c/a\u003e!\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eSmall additions\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eAdded \u003ccode\u003eCompletableDeferred.asDeferred\u003c/code\u003e for obtaining a read-only \u003ccode\u003eDeferred\u003c/code\u003e view (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4408\"\u003e#4408\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdded \u003ccode\u003eSharedFlow.asFlow\u003c/code\u003e for obtaining a \u003ccode\u003eFlow\u003c/code\u003e view with hidden hot flow semantics (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4530\"\u003e#4530\u003c/a\u003e). Thanks, \u003ca href=\"https://github.com/g000sha256\"\u003e\u003ccode\u003e@​g000sha256\u003c/code\u003e\u003c/a\u003e!\u003c/li\u003e\n\u003cli\u003eAdded a \u003ccode\u003eStateFlow.collectLatest\u003c/code\u003e overload returning \u003ccode\u003eNothing\u003c/code\u003e to assist with finding unreachable code (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4454\"\u003e#4454\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdded \u003ccode\u003eReceiveChannel.consumeTo\u003c/code\u003e for consuming a \u003ccode\u003eReceiveChannel\u003c/code\u003e into a \u003ccode\u003eMutableCollection\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4520\"\u003e#4520\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdded a \u003ccode\u003eStateFlow\u0026lt;T\u0026gt;.onSubscription\u003c/code\u003e overload returning a \u003ccode\u003eStateFlow\u0026lt;T\u0026gt;\u003c/code\u003e, similar to \u003ccode\u003eSharedFlow\u0026lt;T\u0026gt;.onSubscription\u003c/code\u003e returning \u003ccode\u003eSharedFlow\u0026lt;T\u0026gt;\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4275\"\u003e#4275\u003c/a\u003e). Thanks, \u003ca href=\"https://github.com/xit0c\"\u003e\u003ccode\u003e@​xit0c\u003c/code\u003e\u003c/a\u003e!\u003c/li\u003e\n\u003cli\u003eAdded terminal \u003ccode\u003eFlow\u003c/code\u003e operators for collecting a \u003ccode\u003eFlow\u003c/code\u003e to a \u003ccode\u003eMap\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/1541\"\u003e#1541\u003c/a\u003e).\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChangelog relative to version 1.11.0\u003c/h3\u003e\n\u003cp\u003eNo changes, only the version is increased.\u003c/p\u003e\n\u003ch2\u003eVersion 1.11.0-rc02\u003c/h2\u003e\n\u003cp\u003eRestored binary compatibility with 1.10.2 and older versions on Wasm/JS for usages of \u003ccode\u003ePromise\u003c/code\u003e-related functions (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4661\"\u003e#4661\u003c/a\u003e).\u003c/p\u003e\n\u003ch2\u003eVersion 1.11.0-rc01\u003c/h2\u003e\n\u003ch3\u003eVarious\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eKotlin was updated to 2.2.20 (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4545\"\u003e#4545\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eImproved the published jar files (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/3842\"\u003e#3842\u003c/a\u003e, \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4599\"\u003e#4599\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eVarious documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4433\"\u003e#4433\u003c/a\u003e, \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4596\"\u003e#4596\u003c/a\u003e).\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.coroutines/commit/8564f65764d3d05893cec026c6e94250e2b23874\"\u003e\u003ccode\u003e8564f65\u003c/code\u003e\u003c/a\u003e Version 1.11.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.coroutines/commit/a4c6af96c15fe30f5d4e8b810ea74f8babd5805c\"\u003e\u003ccode\u003ea4c6af9\u003c/code\u003e\u003c/a\u003e Merge remote-tracking branch 'origin/master' into develop\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.coroutines/commit/ef917b460aa741691fbf991ee1b813049cae18c9\"\u003e\u003ccode\u003eef917b4\u003c/code\u003e\u003c/a\u003e KT-84955: mark apple x64 tagets as deprecated error (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4645\"\u003e#4645\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.coroutines/commit/5ebc421e341bf2ddce734d369da87df1985e80bd\"\u003e\u003ccode\u003e5ebc421\u003c/code\u003e\u003c/a\u003e Update the release procedure description (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4670\"\u003e#4670\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.coroutines/commit/95f46a073bc4a1230352108cea1835fd22219a80\"\u003e\u003ccode\u003e95f46a0\u003c/code\u003e\u003c/a\u003e Remove old maven repository settings (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4672\"\u003e#4672\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.coroutines/commit/b4f4f0aa6acb692f3fbcadd70e4958e3e9d370fc\"\u003e\u003ccode\u003eb4f4f0a\u003c/code\u003e\u003c/a\u003e Fix package name of \u003ccode\u003eToMapCollectionSamplesTest\u003c/code\u003e. (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4674\"\u003e#4674\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.coroutines/commit/86738dca7dc9ac82249abc8206263fa0065ee631\"\u003e\u003ccode\u003e86738dc\u003c/code\u003e\u003c/a\u003e Added templates to the issue creation wizard (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4654\"\u003e#4654\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.coroutines/commit/330fcc221fb583f0b119f34191f735a73b827378\"\u003e\u003ccode\u003e330fcc2\u003c/code\u003e\u003c/a\u003e Version 1.11.0-rc02\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.coroutines/commit/e31cef6e9f2d26794be7d75ecbf3033b6432d582\"\u003e\u003ccode\u003ee31cef6\u003c/code\u003e\u003c/a\u003e Merge remote-tracking branch 'origin/master' into develop\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.coroutines/commit/dc6e9f61eaf3a67f4bf474a7987aedc3f16cef37\"\u003e\u003ccode\u003edc6e9f6\u003c/code\u003e\u003c/a\u003e Restore Promise-related functions on Wasm/JS as HIDDEN (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4661\"\u003e#4661\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/Kotlin/kotlinx.coroutines/compare/1.9.0...1.11.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.jetbrains.kotlinx:kotlinx-coroutines-test` from 1.9.0 to 1.11.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/Kotlin/kotlinx.coroutines/releases\"\u003eorg.jetbrains.kotlinx:kotlinx-coroutines-test's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e1.11.0\u003c/h2\u003e\n\u003ch3\u003eVarious\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eKotlin was updated to 2.2.20 (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4545\"\u003e#4545\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eImproved the published jar files (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/3842\"\u003e#3842\u003c/a\u003e, \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4599\"\u003e#4599\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eVarious documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4433\"\u003e#4433\u003c/a\u003e, \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4596\"\u003e#4596\u003c/a\u003e).\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eBreaking changes and deprecations\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eMoved \u003ccode\u003ePromise\u003c/code\u003e-related functions from JS and Wasm/JS to the new \u003ccode\u003eweb\u003c/code\u003e target. On Wasm/JS, this is a breaking change. Before the change, \u003ccode\u003ePromise\u003c/code\u003e on Wasm/JS could work with arbitrary Kotlin types, but now, only \u003ccode\u003eJsAny\u003c/code\u003e subtypes are accepted (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4563\"\u003e#4563\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eChanged handling of coroutine exceptions that can't be propagated on JS and Wasm/JS. B\nefore, exceptions were logged, but now, they are reported to the JS runtime (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4451\"\u003e#4451\u003c/a\u003e, \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4631\"\u003e#4631\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eDeprecated using \u003ccode\u003eCoroutineDispatcher\u003c/code\u003e as the coroutine context key; now, \u003ccode\u003eContinuationInterceptor\u003c/code\u003e has to be used instead (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4333\"\u003e#4333\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdvanced the deprecation levels on \u003ccode\u003ekotlinx-coroutines-test\u003c/code\u003e APIs (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4604\"\u003e#4604\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdded lint functions that mark passing a \u003ccode\u003eJob\u003c/code\u003e to coroutine builders as deprecated (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4435\"\u003e#4435\u003c/a\u003e).\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eBug fixes and improvements\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eAdded a \u003ccode\u003ecallsInPlace(EXACTLY_ONCE)\u003c/code\u003e contract to \u003ccode\u003erunBlocking\u003c/code\u003e in code shared between JVM and Native (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4368\"\u003e#4368\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdded a \u003ccode\u003ecallsInPlace(EXACTLY_ONCE)\u003c/code\u003e contract to \u003ccode\u003esuspendCancellableCoroutine\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4574\"\u003e#4574\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFixed \u003ccode\u003eflowOn\u003c/code\u003e incorrectly handling \u003ccode\u003eThreadContextElement\u003c/code\u003e updates (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4403\"\u003e#4403\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFixed exceptions in user-supplied \u003ccode\u003eThread.UncaughtExceptionHandler\u003c/code\u003e instances causing the internal coroutines machinery to fail (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4516\"\u003e#4516\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFixed \u003ccode\u003eCoroutineDispatcher.asScheduler\u003c/code\u003e in the RxJava integration not cancelling outstanding work when a \u003ccode\u003eWorker\u003c/code\u003e gets cancelled, which led to memory leaks in some scenarios (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4615\"\u003e#4615\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFixed \u003ccode\u003eSharedFlow\u003c/code\u003e entering an invalid state when a subscriber and an emitter are cancelled simultaneously (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4583\"\u003e#4583\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFixed an R8 optimization leading to \u003ccode\u003eshareIn\u003c/code\u003e/\u003ccode\u003estateIn\u003c/code\u003e coroutines getting garbage-collected (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4646\"\u003e#4646\u003c/a\u003e). Thanks, \u003ca href=\"https://github.com/solevic\"\u003e\u003ccode\u003e@​solevic\u003c/code\u003e\u003c/a\u003e!\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eSmall additions\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eAdded \u003ccode\u003eCompletableDeferred.asDeferred\u003c/code\u003e for obtaining a read-only \u003ccode\u003eDeferred\u003c/code\u003e view (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4408\"\u003e#4408\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdded \u003ccode\u003eSharedFlow.asFlow\u003c/code\u003e for obtaining a \u003ccode\u003eFlow\u003c/code\u003e view with hidden hot flow semantics (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4530\"\u003e#4530\u003c/a\u003e). Thanks, \u003ca href=\"https://github.com/g000sha256\"\u003e\u003ccode\u003e@​g000sha256\u003c/code\u003e\u003c/a\u003e!\u003c/li\u003e\n\u003cli\u003eAdded a \u003ccode\u003eStateFlow.collectLatest\u003c/code\u003e overload returning \u003ccode\u003eNothing\u003c/code\u003e to assist with finding unreachable code (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4454\"\u003e#4454\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdded \u003ccode\u003eReceiveChannel.consumeTo\u003c/code\u003e for consuming a \u003ccode\u003eReceiveChannel\u003c/code\u003e into a \u003ccode\u003eMutableCollection\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4520\"\u003e#4520\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdded a \u003ccode\u003eStateFlow\u0026lt;T\u0026gt;.onSubscription\u003c/code\u003e overload returning a \u003ccode\u003eStateFlow\u0026lt;T\u0026gt;\u003c/code\u003e, similar to \u003ccode\u003eSharedFlow\u0026lt;T\u0026gt;.onSubscription\u003c/code\u003e returning \u003ccode\u003eSharedFlow\u0026lt;T\u0026gt;\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4275\"\u003e#4275\u003c/a\u003e). Thanks, \u003ca href=\"https://github.com/xit0c\"\u003e\u003ccode\u003e@​xit0c\u003c/code\u003e\u003c/a\u003e!\u003c/li\u003e\n\u003cli\u003eAdded terminal \u003ccode\u003eFlow\u003c/code\u003e operators for collecting a \u003ccode\u003eFlow\u003c/code\u003e to a \u003ccode\u003eMap\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/1541\"\u003e#1541\u003c/a\u003e).\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChangelog relative to version 1.11.0\u003c/h3\u003e\n\u003cp\u003eNo changes, only the version is increased.\u003c/p\u003e\n\u003ch2\u003e1.11.0-rc02\u003c/h2\u003e\n\u003cp\u003eRestored binary compatibility with 1.10.2 and older versions on Wasm/JS for usages of \u003ccode\u003ePromise\u003c/code\u003e-related functions (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4661\"\u003e#4661\u003c/a\u003e).\u003c/p\u003e\n\u003ch2\u003e1.11.0-rc01\u003c/h2\u003e\n\u003ch3\u003eVarious\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eKotlin was updated to 2.2.20 (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4545\"\u003e#4545\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eImproved the published jar files (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/3842\"\u003e#3842\u003c/a\u003e, \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4599\"\u003e#4599\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eVarious documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4433\"\u003e#4433\u003c/a\u003e, \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4596\"\u003e#4596\u003c/a\u003e).\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eBreaking changes and deprecations\u003c/h3\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/Kotlin/kotlinx.coroutines/blob/master/CHANGES.md\"\u003eorg.jetbrains.kotlinx:kotlinx-coroutines-test's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003eVersion 1.11.0\u003c/h2\u003e\n\u003ch3\u003eVarious\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eKotlin was updated to 2.2.20 (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4545\"\u003e#4545\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eImproved the published jar files (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/3842\"\u003e#3842\u003c/a\u003e, \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4599\"\u003e#4599\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eVarious documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4433\"\u003e#4433\u003c/a\u003e, \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4596\"\u003e#4596\u003c/a\u003e).\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eBreaking changes and deprecations\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eMoved \u003ccode\u003ePromise\u003c/code\u003e-related functions from JS and Wasm/JS to the new \u003ccode\u003eweb\u003c/code\u003e target. On Wasm/JS, this is a breaking change. Before the change, \u003ccode\u003ePromise\u003c/code\u003e on Wasm/JS could work with arbitrary Kotlin types, but now, only \u003ccode\u003eJsAny\u003c/code\u003e subtypes are accepted (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4563\"\u003e#4563\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eChanged handling of coroutine exceptions that can't be propagated on JS and Wasm/JS. Before, exceptions were logged, but now, they are reported to the JS runtime (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4451\"\u003e#4451\u003c/a\u003e, \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4631\"\u003e#4631\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eDeprecated using \u003ccode\u003eCoroutineDispatcher\u003c/code\u003e as the coroutine context key; now, \u003ccode\u003eContinuationInterceptor\u003c/code\u003e has to be used instead (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4333\"\u003e#4333\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdvanced the deprecation levels on \u003ccode\u003ekotlinx-coroutines-test\u003c/code\u003e APIs (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4604\"\u003e#4604\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdded lint functions that mark passing a \u003ccode\u003eJob\u003c/code\u003e to coroutine builders as deprecated (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4435\"\u003e#4435\u003c/a\u003e).\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eBug fixes and improvements\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eAdded a \u003ccode\u003ecallsInPlace(EXACTLY_ONCE)\u003c/code\u003e contract to \u003ccode\u003erunBlocking\u003c/code\u003e in code shared between JVM and Native (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4368\"\u003e#4368\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdded a \u003ccode\u003ecallsInPlace(EXACTLY_ONCE)\u003c/code\u003e contract to \u003ccode\u003esuspendCancellableCoroutine\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4574\"\u003e#4574\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFixed \u003ccode\u003eflowOn\u003c/code\u003e incorrectly handling \u003ccode\u003eThreadContextElement\u003c/code\u003e updates (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4403\"\u003e#4403\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFixed exceptions in user-supplied \u003ccode\u003eThread.UncaughtExceptionHandler\u003c/code\u003e instances causing the internal coroutines machinery to fail (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4516\"\u003e#4516\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFixed \u003ccode\u003eCoroutineDispatcher.asScheduler\u003c/code\u003e in the RxJava integration not cancelling outstanding work when a \u003ccode\u003eWorker\u003c/code\u003e gets cancelled, which led to memory leaks in some scenarios (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4615\"\u003e#4615\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFixed \u003ccode\u003eSharedFlow\u003c/code\u003e entering an invalid state when a subscriber and an emitter are cancelled simultaneously (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4583\"\u003e#4583\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFixed an R8 optimization leading to \u003ccode\u003eshareIn\u003c/code\u003e/\u003ccode\u003estateIn\u003c/code\u003e coroutines getting garbage-collected (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4646\"\u003e#4646\u003c/a\u003e). Thanks, \u003ca href=\"https://github.com/solevic\"\u003e\u003ccode\u003e@​solevic\u003c/code\u003e\u003c/a\u003e!\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eSmall additions\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eAdded \u003ccode\u003eCompletableDeferred.asDeferred\u003c/code\u003e for obtaining a read-only \u003ccode\u003eDeferred\u003c/code\u003e view (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4408\"\u003e#4408\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdded \u003ccode\u003eSharedFlow.asFlow\u003c/code\u003e for obtaining a \u003ccode\u003eFlow\u003c/code\u003e view with hidden hot flow semantics (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4530\"\u003e#4530\u003c/a\u003e). Thanks, \u003ca href=\"https://github.com/g000sha256\"\u003e\u003ccode\u003e@​g000sha256\u003c/code\u003e\u003c/a\u003e!\u003c/li\u003e\n\u003cli\u003eAdded a \u003ccode\u003eStateFlow.collectLatest\u003c/code\u003e overload returning \u003ccode\u003eNothing\u003c/code\u003e to assist with finding unreachable code (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4454\"\u003e#4454\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdded \u003ccode\u003eReceiveChannel.consumeTo\u003c/code\u003e for consuming a \u003ccode\u003eReceiveChannel\u003c/code\u003e into a \u003ccode\u003eMutableCollection\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4520\"\u003e#4520\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdded a \u003ccode\u003eStateFlow\u0026lt;T\u0026gt;.onSubscription\u003c/code\u003e overload returning a \u003ccode\u003eStateFlow\u0026lt;T\u0026gt;\u003c/code\u003e, similar to \u003ccode\u003eSharedFlow\u0026lt;T\u0026gt;.onSubscription\u003c/code\u003e returning \u003ccode\u003eSharedFlow\u0026lt;T\u0026gt;\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4275\"\u003e#4275\u003c/a\u003e). Thanks, \u003ca href=\"https://github.com/xit0c\"\u003e\u003ccode\u003e@​xit0c\u003c/code\u003e\u003c/a\u003e!\u003c/li\u003e\n\u003cli\u003eAdded terminal \u003ccode\u003eFlow\u003c/code\u003e operators for collecting a \u003ccode\u003eFlow\u003c/code\u003e to a \u003ccode\u003eMap\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/1541\"\u003e#1541\u003c/a\u003e).\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChangelog relative to version 1.11.0\u003c/h3\u003e\n\u003cp\u003eNo changes, only the version is increased.\u003c/p\u003e\n\u003ch2\u003eVersion 1.11.0-rc02\u003c/h2\u003e\n\u003cp\u003eRestored binary compatibility with 1.10.2 and older versions on Wasm/JS for usages of \u003ccode\u003ePromise\u003c/code\u003e-related functions (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4661\"\u003e#4661\u003c/a\u003e).\u003c/p\u003e\n\u003ch2\u003eVersion 1.11.0-rc01\u003c/h2\u003e\n\u003ch3\u003eVarious\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eKotlin was updated to 2.2.20 (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4545\"\u003e#4545\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eImproved the published jar files (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/3842\"\u003e#3842\u003c/a\u003e, \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4599\"\u003e#4599\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eVarious documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4433\"\u003e#4433\u003c/a\u003e, \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4596\"\u003e#4596\u003c/a\u003e).\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.coroutines/commit/8564f65764d3d05893cec026c6e94250e2b23874\"\u003e\u003ccode\u003e8564f65\u003c/code\u003e\u003c/a\u003e Version 1.11.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.coroutines/commit/a4c6af96c15fe30f5d4e8b810ea74f8babd5805c\"\u003e\u003ccode\u003ea4c6af9\u003c/code\u003e\u003c/a\u003e Merge remote-tracking branch 'origin/master' into develop\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.coroutines/commit/ef917b460aa741691fbf991ee1b813049cae18c9\"\u003e\u003ccode\u003eef917b4\u003c/code\u003e\u003c/a\u003e KT-84955: mark apple x64 tagets as deprecated error (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4645\"\u003e#4645\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.coroutines/commit/5ebc421e341bf2ddce734d369da87df1985e80bd\"\u003e\u003ccode\u003e5ebc421\u003c/code\u003e\u003c/a\u003e Update the release procedure description (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4670\"\u003e#4670\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.coroutines/commit/95f46a073bc4a1230352108cea1835fd22219a80\"\u003e\u003ccode\u003e95f46a0\u003c/code\u003e\u003c/a\u003e Remove old maven repository settings (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4672\"\u003e#4672\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.coroutine...\n\n_Description has been truncated_","html_url":"https://github.com/Classxx/walkie/pull/5","url":"https://dependabot.ecosyste.ms/api/v1/hosts/GitHub/repositories/Classxx%2Fwalkie/issues/5","packages_url":"https://dependabot.ecosyste.ms/api/v1/issues/5/packages"},{"uuid":"5368832045","node_id":"PR_kwDOJ9Dpyc8AAAABCcn4eQ","number":630,"state":"open","title":"chore(deps-dev): bump com.squareup.okhttp3:mockwebserver from 4.12.0 to 5.5.0","user":"dependabot[bot]","labels":[],"assignees":[],"locked":false,"comments_count":1,"pull_request":true,"closed_at":null,"author_association":null,"state_reason":null,"created_at":"2026-09-07T01:05:42.000Z","updated_at":"2026-09-07T01:05:43.000Z","time_to_close":null,"merged_at":null,"merged_by":null,"closed_by":null,"dependency_metadata":{"prefix":"chore(deps-dev)","packages":[{"name":"com.squareup.okhttp3:mockwebserver","old_version":"4.12.0","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"}],"path":null,"ecosystem":"maven"},"body":"Bumps [com.squareup.okhttp3:mockwebserver](https://github.com/lysine-dev/okhttp) from 4.12.0 to 5.5.0.\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/lysine-dev/okhttp/blob/main/CHANGELOG.md\"\u003ecom.squareup.okhttp3:mockwebserver's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003eVersion 5.5.0\u003c/h2\u003e\n\u003cp\u003e\u003cem\u003e2026-08-16\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003eThis release introduces \u003cstrong\u003eopt-in\u003c/strong\u003e support for [Encrypted Client Hello (ECH)]. This new feature\nimproves user privacy by encrypting domain names in transit. With regular TLS, your coffee shop’s\nWi-Fi router can see that you’re visiting \u003cem\u003ewikipedia.com\u003c/em\u003e, but it cannot see which page you’re\nlooking at. With ECH, the router observes only the IP address. This additional privacy is most\neffective on sites hosted by big CDNs because the IP address doesn’t imply a particular website.\u003c/p\u003e\n\u003cp\u003eThis requires ECH support in the platform’s TLS stack. Today this is only Android 17 (API 37,\nreleased June 2026). When other TLS stacks add ECH support, we'll integrate them.\u003c/p\u003e\n\u003cp\u003eECH took a lot of work to implement because the encryption keys are published over DNS in the\n[HTTPS resource record], and we needed to write new code to fetch these records. This release\nincludes a major update to OkHttp’s DNS API: it now supports multiple resource record types (not\njust IP addresses!), asynchronous streaming results, and in-memory caching.\u003c/p\u003e\n\u003cp\u003eTo opt in, you can use \u003ccode\u003eDnsOverHttps\u003c/code\u003e:\u003c/p\u003e\n\u003cpre lang=\"kotlin\"\u003e\u003ccode\u003e// DnsOverHttps itself uses OkHttpClient. Build both clients upon the\n// same bootstrap client so they share a connection pool and dispatcher.\nval bootstrapClient = OkHttpClient()\n\u003cp\u003e// This sample uses Cloudflare's 1.1.1.1 DnsOverHttps service.\nval client = bootstrapClient.newBuilder()\n.dns(DnsOverHttps.Builder()\n.client(bootstrapClient)\n.url(\u0026quot;\u003ca href=\"https://1.1.1.1/dns-query\u0026amp;quot;.toHttpUrl()\"\u003ehttps://1.1.1.1/dns-query\u0026amp;quot;.toHttpUrl()\u003c/a\u003e)\n.build())\n.build()\n\u003c/code\u003e\u003c/pre\u003e\u003c/p\u003e\n\u003cp\u003eYou could also opt in with our new \u003ccode\u003eAndroidDns\u003c/code\u003e API. Unfortunately, the privacy benefits of ECH are\nthwarted because its DNS queries are not encrypted by default.\u003c/p\u003e\n\u003cpre lang=\"kotlin\"\u003e\u003ccode\u003e// AndroidDns fetches the HTTPS DNS resource records necessary for ECH.\nval client = OkHttpClient.Builder()\n  .dns(AndroidDns())\n  .build()\n\u003c/code\u003e\u003c/pre\u003e\n\u003cul\u003e\n\u003cli\u003eNew: OkHttp artifacts are now signed with our [new signing key]. This project and three sibling\nprojects ([Retrofit], [Okio], and [SQLDelight]) recently joined [the Commonhaus Foundation].\u003c/li\u003e\n\u003cli\u003eFix: MockWebServer’s \u003ccode\u003e@StartStop\u003c/code\u003e annotation now supports \u003ccode\u003e@Nested\u003c/code\u003e JUnit 5 tests.\u003c/li\u003e\n\u003cli\u003eFix: Our default TLS hostname verifier now reject hosts that fail IP canonicalization.\u003c/li\u003e\n\u003cli\u003eFix: Closing a multipart part's sink no longer closes the entire request body.\u003c/li\u003e\n\u003cli\u003eFix: Flush HTTP/1 request bodies before detaching the timeout. We had a bug where timeouts\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/a94bdf152084d11acecd44dcd09ffef203f4f0aa\"\u003e\u003ccode\u003ea94bdf1\u003c/code\u003e\u003c/a\u003e Prepare for release 5.5.0.\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/ecc3b05adfe6b2607b8ec251562c2cccf7c1923a\"\u003e\u003ccode\u003eecc3b05\u003c/code\u003e\u003c/a\u003e Use a fixed size for DoH request body (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9687\"\u003e#9687\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/9926082660dfa6f1cc848c6f465cf5ccb998e415\"\u003e\u003ccode\u003e9926082\u003c/code\u003e\u003c/a\u003e Revert \u0026quot;Use a fixed size for DoH request body\u0026quot; (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9686\"\u003e#9686\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/0070c2e7b4c162ee03abf1c88fd94083e94697f4\"\u003e\u003ccode\u003e0070c2e\u003c/code\u003e\u003c/a\u003e Use a fixed size for DoH request body\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/15764539c69842dad607462f102a2507223dbfe7\"\u003e\u003ccode\u003e1576453\u003c/code\u003e\u003c/a\u003e Order ServiceMetadata records per the spec (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9683\"\u003e#9683\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/fb582e976a9a82d691342a4d57b3c72208ce416c\"\u003e\u003ccode\u003efb582e9\u003c/code\u003e\u003c/a\u003e Flip wiring of Dns.SYSTEM (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9682\"\u003e#9682\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/4e884abb1a207c321acffb070c476acb4b89fa3f\"\u003e\u003ccode\u003e4e884ab\u003c/code\u003e\u003c/a\u003e retryOnConnectionFailure doesn't impact ECH retries (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9681\"\u003e#9681\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/0433cee8131b63fa2c0634fa2f9b3a01f9a8b1f3\"\u003e\u003ccode\u003e0433cee\u003c/code\u003e\u003c/a\u003e Only one contributing.md doc (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9678\"\u003e#9678\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/a2cf5aa9f8711dabe514871e9dc4a9336a0e403f\"\u003e\u003ccode\u003ea2cf5aa\u003c/code\u003e\u003c/a\u003e Don't recover after an ECH public_name fails to verify (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9680\"\u003e#9680\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/5410de9760bce8719129c3d08eb19e5bace75f6e\"\u003e\u003ccode\u003e5410de9\u003c/code\u003e\u003c/a\u003e Test ECH + HTTP proxy (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9671\"\u003e#9671\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/lysine-dev/okhttp/compare/parent-4.12.0...parent-5.5.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\n\n[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=com.squareup.okhttp3:mockwebserver\u0026package-manager=maven\u0026previous-version=4.12.0\u0026new-version=5.5.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)\n\nDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.\n\n[//]: # (dependabot-automerge-start)\n[//]: # (dependabot-automerge-end)\n\n---\n\n\u003cdetails\u003e\n\u003csummary\u003eDependabot commands and options\u003c/summary\u003e\n\u003cbr /\u003e\n\nYou can trigger Dependabot actions by commenting on this PR:\n- `@dependabot rebase` will rebase this PR\n- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it\n- `@dependabot show \u003cdependency name\u003e ignore conditions` will show all of the ignore conditions of the specified dependency\n- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)\n\n\n\u003c/details\u003e","html_url":"https://github.com/Jason-Clark-FG/OpenMetadata-FG/pull/630","url":"https://dependabot.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jason-Clark-FG%2FOpenMetadata-FG/issues/630","packages_url":"https://dependabot.ecosyste.ms/api/v1/issues/630/packages"},{"uuid":"5367280542","node_id":"PR_kwDOUI8uTs8AAAABCbceaw","number":9,"state":"closed","title":"build(deps): bump com.squareup.okhttp3:mockwebserver from 4.12.0 to 5.5.0 in /android","user":"dependabot[bot]","labels":["dependencies","java"],"assignees":[],"locked":false,"comments_count":2,"pull_request":true,"closed_at":"2026-09-10T20:52:27.000Z","author_association":null,"state_reason":null,"created_at":"2026-09-06T19:52:49.000Z","updated_at":"2026-09-10T20:52:29.000Z","time_to_close":349178,"merged_at":null,"merged_by":null,"closed_by":null,"dependency_metadata":{"prefix":"build(deps)","packages":[{"name":"com.squareup.okhttp3:mockwebserver","old_version":"4.12.0","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"}],"path":"/android","ecosystem":"maven"},"body":"Bumps [com.squareup.okhttp3:mockwebserver](https://github.com/lysine-dev/okhttp) from 4.12.0 to 5.5.0.\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/lysine-dev/okhttp/blob/main/CHANGELOG.md\"\u003ecom.squareup.okhttp3:mockwebserver's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003eVersion 5.5.0\u003c/h2\u003e\n\u003cp\u003e\u003cem\u003e2026-08-16\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003eThis release introduces \u003cstrong\u003eopt-in\u003c/strong\u003e support for [Encrypted Client Hello (ECH)]. This new feature\nimproves user privacy by encrypting domain names in transit. With regular TLS, your coffee shop’s\nWi-Fi router can see that you’re visiting \u003cem\u003ewikipedia.com\u003c/em\u003e, but it cannot see which page you’re\nlooking at. With ECH, the router observes only the IP address. This additional privacy is most\neffective on sites hosted by big CDNs because the IP address doesn’t imply a particular website.\u003c/p\u003e\n\u003cp\u003eThis requires ECH support in the platform’s TLS stack. Today this is only Android 17 (API 37,\nreleased June 2026). When other TLS stacks add ECH support, we'll integrate them.\u003c/p\u003e\n\u003cp\u003eECH took a lot of work to implement because the encryption keys are published over DNS in the\n[HTTPS resource record], and we needed to write new code to fetch these records. This release\nincludes a major update to OkHttp’s DNS API: it now supports multiple resource record types (not\njust IP addresses!), asynchronous streaming results, and in-memory caching.\u003c/p\u003e\n\u003cp\u003eTo opt in, you can use \u003ccode\u003eDnsOverHttps\u003c/code\u003e:\u003c/p\u003e\n\u003cpre lang=\"kotlin\"\u003e\u003ccode\u003e// DnsOverHttps itself uses OkHttpClient. Build both clients upon the\n// same bootstrap client so they share a connection pool and dispatcher.\nval bootstrapClient = OkHttpClient()\n\u003cp\u003e// This sample uses Cloudflare's 1.1.1.1 DnsOverHttps service.\nval client = bootstrapClient.newBuilder()\n.dns(DnsOverHttps.Builder()\n.client(bootstrapClient)\n.url(\u0026quot;\u003ca href=\"https://1.1.1.1/dns-query\u0026amp;quot;.toHttpUrl()\"\u003ehttps://1.1.1.1/dns-query\u0026amp;quot;.toHttpUrl()\u003c/a\u003e)\n.build())\n.build()\n\u003c/code\u003e\u003c/pre\u003e\u003c/p\u003e\n\u003cp\u003eYou could also opt in with our new \u003ccode\u003eAndroidDns\u003c/code\u003e API. Unfortunately, the privacy benefits of ECH are\nthwarted because its DNS queries are not encrypted by default.\u003c/p\u003e\n\u003cpre lang=\"kotlin\"\u003e\u003ccode\u003e// AndroidDns fetches the HTTPS DNS resource records necessary for ECH.\nval client = OkHttpClient.Builder()\n  .dns(AndroidDns())\n  .build()\n\u003c/code\u003e\u003c/pre\u003e\n\u003cul\u003e\n\u003cli\u003eNew: OkHttp artifacts are now signed with our [new signing key]. This project and three sibling\nprojects ([Retrofit], [Okio], and [SQLDelight]) recently joined [the Commonhaus Foundation].\u003c/li\u003e\n\u003cli\u003eFix: MockWebServer’s \u003ccode\u003e@StartStop\u003c/code\u003e annotation now supports \u003ccode\u003e@Nested\u003c/code\u003e JUnit 5 tests.\u003c/li\u003e\n\u003cli\u003eFix: Our default TLS hostname verifier now reject hosts that fail IP canonicalization.\u003c/li\u003e\n\u003cli\u003eFix: Closing a multipart part's sink no longer closes the entire request body.\u003c/li\u003e\n\u003cli\u003eFix: Flush HTTP/1 request bodies before detaching the timeout. We had a bug where timeouts\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/a94bdf152084d11acecd44dcd09ffef203f4f0aa\"\u003e\u003ccode\u003ea94bdf1\u003c/code\u003e\u003c/a\u003e Prepare for release 5.5.0.\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/ecc3b05adfe6b2607b8ec251562c2cccf7c1923a\"\u003e\u003ccode\u003eecc3b05\u003c/code\u003e\u003c/a\u003e Use a fixed size for DoH request body (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9687\"\u003e#9687\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/9926082660dfa6f1cc848c6f465cf5ccb998e415\"\u003e\u003ccode\u003e9926082\u003c/code\u003e\u003c/a\u003e Revert \u0026quot;Use a fixed size for DoH request body\u0026quot; (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9686\"\u003e#9686\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/0070c2e7b4c162ee03abf1c88fd94083e94697f4\"\u003e\u003ccode\u003e0070c2e\u003c/code\u003e\u003c/a\u003e Use a fixed size for DoH request body\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/15764539c69842dad607462f102a2507223dbfe7\"\u003e\u003ccode\u003e1576453\u003c/code\u003e\u003c/a\u003e Order ServiceMetadata records per the spec (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9683\"\u003e#9683\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/fb582e976a9a82d691342a4d57b3c72208ce416c\"\u003e\u003ccode\u003efb582e9\u003c/code\u003e\u003c/a\u003e Flip wiring of Dns.SYSTEM (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9682\"\u003e#9682\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/4e884abb1a207c321acffb070c476acb4b89fa3f\"\u003e\u003ccode\u003e4e884ab\u003c/code\u003e\u003c/a\u003e retryOnConnectionFailure doesn't impact ECH retries (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9681\"\u003e#9681\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/0433cee8131b63fa2c0634fa2f9b3a01f9a8b1f3\"\u003e\u003ccode\u003e0433cee\u003c/code\u003e\u003c/a\u003e Only one contributing.md doc (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9678\"\u003e#9678\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/a2cf5aa9f8711dabe514871e9dc4a9336a0e403f\"\u003e\u003ccode\u003ea2cf5aa\u003c/code\u003e\u003c/a\u003e Don't recover after an ECH public_name fails to verify (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9680\"\u003e#9680\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/5410de9760bce8719129c3d08eb19e5bace75f6e\"\u003e\u003ccode\u003e5410de9\u003c/code\u003e\u003c/a\u003e Test ECH + HTTP proxy (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9671\"\u003e#9671\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/lysine-dev/okhttp/compare/parent-4.12.0...parent-5.5.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\n\n[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=com.squareup.okhttp3:mockwebserver\u0026package-manager=gradle\u0026previous-version=4.12.0\u0026new-version=5.5.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)\n\nDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.\n\n[//]: # (dependabot-automerge-start)\n[//]: # (dependabot-automerge-end)\n\n---\n\n\u003cdetails\u003e\n\u003csummary\u003eDependabot commands and options\u003c/summary\u003e\n\u003cbr /\u003e\n\nYou can trigger Dependabot actions by commenting on this PR:\n- `@dependabot rebase` will rebase this PR\n- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it\n- `@dependabot show \u003cdependency name\u003e ignore conditions` will show all of the ignore conditions of the specified dependency\n- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)\n\n\n\u003c/details\u003e","html_url":"https://github.com/ersingundem/larenor/pull/9","url":"https://dependabot.ecosyste.ms/api/v1/hosts/GitHub/repositories/ersingundem%2Flarenor/issues/9","packages_url":"https://dependabot.ecosyste.ms/api/v1/issues/9/packages"},{"uuid":"5328543030","node_id":"PR_kwDOTDTeds8AAAABB9DfdA","number":30,"state":"closed","title":"build(deps): bump the android-deps group across 1 directory with 19 updates","user":"dependabot[bot]","labels":["dependencies","java"],"assignees":[],"locked":false,"comments_count":3,"pull_request":true,"closed_at":"2026-09-09T19:45:28.000Z","author_association":null,"state_reason":null,"created_at":"2026-09-02T19:52:55.000Z","updated_at":"2026-09-09T19:45:28.000Z","time_to_close":604353,"merged_at":null,"merged_by":null,"closed_by":null,"dependency_metadata":{"prefix":"build(deps): bump","group_name":"android-deps","update_count":19,"packages":[{"name":"gradle-wrapper","old_version":"9.5.1","new_version":"9.7.1","repository_url":"https://github.com/gradle/gradle"},{"name":"androidx.compose:compose-bom","old_version":"2026.05.01","new_version":"2026.08.00"},{"name":"androidx.core:core-ktx","old_version":"1.18.0","new_version":"1.19.0"},{"name":"androidx.webkit:webkit","old_version":"1.15.0","new_version":"1.17.0"},{"name":"org.bouncycastle:bcprov-jdk18on","old_version":"1.84","new_version":"1.85.2","repository_url":"https://github.com/bcgit/bc-java"},{"name":"org.commonmark:commonmark","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-autolink","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-strikethrough","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-tables","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-task-list-items","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.junit.vintage:junit-vintage-engine","old_version":"6.1.0","new_version":"6.1.3","repository_url":"https://github.com/junit-team/junit-framework"},{"name":"io.kotest:kotest-assertions-core-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"io.kotest:kotest-runner-junit5-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"com.squareup.okhttp3:mockwebserver","old_version":"5.3.2","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.squareup.okhttp3:okhttp","old_version":"5.3.2","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.android.application","old_version":"9.2.1","new_version":"9.4.0"},{"name":"com.android.test","old_version":"9.2.1","new_version":"9.4.0"},{"name":"org.jetbrains.kotlin.plugin.compose","old_version":"2.4.0","new_version":"2.4.10","repository_url":"https://github.com/JetBrains/kotlin"},{"name":"org.jetbrains.kotlin.plugin.serialization","old_version":"2.4.0","new_version":"2.4.10","repository_url":"https://github.com/JetBrains/kotlin"}],"path":null,"ecosystem":"maven"},"body":"Bumps the android-deps group with 19 updates in the /apps/android directory:\n\n| Package | From | To |\n| --- | --- | --- |\n| [gradle-wrapper](https://github.com/gradle/gradle) | `9.5.1` | `9.7.1` |\n| androidx.compose:compose-bom | `2026.05.01` | `2026.08.00` |\n| androidx.core:core-ktx | `1.18.0` | `1.19.0` |\n| androidx.webkit:webkit | `1.15.0` | `1.17.0` |\n| [org.bouncycastle:bcprov-jdk18on](https://github.com/bcgit/bc-java) | `1.84` | `1.85.2` |\n| [org.commonmark:commonmark](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-autolink](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-strikethrough](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-tables](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-task-list-items](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.junit.vintage:junit-vintage-engine](https://github.com/junit-team/junit-framework) | `6.1.0` | `6.1.3` |\n| [io.kotest:kotest-assertions-core-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [io.kotest:kotest-runner-junit5-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [com.squareup.okhttp3:mockwebserver](https://github.com/lysine-dev/okhttp) | `5.3.2` | `5.5.0` |\n| [com.squareup.okhttp3:okhttp](https://github.com/lysine-dev/okhttp) | `5.3.2` | `5.5.0` |\n| com.android.application | `9.2.1` | `9.4.0` |\n| com.android.test | `9.2.1` | `9.4.0` |\n| [org.jetbrains.kotlin.plugin.compose](https://github.com/JetBrains/kotlin) | `2.4.0` | `2.4.10` |\n| [org.jetbrains.kotlin.plugin.serialization](https://github.com/JetBrains/kotlin) | `2.4.0` | `2.4.10` |\n\n\nUpdates `gradle-wrapper` from 9.5.1 to 9.7.1\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/gradle/gradle/releases\"\u003egradle-wrapper's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e9.7.1\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.1.\u003c/p\u003e\n\u003cp\u003eThis is a patch release for 9.7.0. We recommend using 9.7.1 instead of 9.7.0.\u003c/p\u003e\n\u003cp\u003eHere are the highlights of 9.7.0 release:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIsolated Projects graduates to incubating\u003c/li\u003e\n\u003cli\u003eBroader Configuration Cache compatibility\u003c/li\u003e\n\u003cli\u003eResilient Sync helps you fix broken builds\u003c/li\u003e\n\u003cli\u003eMore source locations in problem reports\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003ca href=\"https://docs.gradle.org/9.7.1/release-notes.html\"\u003eRead the Release Notes\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eWe would like to thank the following community members for their contributions to this release of Gradle:\n\u003ca href=\"https://github.com/aSemy\"\u003eAdam\u003c/a\u003e,\n\u003ca href=\"https://github.com/Gautam-aman\"\u003eAman Gautam\u003c/a\u003e,\n\u003ca href=\"https://github.com/YukiCodepth\"\u003eAman Kumar\u003c/a\u003e,\n\u003ca href=\"https://github.com/adubrouski\"\u003eAnton Dubrouski\u003c/a\u003e,\n\u003ca href=\"https://github.com/liutikas\"\u003eAurimas\u003c/a\u003e,\n\u003ca href=\"https://github.com/gbhavya07\"\u003egbhavya07\u003c/a\u003e,\n\u003ca href=\"https://github.com/joshfriend\"\u003eJosh Friend\u003c/a\u003e,\n\u003ca href=\"https://github.com/nicklauslittle-gov\"\u003enicklauslittle-gov\u003c/a\u003e,\n\u003ca href=\"https://github.com/psoni674\"\u003ePragati\u003c/a\u003e,\n\u003ca href=\"https://github.com/Project516\"\u003eproject516\u003c/a\u003e,\n\u003ca href=\"https://github.com/Uomocapra\"\u003eQin Mi\u003c/a\u003e,\n\u003ca href=\"https://github.com/rkdfx\"\u003eRavi\u003c/a\u003e,\n\u003ca href=\"https://github.com/sk-reddy17\"\u003esk-reddy17\u003c/a\u003e,\n\u003ca href=\"https://github.com/Suvrat1629\"\u003eSuvrat Acharya\u003c/a\u003e,\n\u003ca href=\"https://github.com/ShreckYe\"\u003eYongshun Ye\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eUpgrade instructions\u003c/h2\u003e\n\u003cp\u003eSwitch your build to use Gradle 9.7.1 by updating your wrapper:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e./gradlew :wrapper --gradle-version=9.7.1 \u0026amp;\u0026amp; ./gradlew :wrapper\r\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eSee the Gradle \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/upgrading_version_9.html\"\u003e9.x upgrade guide\u003c/a\u003e to learn about deprecations, breaking changes and other considerations when upgrading.\u003c/p\u003e\n\u003cp\u003eFor Java, Groovy, Kotlin and Android compatibility, see the \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/compatibility.html\"\u003efull compatibility notes\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eReporting problems\u003c/h2\u003e\n\u003cp\u003eIf you find a problem with this release, please file a bug on \u003ca href=\"https://github.com/gradle/gradle/issues\"\u003eGitHub Issues\u003c/a\u003e adhering to our issue guidelines.\nIf you're not sure you're encountering a bug, please use the \u003ca href=\"https://discuss.gradle.org/c/help-discuss\"\u003eforum\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eWe hope you will build happiness with Gradle, and we look forward to your feedback via \u003ca href=\"https://twitter.com/gradle\"\u003eTwitter\u003c/a\u003e or on \u003ca href=\"https://github.com/gradle\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003e9.7.0\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.0.\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/92f0512e7f06d84621afba191f75e265363890cf\"\u003e\u003ccode\u003e92f0512\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38892\"\u003e#38892\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/820ee75a99a179bbffa41bcedc6477b685fabb9f\"\u003e\u003ccode\u003e820ee75\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/82c23f9bd2a89b4cc644e1f90a28a8668feb3dee\"\u003e\u003ccode\u003e82c23f9\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering problem in KTS (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38878\"\u003e#38878\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/ef11a7268fe8cc8d6ab849ec911aa11220180553\"\u003e\u003ccode\u003eef11a72\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering issue\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/bb0d8a974a71b1003efea41e4046e98855cd5ff8\"\u003e\u003ccode\u003ebb0d8a9\u003c/code\u003e\u003c/a\u003e Make relevant tests polyglot (run for multiple DSLs)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/336e129d7f95c03486acafc97abf59734acfed48\"\u003e\u003ccode\u003e336e129\u003c/code\u003e\u003c/a\u003e Update signing configuration (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38874\"\u003e#38874\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/4bdf0da2dad9884d089a6062a45ea7183e7d735d\"\u003e\u003ccode\u003e4bdf0da\u003c/code\u003e\u003c/a\u003e Update signing configuration\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/cd9b92c1b82856248cf1dc58b50378238bec7b52\"\u003e\u003ccode\u003ecd9b92c\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38839\"\u003e#38839\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/5f4e381964897ad8d6b99e5a7c77f26dba3259fb\"\u003e\u003ccode\u003e5f4e381\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/1e08ab551367aeb5fb48b26e72807e1d2b27c939\"\u003e\u003ccode\u003e1e08ab5\u003c/code\u003e\u003c/a\u003e Keep type-use annotations in extracted ABI classes (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38810\"\u003e#38810\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/gradle/gradle/compare/v9.5.1...v9.7.1\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `androidx.compose:compose-bom` from 2026.05.01 to 2026.08.00\n\nUpdates `androidx.core:core-ktx` from 1.18.0 to 1.19.0\n\nUpdates `androidx.webkit:webkit` from 1.15.0 to 1.17.0\n\nUpdates `org.bouncycastle:bcprov-jdk18on` from 1.84 to 1.85.2\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.md\"\u003eorg.bouncycastle:bcprov-jdk18on's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch1\u003eBouncy Castle Crypto Package - Release Notes\u003c/h1\u003e\n\u003ch2\u003e1.0 Introduction\u003c/h2\u003e\n\u003cp\u003eThe Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. The package is organised so that it contains a light-weight API suitable for use in any environment (including the J2ME) with the additional infrastructure to conform the algorithms to the JCE framework.\u003c/p\u003e\n\u003ch2\u003e2.0 Release History\u003c/h2\u003e\n\u003cp\u003e\u003c!-- raw HTML omitted --\u003e\u003c!-- raw HTML omitted --\u003e\u003c/p\u003e\n\u003ch3\u003e2.1.1 Version\u003c/h3\u003e\n\u003cp\u003eRelease: 1.86\u003cbr /\u003e\nDate: 2026, TBD\u003c/p\u003e\n\u003ch3\u003e2.1.2 Defects Fixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) let a subkey inherit the primary key's Key Flags when its own Subkey Binding signature carried no Key Flags subpacket, which made the two capability decisions taken for one subkey disagree. OpenPGPCertificate.OpenPGPComponentKey.isSigningKey() reads the effective flags, which fell back to the primary key's direct-key or primary user ID self-signature, so a subkey bound with no flags of its own counted as signing-capable; verifyEmbeddedPrimaryKeyBinding reads the binding signature's own flags, found no signing capability there, and so skipped the embedded Primary Key Binding (cross-certification) signature that RFC 9580 sec. 5.2.1.8 and sec. 10.1.3 require of a subkey that can issue signatures. A data signature made by such a subkey was therefore attributed to the certificate and reported valid by OpenPGPSignature.OpenPGPDocumentSignature.isValid() with the cross-certification requirement never applied, where GnuPG refuses the same certificate and message as not cross-certified. An attacker holding a third party's public signing subkey - which is public material - could bind it to their own primary key with a Subkey Binding signature they are able to make, carrying no Key Flags and no embedded Primary Key Binding signature, which they cannot make without the subkey's private key, and have that party's genuine signatures verify as valid under the attacker's own identity: misattribution of a real signature rather than a forgery of a new one, since the signature still has to be one the subkey actually made. Key Flags are a statement about the key the carrying signature refers to (RFC 9580 sec. 5.2.3.29), so a subkey no longer inherits them from the certificate-wide signatures of the primary key: a Subkey Binding signature that omits the subpacket now leaves the subkey with no capabilities rather than the primary's, which makes the flags the cross-certification check consults the same flags every other decision consults. Preferences and the other subpackets a direct-key signature carries are inherited as before, and the primary key itself - whose flags legitimately come from its direct-key or user ID self-signature - is unaffected. The low-level PGPSignature / PGPPublicKeyRing API performs no binding checks by design and is unchanged.\u003c/li\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) used a version 6 key that carried no valid Direct Key signature, falling back to the primary user ID binding as it correctly does for a version 4 key. RFC 9580 sec. 5.2.3.10 requires the opposite: \u0026quot;An implementation MUST ensure that a valid Direct Key signature is present before using a version 6 key. This prevents certain attacks where an adversary strips a self-signature specifying a Key Expiration Time or certain preferences.\u0026quot; The certificate grammar says the same structurally, the Direct Key signature being mandatory in the version 6 structure of sec. 10.1.1 and optional in the version 4 one of sec. 10.1.3. Because a version 6 certificate carries its key expiration, features and algorithm preferences on the Direct Key signature - the convention the RFC recommends and the one OpenPGPKeyGenerator follows, its user ID certification carrying no expiration at all - removing that single signature packet from a published certificate silently dropped the expiration along with the preferences and features: OpenPGPCertificate.getSignatureChainFor fell back to the user ID binding, the primary key was still reported bound, and getEncryptionKeys() and getSigningKeys() went on returning the subkeys of a key whose owner had set it to expire. The primary key fingerprint is unchanged by the removal, so a relying party pinning the key by fingerprint still treats it as the same key, and no private key or hash collision is involved; the natural moment for the strip is the key refresh that RFC 9580 names as the reason to refetch a key at all - to learn about changes in expiration, features, preferences and revocation - which is exactly the update it defeats. This is a downgrade rather than a forgery, nothing being attributed to a key that did not authorise it, and the concerning direction is encryption, to a key meant to have been retired. OpenPGPCertificate.isBoundBy now requires a valid Direct Key self-signature on a version 6 primary key before any component of the certificate - the primary key, its subkeys or its identities - is treated as bound, so a version 6 certificate stripped of it offers no keys at all rather than an unexpiring set. Version 4 certificates are unaffected: there the key expiration legitimately lives on the user ID self-signature and the fallback is correct, so it stays. The revocation-only version 6 certificate of sec. 10.1.2, which legitimately carries no Direct Key signature, is unaffected as well - its key was already refused as revoked, and reading the revocation does not go through the binding check.\u003c/li\u003e\n\u003cli\u003eThe lightweight LMSSigner and HSSSigner refused a key wrapped in ParametersWithRandom, which is how BcContentSignerBuilder passes a key whenever setSecureRandom() has been called - so BcHssLmsContentSignerBuilder built a working signer until a random was set and then failed with \u0026quot;Incorrect Key Parameters\u0026quot;, and the two signers themselves raised ClassCastException on the same input. All three now unwrap it, as the promoted ML-DSA and SLH-DSA signers already did. The random is accepted and not used: LMS derives its message randomiser C from the key's seed and the one-time index, so it is deterministic and cannot repeat while q does not. Note SP 800-208 sec. 6.1 asks for C to come from an approved random bit generator, which this implementation does not do; that is unchanged here, and a supplied random is now ignored rather than refused.\u003c/li\u003e\n\u003cli\u003eLMS signature verification did not apply two of the checks RFC 8554 sec. 5.4.2 requires before a signature is processed. Step 2g refuses a signature whose LMS typecode is not the one from the public key, and without it the path computation took its height and tree digest from the parameter set the signature named rather than the key's, so a signature claiming a height-25 parameter set drove a 25-level computation against a height-5 key. Step 2i refuses a leaf number q outside the tree, and without it an out-of-range q flowed into the node arithmetic and was left for the candidate-root comparison to catch. Neither was a forgery - the domain separation between D_LEAF and D_INTR and the final comparison saw to that - but both are attacker-chosen work the specification says to refuse up front. Both are now checked, and a signature failing either is still reported as not verifying rather than thrown out of Signature.verify(). The catch around the signature decode in LMSSigner and HSSSigner has also been narrowed to the decode itself, as the corresponding SPI was corrected to do for github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2408\"\u003e#2408\u003c/a\u003e: past the parse the engine reports an inconsistent signature by returning false rather than by throwing, so the wider catch caught nothing while standing ready to turn a future internal error into a quiet false.\u003c/li\u003e\n\u003cli\u003eThe LMS and HSS key parameter classes now apply at construction the checks their decoders apply, so a key built directly cannot be one the decoder would refuse. LMSPrivateKeyParameters accepted an identifier of any length although the decoder reads exactly 16 bytes - such a key encoded but could not be read back - and left q, maxQ and the seed length unchecked; the seed is now required to be at least m bytes at decode as well, where a one-byte seed had been decoding silently and then deriving every one-time key from it. HSSPrivateKeyParameters checked neither its level count nor that it had been given a component key per level and a chaining signature per level below the root, and then indexed both lists, so a mismatch surfaced as IndexOutOfBoundsException - or, where a level happened to match, as a null chaining signature that only failed at signing time; the level is now checked after the reset that fills it in, since a null is legitimate on the way in. LMSPrivateKeyParameters.getInstance(byte[], byte[]) adopted the public key supplied beside the private one without comparing them, so a mismatched public key was simply reported by getPublicKey(); it now cross-checks the identifier, both parameter sets and, where the tree cache already holds it, the root, as the HSS entry point does. The decoders also now report a bad version or seed length as IOException rather than IllegalStateException, so a caller can catch one type for a malformed key, and the package-private LM-OTS public key decoder no longer declares throws Exception or dereferences an unrecognised typecode. The deprecated org.bouncycastle.pqc.crypto.lms copies carry the decoder corrections.\u003c/li\u003e\n\u003cli\u003eIn the LMS JCE layer, LMSKeyGenParameterSpec.fromNames knew all twenty LMS parameter-set names but only four of the sixteen LM-OTS ones, so none of the SP 800-208 n24 or SHAKE sets could be named; all sixteen are now present. KeyPairGenerator.initialize(int, SecureRandom) reports InvalidParameterException, which is what the JCA specifies and which extends the IllegalArgumentException it raised before, so existing catches still match. BCLMSPrivateKey.getIndex now takes the exhaustion check and the index read under the key's own monitor rather than as two separate calls, and two unused fields have gone from LMSSignatureSpi. Note that the LMS Signature claims its one-time key at the first update() rather than at sign(), so a Signature that is initialised and updated and then abandoned spends an index without producing a signature - the safe direction for a one-time scheme, and now documented on the SPI.\u003c/li\u003e\n\u003cli\u003eAn HSS private key claimed the two records of its position under two different monitors. The top-level index and the bottom component key's one-time index q are independent records of the same position - the decoder requires them to agree, see the entry below - but generateLMSContext incremented the index under the HSS key's own monitor, released it, and only then claimed q under the component key's. A getEncoded() issued in between saw the index advanced and q not, and produced an encoding this implementation's own decoder rejects; and two threads meeting at a bottom-tree boundary could both pass the exhaustion test, take consecutive top-level indices and claim the same q, after which one of them was refused with \u0026quot;ots private key exhausted\u0026quot; by a key still reporting usages remaining, a top-level index had been spent with no signature made, and the two records stayed one apart for the rest of the key's life in that process - so it could no longer be encoded, cloned or sharded, and getIndex() and getUsagesRemaining() misreported by one. No one-time key was reused: the component key's claim is itself atomic, and the divergence runs index ahead of leaves, so the effect was on the key's usability rather than on the signatures it had made. Both records are now claimed under the one monitor, and the component key is claimed before the index is incremented so that an exhausted one leaves both untouched. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the same correction.\u003c/li\u003e\n\u003cli\u003eNeither the HSS nor the XMSS^MT private key decoder checked its declared index against the traversal state stored beside it, although the two are independent records of the same position in the key and so can be compared. For HSS the records are the top-level index and the component keys' one-time indices q; for XMSS^MT they are the global index and the per-layer BDS states. A stored key whose index had been rolled back while its state stayed advanced - a partial write, a restore from backup, a buggy storage layer - was therefore accepted, and it then signed a second message under a one-time key the key had already used, producing a signature that verified, so nothing anywhere surfaced the reuse. RFC 8554 sec. 1 and RFC 8391 sec. 1.1 both require each one-time key to be used exactly once, and this is the failure those requirements exist to prevent; the single-tree XMSS decoder has tied its BDS state to its index since that state was first validated, and this brings the two multi-tree schemes into line. HSS decode now requires the declared index to equal the position the component q values imply - a level above the last contributes (q - 1) leaves of the levels beneath it, since its q has already advanced past the subtree it signed - and XMSS^MT decode now requires each present layer's BDS index to equal the leaf index that layer derives from the global index, allowing the one position where a layer has moved into a new subtree and its state legitimately still carries the previous subtree's final index. A layer with no state yet is unaffected, since those are built lazily at signing time. Related, and the same shape of omission: an XMSS or XMSS^MT private key encoding carries the tree root twice - the key's own root field and the root node of the BDS state stored beside it, which for XMSS^MT is the top layer's - and the two were never compared either. A corrupted root was accepted and then poisoned every signature the key made, because the root is hashed into the message digest: the signature did not verify and nothing indicated why. Decode now requires the two copies to agree. The BDS node values themselves are not checkable the way the LMS tree cache above is - a BDS authentication path, stack, retain or keep node does not have its children stored alongside it, so recomputing one means building a subtree, which is the work the state exists to avoid. Both checks are integer comparisons over the levels of the key, too small to measure against the surrounding decode, and both were verified not to reject any legitimate key by walking every index a key can reach: the full key space of the two-level HSS and the h=4/d=2, h=6/d=2, h=6/d=3, h=9/d=3 and h=8/d=4 XMSS^MT parameter sets, plus a three-level HSS key across a subtree boundary and an HSS shard. Since those node values cannot be recomputed, the encoded state now carries a checksum over itself instead, with the owning key's public seed hashed in front of it. Any corruption of the stored state is refused at decode rather than being loaded and then producing signatures that silently do not verify, and because the public seed is bound in, a state transplanted between two keys of the same parameter set is refused too, even though it is internally consistent and arrives with its own matching root. The public seed is bound rather than the secret seed or the PRF key deliberately: the state's own root and index are inside the encoding and so are already covered, hashing secret material would make the stored checksum a commitment to it for no gain in detection, and the PRF key does not influence the state at all. \u003cstrong\u003eThis is an error-detecting code and not integrity protection\u003c/strong\u003e - anyone able to rewrite the stored key recomputes it, so it establishes that the state is unchanged since it was written, never that it was correct when written, and the allocation bounds on the encoding remain the guard against a crafted one. It costs one SHA-256 over the state, measured at 5 to 8 microseconds each way for the h=10 and h=16 parameter sets, and 32 bytes of encoding. The state encoding was added earlier in this same cycle and has not been released, so the checksum is simply part of it rather than a new version: a state written by a 1.86 beta is rejected, which is recovered from by re-exporting the key. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the HSS check as well (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2414\"\u003e#2414\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe S/MIME example smoke test in the misc module (org.bouncycastle.mail.smime.examples.test.AllTests) drove SendSignedAndEncryptedMail against smtp.gmail.com, and that example finishes with Transport.send() under JavaMail's default settings, which have no connect timeout. Where outbound port 25 is refused the failure was swallowed and the test passed; where it is silently dropped, as on many home networks, the connect blocked and ./gradlew build hung in :misc:test indefinitely with \u0026quot;0 tests completed\u0026quot;. The test now delivers to an SMTP stub on a loopback port, with connect / read / write timeouts as a backstop, and asserts the message arrived (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2407\"\u003e#2407\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation took the traditional component public key bytes it feeds the KEM combiner from the recipient key's own encoding, while decapsulation recomputes the point from the private key and so always produced an uncompressed one. Section 4 of draft-ietf-lamps-pq-composite-kem requires an EC component to be carried as an uncompressed point, but a component key that encodes itself compressed - a BC EC key whose point format has been set through org.bouncycastle.jce.interfaces.ECPointEncoder, or a key from a provider that preserves a compressed encoding - was passed through as it came. Both sides then combined a different tradPK and derived different shared secrets, with no error reported on either: encapsulation and decapsulation both succeeded and the recipient simply could not decrypt. The EC component is now normalised to an uncompressed point wherever the engine serialises one, which covers the ephemeral key that forms the ciphertext as well. X25519 and X448 components have a single encoding and were unaffected, as were EC keys left in their default (uncompressed) format, whose shared secrets are unchanged. CompositePublicKey.getEncoded() took its component bytes the same way, so such a key also encoded to a composite key other implementations reject and whose bytes changed across an encode / decode / encode round trip - 1238 bytes rather than 1270 for MLKEM768-ECDH-P256, and for the composite ML-DSA keys sharing that method, 2006 rather than 2038 for MLDSA65-ECDSA-P256. It now normalises the component the same way. This is a write-side change only: a composite key carrying a compressed EC component is still decoded, since the component key factories accept either form, and continues to verify signatures as before - it simply re-encodes in the normalised form. The shared normalisation is org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil.getUncompressedSubjectPublicKeyBytes.\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation threw a NullPointerException, wrapped in an IllegalStateException out of KeyGenerator.generateKey(), when the SecureRandom it was given was null - which javax.crypto.KEM.newEncapsulator() documents as a request for the provider's default, and which KeyGenerator.init(spec, null) passes straight through. The three RSA-OAEP composites draw the traditional shared secret from that random directly, so they were the ones affected; the ECDH and X25519 / X448 composites escaped only because their component KeyPairGenerators default a random of their own. CompositeMLKEMEngine now defaults one through CryptoServicesRegistrar.getSecureRandom() on first use, as the composite KEM Cipher's wrap path already did, and as the KEM generators corrected earlier in this cycle now do. Related, the engine now also clears the ML-KEM component's shared secret alongside the traditional one on both the encapsulate and decapsulate paths - the copy handed back by getEncoded() was left in the heap - as section 3.5 of draft-ietf-lamps-pq-composite-kem requires.\u003c/li\u003e\n\u003cli\u003eCompositePublicKey.getAlgorithm() and CompositePrivateKey.getAlgorithm() returned null for all twelve Composite ML-KEM (draft-ietf-lamps-pq-composite-kem) parameter sets. Both classes resolved the name through the composite signature index only, which holds the composite ML-DSA OIDs, so a composite KEM key pair - generated, parsed from a certificate, or read from PKCS#8 - reported no algorithm at all, and the standard JCA idiom of reconstructing a key with KeyFactory.getInstance(key.getAlgorithm()) raised a NullPointerException. The lookup now falls back to the composite KEM index, so the name returned is the one the provider registers the algorithm under (e.g. MLKEM768-X25519-SHA3-256), matching the composite ML-DSA behaviour. The same single-index assumption made the CompositePublicKey(SubjectPublicKeyInfo) and CompositePrivateKey(PrivateKeyInfo) constructors reject a composite KEM key with \u0026quot;unable to create CompositePublicKey from SubjectPublicKeyInfo\u0026quot;; they now dispatch to the composite KEM key factory for those OIDs. Keys obtained through KeyFactory or through BouncyCastleProvider.getPublicKey / getPrivateKey were unaffected and are unchanged (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2404\"\u003e#2404\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe org.bouncycastle.jcajce.spec.KEMKDFSpec constructor stored a null otherInfo as given, so getOtherInfo() returned null, and three of the KDF branches KdfUtil.makeKeyBytes dispatches to - KMAC-128, KMAC-256 and SHAKE-256 - read the otherInfo length without a guard and threw NullPointerException out of the KEM operation, where the KDF2, KDF3 and HKDF branches tolerate a null through KDFParameters / HKDFParameters. The Builder of every spec in the package already mapped null to empty, so no provider path reached it, but the constructor is protected on a public class and KdfUtil is documented for callers building their own KEM integration; the deprecated KEMParameterSpec passes a null itself and escaped only because it also pins the KDF to null. The constructor now stores empty for a null, so getOtherInfo() never returns null, and a null and an explicitly empty otherInfo derive the same key.\u003c/li\u003e\n\u003cli\u003eQR-UOV signature verification accepted a signature encoding that was not canonical, so the encoding of a signature was not unique even after the trailing-byte fix of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e. Each F_q element of the signature is stored in ceil(log2 q) bits, one more bit pattern than the field has elements: q itself is representable and is arithmetically congruent to zero, so an element written as q verified exactly as the same element written as zero would, and the bits padding the last element out to the byte boundary were never read at all. Every zero element of a signature therefore carried a second encoding, and for the q = 7 parameter sets roughly one element in seven is zero - a single qruov_5_q7_L10 signature measured 256 spare bits, so on the order of 2^256 distinct byte strings verified for the one message and key. Verification now rejects any element outside [0, q) and any set padding bit; a signature produced by this or by the reference implementation is unaffected, as the KAT vectors of every parameter set confirm. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSNOVA signature verification ignored four bits inside the signature for any parameter set whose solution is an odd number of GF(16) nibbles - the SNOVA_24_5_5, SNOVA_25_8_3, SNOVA_29_6_5 and SNOVA_66_15_3 families, sixteen of the forty-four parameter sets. The last byte of the encoded solution carries a single nibble and the signer leaves the top four bits zero, but the decoder did not read them, so sixteen distinct byte strings verified for one signature. This is the same non-unique encoding github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e closed for bytes following the signature, applied inside it; the verifier now requires those bits to be zero. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSnovaPrivateKeyParameters did not validate the length of the private key encoding handed to it - the only one of the five schemes of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e that did not - and SnovaParameters.getPrivateKeyLength() reported the expanded (\u0026quot;ESK\u0026quot;) length even for a parameter set whose private key is the seed pair. A private key encoding reaches this constructor straight from a PKCS#8 blob, so a wrong length went undetected: a seed-form key with extra bytes appended was accepted and signed under a different derived key, and a short expanded-form key sized the signer's decode buffer negatively, throwing NegativeArraySizeException out of generateSignature() rather than being reported at construction. Related, the signing retry loop could not terminate: the vinegar values are derived from a single-byte counter, so only 256 distinct linear systems can be tried, and an expanded-form private key that is not a real central map is singular for all of them - generateSignature() then span forever rather than failing. The length is now checked at construction, getPrivateKeyLength() reports the length that parameter set's private key actually has, and the retry loop gives up after its 256 attempts as MAYO's does.\u003c/li\u003e\n\u003cli\u003eMayoSigner and MayoKeyPairGenerator did not clear several buffers holding secret key material that the MAYO reference implementation explicitly clears. Signing left the secret oil space O, the expanded L = (P1 + P1^t) * O + P2, and the M / VPV / Ox intermediates of the central map in place, having gone to the trouble of clearing eleven other buffers; key generation left the expanded seed, whose tail is the encoded oil space, and the P1 * O + P2 half of P; and the row-echelon step left the packed echelon form of the secret linear system and its pivot rows. Separately, if all 256 attempts at solving for the signature had given a rank-deficient system, signing emitted a signature built from the failed attempt's state instead of reporting the failure the reference returns, and AIMerSigner.generateSignature returned an empty array on failure, which a caller would hand on as though it were a signature. Both now throw.\u003c/li\u003e\n\u003cli\u003eFive PQC signature schemes - MAYO, SNOVA, QR-UOV, SQIsign and AIMer - returned the NIST crypto_sign \u0026quot;sm\u0026quot; signed-message envelope from generateSignature() rather than the signature. That envelope is an artefact of the reference KAT harness, which records the message alongside the signature so a vector file can be self-contained; it is not part of any of the five specifications, and no other BC signer emits it (Falcon's KAT test rebuilds the equivalent envelope in the test, which is where it belongs). Two consequences followed, both reaching the JCA Signature services of every parameter set of the five schemes in BouncyCastlePQCProvider. First, since the message was appended to the signature, verification had to skip whatever followed the signature proper, and it did so by checking only that the buffer was long enough - so any number of trailing bytes could be added to a valid signature, or the appended message replaced with unrelated data, and it still verified. A signature encoding was therefore not unique: anyone holding one valid signature could produce unlimited distinct byte strings that all verified for the same message and key, which breaks any use that treats the signature bytes as an identifier, deduplicates on them, or records them as evidence. Second, the envelope propagated into everything built on the operator layer: because ContentSigner hands the signature straight into the structure being signed, every X.509 certificate, CRL, CMS SignedData and TLS CertificateVerify BC produced with one of these algorithms carried a verbatim copy of the signed data inside its own signature field - a self-signed MAYO-1 certificate came to 3567 bytes where the same certificate is now 2020 - which no other implementation can parse as a signature, and which in a detached CMS signature meant the \u0026quot;detached\u0026quot; signature carried the content. generateSignature() now returns the bare signature, and verifySignature() requires exactly the parameter set's signature length, so appended or truncated data is rejected rather than ignored. \u003cstrong\u003eThis is a behavioural change for signatures produced by an earlier release\u003c/strong\u003e - MAYO and SNOVA from 1.84, QR-UOV, SQIsign and AIMer from 1.85 - which are no longer accepted in the envelope form they were emitted in; the signature bytes themselves are unchanged, so a stored value can be recovered by taking the leading signature-length bytes, or for AIMer, whose envelope was message || signature rather than signature || message, the trailing ones. The KAT tests now rebuild the envelope before comparing against the vector files, which continue to record it. Note that AIMer's verification had already been made length-exact during this cycle (see the entry below relating to github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2401\"\u003e#2401\u003c/a\u003e), so of the five only its envelope remained (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe MLS implementation did not bind an X.509 credential to the LeafNode's signature_key. LeafNode.verify() checked a leaf's signature against the signature_key declared in the leaf itself, while the X.509 credential's certificate chain was stored but never parsed or checked, so the certificate's public key was never required to match signature_key (RFC 9420 sec. 5.3). A leaf could therefore carry one party's certificate while being signed by an unrelated key and still be accepted under that party's identity through KeyPackage.verify() and the Group leaf-validation path. LeafNode.verify() now requires the end-entity certificate's subject public key, in the cipher suite's signature encoding, to equal signature_key for an X.509 credential, and rejects the leaf otherwise - including an empty chain or a certificate whose key type does not match the cipher suite; certificate-chain and identity validation to a trust anchor remain the application's responsibility per RFC 9420 sec. 5.3.1. A public org.bouncycastle.mls.codec.Certificate(byte[]) constructor and a Credential.getCertificates() accessor are added so callers can build and inspect X.509 credentials. Basic credentials are unaffected.\u003c/li\u003e\n\u003cli\u003eThe SecureRandom supplied to org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder.setSecureRandom() did not drive the content IV / nonce for any algorithm other than RC2. EnvelopedDataHelper.generateParameters passed the caller's SecureRandom to the AlgorithmParameterGenerator only in the RC2_CBC branch; every other content-encryption algorithm - AES-CBC, AES-GCM, AES-CCM, Camellia, ARIA, SEED and the rest - reached pGen.generateParameters() on an uninitialised generator, so the IV / nonce was drawn from a default SecureRandom and setSecureRandom() was silently ignored (the builder's javadoc states that random is used for IV/nonce generation). The generator is now initialised with the supplied random on the general path as well, so a caller who provides a specific randomness source - for a controlled or FIPS-approved DRBG, say - has it honoured for the content IV / nonce. The session-key generation path was unaffected and already used the supplied random. Because the content IV / nonce now comes from the supplied SecureRandom, the org.bouncycastle.crypto.util JournalingSecureRandom / JournaledAlgorithm reproducible-encryption support records it in the transcript: a resumed session reproduces the IV / nonce by regenerating it from the replayed randomness - build the resuming encryptor from the content-algorithm OID - rather than by reusing the AlgorithmIdentifier captured from the first encryption, which no longer keeps the transcript aligned.\u003c/li\u003e\n\u003cli\u003eThe NTRU LPRime, NTRU+ and SMAUG-T KEM generators threw a NullPointerException when constructed with a null SecureRandom, where every other KEM generator - including NTRU LPRime's own SNTRU Prime counterpart in the same package - defaults one through CryptoServicesRegistrar.getSecureRandom(). This is reachable from the lightweight API directly, and from javax.crypto.KEM, whose newEncapsulator() documents a null random as a request for the provider's default.\u003c/li\u003e\n\u003cli\u003eFrodoKEMEngine kept a single SHAKE instance in a field, so an engine reached concurrently produced wrong results. It is reached that way through org.bouncycastle.crypto.kems.FrodoKEMExtractor, which holds one engine for its lifetime: two threads extracting through one extractor interleaved the digest's absorb and squeeze phases, yielding shared secrets that silently did not match the sender's, or an IllegalStateException of \u0026quot;attempt to absorb while squeezing\u0026quot; from inside extractSecret. The digest is now built per call, as CMCEEngine's already was, which makes an extractor safe to share. Encapsulation was unaffected, since FrodoKEMGenerator builds an engine per call. Results for any single-threaded use are unchanged - the reference KAT vectors are byte-identical.\u003c/li\u003e\n\u003cli\u003eThe BCJSSE provider carried the TLS 1.2 coupling between the supported_groups extension and ECDSA over into TLS 1.3: an ECDSA signature scheme was treated as usable - offered in the signature_algorithms and signature_algorithms_cert extensions, and eligible when selecting the local credentials - only while the corresponding curve was among the named groups enabled for key exchange, both per context (a group unavailable for key agreement disabled the scheme outright) and per connection (the curve had to be in the supported_groups list about to be sent). RFC 8446 sec. 4.2.7 scopes supported_groups to key exchange only, with signature algorithms negotiated independently (sec. 4.2.3), so this incorrect restriction in TLS 1.3 has been removed. Ed25519, Ed448 and the RSA schemes were unaffected (as well as typical deployments using a default configuration for named groups).\u003c/li\u003e\n\u003cli\u003eThe bcmail module descriptor did not declare its javax.mail/javax.activation dependences, so a modular (module-path) consumer of the jar hit IllegalAccessError/module-resolution failures when the S/MIME classes touched the mail API. The descriptor now requires them optionally (requires static) under all four module names those libraries are known by - the automatic names mail and activation carried by the javax.mail:mail / javax.activation:activation artifacts, and the explicit names java.mail and java.activation carried by the newer com.sun.mail / com.sun.activation ones - a hard requires on any one name would break users of the others (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2389\"\u003e#2389\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFour type-coercion helpers in the OER / IEEE 1609.2 (ITS) decoder tested the wrong type in the identity fast path that lets a getInstance() factory return an argument that is already of the target type. org.bouncycastle.oer.its.ieee1609dot2.basetypes.UINT32.getInstance and org.bouncycastle.oer.its.etsi102941.basetypes.Version.getInstance guarded on UINT8 - a sibling of UINT32 under UintBase, and unrelated to Version - so passing a UINT8 threw ClassCastException, while passing an actual UINT32 or Version missed the fast path and fell through to ASN1Integer.getInstance, which rejects them: neither factory accepted its own type. org.bouncycastle.oer.its.etsi103097.EtsiTs103097DataEncryptedUnicast.getInstance guarded on its sibling EtsiTs103097DataEncrypted and then cast to the unicast type, so an EtsiTs103097DataEncrypted threw ClassCastException. org.bouncycastle.oer.OEROptional.getObject(Class) called value.getClass().isInstance(type) with the arguments transposed, which is always false because the argument is a java.lang.Class, so the cast path was dead and every optional field was resolved reflectively, failing with IllegalStateException for a target type with no static getInstance. Each guard now names the type it returns, matching the sibling UINT8 / UINT16 / UINT64 and EtsiTs103097DataEncrypted factories (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2373\"\u003e#2373\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eDefaultAlgorithmNameFinder and DefaultSignatureNameFinder had no entries at all for the ShangMi algorithms, so an SM2 signature AlgorithmIdentifier that DefaultSignatureAlgorithmIdentifierFinder itself produces came back named only by its OID string - getAlgorithmName(GMObjectIdentifiers.sm2sign_with_sm3) returned \u0026quot;1.2.156.10197.1.501\u0026quot; and hasAlgorithmName returned false. Both finders now name sm2sign_with_sm3 as SM3WITHSM2 and sm2sign_with_sha256 as SHA256WITHSM2, and DefaultAlgorithmNameFinder additionally names the sm3 digest. All three resolve through the BC provider, as Signature and MessageDigest respectively. The remaining GM arc - the SM4 cipher modes, the sm2encrypt variants, and the SM1 / SM6 / SSF33 ciphers BC does not implement - is still unnamed (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2377\"\u003e#2377\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe RFC 4998 evidence-record classes compared the digest AlgorithmIdentifier named by a time-stamp authority with the one their own DigestCalculator uses, and did so with AlgorithmIdentifier.equals(), which compares the encodings. A TSA that names SHA-256 with an explicit NULL parameters field - DigiCert among them - therefore failed against BC's own calculator, which names it with the parameters absent, and ERSArchiveTimeStampGenerator.generateArchiveTimeStamp rejected the response with \u0026quot;time stamp imprint for wrong algorithm\u0026quot;. Both spellings name the same digest and RFC 5754 sec. 2 requires a receiver to accept either, while requiring that identifiers be generated with the parameters absent, which BC already does. The three affected comparisons - the two in ERSArchiveTimeStampGenerator and the digest check in ERSEvidenceRecord.renew - now use the new AlgorithmIdentifier.areEquivalent, which matches on the algorithm and treats an absent parameters field and NULL as the same, and the consistency check across an evidence record's archive time stamp chain uses it too. An identifier carrying an actual parameter structure is never equivalent to one carrying none (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2379\"\u003e#2379\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eEDIPartyName.toASN1Primitive emitted the nameAssigner and partyName DirectoryStrings without their context tags, so an EDIPartyName built through its public constructor could not be parsed back by EDIPartyName.getInstance, which correctly requires them. RFC 5280 sec. 4.2.1.6 tags both members [0] and [1], and those tags are explicit despite the module's IMPLICIT TAGS because DirectoryString is a CHOICE, which X.680 does not allow to be tagged implicitly - the decoder already had this right. The encoder now matches it. Note the type was added during the 1.85 cycle and GeneralName validates its ediPartyName alternative through it, so a GeneralName carrying an untagged ediPartyName - including one BC itself produced - is rejected where 1.84 passed it through unexamined; the untagged form is not read leniently (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2380\"\u003e#2380\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eRSASSA-PSS could not be used with a RIPEMD digest through the JCA API. Nothing registered the RIPEMD PSS signatures, so Signature.getInstance(\u0026quot;RIPEMD160WITHRSAANDMGF1\u0026quot;) raised NoSuchAlgorithmException, and the generic RSASSA-PSS route with an explicit PSSParameterSpec failed too: org.bouncycastle.jcajce.provider.util.DigestFactory.getDigest returned null for a RIPEMD name, and isSameDigest - an allow-list of the SHA families and MD5 - reported two identical RIPEMD names as different digests, so the spec was rejected with \u0026quot;digest algorithm for MGF should be the same as for PSS parameters\u0026quot;. isSameDigest now answers true for equal names whatever the digest, which also covers Whirlpool, SM3, GOST3411 and anything else outside that allow-list; DigestFactory recognises RIPEMD128, RIPEMD160 and RIPEMD256 by name and OID; the three PSS signatures are registered with MGF1 over the same digest and a salt of the digest length; and DefaultSignatureAlgorithmIdentifierFinder gains the matching RIPEMD*WITHRSAANDMGF1 entries with their RSASSA-PSS-params, so the operator/JcaContentSignerBuilder path works as well. Note BC continues to require the PSS hash and the MGF1 hash to be the same, which RFC 8017 does not itself demand (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2381\"\u003e#2381\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe opt-in key-size validation on CMS key-transport recipients (org.bouncycastle.cms.jcajce.JceKeyTransRecipient.setKeySizeValidation(true)) never ran for a message using RFC 9709 CEK derivation (id-alg-cek-hkdf-sha256): the branch that should have selected the actual content-encryption algorithm carried in the KDF AlgorithmIdentifier's parameters compared the encrypted-key byte array against the id-alg-cek-hkdf-sha256 object identifier - a comparison that is always false - so the check fell through to a key-size lookup on the outer KDF OID, which has no registered key size, and silently checked nothing. A key-transport EnvelopedData/AuthEnvelopedData whose transported (and HKDF-derived) content-encryption key did not match the key size of the advertised content-encryption algorithm was therefore accepted even with validation enabled. The recipient now dispatches on the content-encryption AlgorithmIdentifier's algorithm OID, so key-size validation of RFC 9709 messages checks the recovered key against the inner content-encryption algorithm. Messages with a matching key size, non-HKDF messages, and recipients that do not enable validation are unaffected.\u003c/li\u003e\n\u003cli\u003eThe OpenPGP v6 SEIPD (Symmetrically Encrypted Integrity Protected Data, version 2 / RFC 9580 sec. 5.13.2) packet parser read the AEAD chunk-size octet without bounding it. The chunk length is 2^(chunkSize + 6) bytes and the AEAD decryptor allocates a buffer of that size up front, so a crafted v6 encrypted message (reachable with only the recipient's public key) declaring chunkSize 24 forced a 1 GiB allocation on decrypt, and chunkSize 25 (where the int cast of the chunk length wraps negative) threw a NegativeArraySizeException -- a pre-authentication resource-exhaustion denial of service. This is the version 6 sibling of the version 5 AEADEncDataPacket issue fixed under CVE-2026-3505, which bounded that packet's chunk size at 16 but left the v6 SymmetricEncIntegrityPacket unbounded. SymmetricEncIntegrityPacket now rejects a chunk-size octet outside 0..16 (a 4 MiB chunk, matching the v5 ceiling) with a MalformedPacketException at parse, before any allocation.\u003c/li\u003e\n\u003cli\u003eThe Ed25519 KeyFactory in the JDK 11+ and JDK 15+ multi-release overlays (META-INF/versions/11 and /15) had drifted from the base implementation on the OpenSSH key-spec path: it used the no-passphrase OpenSSHPrivateKeyUtil.parsePrivateKeyBlob overload, so a passphrase-encrypted openssh-key-v1 Ed25519 private key that KeyFactory.getInstance(\u0026quot;Ed25519\u0026quot;, \u0026quot;BC\u0026quot;).generatePrivate(new OpenSSHPrivateKeySpec(blob, passphrase)) decoded correctly on JDK 8 failed on JDK 11 and later; it also let a raw RuntimeException escape on a malformed blob and threw IllegalStateException (JDK 11) instead of InvalidKeySpecException for a non-Ed25519 key. The overlays now match the base implementation (passphrase support, parse errors wrapped as InvalidKeySpecException). Relatedly, the OpenSSH wrong-key-type and decode-failure paths across the RSA, DSA, EC and Ed25519 KeyFactorySpi implementations now consistently raise InvalidKeySpecException (previously a mix of IllegalArgumentException / IllegalStateException) and wrap a malformed OpenSSH public key, and an incorrect \u0026quot;public key is not RSA private key\u0026quot; message on the RSA private path was corrected. The multi-release test tasks now exercise the OpenSSH key specs against the multi-release jar.\u003c/li\u003e\n\u003cli\u003eThe Ant-built utility jars (bcutil-jdk15to18, bcutil-jdk14) duplicated org.bouncycastle.asn1.iana.IANAObjectIdentifiers, which since 1.85 (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2176\"\u003e#2176\u003c/a\u003e) lives only in core and is therefore already shipped in bcprov. The shared ant/bc+-build.xml build-util target still copied org/bouncycastle/asn1/iana/** into bcutil, so a project depending on both bcprov and bcutil (for example via bcpkix) failed an Android/R8 build with \u0026quot;Duplicate class org.bouncycastle.asn1.iana.IANAObjectIdentifiers found in modules bcprov-jdk15to18-1.85.jar and bcutil-jdk15to18-1.85.jar\u0026quot;. The iana package is no longer bundled into bcutil (it remains in bcprov); the Gradle jdk18on jars were already correct (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2356\"\u003e#2356\u003c/a\u003e).\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003eSee full diff in \u003ca href=\"https://github.com/bcgit/bc-java/commits\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003ecommonmark-java 0.29.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e[0.29.0] - 2026-06-20\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/42b4fb7adfe288ef13e9e27ab20aff7e91b0ab9d\"\u003e\u003ccode\u003e42b4fb7\u003c/code\u003e\u003c/a\u003e Prepare CHANGELOG for version 0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/b76e09d7a8362abb5f04e1d6b91dbd6da279a6fc\"\u003e\u003ccode\u003eb76e09d\u003c/code\u003e\u003c/a\u003e Limit how deep inline nodes may nest by default (100)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/49f65cb5cbec93cff713179990307145198e7061\"\u003e\u003ccode\u003e49f65cb\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing deeply nested emphasis\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/610f84b83e68c381e8f784ae4d044c80e1948b67\"\u003e\u003ccode\u003e610f84b\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological autolink email addresses\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/9f1d73897a56cbd74c39347af351a473e70297e1\"\u003e\u003ccode\u003e9f1d738\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological HTML block attributes\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/e13297e849995fdd582a85841067bff1d9c35ee5\"\u003e\u003ccode\u003ee13297e\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing pathological backticks\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/89d1bd3fa1524e8217ed61db5e8116c82434470f\"\u003e\u003ccode\u003e89d1bd3\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing with lots of \u003ccode\u003e\u0026lt;\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/commonmark/commonmark-java/compare/commonmark-parent-0.28.0...commonmark-parent-0.30.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark-ext-autolink` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark-ext-autolink's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of...\n\n_Description has been truncated_","html_url":"https://github.com/ifabrish/openclaw-ifabrish-/pull/30","url":"https://dependabot.ecosyste.ms/api/v1/hosts/GitHub/repositories/ifabrish%2Fopenclaw-ifabrish-/issues/30","packages_url":"https://dependabot.ecosyste.ms/api/v1/issues/30/packages"},{"uuid":"5295533440","node_id":"PR_kwDOSB4jqM8AAAABBitosA","number":70,"state":"closed","title":"build(deps): bump the android-deps group across 1 directory with 28 updates","user":"dependabot[bot]","labels":["dependencies","java"],"assignees":[],"locked":false,"comments_count":1,"pull_request":true,"closed_at":"2026-09-04T05:38:51.000Z","author_association":null,"state_reason":null,"created_at":"2026-08-31T01:38:15.000Z","updated_at":"2026-09-04T05:38:53.000Z","time_to_close":360036,"merged_at":null,"merged_by":null,"closed_by":null,"dependency_metadata":{"prefix":"build(deps): bump","group_name":"android-deps","update_count":28,"packages":[{"name":"gradle-wrapper","old_version":"9.6.1","new_version":"9.7.1","repository_url":"https://github.com/gradle/gradle"},{"name":"androidx.appcompat:appcompat","old_version":"1.7.1","new_version":"1.8.0"},{"name":"androidx.compose:compose-bom","old_version":"2026.06.01","new_version":"2026.08.00"},{"name":"androidx.webkit:webkit","old_version":"1.16.0","new_version":"1.17.0"},{"name":"androidx.wear.protolayout:protolayout","old_version":"1.4.1","new_version":"1.4.2"},{"name":"androidx.wear.protolayout:protolayout-material3","old_version":"1.4.1","new_version":"1.4.2"},{"name":"androidx.wear.tiles:tiles","old_version":"1.6.1","new_version":"1.6.2"},{"name":"org.bouncycastle:bcprov-jdk18on","old_version":"1.85","new_version":"1.85.2","repository_url":"https://github.com/bcgit/bc-java"},{"name":"org.commonmark:commonmark","old_version":"0.29.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-autolink","old_version":"0.29.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-strikethrough","old_version":"0.29.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-tables","old_version":"0.29.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-task-list-items","old_version":"0.29.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"io.coil-kt.coil3:coil-compose","old_version":"3.5.0","new_version":"3.6.0","repository_url":"https://github.com/coil-kt/coil"},{"name":"io.coil-kt.coil3:coil-svg","old_version":"3.5.0","new_version":"3.6.0","repository_url":"https://github.com/coil-kt/coil"},{"name":"org.junit.vintage:junit-vintage-engine","old_version":"6.1.2","new_version":"6.1.3","repository_url":"https://github.com/junit-team/junit-framework"},{"name":"io.kotest:kotest-assertions-core-jvm","old_version":"6.2.3","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"io.kotest:kotest-runner-junit5-jvm","old_version":"6.2.3","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"androidx.media3:media3-datasource-okhttp","old_version":"1.10.1","new_version":"1.11.0","repository_url":"https://github.com/androidx/media"},{"name":"androidx.media3:media3-exoplayer","old_version":"1.10.1","new_version":"1.11.0","repository_url":"https://github.com/androidx/media"},{"name":"androidx.media3:media3-session","old_version":"1.10.1","new_version":"1.11.0","repository_url":"https://github.com/androidx/media"},{"name":"androidx.media3:media3-ui","old_version":"1.10.1","new_version":"1.11.0","repository_url":"https://github.com/androidx/media"},{"name":"com.squareup.okhttp3:mockwebserver","old_version":"5.4.0","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.squareup.okhttp3:okhttp","old_version":"5.4.0","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.android.application","old_version":"9.3.1","new_version":"9.3.2"},{"name":"com.android.library","old_version":"9.3.1","new_version":"9.3.2"},{"name":"com.android.test","old_version":"9.3.1","new_version":"9.3.2"},{"name":"com.google.devtools.ksp","old_version":"2.3.10","new_version":"2.3.11","repository_url":"https://github.com/google/ksp"}],"path":null,"ecosystem":"maven"},"body":"Bumps the android-deps group with 28 updates in the /apps/android directory:\n\n| Package | From | To |\n| --- | --- | --- |\n| [gradle-wrapper](https://github.com/gradle/gradle) | `9.6.1` | `9.7.1` |\n| androidx.appcompat:appcompat | `1.7.1` | `1.8.0` |\n| androidx.compose:compose-bom | `2026.06.01` | `2026.08.00` |\n| androidx.webkit:webkit | `1.16.0` | `1.17.0` |\n| androidx.wear.protolayout:protolayout | `1.4.1` | `1.4.2` |\n| androidx.wear.protolayout:protolayout-material3 | `1.4.1` | `1.4.2` |\n| androidx.wear.tiles:tiles | `1.6.1` | `1.6.2` |\n| [org.bouncycastle:bcprov-jdk18on](https://github.com/bcgit/bc-java) | `1.85` | `1.85.2` |\n| [org.commonmark:commonmark](https://github.com/commonmark/commonmark-java) | `0.29.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-autolink](https://github.com/commonmark/commonmark-java) | `0.29.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-strikethrough](https://github.com/commonmark/commonmark-java) | `0.29.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-tables](https://github.com/commonmark/commonmark-java) | `0.29.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-task-list-items](https://github.com/commonmark/commonmark-java) | `0.29.0` | `0.30.0` |\n| [io.coil-kt.coil3:coil-compose](https://github.com/coil-kt/coil) | `3.5.0` | `3.6.0` |\n| [io.coil-kt.coil3:coil-svg](https://github.com/coil-kt/coil) | `3.5.0` | `3.6.0` |\n| [org.junit.vintage:junit-vintage-engine](https://github.com/junit-team/junit-framework) | `6.1.2` | `6.1.3` |\n| [io.kotest:kotest-assertions-core-jvm](https://github.com/kotest/kotest) | `6.2.3` | `6.2.4` |\n| [io.kotest:kotest-runner-junit5-jvm](https://github.com/kotest/kotest) | `6.2.3` | `6.2.4` |\n| [androidx.media3:media3-datasource-okhttp](https://github.com/androidx/media) | `1.10.1` | `1.11.0` |\n| [androidx.media3:media3-exoplayer](https://github.com/androidx/media) | `1.10.1` | `1.11.0` |\n| [androidx.media3:media3-session](https://github.com/androidx/media) | `1.10.1` | `1.11.0` |\n| [androidx.media3:media3-ui](https://github.com/androidx/media) | `1.10.1` | `1.11.0` |\n| [com.squareup.okhttp3:mockwebserver](https://github.com/lysine-dev/okhttp) | `5.4.0` | `5.5.0` |\n| [com.squareup.okhttp3:okhttp](https://github.com/lysine-dev/okhttp) | `5.4.0` | `5.5.0` |\n| com.android.application | `9.3.1` | `9.3.2` |\n| com.android.library | `9.3.1` | `9.3.2` |\n| com.android.test | `9.3.1` | `9.3.2` |\n| [com.google.devtools.ksp](https://github.com/google/ksp) | `2.3.10` | `2.3.11` |\n\n\nUpdates `gradle-wrapper` from 9.6.1 to 9.7.1\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/gradle/gradle/releases\"\u003egradle-wrapper's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e9.7.1\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.1.\u003c/p\u003e\n\u003cp\u003eThis is a patch release for 9.7.0. We recommend using 9.7.1 instead of 9.7.0.\u003c/p\u003e\n\u003cp\u003eHere are the highlights of 9.7.0 release:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIsolated Projects graduates to incubating\u003c/li\u003e\n\u003cli\u003eBroader Configuration Cache compatibility\u003c/li\u003e\n\u003cli\u003eResilient Sync helps you fix broken builds\u003c/li\u003e\n\u003cli\u003eMore source locations in problem reports\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003ca href=\"https://docs.gradle.org/9.7.1/release-notes.html\"\u003eRead the Release Notes\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eWe would like to thank the following community members for their contributions to this release of Gradle:\n\u003ca href=\"https://github.com/aSemy\"\u003eAdam\u003c/a\u003e,\n\u003ca href=\"https://github.com/Gautam-aman\"\u003eAman Gautam\u003c/a\u003e,\n\u003ca href=\"https://github.com/YukiCodepth\"\u003eAman Kumar\u003c/a\u003e,\n\u003ca href=\"https://github.com/adubrouski\"\u003eAnton Dubrouski\u003c/a\u003e,\n\u003ca href=\"https://github.com/liutikas\"\u003eAurimas\u003c/a\u003e,\n\u003ca href=\"https://github.com/gbhavya07\"\u003egbhavya07\u003c/a\u003e,\n\u003ca href=\"https://github.com/joshfriend\"\u003eJosh Friend\u003c/a\u003e,\n\u003ca href=\"https://github.com/nicklauslittle-gov\"\u003enicklauslittle-gov\u003c/a\u003e,\n\u003ca href=\"https://github.com/psoni674\"\u003ePragati\u003c/a\u003e,\n\u003ca href=\"https://github.com/Project516\"\u003eproject516\u003c/a\u003e,\n\u003ca href=\"https://github.com/Uomocapra\"\u003eQin Mi\u003c/a\u003e,\n\u003ca href=\"https://github.com/rkdfx\"\u003eRavi\u003c/a\u003e,\n\u003ca href=\"https://github.com/sk-reddy17\"\u003esk-reddy17\u003c/a\u003e,\n\u003ca href=\"https://github.com/Suvrat1629\"\u003eSuvrat Acharya\u003c/a\u003e,\n\u003ca href=\"https://github.com/ShreckYe\"\u003eYongshun Ye\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eUpgrade instructions\u003c/h2\u003e\n\u003cp\u003eSwitch your build to use Gradle 9.7.1 by updating your wrapper:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e./gradlew :wrapper --gradle-version=9.7.1 \u0026amp;\u0026amp; ./gradlew :wrapper\r\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eSee the Gradle \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/upgrading_version_9.html\"\u003e9.x upgrade guide\u003c/a\u003e to learn about deprecations, breaking changes and other considerations when upgrading.\u003c/p\u003e\n\u003cp\u003eFor Java, Groovy, Kotlin and Android compatibility, see the \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/compatibility.html\"\u003efull compatibility notes\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eReporting problems\u003c/h2\u003e\n\u003cp\u003eIf you find a problem with this release, please file a bug on \u003ca href=\"https://github.com/gradle/gradle/issues\"\u003eGitHub Issues\u003c/a\u003e adhering to our issue guidelines.\nIf you're not sure you're encountering a bug, please use the \u003ca href=\"https://discuss.gradle.org/c/help-discuss\"\u003eforum\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eWe hope you will build happiness with Gradle, and we look forward to your feedback via \u003ca href=\"https://twitter.com/gradle\"\u003eTwitter\u003c/a\u003e or on \u003ca href=\"https://github.com/gradle\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003e9.7.0\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.0.\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/92f0512e7f06d84621afba191f75e265363890cf\"\u003e\u003ccode\u003e92f0512\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38892\"\u003e#38892\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/820ee75a99a179bbffa41bcedc6477b685fabb9f\"\u003e\u003ccode\u003e820ee75\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/82c23f9bd2a89b4cc644e1f90a28a8668feb3dee\"\u003e\u003ccode\u003e82c23f9\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering problem in KTS (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38878\"\u003e#38878\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/ef11a7268fe8cc8d6ab849ec911aa11220180553\"\u003e\u003ccode\u003eef11a72\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering issue\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/bb0d8a974a71b1003efea41e4046e98855cd5ff8\"\u003e\u003ccode\u003ebb0d8a9\u003c/code\u003e\u003c/a\u003e Make relevant tests polyglot (run for multiple DSLs)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/336e129d7f95c03486acafc97abf59734acfed48\"\u003e\u003ccode\u003e336e129\u003c/code\u003e\u003c/a\u003e Update signing configuration (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38874\"\u003e#38874\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/4bdf0da2dad9884d089a6062a45ea7183e7d735d\"\u003e\u003ccode\u003e4bdf0da\u003c/code\u003e\u003c/a\u003e Update signing configuration\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/cd9b92c1b82856248cf1dc58b50378238bec7b52\"\u003e\u003ccode\u003ecd9b92c\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38839\"\u003e#38839\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/5f4e381964897ad8d6b99e5a7c77f26dba3259fb\"\u003e\u003ccode\u003e5f4e381\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/1e08ab551367aeb5fb48b26e72807e1d2b27c939\"\u003e\u003ccode\u003e1e08ab5\u003c/code\u003e\u003c/a\u003e Keep type-use annotations in extracted ABI classes (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38810\"\u003e#38810\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/gradle/gradle/compare/v9.6.1...v9.7.1\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `androidx.appcompat:appcompat` from 1.7.1 to 1.8.0\n\nUpdates `androidx.compose:compose-bom` from 2026.06.01 to 2026.08.00\n\nUpdates `androidx.webkit:webkit` from 1.16.0 to 1.17.0\n\nUpdates `androidx.wear.protolayout:protolayout` from 1.4.1 to 1.4.2\n\nUpdates `androidx.wear.protolayout:protolayout-material3` from 1.4.1 to 1.4.2\n\nUpdates `androidx.wear.protolayout:protolayout-material3` from 1.4.1 to 1.4.2\n\nUpdates `androidx.wear.tiles:tiles` from 1.6.1 to 1.6.2\n\nUpdates `org.bouncycastle:bcprov-jdk18on` from 1.85 to 1.85.2\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.md\"\u003eorg.bouncycastle:bcprov-jdk18on's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch1\u003eBouncy Castle Crypto Package - Release Notes\u003c/h1\u003e\n\u003ch2\u003e1.0 Introduction\u003c/h2\u003e\n\u003cp\u003eThe Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. The package is organised so that it contains a light-weight API suitable for use in any environment (including the J2ME) with the additional infrastructure to conform the algorithms to the JCE framework.\u003c/p\u003e\n\u003ch2\u003e2.0 Release History\u003c/h2\u003e\n\u003cp\u003e\u003c!-- raw HTML omitted --\u003e\u003c!-- raw HTML omitted --\u003e\u003c/p\u003e\n\u003ch3\u003e2.1.1 Version\u003c/h3\u003e\n\u003cp\u003eRelease: 1.86\u003cbr /\u003e\nDate: 2026, TBD\u003c/p\u003e\n\u003ch3\u003e2.1.2 Defects Fixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) let a subkey inherit the primary key's Key Flags when its own Subkey Binding signature carried no Key Flags subpacket, which made the two capability decisions taken for one subkey disagree. OpenPGPCertificate.OpenPGPComponentKey.isSigningKey() reads the effective flags, which fell back to the primary key's direct-key or primary user ID self-signature, so a subkey bound with no flags of its own counted as signing-capable; verifyEmbeddedPrimaryKeyBinding reads the binding signature's own flags, found no signing capability there, and so skipped the embedded Primary Key Binding (cross-certification) signature that RFC 9580 sec. 5.2.1.8 and sec. 10.1.3 require of a subkey that can issue signatures. A data signature made by such a subkey was therefore attributed to the certificate and reported valid by OpenPGPSignature.OpenPGPDocumentSignature.isValid() with the cross-certification requirement never applied, where GnuPG refuses the same certificate and message as not cross-certified. An attacker holding a third party's public signing subkey - which is public material - could bind it to their own primary key with a Subkey Binding signature they are able to make, carrying no Key Flags and no embedded Primary Key Binding signature, which they cannot make without the subkey's private key, and have that party's genuine signatures verify as valid under the attacker's own identity: misattribution of a real signature rather than a forgery of a new one, since the signature still has to be one the subkey actually made. Key Flags are a statement about the key the carrying signature refers to (RFC 9580 sec. 5.2.3.29), so a subkey no longer inherits them from the certificate-wide signatures of the primary key: a Subkey Binding signature that omits the subpacket now leaves the subkey with no capabilities rather than the primary's, which makes the flags the cross-certification check consults the same flags every other decision consults. Preferences and the other subpackets a direct-key signature carries are inherited as before, and the primary key itself - whose flags legitimately come from its direct-key or user ID self-signature - is unaffected. The low-level PGPSignature / PGPPublicKeyRing API performs no binding checks by design and is unchanged.\u003c/li\u003e\n\u003cli\u003eNeither the HSS nor the XMSS^MT private key decoder checked its declared index against the traversal state stored beside it, although the two are independent records of the same position in the key and so can be compared. For HSS the records are the top-level index and the component keys' one-time indices q; for XMSS^MT they are the global index and the per-layer BDS states. A stored key whose index had been rolled back while its state stayed advanced - a partial write, a restore from backup, a buggy storage layer - was therefore accepted, and it then signed a second message under a one-time key the key had already used, producing a signature that verified, so nothing anywhere surfaced the reuse. RFC 8554 sec. 1 and RFC 8391 sec. 1.1 both require each one-time key to be used exactly once, and this is the failure those requirements exist to prevent; the single-tree XMSS decoder has tied its BDS state to its index since that state was first validated, and this brings the two multi-tree schemes into line. HSS decode now requires the declared index to equal the position the component q values imply - a level above the last contributes (q - 1) leaves of the levels beneath it, since its q has already advanced past the subtree it signed - and XMSS^MT decode now requires each present layer's BDS index to equal the leaf index that layer derives from the global index, allowing the one position where a layer has moved into a new subtree and its state legitimately still carries the previous subtree's final index. A layer with no state yet is unaffected, since those are built lazily at signing time. Related, and the same shape of omission: an XMSS or XMSS^MT private key encoding carries the tree root twice - the key's own root field and the root node of the BDS state stored beside it, which for XMSS^MT is the top layer's - and the two were never compared either. A corrupted root was accepted and then poisoned every signature the key made, because the root is hashed into the message digest: the signature did not verify and nothing indicated why. Decode now requires the two copies to agree. The BDS node values themselves are not checkable the way the LMS tree cache above is - a BDS authentication path, stack, retain or keep node does not have its children stored alongside it, so recomputing one means building a subtree, which is the work the state exists to avoid. Both checks are integer comparisons over the levels of the key, too small to measure against the surrounding decode, and both were verified not to reject any legitimate key by walking every index a key can reach: the full key space of the two-level HSS and the h=4/d=2, h=6/d=2, h=6/d=3, h=9/d=3 and h=8/d=4 XMSS^MT parameter sets, plus a three-level HSS key across a subtree boundary and an HSS shard. Since those node values cannot be recomputed, the encoded state now carries a checksum over itself instead, with the owning key's public seed hashed in front of it. Any corruption of the stored state is refused at decode rather than being loaded and then producing signatures that silently do not verify, and because the public seed is bound in, a state transplanted between two keys of the same parameter set is refused too, even though it is internally consistent and arrives with its own matching root. The public seed is bound rather than the secret seed or the PRF key deliberately: the state's own root and index are inside the encoding and so are already covered, hashing secret material would make the stored checksum a commitment to it for no gain in detection, and the PRF key does not influence the state at all. \u003cstrong\u003eThis is an error-detecting code and not integrity protection\u003c/strong\u003e - anyone able to rewrite the stored key recomputes it, so it establishes that the state is unchanged since it was written, never that it was correct when written, and the allocation bounds on the encoding remain the guard against a crafted one. It costs one SHA-256 over the state, measured at 5 to 8 microseconds each way for the h=10 and h=16 parameter sets, and 32 bytes of encoding. The state encoding was added earlier in this same cycle and has not been released, so the checksum is simply part of it rather than a new version: a state written by a 1.86 beta is rejected, which is recovered from by re-exporting the key. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the HSS check as well (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2414\"\u003e#2414\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe S/MIME example smoke test in the misc module (org.bouncycastle.mail.smime.examples.test.AllTests) drove SendSignedAndEncryptedMail against smtp.gmail.com, and that example finishes with Transport.send() under JavaMail's default settings, which have no connect timeout. Where outbound port 25 is refused the failure was swallowed and the test passed; where it is silently dropped, as on many home networks, the connect blocked and ./gradlew build hung in :misc:test indefinitely with \u0026quot;0 tests completed\u0026quot;. The test now delivers to an SMTP stub on a loopback port, with connect / read / write timeouts as a backstop, and asserts the message arrived (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2407\"\u003e#2407\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation took the traditional component public key bytes it feeds the KEM combiner from the recipient key's own encoding, while decapsulation recomputes the point from the private key and so always produced an uncompressed one. Section 4 of draft-ietf-lamps-pq-composite-kem requires an EC component to be carried as an uncompressed point, but a component key that encodes itself compressed - a BC EC key whose point format has been set through org.bouncycastle.jce.interfaces.ECPointEncoder, or a key from a provider that preserves a compressed encoding - was passed through as it came. Both sides then combined a different tradPK and derived different shared secrets, with no error reported on either: encapsulation and decapsulation both succeeded and the recipient simply could not decrypt. The EC component is now normalised to an uncompressed point wherever the engine serialises one, which covers the ephemeral key that forms the ciphertext as well. X25519 and X448 components have a single encoding and were unaffected, as were EC keys left in their default (uncompressed) format, whose shared secrets are unchanged. CompositePublicKey.getEncoded() took its component bytes the same way, so such a key also encoded to a composite key other implementations reject and whose bytes changed across an encode / decode / encode round trip - 1238 bytes rather than 1270 for MLKEM768-ECDH-P256, and for the composite ML-DSA keys sharing that method, 2006 rather than 2038 for MLDSA65-ECDSA-P256. It now normalises the component the same way. This is a write-side change only: a composite key carrying a compressed EC component is still decoded, since the component key factories accept either form, and continues to verify signatures as before - it simply re-encodes in the normalised form. The shared normalisation is org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil.getUncompressedSubjectPublicKeyBytes.\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation threw a NullPointerException, wrapped in an IllegalStateException out of KeyGenerator.generateKey(), when the SecureRandom it was given was null - which javax.crypto.KEM.newEncapsulator() documents as a request for the provider's default, and which KeyGenerator.init(spec, null) passes straight through. The three RSA-OAEP composites draw the traditional shared secret from that random directly, so they were the ones affected; the ECDH and X25519 / X448 composites escaped only because their component KeyPairGenerators default a random of their own. CompositeMLKEMEngine now defaults one through CryptoServicesRegistrar.getSecureRandom() on first use, as the composite KEM Cipher's wrap path already did, and as the KEM generators corrected earlier in this cycle now do. Related, the engine now also clears the ML-KEM component's shared secret alongside the traditional one on both the encapsulate and decapsulate paths - the copy handed back by getEncoded() was left in the heap - as section 3.5 of draft-ietf-lamps-pq-composite-kem requires.\u003c/li\u003e\n\u003cli\u003eCompositePublicKey.getAlgorithm() and CompositePrivateKey.getAlgorithm() returned null for all twelve Composite ML-KEM (draft-ietf-lamps-pq-composite-kem) parameter sets. Both classes resolved the name through the composite signature index only, which holds the composite ML-DSA OIDs, so a composite KEM key pair - generated, parsed from a certificate, or read from PKCS#8 - reported no algorithm at all, and the standard JCA idiom of reconstructing a key with KeyFactory.getInstance(key.getAlgorithm()) raised a NullPointerException. The lookup now falls back to the composite KEM index, so the name returned is the one the provider registers the algorithm under (e.g. MLKEM768-X25519-SHA3-256), matching the composite ML-DSA behaviour. The same single-index assumption made the CompositePublicKey(SubjectPublicKeyInfo) and CompositePrivateKey(PrivateKeyInfo) constructors reject a composite KEM key with \u0026quot;unable to create CompositePublicKey from SubjectPublicKeyInfo\u0026quot;; they now dispatch to the composite KEM key factory for those OIDs. Keys obtained through KeyFactory or through BouncyCastleProvider.getPublicKey / getPrivateKey were unaffected and are unchanged (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2404\"\u003e#2404\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe org.bouncycastle.jcajce.spec.KEMKDFSpec constructor stored a null otherInfo as given, so getOtherInfo() returned null, and three of the KDF branches KdfUtil.makeKeyBytes dispatches to - KMAC-128, KMAC-256 and SHAKE-256 - read the otherInfo length without a guard and threw NullPointerException out of the KEM operation, where the KDF2, KDF3 and HKDF branches tolerate a null through KDFParameters / HKDFParameters. The Builder of every spec in the package already mapped null to empty, so no provider path reached it, but the constructor is protected on a public class and KdfUtil is documented for callers building their own KEM integration; the deprecated KEMParameterSpec passes a null itself and escaped only because it also pins the KDF to null. The constructor now stores empty for a null, so getOtherInfo() never returns null, and a null and an explicitly empty otherInfo derive the same key.\u003c/li\u003e\n\u003cli\u003eQR-UOV signature verification accepted a signature encoding that was not canonical, so the encoding of a signature was not unique even after the trailing-byte fix of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e. Each F_q element of the signature is stored in ceil(log2 q) bits, one more bit pattern than the field has elements: q itself is representable and is arithmetically congruent to zero, so an element written as q verified exactly as the same element written as zero would, and the bits padding the last element out to the byte boundary were never read at all. Every zero element of a signature therefore carried a second encoding, and for the q = 7 parameter sets roughly one element in seven is zero - a single qruov_5_q7_L10 signature measured 256 spare bits, so on the order of 2^256 distinct byte strings verified for the one message and key. Verification now rejects any element outside [0, q) and any set padding bit; a signature produced by this or by the reference implementation is unaffected, as the KAT vectors of every parameter set confirm. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSNOVA signature verification ignored four bits inside the signature for any parameter set whose solution is an odd number of GF(16) nibbles - the SNOVA_24_5_5, SNOVA_25_8_3, SNOVA_29_6_5 and SNOVA_66_15_3 families, sixteen of the forty-four parameter sets. The last byte of the encoded solution carries a single nibble and the signer leaves the top four bits zero, but the decoder did not read them, so sixteen distinct byte strings verified for one signature. This is the same non-unique encoding github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e closed for bytes following the signature, applied inside it; the verifier now requires those bits to be zero. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSnovaPrivateKeyParameters did not validate the length of the private key encoding handed to it - the only one of the five schemes of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e that did not - and SnovaParameters.getPrivateKeyLength() reported the expanded (\u0026quot;ESK\u0026quot;) length even for a parameter set whose private key is the seed pair. A private key encoding reaches this constructor straight from a PKCS#8 blob, so a wrong length went undetected: a seed-form key with extra bytes appended was accepted and signed under a different derived key, and a short expanded-form key sized the signer's decode buffer negatively, throwing NegativeArraySizeException out of generateSignature() rather than being reported at construction. Related, the signing retry loop could not terminate: the vinegar values are derived from a single-byte counter, so only 256 distinct linear systems can be tried, and an expanded-form private key that is not a real central map is singular for all of them - generateSignature() then span forever rather than failing. The length is now checked at construction, getPrivateKeyLength() reports the length that parameter set's private key actually has, and the retry loop gives up after its 256 attempts as MAYO's does.\u003c/li\u003e\n\u003cli\u003eMayoSigner and MayoKeyPairGenerator did not clear several buffers holding secret key material that the MAYO reference implementation explicitly clears. Signing left the secret oil space O, the expanded L = (P1 + P1^t) * O + P2, and the M / VPV / Ox intermediates of the central map in place, having gone to the trouble of clearing eleven other buffers; key generation left the expanded seed, whose tail is the encoded oil space, and the P1 * O + P2 half of P; and the row-echelon step left the packed echelon form of the secret linear system and its pivot rows. Separately, if all 256 attempts at solving for the signature had given a rank-deficient system, signing emitted a signature built from the failed attempt's state instead of reporting the failure the reference returns, and AIMerSigner.generateSignature returned an empty array on failure, which a caller would hand on as though it were a signature. Both now throw.\u003c/li\u003e\n\u003cli\u003eFive PQC signature schemes - MAYO, SNOVA, QR-UOV, SQIsign and AIMer - returned the NIST crypto_sign \u0026quot;sm\u0026quot; signed-message envelope from generateSignature() rather than the signature. That envelope is an artefact of the reference KAT harness, which records the message alongside the signature so a vector file can be self-contained; it is not part of any of the five specifications, and no other BC signer emits it (Falcon's KAT test rebuilds the equivalent envelope in the test, which is where it belongs). Two consequences followed, both reaching the JCA Signature services of every parameter set of the five schemes in BouncyCastlePQCProvider. First, since the message was appended to the signature, verification had to skip whatever followed the signature proper, and it did so by checking only that the buffer was long enough - so any number of trailing bytes could be added to a valid signature, or the appended message replaced with unrelated data, and it still verified. A signature encoding was therefore not unique: anyone holding one valid signature could produce unlimited distinct byte strings that all verified for the same message and key, which breaks any use that treats the signature bytes as an identifier, deduplicates on them, or records them as evidence. Second, the envelope propagated into everything built on the operator layer: because ContentSigner hands the signature straight into the structure being signed, every X.509 certificate, CRL, CMS SignedData and TLS CertificateVerify BC produced with one of these algorithms carried a verbatim copy of the signed data inside its own signature field - a self-signed MAYO-1 certificate came to 3567 bytes where the same certificate is now 2020 - which no other implementation can parse as a signature, and which in a detached CMS signature meant the \u0026quot;detached\u0026quot; signature carried the content. generateSignature() now returns the bare signature, and verifySignature() requires exactly the parameter set's signature length, so appended or truncated data is rejected rather than ignored. \u003cstrong\u003eThis is a behavioural change for signatures produced by an earlier release\u003c/strong\u003e - MAYO and SNOVA from 1.84, QR-UOV, SQIsign and AIMer from 1.85 - which are no longer accepted in the envelope form they were emitted in; the signature bytes themselves are unchanged, so a stored value can be recovered by taking the leading signature-length bytes, or for AIMer, whose envelope was message || signature rather than signature || message, the trailing ones. The KAT tests now rebuild the envelope before comparing against the vector files, which continue to record it. Note that AIMer's verification had already been made length-exact during this cycle (see the entry below relating to github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2401\"\u003e#2401\u003c/a\u003e), so of the five only its envelope remained (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe MLS implementation did not bind an X.509 credential to the LeafNode's signature_key. LeafNode.verify() checked a leaf's signature against the signature_key declared in the leaf itself, while the X.509 credential's certificate chain was stored but never parsed or checked, so the certificate's public key was never required to match signature_key (RFC 9420 sec. 5.3). A leaf could therefore carry one party's certificate while being signed by an unrelated key and still be accepted under that party's identity through KeyPackage.verify() and the Group leaf-validation path. LeafNode.verify() now requires the end-entity certificate's subject public key, in the cipher suite's signature encoding, to equal signature_key for an X.509 credential, and rejects the leaf otherwise - including an empty chain or a certificate whose key type does not match the cipher suite; certificate-chain and identity validation to a trust anchor remain the application's responsibility per RFC 9420 sec. 5.3.1. A public org.bouncycastle.mls.codec.Certificate(byte[]) constructor and a Credential.getCertificates() accessor are added so callers can build and inspect X.509 credentials. Basic credentials are unaffected.\u003c/li\u003e\n\u003cli\u003eThe SecureRandom supplied to org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder.setSecureRandom() did not drive the content IV / nonce for any algorithm other than RC2. EnvelopedDataHelper.generateParameters passed the caller's SecureRandom to the AlgorithmParameterGenerator only in the RC2_CBC branch; every other content-encryption algorithm - AES-CBC, AES-GCM, AES-CCM, Camellia, ARIA, SEED and the rest - reached pGen.generateParameters() on an uninitialised generator, so the IV / nonce was drawn from a default SecureRandom and setSecureRandom() was silently ignored (the builder's javadoc states that random is used for IV/nonce generation). The generator is now initialised with the supplied random on the general path as well, so a caller who provides a specific randomness source - for a controlled or FIPS-approved DRBG, say - has it honoured for the content IV / nonce. The session-key generation path was unaffected and already used the supplied random. Because the content IV / nonce now comes from the supplied SecureRandom, the org.bouncycastle.crypto.util JournalingSecureRandom / JournaledAlgorithm reproducible-encryption support records it in the transcript: a resumed session reproduces the IV / nonce by regenerating it from the replayed randomness - build the resuming encryptor from the content-algorithm OID - rather than by reusing the AlgorithmIdentifier captured from the first encryption, which no longer keeps the transcript aligned.\u003c/li\u003e\n\u003cli\u003eThe NTRU LPRime, NTRU+ and SMAUG-T KEM generators threw a NullPointerException when constructed with a null SecureRandom, where every other KEM generator - including NTRU LPRime's own SNTRU Prime counterpart in the same package - defaults one through CryptoServicesRegistrar.getSecureRandom(). This is reachable from the lightweight API directly, and from javax.crypto.KEM, whose newEncapsulator() documents a null random as a request for the provider's default.\u003c/li\u003e\n\u003cli\u003eFrodoKEMEngine kept a single SHAKE instance in a field, so an engine reached concurrently produced wrong results. It is reached that way through org.bouncycastle.crypto.kems.FrodoKEMExtractor, which holds one engine for its lifetime: two threads extracting through one extractor interleaved the digest's absorb and squeeze phases, yielding shared secrets that silently did not match the sender's, or an IllegalStateException of \u0026quot;attempt to absorb while squeezing\u0026quot; from inside extractSecret. The digest is now built per call, as CMCEEngine's already was, which makes an extractor safe to share. Encapsulation was unaffected, since FrodoKEMGenerator builds an engine per call. Results for any single-threaded use are unchanged - the reference KAT vectors are byte-identical.\u003c/li\u003e\n\u003cli\u003eThe BCJSSE provider carried the TLS 1.2 coupling between the supported_groups extension and ECDSA over into TLS 1.3: an ECDSA signature scheme was treated as usable - offered in the signature_algorithms and signature_algorithms_cert extensions, and eligible when selecting the local credentials - only while the corresponding curve was among the named groups enabled for key exchange, both per context (a group unavailable for key agreement disabled the scheme outright) and per connection (the curve had to be in the supported_groups list about to be sent). RFC 8446 sec. 4.2.7 scopes supported_groups to key exchange only, with signature algorithms negotiated independently (sec. 4.2.3), so this incorrect restriction in TLS 1.3 has been removed. Ed25519, Ed448 and the RSA schemes were unaffected (as well as typical deployments using a default configuration for named groups).\u003c/li\u003e\n\u003cli\u003eThe bcmail module descriptor did not declare its javax.mail/javax.activation dependences, so a modular (module-path) consumer of the jar hit IllegalAccessError/module-resolution failures when the S/MIME classes touched the mail API. The descriptor now requires them optionally (requires static) under all four module names those libraries are known by - the automatic names mail and activation carried by the javax.mail:mail / javax.activation:activation artifacts, and the explicit names java.mail and java.activation carried by the newer com.sun.mail / com.sun.activation ones - a hard requires on any one name would break users of the others (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2389\"\u003e#2389\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFour type-coercion helpers in the OER / IEEE 1609.2 (ITS) decoder tested the wrong type in the identity fast path that lets a getInstance() factory return an argument that is already of the target type. org.bouncycastle.oer.its.ieee1609dot2.basetypes.UINT32.getInstance and org.bouncycastle.oer.its.etsi102941.basetypes.Version.getInstance guarded on UINT8 - a sibling of UINT32 under UintBase, and unrelated to Version - so passing a UINT8 threw ClassCastException, while passing an actual UINT32 or Version missed the fast path and fell through to ASN1Integer.getInstance, which rejects them: neither factory accepted its own type. org.bouncycastle.oer.its.etsi103097.EtsiTs103097DataEncryptedUnicast.getInstance guarded on its sibling EtsiTs103097DataEncrypted and then cast to the unicast type, so an EtsiTs103097DataEncrypted threw ClassCastException. org.bouncycastle.oer.OEROptional.getObject(Class) called value.getClass().isInstance(type) with the arguments transposed, which is always false because the argument is a java.lang.Class, so the cast path was dead and every optional field was resolved reflectively, failing with IllegalStateException for a target type with no static getInstance. Each guard now names the type it returns, matching the sibling UINT8 / UINT16 / UINT64 and EtsiTs103097DataEncrypted factories (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2373\"\u003e#2373\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eDefaultAlgorithmNameFinder and DefaultSignatureNameFinder had no entries at all for the ShangMi algorithms, so an SM2 signature AlgorithmIdentifier that DefaultSignatureAlgorithmIdentifierFinder itself produces came back named only by its OID string - getAlgorithmName(GMObjectIdentifiers.sm2sign_with_sm3) returned \u0026quot;1.2.156.10197.1.501\u0026quot; and hasAlgorithmName returned false. Both finders now name sm2sign_with_sm3 as SM3WITHSM2 and sm2sign_with_sha256 as SHA256WITHSM2, and DefaultAlgorithmNameFinder additionally names the sm3 digest. All three resolve through the BC provider, as Signature and MessageDigest respectively. The remaining GM arc - the SM4 cipher modes, the sm2encrypt variants, and the SM1 / SM6 / SSF33 ciphers BC does not implement - is still unnamed (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2377\"\u003e#2377\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe RFC 4998 evidence-record classes compared the digest AlgorithmIdentifier named by a time-stamp authority with the one their own DigestCalculator uses, and did so with AlgorithmIdentifier.equals(), which compares the encodings. A TSA that names SHA-256 with an explicit NULL parameters field - DigiCert among them - therefore failed against BC's own calculator, which names it with the parameters absent, and ERSArchiveTimeStampGenerator.generateArchiveTimeStamp rejected the response with \u0026quot;time stamp imprint for wrong algorithm\u0026quot;. Both spellings name the same digest and RFC 5754 sec. 2 requires a receiver to accept either, while requiring that identifiers be generated with the parameters absent, which BC already does. The three affected comparisons - the two in ERSArchiveTimeStampGenerator and the digest check in ERSEvidenceRecord.renew - now use the new AlgorithmIdentifier.areEquivalent, which matches on the algorithm and treats an absent parameters field and NULL as the same, and the consistency check across an evidence record's archive time stamp chain uses it too. An identifier carrying an actual parameter structure is never equivalent to one carrying none (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2379\"\u003e#2379\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eEDIPartyName.toASN1Primitive emitted the nameAssigner and partyName DirectoryStrings without their context tags, so an EDIPartyName built through its public constructor could not be parsed back by EDIPartyName.getInstance, which correctly requires them. RFC 5280 sec. 4.2.1.6 tags both members [0] and [1], and those tags are explicit despite the module's IMPLICIT TAGS because DirectoryString is a CHOICE, which X.680 does not allow to be tagged implicitly - the decoder already had this right. The encoder now matches it. Note the type was added during the 1.85 cycle and GeneralName validates its ediPartyName alternative through it, so a GeneralName carrying an untagged ediPartyName - including one BC itself produced - is rejected where 1.84 passed it through unexamined; the untagged form is not read leniently (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2380\"\u003e#2380\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eRSASSA-PSS could not be used with a RIPEMD digest through the JCA API. Nothing registered the RIPEMD PSS signatures, so Signature.getInstance(\u0026quot;RIPEMD160WITHRSAANDMGF1\u0026quot;) raised NoSuchAlgorithmException, and the generic RSASSA-PSS route with an explicit PSSParameterSpec failed too: org.bouncycastle.jcajce.provider.util.DigestFactory.getDigest returned null for a RIPEMD name, and isSameDigest - an allow-list of the SHA families and MD5 - reported two identical RIPEMD names as different digests, so the spec was rejected with \u0026quot;digest algorithm for MGF should be the same as for PSS parameters\u0026quot;. isSameDigest now answers true for equal names whatever the digest, which also covers Whirlpool, SM3, GOST3411 and anything else outside that allow-list; DigestFactory recognises RIPEMD128, RIPEMD160 and RIPEMD256 by name and OID; the three PSS signatures are registered with MGF1 over the same digest and a salt of the digest length; and DefaultSignatureAlgorithmIdentifierFinder gains the matching RIPEMD*WITHRSAANDMGF1 entries with their RSASSA-PSS-params, so the operator/JcaContentSignerBuilder path works as well. Note BC continues to require the PSS hash and the MGF1 hash to be the same, which RFC 8017 does not itself demand (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2381\"\u003e#2381\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe opt-in key-size validation on CMS key-transport recipients (org.bouncycastle.cms.jcajce.JceKeyTransRecipient.setKeySizeValidation(true)) never ran for a message using RFC 9709 CEK derivation (id-alg-cek-hkdf-sha256): the branch that should have selected the actual content-encryption algorithm carried in the KDF AlgorithmIdentifier's parameters compared the encrypted-key byte array against the id-alg-cek-hkdf-sha256 object identifier - a comparison that is always false - so the check fell through to a key-size lookup on the outer KDF OID, which has no registered key size, and silently checked nothing. A key-transport EnvelopedData/AuthEnvelopedData whose transported (and HKDF-derived) content-encryption key did not match the key size of the advertised content-encryption algorithm was therefore accepted even with validation enabled. The recipient now dispatches on the content-encryption AlgorithmIdentifier's algorithm OID, so key-size validation of RFC 9709 messages checks the recovered key against the inner content-encryption algorithm. Messages with a matching key size, non-HKDF messages, and recipients that do not enable validation are unaffected.\u003c/li\u003e\n\u003cli\u003eThe OpenPGP v6 SEIPD (Symmetrically Encrypted Integrity Protected Data, version 2 / RFC 9580 sec. 5.13.2) packet parser read the AEAD chunk-size octet without bounding it. The chunk length is 2^(chunkSize + 6) bytes and the AEAD decryptor allocates a buffer of that size up front, so a crafted v6 encrypted message (reachable with only the recipient's public key) declaring chunkSize 24 forced a 1 GiB allocation on decrypt, and chunkSize 25 (where the int cast of the chunk length wraps negative) threw a NegativeArraySizeException -- a pre-authentication resource-exhaustion denial of service. This is the version 6 sibling of the version 5 AEADEncDataPacket issue fixed under CVE-2026-3505, which bounded that packet's chunk size at 16 but left the v6 SymmetricEncIntegrityPacket unbounded. SymmetricEncIntegrityPacket now rejects a chunk-size octet outside 0..16 (a 4 MiB chunk, matching the v5 ceiling) with a MalformedPacketException at parse, before any allocation.\u003c/li\u003e\n\u003cli\u003eThe Ed25519 KeyFactory in the JDK 11+ and JDK 15+ multi-release overlays (META-INF/versions/11 and /15) had drifted from the base implementation on the OpenSSH key-spec path: it used the no-passphrase OpenSSHPrivateKeyUtil.parsePrivateKeyBlob overload, so a passphrase-encrypted openssh-key-v1 Ed25519 private key that KeyFactory.getInstance(\u0026quot;Ed25519\u0026quot;, \u0026quot;BC\u0026quot;).generatePrivate(new OpenSSHPrivateKeySpec(blob, passphrase)) decoded correctly on JDK 8 failed on JDK 11 and later; it also let a raw RuntimeException escape on a malformed blob and threw IllegalStateException (JDK 11) instead of InvalidKeySpecException for a non-Ed25519 key. The overlays now match the base implementation (passphrase support, parse errors wrapped as InvalidKeySpecException). Relatedly, the OpenSSH wrong-key-type and decode-failure paths across the RSA, DSA, EC and Ed25519 KeyFactorySpi implementations now consistently raise InvalidKeySpecException (previously a mix of IllegalArgumentException / IllegalStateException) and wrap a malformed OpenSSH public key, and an incorrect \u0026quot;public key is not RSA private key\u0026quot; message on the RSA private path was corrected. The multi-release test tasks now exercise the OpenSSH key specs against the multi-release jar.\u003c/li\u003e\n\u003cli\u003eThe Ant-built utility jars (bcutil-jdk15to18, bcutil-jdk14) duplicated org.bouncycastle.asn1.iana.IANAObjectIdentifiers, which since 1.85 (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2176\"\u003e#2176\u003c/a\u003e) lives only in core and is therefore already shipped in bcprov. The shared ant/bc+-build.xml build-util target still copied org/bouncycastle/asn1/iana/** into bcutil, so a project depending on both bcprov and bcutil (for example via bcpkix) failed an Android/R8 build with \u0026quot;Duplicate class org.bouncycastle.asn1.iana.IANAObjectIdentifiers found in modules bcprov-jdk15to18-1.85.jar and bcutil-jdk15to18-1.85.jar\u0026quot;. The iana package is no longer bundled into bcutil (it remains in bcprov); the Gradle jdk18on jars were already correct (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2356\"\u003e#2356\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eorg.bouncycastle.util.BigIntegers.intValueExact (and the byte/short/long variants) delegated to BigInteger.intValueExact from 1.85, a Java 8 method Android only provides from API level 33, so on earlier Android versions any code path using them - most visibly loading a PKCS12 keystore, whose iteration-count validation calls intValueExact - crashed with NoSuchMethodError. The range checks are open-coded again, as they were in 1.84 (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2369\"\u003e#2369\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eGOST R 34.10-94 signing (org.bouncycastle.crypto.signers.GOST3410Signer) raised the domain generator to the per-signature nonce k with a bare BigInteger.modPow, whose running time varies with the exponent. Recovering k from that timing yields the private key straight out of the signature equation s = k*m + x*r, so k is now randomised with a random multiple of q before it is raised, exactly as DSASigner already does with its own k. Since the domain parameter a has order q, raising it to a multiple of q gives 1 and the signature is unchanged - the RFC-style known-answer vectors in GOST3410Test still produce the same r and s. Those vectors drive signing from a FixedSecureRandom, so they now carry one further byte for the randomiser to consume, in the same way the DSA signing vectors already do.\u003c/li\u003e\n\u003cli\u003eKCCMBlockCipher (DSTU7624-128/256/512 CCM mode) returned the input length rather than 0 from getUpdateOutputSize(int), but like CCMBlockCipher/KGCMBlockCipher it buffers all input until doFinal and produces no output on an update. Through the JCA layer this made the caller-supplied-buffer Cipher.update(input, inOff, inLen, output, outOff) reject a correctly sized output buffer with \u0026quot;javax.crypto.ShortBufferException: output buffer too short for input.\u0026quot; when decrypting. getUpdateOutputSize now returns 0, matching the sibling CCM/KGCM modes (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2354\"\u003e#2354\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eJ-PAKE raised values to exponents carrying private material with bare BigInteger.modPow calls, whose running time varies with the exponent: the private ephemerals x1 and x2 in round 1, x2*s and the negated form of it in round 2 and in the keying material - both of which carry the password - and the v behind each Schnorr zero-knowledge proof, which together with the published r would give up x. JPAKEParticipant itself notes that leaking x1 or x2 lets an attacker brute-force the password. All of these exponents are now randomised with a random multiple of q before they are raised. A multiple of q rather than of p-1 is sound here, and much cheaper since the exponents are the size of q: the generator is checked with g^q = 1 when the JPAKEPrimeOrderGroup is built, and each value received from the other participant is checked the same way by validateZeroKnowledgeProof before it is used as a base. JPAKEUtil.calculateA and JPAKEUtil.calculateKeyingMaterial gained overloads taking a SecureRandom, and there is a new JPAKEUtil.calculateGx taking q and a SecureRandom; the existing overloads still work, taking the default from CryptoServicesRegistrar. The three-argument calculateGx has no q to work with, so it blinds with a multiple of p-1 and is deprecated in favour of the new one. The three modPow calls in validateZeroKnowledgeProof are unchanged, since their exponents are all public. The elliptic-curve variant was already routing its private scalars through ECAlgorithms.multiplySecret and needed no change.\u003c/li\u003e\n\u003cli\u003eThe PKIX CertPathBuilder (\u0026quot;PKIX\u0026quot;/\u0026quot;RFC5280\u0026quot;/\u0026quot;RFC3280\u0026quot;) matched candidate issuers by subject name only during its depth-first search, so a CertStore containing many self-issued certificates that share a single subject name and never chain to a trust anchor could be explored as a large number of partial paths before the build concluded no chain exists. The builder now bounds the total number of nodes visited per build; the limit is configurable via the org.bouncycastle.x509.max_cert_path_build_nodes system property (default 262144, far above any legitimate build) and, when exceeded, the build fails with a CertPathBuilderException naming the property. This is the builder-side companion to the existing org.bouncycastle.x509.max_policy_nodes bound.\u003c/li\u003e\n\u003cli\u003eA group of parse and revocation-handling entry points let an unchecked runtime exception (NullPointerException, ArrayIndexOutOfBoundsException, IllegalStateException or ArithmeticException) escape on empty, content-less or out-of-range input instead of the checked exception each entry point declares - the malformed input was rejected either way, but the leaked type could escape a documented throws contract. Each now fails with its declared type, and well-formed input is unaffected: org.bouncycastle.tsp.cms.CMSTimeStampedData (an empty or truncated stream; the fix also covers its org.bouncycastle.asn1.cms.MetaData and TimeStampDataUtil helpers) and org.bouncycastle.cms.CMSEnvelopedData (an EnvelopedData carrying no encryptedContent) now throw IOException / CMSException rather than NullPointerException; org.bouncycastle.tsp.TimeStampToken rejects a token whose SignerInfo carries no signed attributes with TSPValidationException rather than NullPointerException; org.bouncycastle.cert.cmp.GeneralPKIMessage, org.bouncycastle.est.CSRAttributesResponse, org.bouncycastle.cmc.SimplePKIResponse, org.bouncycastle.openssl.X509TrustedCertificateBlock, org.bouncycastle.tsp.TimeStampRequest, org.bouncycastle.tsp.TimeStampResponse, org.bouncycastle.pkcs.PKCS12PfxPdu and org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo reject empty / no-content / truncated input with their declared CertIOException / IOException / PKCSIOException rather than a leaked NullPointerException, and org.bouncycastle.cert.crmf.CertificateRequestMessage.hasSigningKeyProofOfPossessionWithPKMAC answers false for an absent or non-signing-key proof-of-possession rather than throwing NullPointerException; org.bouncycastle.crypto.util.OpenSSHPrivateKeyUtil.parsePrivateKeyBlob and org.bouncycastle.math.ec.ECCurve.decodePoint reject an empty (or null) blob / point encoding with IllegalArgumentException rather than ArrayIndexOutOfBoundsException, closing the point-decode path reached by every untrusted-point consumer (EC key parsing, ECDH/ECIES, TLS); and the PKIX revocation code no longer leaks a runtime exception on attacker-controlled CRL/OCSP fields - PKIXCertPathReviewer and X509RevocationChecker bound an out-of-range CRLReason code against their fixed reason table (reporting \u0026quot;unknown\u0026quot; instead of ArrayIndexOutOfBoundsException / ArithmeticException), RFC3280CertPathUtilities tolerates an absent reasons mask on a CRL distribution point, and ProvOcspRevocationChecker tolerates an OCSP response with no nonce extension.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003eSee full diff in \u003ca href=\"https://github.com/bcgit/bc-java/commits\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark` from 0.29.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/blockquote\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/blockquote\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/42b4fb7adfe288ef13e9e27ab20aff7e91b0ab9d\"\u003e\u003ccode\u003e42b4fb7\u003c/code\u003e\u003c/a\u003e Prepare CHANGELOG for version 0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/b76e09d7a8362abb5f04e1d6b91dbd6da279a6fc\"\u003e\u003ccode\u003eb76e09d\u003c/code\u003e\u003c/a\u003e Limit how deep inline nodes may nest by default (100)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/49f65cb5cbec93cff713179990307145198e7061\"\u003e\u003ccode\u003e49f65cb\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing deeply nested emphasis\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/610f84b83e68c381e8f784ae4d044c80e1948b67\"\u003e\u003ccode\u003e610f84b\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological autolink email addresses\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/9f1d73897a56cbd74c39347af351a473e70297e1\"\u003e\u003ccode\u003e9f1d738\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological HTML block attributes\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/e13297e849995fdd582a85841067bff1d9c35ee5\"\u003e\u003ccode\u003ee13297e\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing pathological backticks\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/89d1bd3fa1524e8217ed61db5e8116c82434470f\"\u003e\u003ccode\u003e89d1bd3\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing with lots of \u003ccode\u003e\u0026lt;\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/commonmark/commonmark-java/compare/commonmark-parent-0.29.0...commonmark-parent-0.30.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark-ext-autolink` from 0.29.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark-ext-autolink's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/blockquote\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark-ext-autolink's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply ...\n\n_Description has been truncated_","html_url":"https://github.com/jckm14/openclaw/pull/70","url":"https://dependabot.ecosyste.ms/api/v1/hosts/GitHub/repositories/jckm14%2Fopenclaw/issues/70","packages_url":"https://dependabot.ecosyste.ms/api/v1/issues/70/packages"},{"uuid":"5174169869","node_id":"PR_kwDOTHJXZM8AAAABADENkQ","number":29,"state":"closed","title":"chore(deps): bump the android-deps group across 1 directory with 19 updates","user":"dependabot[bot]","labels":["dependencies","java"],"assignees":[],"locked":false,"comments_count":2,"pull_request":true,"closed_at":"2026-09-10T15:45:32.000Z","author_association":null,"state_reason":null,"created_at":"2026-08-17T18:23:33.000Z","updated_at":"2026-09-10T15:45:34.000Z","time_to_close":2064119,"merged_at":null,"merged_by":null,"closed_by":null,"dependency_metadata":{"prefix":"chore(deps): bump","group_name":"android-deps","update_count":19,"packages":[{"name":"gradle-wrapper","old_version":"9.5.1","new_version":"9.7.0","repository_url":"https://github.com/gradle/gradle"},{"name":"androidx.compose:compose-bom","old_version":"2026.05.01","new_version":"2026.08.00"},{"name":"androidx.core:core-ktx","old_version":"1.18.0","new_version":"1.19.0"},{"name":"androidx.webkit:webkit","old_version":"1.15.0","new_version":"1.17.0"},{"name":"org.bouncycastle:bcprov-jdk18on","old_version":"1.84","new_version":"1.85.2","repository_url":"https://github.com/bcgit/bc-java"},{"name":"org.commonmark:commonmark","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-autolink","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-strikethrough","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-tables","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-task-list-items","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.junit.vintage:junit-vintage-engine","old_version":"6.1.0","new_version":"6.1.3","repository_url":"https://github.com/junit-team/junit-framework"},{"name":"io.kotest:kotest-assertions-core-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"io.kotest:kotest-runner-junit5-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"com.squareup.okhttp3:mockwebserver","old_version":"5.3.2","new_version":"5.4.0","repository_url":"https://github.com/square/okhttp"},{"name":"com.squareup.okhttp3:okhttp","old_version":"5.3.2","new_version":"5.4.0","repository_url":"https://github.com/square/okhttp"},{"name":"com.android.application","old_version":"9.2.1","new_version":"9.3.1"},{"name":"com.android.test","old_version":"9.2.1","new_version":"9.3.1"},{"name":"org.jetbrains.kotlin.plugin.compose","old_version":"2.4.0","new_version":"2.4.10","repository_url":"https://github.com/JetBrains/kotlin"},{"name":"org.jetbrains.kotlin.plugin.serialization","old_version":"2.4.0","new_version":"2.4.10","repository_url":"https://github.com/JetBrains/kotlin"}],"path":null,"ecosystem":"maven"},"body":"Bumps the android-deps group with 19 updates in the /apps/android directory:\n\n| Package | From | To |\n| --- | --- | --- |\n| [gradle-wrapper](https://github.com/gradle/gradle) | `9.5.1` | `9.7.0` |\n| androidx.compose:compose-bom | `2026.05.01` | `2026.08.00` |\n| androidx.core:core-ktx | `1.18.0` | `1.19.0` |\n| androidx.webkit:webkit | `1.15.0` | `1.17.0` |\n| [org.bouncycastle:bcprov-jdk18on](https://github.com/bcgit/bc-java) | `1.84` | `1.85.2` |\n| [org.commonmark:commonmark](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-autolink](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-strikethrough](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-tables](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-task-list-items](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.junit.vintage:junit-vintage-engine](https://github.com/junit-team/junit-framework) | `6.1.0` | `6.1.3` |\n| [io.kotest:kotest-assertions-core-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [io.kotest:kotest-runner-junit5-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [com.squareup.okhttp3:mockwebserver](https://github.com/square/okhttp) | `5.3.2` | `5.4.0` |\n| [com.squareup.okhttp3:okhttp](https://github.com/square/okhttp) | `5.3.2` | `5.4.0` |\n| com.android.application | `9.2.1` | `9.3.1` |\n| com.android.test | `9.2.1` | `9.3.1` |\n| [org.jetbrains.kotlin.plugin.compose](https://github.com/JetBrains/kotlin) | `2.4.0` | `2.4.10` |\n| [org.jetbrains.kotlin.plugin.serialization](https://github.com/JetBrains/kotlin) | `2.4.0` | `2.4.10` |\n\n\nUpdates `gradle-wrapper` from 9.5.1 to 9.7.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/gradle/gradle/releases\"\u003egradle-wrapper's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e9.7.0\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.0.\u003c/p\u003e\n\u003cp\u003eHere are the highlights of this release:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIsolated Projects graduates to incubating\u003c/li\u003e\n\u003cli\u003eBroader Configuration Cache compatibility\u003c/li\u003e\n\u003cli\u003eMore source locations in problem reports\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003ca href=\"https://docs.gradle.org/9.7.0/release-notes.html\"\u003eRead the Release Notes\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eWe would like to thank the following community members for their contributions to this release of Gradle:\n\u003ca href=\"https://github.com/aSemy\"\u003eAdam\u003c/a\u003e,\n\u003ca href=\"https://github.com/Gautam-aman\"\u003eAman Gautam\u003c/a\u003e,\n\u003ca href=\"https://github.com/YukiCodepth\"\u003eAman Kumar\u003c/a\u003e,\n\u003ca href=\"https://github.com/adubrouski\"\u003eAnton Dubrouski\u003c/a\u003e,\n\u003ca href=\"https://github.com/liutikas\"\u003eAurimas\u003c/a\u003e,\n\u003ca href=\"https://github.com/gbhavya07\"\u003egbhavya07\u003c/a\u003e,\n\u003ca href=\"https://github.com/joshfriend\"\u003eJosh Friend\u003c/a\u003e,\n\u003ca href=\"https://github.com/nicklauslittle-gov\"\u003enicklauslittle-gov\u003c/a\u003e,\n\u003ca href=\"https://github.com/psoni674\"\u003ePragati\u003c/a\u003e,\n\u003ca href=\"https://github.com/Project516\"\u003eproject516\u003c/a\u003e,\n\u003ca href=\"https://github.com/Uomocapra\"\u003eQin Mi\u003c/a\u003e,\n\u003ca href=\"https://github.com/rkdfx\"\u003eRavi\u003c/a\u003e,\n\u003ca href=\"https://github.com/sk-reddy17\"\u003esk-reddy17\u003c/a\u003e,\n\u003ca href=\"https://github.com/Suvrat1629\"\u003eSuvrat Acharya\u003c/a\u003e,\n\u003ca href=\"https://github.com/ShreckYe\"\u003eYongshun Ye\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eUpgrade instructions\u003c/h2\u003e\n\u003cp\u003eSwitch your build to use Gradle 9.7.0 by updating your wrapper:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e./gradlew :wrapper --gradle-version=9.7.0 \u0026amp;\u0026amp; ./gradlew :wrapper\r\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eSee the Gradle \u003ca href=\"https://docs.gradle.org/9.7.0/userguide/upgrading_version_9.html\"\u003e9.x upgrade guide\u003c/a\u003e to learn about deprecations, breaking changes and other considerations when upgrading.\u003c/p\u003e\n\u003cp\u003eFor Java, Groovy, Kotlin and Android compatibility, see the \u003ca href=\"https://docs.gradle.org/9.7.0/userguide/compatibility.html\"\u003efull compatibility notes\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eReporting problems\u003c/h2\u003e\n\u003cp\u003eIf you find a problem with this release, please file a bug on \u003ca href=\"https://github.com/gradle/gradle/issues\"\u003eGitHub Issues\u003c/a\u003e adhering to our issue guidelines.\nIf you're not sure you're encountering a bug, please use the \u003ca href=\"https://discuss.gradle.org/c/help-discuss\"\u003eforum\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eWe hope you will build happiness with Gradle, and we look forward to your feedback via \u003ca href=\"https://twitter.com/gradle\"\u003eTwitter\u003c/a\u003e or on \u003ca href=\"https://github.com/gradle\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003e9.7.0 RC3\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.0 RC3.\u003c/p\u003e\n\u003cp\u003eHere are the highlights of this release:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIsolated Projects graduates to incubating\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/3defbfc59d757b873d787b2261de5c7f8a00970a\"\u003e\u003ccode\u003e3defbfc\u003c/code\u003e\u003c/a\u003e make DistributionIntegrationSpec more permissive for releases (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38766\"\u003e#38766\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/f176043d6416ca85dab736b6e7581d1f0018ee8e\"\u003e\u003ccode\u003ef176043\u003c/code\u003e\u003c/a\u003e make DistributionIntegrationSpec more permissive for releases\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/b0828dad52cf99112e2071fb10547c0d2293a51b\"\u003e\u003ccode\u003eb0828da\u003c/code\u003e\u003c/a\u003e Prepare release notes for Gradle 9.7.0GA (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38756\"\u003e#38756\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/064b6d6161b55f531be7710d68efe4404b48558a\"\u003e\u003ccode\u003e064b6d6\u003c/code\u003e\u003c/a\u003e cleanup\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/dfe7bdcc464152313992f49b6ea3846d7c0119ed\"\u003e\u003ccode\u003edfe7bdc\u003c/code\u003e\u003c/a\u003e add new training to release notes\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/756196837a985dd030d596411852b99c43d6880e\"\u003e\u003ccode\u003e7561968\u003c/code\u003e\u003c/a\u003e add release notes for 37801\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/68a1f351d3ba32e09523e5d67949cea326c0d781\"\u003e\u003ccode\u003e68a1f35\u003c/code\u003e\u003c/a\u003e cherrypick 38367 to release\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/a462c95ca92b7a5cc55172a42608fcab5fd43b4c\"\u003e\u003ccode\u003ea462c95\u003c/code\u003e\u003c/a\u003e Rebalance AllVersionsCrossVersion buckets for agents without TestDistribution...\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/820e2b14ad6b0f64a1a042dcfb43ea7e3e8f7ada\"\u003e\u003ccode\u003e820e2b1\u003c/code\u003e\u003c/a\u003e Update Gradle wrapper to version 9.7.0-rc-3 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38743\"\u003e#38743\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/75ea3d7671b4c52daf3fd26d0824b8fa7c752181\"\u003e\u003ccode\u003e75ea3d7\u003c/code\u003e\u003c/a\u003e Update Gradle wrapper to version 9.7.0-rc-3\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/gradle/gradle/compare/v9.5.1...v9.7.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `androidx.compose:compose-bom` from 2026.05.01 to 2026.08.00\n\nUpdates `androidx.core:core-ktx` from 1.18.0 to 1.19.0\n\nUpdates `androidx.webkit:webkit` from 1.15.0 to 1.17.0\n\nUpdates `org.bouncycastle:bcprov-jdk18on` from 1.84 to 1.85.2\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.html\"\u003eorg.bouncycastle:bcprov-jdk18on's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003eSee full diff in \u003ca href=\"https://github.com/bcgit/bc-java/commits\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003ecommonmark-java 0.29.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e[0.29.0] - 2026-06-20\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/42b4fb7adfe288ef13e9e27ab20aff7e91b0ab9d\"\u003e\u003ccode\u003e42b4fb7\u003c/code\u003e\u003c/a\u003e Prepare CHANGELOG for version 0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/b76e09d7a8362abb5f04e1d6b91dbd6da279a6fc\"\u003e\u003ccode\u003eb76e09d\u003c/code\u003e\u003c/a\u003e Limit how deep inline nodes may nest by default (100)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/49f65cb5cbec93cff713179990307145198e7061\"\u003e\u003ccode\u003e49f65cb\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing deeply nested emphasis\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/610f84b83e68c381e8f784ae4d044c80e1948b67\"\u003e\u003ccode\u003e610f84b\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological autolink email addresses\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/9f1d73897a56cbd74c39347af351a473e70297e1\"\u003e\u003ccode\u003e9f1d738\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological HTML block attributes\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/e13297e849995fdd582a85841067bff1d9c35ee5\"\u003e\u003ccode\u003ee13297e\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing pathological backticks\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/89d1bd3fa1524e8217ed61db5e8116c82434470f\"\u003e\u003ccode\u003e89d1bd3\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing with lots of \u003ccode\u003e\u0026lt;\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/commonmark/commonmark-java/compare/commonmark-parent-0.28.0...commonmark-parent-0.30.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark-ext-autolink` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark-ext-autolink's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003ecommonmark-java 0.29.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark-ext-autolink's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e[0.29.0] - 2026-06-20\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/42b4fb7adfe288ef13e9e27ab20aff7e91b0ab9d\"\u003e\u003ccode\u003e42b4fb7\u003c/code\u003e\u003c/a\u003e Prepare CHANGELOG for version 0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/b76e09d7a8362abb5f04e1d6b91dbd6da279a6fc\"\u003e\u003ccode\u003eb76e09d\u003c/code\u003e\u003c/a\u003e Limit how deep inline nodes may nest by default (100)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/49f65cb5cbec93cff713179990307145198e7061\"\u003e\u003ccode\u003e49f65cb\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing deeply nested emphasis\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/610f84b83e68c381e8f784ae4d044c80e1948b67\"\u003e\u003ccode\u003e610f84b\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological autolink email addresses\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/9f1d73897a56cbd74c39347af351a473e70297e1\"\u003e\u003ccode\u003e9f1d738\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological HTML block attributes\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/e13297e849995fdd582a85841067bff1d9c35ee5\"\u003e\u003ccode\u003ee13297e\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing pathological backticks\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/89d1bd3fa1524e8217ed61db5e8116c82434470f\"\u003e\u003ccode\u003e89d1bd3\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing with lots of \u003ccode\u003e\u0026lt;\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/commonmark/commonmark-java/compare/commonmark-parent-0.28.0...commonmark-parent-0.30.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark-ext-gfm-strikethrough` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark-ext-gfm-strikethrough's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003ecommonmark-java 0.29.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark-ext-gfm-strikethrough's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e[0.29.0] - 2026-06-20\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/42b4fb7adfe288ef13e9e27ab20aff7e91b0ab9d\"\u003e\u003ccode\u003e42b4fb7\u003c/code\u003e\u003c/a\u003e Prepare CHANGELOG for version 0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/b76e09d7a8362abb5f04e1d6b91dbd6da279a6fc\"\u003e\u003ccode\u003eb76e09d\u003c/code\u003e\u003c/a\u003e Limit how deep inline nodes may nest by default (100)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/49f65cb5cbec93cff713179990307145198e7061\"\u003e\u003ccode\u003e49f65cb\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing deeply nested emphasis\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/610f84b83e68c381e8f784ae4d044c80e1948b67\"\u003e\u003ccode\u003e610f84b\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological autolink email addresses\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/9f1d73897a56cbd74c39347af351a473e70297e1\"\u003e\u003ccode\u003e9f1d738\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological HTML block attributes\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/e13297e849995fdd582a85841067bff1d9c35ee5\"\u003e\u003ccode\u003ee13297e\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing pathological backticks\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/89d1bd3fa1524e8217ed61db5e8116c82434470f\"\u003e\u003ccode\u003e89d1bd3\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing with lots of \u003ccode\u003e\u0026lt;\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/commonmark/commonmark-java/compare/commonmark-parent-0.28.0...commonmark-parent-0.30.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark-ext-gfm-tables` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark-ext-gfm-tables's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003ecommonmark-java 0.29.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark-ext-gfm-tables's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e[0.29.0] - 2026-06-20\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/42b4fb7adfe288ef13e9e27ab20aff7e91b0ab9d\"\u003e\u003ccode\u003e42b4fb7\u003c/code\u003e\u003c/a\u003e Prepare CHANGELOG for version 0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/b76e09d7a8362abb5f04e1d6b91dbd6da279a6fc\"\u003e\u003ccode\u003eb76e09d\u003c/code\u003e\u003c/a\u003e Limit how deep inline nodes may nest by default (100)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/49f65cb5cbec93cff713179990307145198e7061\"\u003e\u003ccode\u003e49f65cb\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing deeply nested emphasis\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/610f84b83e68c381e8f784ae4d044c80e1948b67\"\u003e\u003ccode\u003e610f84b\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological autolink email addresses\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/9f1d73897a56cbd74c39347af351a473e70297e1\"\u003e\u003ccode\u003e9f1d738\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological HTML block attributes\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/e13297e849995fdd582a85841067bff1d9c35ee5\"\u003e\u003ccode\u003ee13297e\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing pathological backticks\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/89d1bd3fa1524e8217ed61db5e8116c82434470f\"\u003e\u003ccode\u003e89d1bd3\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing with lots of \u003ccode\u003e\u0026lt;\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/commonmark/commonmark-java/compare/commonmark-parent-0.28.0...commonmark-parent-0.30.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark-ext-task-list-items` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark-ext-task-list-items's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003ecommonmark-java 0.29.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark-ext-task-list-items's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e[0.29.0] - 2026-06-20\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/42b4fb7adfe288ef13e9e27ab20aff7e91b0ab9d\"\u003e\u003ccode\u003e42b4fb7\u003c/code\u003e\u003c/a\u003e Prepare CHANGELOG for version 0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/b76e09d7a8362abb5f04e1d6b91dbd6da279a6fc\"\u003e\u003ccode\u003eb76e09d\u003c/code\u003e\u003c/a\u003e Limit how deep inline nodes may nest by default (100)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/49f65cb5cbec93cff713179990307145198e7061\"\u003e\u003ccode\u003e49f65cb\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing deeply nested emphasis\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/610f84b83e68c381e8f784ae4d044c80e1948b67\"\u003e\u003ccode\u003e610f84b\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological autolink email addresses\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/9f1d73897a56cbd74c39347af351a473e70297e1\"\u003e\u003ccode\u003e9f1d738\u003c/code\u003e\u003c/a\u003e Fix StackOverflowEr...\n\n_Description has been truncated_","html_url":"https://github.com/amstaff666/openclaw/pull/29","url":"https://dependabot.ecosyste.ms/api/v1/hosts/GitHub/repositories/amstaff666%2Fopenclaw/issues/29","packages_url":"https://dependabot.ecosyste.ms/api/v1/issues/29/packages"},{"uuid":"5167091043","node_id":"PR_kwDOS5U1Kc7_1rvw","number":38,"state":"closed","title":"chore(deps): bump the android-deps group across 1 directory with 23 updates","user":"dependabot[bot]","labels":["dependencies","java"],"assignees":[],"locked":false,"comments_count":1,"pull_request":true,"closed_at":"2026-09-10T00:08:35.000Z","author_association":null,"state_reason":null,"created_at":"2026-08-17T00:20:48.000Z","updated_at":"2026-09-10T00:08:37.000Z","time_to_close":2072867,"merged_at":null,"merged_by":null,"closed_by":null,"dependency_metadata":{"prefix":"chore(deps): bump","group_name":"android-deps","update_count":23,"packages":[{"name":"gradle-wrapper","old_version":"9.4.1","new_version":"9.7.0","repository_url":"https://github.com/gradle/gradle"},{"name":"androidx.compose:compose-bom","old_version":"2026.04.01","new_version":"2026.08.00"},{"name":"androidx.core:core-ktx","old_version":"1.18.0","new_version":"1.19.0"},{"name":"androidx.webkit:webkit","old_version":"1.15.0","new_version":"1.17.0"},{"name":"org.bouncycastle:bcprov-jdk18on","old_version":"1.84","new_version":"1.85.2","repository_url":"https://github.com/bcgit/bc-java"},{"name":"org.commonmark:commonmark","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-autolink","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-strikethrough","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-tables","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-task-list-items","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"dnsjava:dnsjava","old_version":"3.6.4","new_version":"3.6.5","repository_url":"https://github.com/dnsjava/dnsjava"},{"name":"org.junit.vintage:junit-vintage-engine","old_version":"6.0.3","new_version":"6.1.3","repository_url":"https://github.com/junit-team/junit-framework"},{"name":"io.kotest:kotest-assertions-core-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"io.kotest:kotest-runner-junit5-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"org.jetbrains.kotlinx:kotlinx-coroutines-android","old_version":"1.10.2","new_version":"1.11.0","repository_url":"https://github.com/Kotlin/kotlinx.coroutines"},{"name":"org.jetbrains.kotlinx:kotlinx-coroutines-test","old_version":"1.10.2","new_version":"1.11.0","repository_url":"https://github.com/Kotlin/kotlinx.coroutines"},{"name":"com.google.android.material:material","old_version":"1.13.0","new_version":"1.14.0","repository_url":"https://github.com/material-components/material-components-android"},{"name":"com.squareup.okhttp3:mockwebserver","old_version":"5.3.2","new_version":"5.4.0","repository_url":"https://github.com/square/okhttp"},{"name":"com.squareup.okhttp3:okhttp","old_version":"5.3.2","new_version":"5.4.0","repository_url":"https://github.com/square/okhttp"},{"name":"com.android.application","old_version":"9.2.0","new_version":"9.3.1"},{"name":"com.android.test","old_version":"9.2.0","new_version":"9.3.1"},{"name":"org.jetbrains.kotlin.plugin.compose","old_version":"2.3.21","new_version":"2.4.10","repository_url":"https://github.com/JetBrains/kotlin"},{"name":"org.jetbrains.kotlin.plugin.serialization","old_version":"2.3.21","new_version":"2.4.10","repository_url":"https://github.com/JetBrains/kotlin"}],"path":null,"ecosystem":"maven"},"body":"Bumps the android-deps group with 23 updates in the /apps/android directory:\n\n| Package | From | To |\n| --- | --- | --- |\n| [gradle-wrapper](https://github.com/gradle/gradle) | `9.4.1` | `9.7.0` |\n| androidx.compose:compose-bom | `2026.04.01` | `2026.08.00` |\n| androidx.core:core-ktx | `1.18.0` | `1.19.0` |\n| androidx.webkit:webkit | `1.15.0` | `1.17.0` |\n| [org.bouncycastle:bcprov-jdk18on](https://github.com/bcgit/bc-java) | `1.84` | `1.85.2` |\n| [org.commonmark:commonmark](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-autolink](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-strikethrough](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-tables](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-task-list-items](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [dnsjava:dnsjava](https://github.com/dnsjava/dnsjava) | `3.6.4` | `3.6.5` |\n| [org.junit.vintage:junit-vintage-engine](https://github.com/junit-team/junit-framework) | `6.0.3` | `6.1.3` |\n| [io.kotest:kotest-assertions-core-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [io.kotest:kotest-runner-junit5-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [org.jetbrains.kotlinx:kotlinx-coroutines-android](https://github.com/Kotlin/kotlinx.coroutines) | `1.10.2` | `1.11.0` |\n| [org.jetbrains.kotlinx:kotlinx-coroutines-test](https://github.com/Kotlin/kotlinx.coroutines) | `1.10.2` | `1.11.0` |\n| [com.google.android.material:material](https://github.com/material-components/material-components-android) | `1.13.0` | `1.14.0` |\n| [com.squareup.okhttp3:mockwebserver](https://github.com/square/okhttp) | `5.3.2` | `5.4.0` |\n| [com.squareup.okhttp3:okhttp](https://github.com/square/okhttp) | `5.3.2` | `5.4.0` |\n| com.android.application | `9.2.0` | `9.3.1` |\n| com.android.test | `9.2.0` | `9.3.1` |\n| [org.jetbrains.kotlin.plugin.compose](https://github.com/JetBrains/kotlin) | `2.3.21` | `2.4.10` |\n| [org.jetbrains.kotlin.plugin.serialization](https://github.com/JetBrains/kotlin) | `2.3.21` | `2.4.10` |\n\n\nUpdates `gradle-wrapper` from 9.4.1 to 9.7.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/gradle/gradle/releases\"\u003egradle-wrapper's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e9.7.0\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.0.\u003c/p\u003e\n\u003cp\u003eHere are the highlights of this release:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIsolated Projects graduates to incubating\u003c/li\u003e\n\u003cli\u003eBroader Configuration Cache compatibility\u003c/li\u003e\n\u003cli\u003eMore source locations in problem reports\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003ca href=\"https://docs.gradle.org/9.7.0/release-notes.html\"\u003eRead the Release Notes\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eWe would like to thank the following community members for their contributions to this release of Gradle:\n\u003ca href=\"https://github.com/aSemy\"\u003eAdam\u003c/a\u003e,\n\u003ca href=\"https://github.com/Gautam-aman\"\u003eAman Gautam\u003c/a\u003e,\n\u003ca href=\"https://github.com/YukiCodepth\"\u003eAman Kumar\u003c/a\u003e,\n\u003ca href=\"https://github.com/adubrouski\"\u003eAnton Dubrouski\u003c/a\u003e,\n\u003ca href=\"https://github.com/liutikas\"\u003eAurimas\u003c/a\u003e,\n\u003ca href=\"https://github.com/gbhavya07\"\u003egbhavya07\u003c/a\u003e,\n\u003ca href=\"https://github.com/joshfriend\"\u003eJosh Friend\u003c/a\u003e,\n\u003ca href=\"https://github.com/nicklauslittle-gov\"\u003enicklauslittle-gov\u003c/a\u003e,\n\u003ca href=\"https://github.com/psoni674\"\u003ePragati\u003c/a\u003e,\n\u003ca href=\"https://github.com/Project516\"\u003eproject516\u003c/a\u003e,\n\u003ca href=\"https://github.com/Uomocapra\"\u003eQin Mi\u003c/a\u003e,\n\u003ca href=\"https://github.com/rkdfx\"\u003eRavi\u003c/a\u003e,\n\u003ca href=\"https://github.com/sk-reddy17\"\u003esk-reddy17\u003c/a\u003e,\n\u003ca href=\"https://github.com/Suvrat1629\"\u003eSuvrat Acharya\u003c/a\u003e,\n\u003ca href=\"https://github.com/ShreckYe\"\u003eYongshun Ye\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eUpgrade instructions\u003c/h2\u003e\n\u003cp\u003eSwitch your build to use Gradle 9.7.0 by updating your wrapper:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e./gradlew :wrapper --gradle-version=9.7.0 \u0026amp;\u0026amp; ./gradlew :wrapper\r\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eSee the Gradle \u003ca href=\"https://docs.gradle.org/9.7.0/userguide/upgrading_version_9.html\"\u003e9.x upgrade guide\u003c/a\u003e to learn about deprecations, breaking changes and other considerations when upgrading.\u003c/p\u003e\n\u003cp\u003eFor Java, Groovy, Kotlin and Android compatibility, see the \u003ca href=\"https://docs.gradle.org/9.7.0/userguide/compatibility.html\"\u003efull compatibility notes\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eReporting problems\u003c/h2\u003e\n\u003cp\u003eIf you find a problem with this release, please file a bug on \u003ca href=\"https://github.com/gradle/gradle/issues\"\u003eGitHub Issues\u003c/a\u003e adhering to our issue guidelines.\nIf you're not sure you're encountering a bug, please use the \u003ca href=\"https://discuss.gradle.org/c/help-discuss\"\u003eforum\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eWe hope you will build happiness with Gradle, and we look forward to your feedback via \u003ca href=\"https://twitter.com/gradle\"\u003eTwitter\u003c/a\u003e or on \u003ca href=\"https://github.com/gradle\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003e9.7.0 RC3\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.0 RC3.\u003c/p\u003e\n\u003cp\u003eHere are the highlights of this release:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIsolated Projects graduates to incubating\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/3defbfc59d757b873d787b2261de5c7f8a00970a\"\u003e\u003ccode\u003e3defbfc\u003c/code\u003e\u003c/a\u003e make DistributionIntegrationSpec more permissive for releases (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38766\"\u003e#38766\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/f176043d6416ca85dab736b6e7581d1f0018ee8e\"\u003e\u003ccode\u003ef176043\u003c/code\u003e\u003c/a\u003e make DistributionIntegrationSpec more permissive for releases\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/b0828dad52cf99112e2071fb10547c0d2293a51b\"\u003e\u003ccode\u003eb0828da\u003c/code\u003e\u003c/a\u003e Prepare release notes for Gradle 9.7.0GA (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38756\"\u003e#38756\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/064b6d6161b55f531be7710d68efe4404b48558a\"\u003e\u003ccode\u003e064b6d6\u003c/code\u003e\u003c/a\u003e cleanup\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/dfe7bdcc464152313992f49b6ea3846d7c0119ed\"\u003e\u003ccode\u003edfe7bdc\u003c/code\u003e\u003c/a\u003e add new training to release notes\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/756196837a985dd030d596411852b99c43d6880e\"\u003e\u003ccode\u003e7561968\u003c/code\u003e\u003c/a\u003e add release notes for 37801\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/68a1f351d3ba32e09523e5d67949cea326c0d781\"\u003e\u003ccode\u003e68a1f35\u003c/code\u003e\u003c/a\u003e cherrypick 38367 to release\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/a462c95ca92b7a5cc55172a42608fcab5fd43b4c\"\u003e\u003ccode\u003ea462c95\u003c/code\u003e\u003c/a\u003e Rebalance AllVersionsCrossVersion buckets for agents without TestDistribution...\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/820e2b14ad6b0f64a1a042dcfb43ea7e3e8f7ada\"\u003e\u003ccode\u003e820e2b1\u003c/code\u003e\u003c/a\u003e Update Gradle wrapper to version 9.7.0-rc-3 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38743\"\u003e#38743\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/75ea3d7671b4c52daf3fd26d0824b8fa7c752181\"\u003e\u003ccode\u003e75ea3d7\u003c/code\u003e\u003c/a\u003e Update Gradle wrapper to version 9.7.0-rc-3\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/gradle/gradle/compare/v9.4.1...v9.7.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `androidx.compose:compose-bom` from 2026.04.01 to 2026.08.00\n\nUpdates `androidx.core:core-ktx` from 1.18.0 to 1.19.0\n\nUpdates `androidx.webkit:webkit` from 1.15.0 to 1.17.0\n\nUpdates `org.bouncycastle:bcprov-jdk18on` from 1.84 to 1.85.2\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.html\"\u003eorg.bouncycastle:bcprov-jdk18on's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003eSee full diff in \u003ca href=\"https://github.com/bcgit/bc-java/commits\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003ecommonmark-java 0.29.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e[0.29.0] - 2026-06-20\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/42b4fb7adfe288ef13e9e27ab20aff7e91b0ab9d\"\u003e\u003ccode\u003e42b4fb7\u003c/code\u003e\u003c/a\u003e Prepare CHANGELOG for version 0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/b76e09d7a8362abb5f04e1d6b91dbd6da279a6fc\"\u003e\u003ccode\u003eb76e09d\u003c/code\u003e\u003c/a\u003e Limit how deep inline nodes may nest by default (100)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/49f65cb5cbec93cff713179990307145198e7061\"\u003e\u003ccode\u003e49f65cb\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing deeply nested emphasis\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/610f84b83e68c381e8f784ae4d044c80e1948b67\"\u003e\u003ccode\u003e610f84b\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological autolink email addresses\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/9f1d73897a56cbd74c39347af351a473e70297e1\"\u003e\u003ccode\u003e9f1d738\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological HTML block attributes\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/e13297e849995fdd582a85841067bff1d9c35ee5\"\u003e\u003ccode\u003ee13297e\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing pathological backticks\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/89d1bd3fa1524e8217ed61db5e8116c82434470f\"\u003e\u003ccode\u003e89d1bd3\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing with lots of \u003ccode\u003e\u0026lt;\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/commonmark/commonmark-java/compare/commonmark-parent-0.28.0...commonmark-parent-0.30.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark-ext-autolink` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark-ext-autolink's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003ecommonmark-java 0.29.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark-ext-autolink's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e[0.29.0] - 2026-06-20\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/42b4fb7adfe288ef13e9e27ab20aff7e91b0ab9d\"\u003e\u003ccode\u003e42b4fb7\u003c/code\u003e\u003c/a\u003e Prepare CHANGELOG for version 0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/b76e09d7a8362abb5f04e1d6b91dbd6da279a6fc\"\u003e\u003ccode\u003eb76e09d\u003c/code\u003e\u003c/a\u003e Limit how deep inline nodes may nest by default (100)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/49f65cb5cbec93cff713179990307145198e7061\"\u003e\u003ccode\u003e49f65cb\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing deeply nested emphasis\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/610f84b83e68c381e8f784ae4d044c80e1948b67\"\u003e\u003ccode\u003e610f84b\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological autolink email addresses\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/9f1d73897a56cbd74c39347af351a473e70297e1\"\u003e\u003ccode\u003e9f1d738\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological HTML block attributes\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/e13297e849995fdd582a85841067bff1d9c35ee5\"\u003e\u003ccode\u003ee13297e\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing pathological backticks\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/89d1bd3fa1524e8217ed61db5e8116c82434470f\"\u003e\u003ccode\u003e89d1bd3\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing with lots of \u003ccode\u003e\u0026lt;\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/commonmark/commonmark-java/compare/commonmark-parent-0.28.0...commonmark-parent-0.30.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark-ext-gfm-strikethrough` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark-ext-gfm-strikethrough's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003ecommonmark-java 0.29.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark-ext-gfm-strikethrough's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e[0.29.0] - 2026-06-20\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/42b4fb7adfe288ef13e9e27ab20aff7e91b0ab9d\"\u003e\u003ccode\u003e42b4fb7\u003c/code\u003e\u003c/a\u003e Prepare CHANGELOG for version 0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/b76e09d7a8362abb5f04e1d6b91dbd6da279a6fc\"\u003e\u003ccode\u003eb76e09d\u003c/code\u003e\u003c/a\u003e Limit how deep inline nodes may nest by default (100)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/49f65cb5cbec93cff713179990307145198e7061\"\u003e\u003ccode\u003e49f65cb\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing deeply nested emphasis\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/610f84b83e68c381e8f784ae4d044c80e1948b67\"\u003e\u003ccode\u003e610f84b\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological autolink email addresses\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/9f1d73897a56cbd74c39347af351a473e70297e1\"\u003e\u003ccode\u003e9f1d738\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological HTML block attributes\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/e13297e849995fdd582a85841067bff1d9c35ee5\"\u003e\u003ccode\u003ee13297e\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing pathological backticks\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/89d1bd3fa1524e8217ed61db5e8116c82434470f\"\u003e\u003ccode\u003e89d1bd3\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing with lots of \u003ccode\u003e\u0026lt;\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/commonmark/commonmark-java/compare/commonmark-parent-0.28.0...commonmark-parent-0.30.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark-ext-gfm-tables` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark-ext-gfm-tables's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003ecommonmark-java 0.29.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark-ext-gfm-tables's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e[0.29.0] - 2026-06-20\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/42b4fb7adfe288ef13e9e27ab20aff7e91b0ab9d\"\u003e\u003ccode\u003e42b4fb7\u003c/code\u003e\u003c/a\u003e Prepare CHANGELOG for version 0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/b76e09d7a8362abb5f04e1d6b91dbd6da279a6fc\"\u003e\u003ccode\u003eb76e09d\u003c/code\u003e\u003c/a\u003e Limit how deep inline nodes may nest by default (100)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/49f65cb5cbec93cff713179990307145198e7061\"\u003e\u003ccode\u003e49f65cb\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing deeply nested emphasis\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/610f84b83e68c381e8f784ae4d044c80e1948b67\"\u003e\u003ccode\u003e610f84b\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological autolink email addresses\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/9f1d73897a56cbd74c39347af351a473e70297e1\"\u003e\u003ccode\u003e9f1d738\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological HTML block attributes\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/e13297e849995fdd582a85841067bff1d9c35ee5\"\u003e\u003ccode\u003ee13297e\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing pathological backticks\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/89d1bd3fa1524e8217ed61db5e8116c82434470f\"\u003e\u003ccode\u003e89d1bd3\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing with lots of \u003ccode\u003e\u0026lt;\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/commonmark/commonmark-java/compare/commonmark-parent-0.28.0...commonmark-parent-0.30.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark-ext-task-list-items` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark-ext-task-list-items's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003ecommonmark-java 0.29.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark-ext-task-list-items's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e[0.29.0] - 2026-06-20\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/42b4fb7adfe288ef13e9e27ab20aff7e91b0ab9d\"\u003e\u003ccode\u003e42b4fb7\u003c/code\u003e\u003c/a\u003e Prepare CHANGELOG for version 0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/b76e09d7a8362abb5f04e1d6b91dbd6da279a6fc\"\u003e\u003ccode\u003eb76e09d\u003c/code\u003e\u003c/a\u003e Limit how deep inline nodes may nest by default (100)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/49f65cb5cbec93cff713179990307145198e706...\n\n_Description has been truncated_","html_url":"https://github.com/wang1314-coder/openclaw/pull/38","url":"https://dependabot.ecosyste.ms/api/v1/hosts/GitHub/repositories/wang1314-coder%2Fopenclaw/issues/38","packages_url":"https://dependabot.ecosyste.ms/api/v1/issues/38/packages"}],"issue_packages":[{"old_version":"5.3.2","new_version":"5.5.0","update_type":"minor","path":null,"pr_created_at":"2026-09-11T17:43:45.000Z","version_change":"5.3.2 → 5.5.0","issue":{"uuid":"5427351762","node_id":"PR_kwDOTHJuas8AAAABDLid1g","number":33,"state":"open","title":"chore(deps): bump the android-deps group across 1 directory with 19 updates","user":"dependabot[bot]","labels":["dependencies","java"],"assignees":[],"locked":false,"comments_count":1,"pull_request":true,"closed_at":null,"author_association":null,"state_reason":null,"created_at":"2026-09-11T17:43:45.000Z","updated_at":"2026-09-11T17:45:39.000Z","time_to_close":null,"merged_at":null,"merged_by":null,"closed_by":null,"dependency_metadata":{"prefix":"chore(deps): bump","group_name":"android-deps","update_count":19,"packages":[{"name":"gradle-wrapper","old_version":"9.5.1","new_version":"9.7.1","repository_url":"https://github.com/gradle/gradle"},{"name":"androidx.benchmark:benchmark-macro-junit4","old_version":"1.4.1","new_version":"1.5.0"},{"name":"androidx.compose:compose-bom","old_version":"2026.05.01","new_version":"2026.09.00"},{"name":"androidx.core:core-ktx","old_version":"1.18.0","new_version":"1.19.0"},{"name":"org.bouncycastle:bcprov-jdk18on","old_version":"1.84","new_version":"1.85.2","repository_url":"https://github.com/bcgit/bc-java"},{"name":"org.commonmark:commonmark","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-autolink","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-strikethrough","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-tables","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-task-list-items","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.junit.vintage:junit-vintage-engine","old_version":"6.1.0","new_version":"6.1.3","repository_url":"https://github.com/junit-team/junit-framework"},{"name":"io.kotest:kotest-assertions-core-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"io.kotest:kotest-runner-junit5-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"com.squareup.okhttp3:mockwebserver","old_version":"5.3.2","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.squareup.okhttp3:okhttp","old_version":"5.3.2","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.android.application","old_version":"9.2.1","new_version":"9.4.0"},{"name":"com.android.test","old_version":"9.2.1","new_version":"9.4.0"},{"name":"org.jetbrains.kotlin.plugin.compose","old_version":"2.4.0","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"},{"name":"org.jetbrains.kotlin.plugin.serialization","old_version":"2.4.0","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"}],"path":null,"ecosystem":"maven"},"body":"Bumps the android-deps group with 19 updates in the /apps/android directory:\n\n| Package | From | To |\n| --- | --- | --- |\n| [gradle-wrapper](https://github.com/gradle/gradle) | `9.5.1` | `9.7.1` |\n| androidx.benchmark:benchmark-macro-junit4 | `1.4.1` | `1.5.0` |\n| androidx.compose:compose-bom | `2026.05.01` | `2026.09.00` |\n| androidx.core:core-ktx | `1.18.0` | `1.19.0` |\n| [org.bouncycastle:bcprov-jdk18on](https://github.com/bcgit/bc-java) | `1.84` | `1.85.2` |\n| [org.commonmark:commonmark](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-autolink](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-strikethrough](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-tables](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-task-list-items](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.junit.vintage:junit-vintage-engine](https://github.com/junit-team/junit-framework) | `6.1.0` | `6.1.3` |\n| [io.kotest:kotest-assertions-core-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [io.kotest:kotest-runner-junit5-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [com.squareup.okhttp3:mockwebserver](https://github.com/lysine-dev/okhttp) | `5.3.2` | `5.5.0` |\n| [com.squareup.okhttp3:okhttp](https://github.com/lysine-dev/okhttp) | `5.3.2` | `5.5.0` |\n| com.android.application | `9.2.1` | `9.4.0` |\n| com.android.test | `9.2.1` | `9.4.0` |\n| [org.jetbrains.kotlin.plugin.compose](https://github.com/JetBrains/kotlin) | `2.4.0` | `2.4.20` |\n| [org.jetbrains.kotlin.plugin.serialization](https://github.com/JetBrains/kotlin) | `2.4.0` | `2.4.20` |\n\n\nUpdates `gradle-wrapper` from 9.5.1 to 9.7.1\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/gradle/gradle/releases\"\u003egradle-wrapper's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e9.7.1\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.1.\u003c/p\u003e\n\u003cp\u003eThis is a patch release for 9.7.0. We recommend using 9.7.1 instead of 9.7.0.\u003c/p\u003e\n\u003cp\u003eHere are the highlights of 9.7.0 release:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIsolated Projects graduates to incubating\u003c/li\u003e\n\u003cli\u003eBroader Configuration Cache compatibility\u003c/li\u003e\n\u003cli\u003eResilient Sync helps you fix broken builds\u003c/li\u003e\n\u003cli\u003eMore source locations in problem reports\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003ca href=\"https://docs.gradle.org/9.7.1/release-notes.html\"\u003eRead the Release Notes\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eWe would like to thank the following community members for their contributions to this release of Gradle:\n\u003ca href=\"https://github.com/aSemy\"\u003eAdam\u003c/a\u003e,\n\u003ca href=\"https://github.com/Gautam-aman\"\u003eAman Gautam\u003c/a\u003e,\n\u003ca href=\"https://github.com/YukiCodepth\"\u003eAman Kumar\u003c/a\u003e,\n\u003ca href=\"https://github.com/adubrouski\"\u003eAnton Dubrouski\u003c/a\u003e,\n\u003ca href=\"https://github.com/liutikas\"\u003eAurimas\u003c/a\u003e,\n\u003ca href=\"https://github.com/gbhavya07\"\u003egbhavya07\u003c/a\u003e,\n\u003ca href=\"https://github.com/joshfriend\"\u003eJosh Friend\u003c/a\u003e,\n\u003ca href=\"https://github.com/nicklauslittle-gov\"\u003enicklauslittle-gov\u003c/a\u003e,\n\u003ca href=\"https://github.com/psoni674\"\u003ePragati\u003c/a\u003e,\n\u003ca href=\"https://github.com/Project516\"\u003eproject516\u003c/a\u003e,\n\u003ca href=\"https://github.com/Uomocapra\"\u003eQin Mi\u003c/a\u003e,\n\u003ca href=\"https://github.com/rkdfx\"\u003eRavi\u003c/a\u003e,\n\u003ca href=\"https://github.com/sk-reddy17\"\u003esk-reddy17\u003c/a\u003e,\n\u003ca href=\"https://github.com/Suvrat1629\"\u003eSuvrat Acharya\u003c/a\u003e,\n\u003ca href=\"https://github.com/ShreckYe\"\u003eYongshun Ye\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eUpgrade instructions\u003c/h2\u003e\n\u003cp\u003eSwitch your build to use Gradle 9.7.1 by updating your wrapper:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e./gradlew :wrapper --gradle-version=9.7.1 \u0026amp;\u0026amp; ./gradlew :wrapper\r\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eSee the Gradle \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/upgrading_version_9.html\"\u003e9.x upgrade guide\u003c/a\u003e to learn about deprecations, breaking changes and other considerations when upgrading.\u003c/p\u003e\n\u003cp\u003eFor Java, Groovy, Kotlin and Android compatibility, see the \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/compatibility.html\"\u003efull compatibility notes\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eReporting problems\u003c/h2\u003e\n\u003cp\u003eIf you find a problem with this release, please file a bug on \u003ca href=\"https://github.com/gradle/gradle/issues\"\u003eGitHub Issues\u003c/a\u003e adhering to our issue guidelines.\nIf you're not sure you're encountering a bug, please use the \u003ca href=\"https://discuss.gradle.org/c/help-discuss\"\u003eforum\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eWe hope you will build happiness with Gradle, and we look forward to your feedback via \u003ca href=\"https://twitter.com/gradle\"\u003eTwitter\u003c/a\u003e or on \u003ca href=\"https://github.com/gradle\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003e9.7.0\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.0.\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/92f0512e7f06d84621afba191f75e265363890cf\"\u003e\u003ccode\u003e92f0512\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38892\"\u003e#38892\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/820ee75a99a179bbffa41bcedc6477b685fabb9f\"\u003e\u003ccode\u003e820ee75\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/82c23f9bd2a89b4cc644e1f90a28a8668feb3dee\"\u003e\u003ccode\u003e82c23f9\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering problem in KTS (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38878\"\u003e#38878\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/ef11a7268fe8cc8d6ab849ec911aa11220180553\"\u003e\u003ccode\u003eef11a72\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering issue\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/bb0d8a974a71b1003efea41e4046e98855cd5ff8\"\u003e\u003ccode\u003ebb0d8a9\u003c/code\u003e\u003c/a\u003e Make relevant tests polyglot (run for multiple DSLs)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/336e129d7f95c03486acafc97abf59734acfed48\"\u003e\u003ccode\u003e336e129\u003c/code\u003e\u003c/a\u003e Update signing configuration (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38874\"\u003e#38874\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/4bdf0da2dad9884d089a6062a45ea7183e7d735d\"\u003e\u003ccode\u003e4bdf0da\u003c/code\u003e\u003c/a\u003e Update signing configuration\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/cd9b92c1b82856248cf1dc58b50378238bec7b52\"\u003e\u003ccode\u003ecd9b92c\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38839\"\u003e#38839\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/5f4e381964897ad8d6b99e5a7c77f26dba3259fb\"\u003e\u003ccode\u003e5f4e381\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/1e08ab551367aeb5fb48b26e72807e1d2b27c939\"\u003e\u003ccode\u003e1e08ab5\u003c/code\u003e\u003c/a\u003e Keep type-use annotations in extracted ABI classes (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38810\"\u003e#38810\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/gradle/gradle/compare/v9.5.1...v9.7.1\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `androidx.benchmark:benchmark-macro-junit4` from 1.4.1 to 1.5.0\n\nUpdates `androidx.compose:compose-bom` from 2026.05.01 to 2026.09.00\n\nUpdates `androidx.core:core-ktx` from 1.18.0 to 1.19.0\n\nUpdates `org.bouncycastle:bcprov-jdk18on` from 1.84 to 1.85.2\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.md\"\u003eorg.bouncycastle:bcprov-jdk18on's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch1\u003eBouncy Castle Crypto Package - Release Notes\u003c/h1\u003e\n\u003ch2\u003e1.0 Introduction\u003c/h2\u003e\n\u003cp\u003eThe Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. The package is organised so that it contains a light-weight API suitable for use in any environment (including the J2ME) with the additional infrastructure to conform the algorithms to the JCE framework.\u003c/p\u003e\n\u003ch2\u003e2.0 Release History\u003c/h2\u003e\n\u003cp\u003e\u003c!-- raw HTML omitted --\u003e\u003c!-- raw HTML omitted --\u003e\u003c/p\u003e\n\u003ch3\u003e2.1.1 Version\u003c/h3\u003e\n\u003cp\u003eRelease: 1.86\u003cbr /\u003e\nDate: 2026, 11th September.\u003c/p\u003e\n\u003ch3\u003e2.1.2 Defects Fixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) let a subkey inherit the primary key's Key Flags when its own Subkey Binding signature carried no Key Flags subpacket, which made the two capability decisions taken for one subkey disagree. OpenPGPCertificate.OpenPGPComponentKey.isSigningKey() reads the effective flags, which fell back to the primary key's direct-key or primary user ID self-signature, so a subkey bound with no flags of its own counted as signing-capable; verifyEmbeddedPrimaryKeyBinding reads the binding signature's own flags, found no signing capability there, and so skipped the embedded Primary Key Binding (cross-certification) signature that RFC 9580 sec. 5.2.1.8 and sec. 10.1.3 require of a subkey that can issue signatures. A data signature made by such a subkey was therefore attributed to the certificate and reported valid by OpenPGPSignature.OpenPGPDocumentSignature.isValid() with the cross-certification requirement never applied, where GnuPG refuses the same certificate and message as not cross-certified. An attacker holding a third party's public signing subkey - which is public material - could bind it to their own primary key with a Subkey Binding signature they are able to make, carrying no Key Flags and no embedded Primary Key Binding signature, which they cannot make without the subkey's private key, and have that party's genuine signatures verify as valid under the attacker's own identity: misattribution of a real signature rather than a forgery of a new one, since the signature still has to be one the subkey actually made. Key Flags are a statement about the key the carrying signature refers to (RFC 9580 sec. 5.2.3.29), so a subkey no longer inherits them from the certificate-wide signatures of the primary key: a Subkey Binding signature that omits the subpacket now leaves the subkey with no capabilities rather than the primary's, which makes the flags the cross-certification check consults the same flags every other decision consults. Preferences and the other subpackets a direct-key signature carries are inherited as before, and the primary key itself - whose flags legitimately come from its direct-key or user ID self-signature - is unaffected. The low-level PGPSignature / PGPPublicKeyRing API performs no binding checks by design and is unchanged (CVE-2026-71887).\u003c/li\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) used a version 6 key that carried no valid Direct Key signature, falling back to the primary user ID binding as it correctly does for a version 4 key. RFC 9580 sec. 5.2.3.10 requires the opposite: \u0026quot;An implementation MUST ensure that a valid Direct Key signature is present before using a version 6 key. This prevents certain attacks where an adversary strips a self-signature specifying a Key Expiration Time or certain preferences.\u0026quot; The certificate grammar says the same structurally, the Direct Key signature being mandatory in the version 6 structure of sec. 10.1.1 and optional in the version 4 one of sec. 10.1.3. Because a version 6 certificate carries its key expiration, features and algorithm preferences on the Direct Key signature - the convention the RFC recommends and the one OpenPGPKeyGenerator follows, its user ID certification carrying no expiration at all - removing that single signature packet from a published certificate silently dropped the expiration along with the preferences and features: OpenPGPCertificate.getSignatureChainFor fell back to the user ID binding, the primary key was still reported bound, and getEncryptionKeys() and getSigningKeys() went on returning the subkeys of a key whose owner had set it to expire. The primary key fingerprint is unchanged by the removal, so a relying party pinning the key by fingerprint still treats it as the same key, and no private key or hash collision is involved; the natural moment for the strip is the key refresh that RFC 9580 names as the reason to refetch a key at all - to learn about changes in expiration, features, preferences and revocation - which is exactly the update it defeats. This is a downgrade rather than a forgery, nothing being attributed to a key that did not authorise it, and the concerning direction is encryption, to a key meant to have been retired. OpenPGPCertificate.isBoundBy now requires a valid Direct Key self-signature on a version 6 primary key before any component of the certificate - the primary key, its subkeys or its identities - is treated as bound, so a version 6 certificate stripped of it offers no keys at all rather than an unexpiring set. Version 4 certificates are unaffected: there the key expiration legitimately lives on the user ID self-signature and the fallback is correct, so it stays. The revocation-only version 6 certificate of sec. 10.1.2, which legitimately carries no Direct Key signature, is unaffected as well - its key was already refused as revoked, and reading the revocation does not go through the binding check.\u003c/li\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) ignored the OpenPGPPolicy a caller had configured when it verified the signatures on an inline message. OpenPGPMessageInputStream took the policy it sanitizes each document signature against from the implementation's own default rather than from the processor the signature is being verified by, so a policy supplied through the documented OpenPGPApi(implementation, policy) / OpenPGPMessageProcessor(implementation, policy) constructor - which is how OpenPGPApi.decryptAndOrVerifyMessage() plumbs the configured policy through - had no bearing on whether a signature was accepted, although the same processor already applied it to the decompressed-size bound. A caller who hardened the policy beyond the default therefore had a signature that policy rejects handed back from getResult().getSignatures() with isTestedCorrect() true, while OpenPGPSignature.isValid(policy) on that same signature reported the rejection. Both verify paths, the one-pass and the prefixed-signature one, now read the configured policy; the detached-signature processor already did.\u003c/li\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) went on offering the subkeys of a certificate whose primary key had expired. OpenPGPCertificate's binding check evaluated only a subkey's own Subkey Binding signature, so a primary key whose Key Expiration Time (RFC 9580 sec. 5.2.3.13) had passed still handed out a longer-lived encryption or signing subkey from getEncryptionKeys() / getSigningKeys(), leaving the certificate contradicting itself - getExpirationTime() in the past and getPrimaryKey().isBoundAt() false, while isBoundAt() on the subkey answered true. An expired primary key can no longer certify, so the subkeys it bound are not usable with it either, which is how GnuPG and Sequoia both treat such a certificate; primary key revocation already propagated, since a revocation appears in the subkey's signature chain, but expiration is not carried there. Relatedly, a subkey no longer inherits the primary key's validity period at all - sec. 5.2.3.13 counts that period from the creation time of the key the carrying self-signature is made on, so re-basing the primary key's period on a subkey created later than it gave that subkey an expiration date later than the primary key's own.\u003c/li\u003e\n\u003cli\u003eOpenPGPSignature.OpenPGPDocumentSignature.isValidAt(Date) in the high-level OpenPGP API reported a data signature as valid at an evaluation time past the signature's own Signature Expiration Time (RFC 9580 sec. 5.2.3.18, hashed subpacket type 3). The method checked that the signature was correct and that the issuing key was bound and signing-capable at that date, but never consulted the signature's own expiration, so it disagreed with isEffectiveAt(Date) on the same object and with its own javadoc, which names being effective as one of the three criteria of a valid signature. Signature expiration is a separate axis from the issuing key's Key Expiration Time that the binding checks already cover, and GnuPG, GPGME, git and Sequoia all keep the two apart and treat a signature past its expiration as not good. isValid() and isValid(policy) evaluate at the signature's creation time, where a signature is always inside its own window, and are unchanged.\u003c/li\u003e\n\u003cli\u003eThe lightweight LMSSigner and HSSSigner refused a key wrapped in ParametersWithRandom, which is how BcContentSignerBuilder passes a key whenever setSecureRandom() has been called - so BcHssLmsContentSignerBuilder built a working signer until a random was set and then failed with \u0026quot;Incorrect Key Parameters\u0026quot;, and the two signers themselves raised ClassCastException on the same input. All three now unwrap it, as the promoted ML-DSA and SLH-DSA signers already did. The random is accepted and not used: LMS derives its message randomiser C from the key's seed and the one-time index, so it is deterministic and cannot repeat while q does not. Note SP 800-208 sec. 6.1 asks for C to come from an approved random bit generator, which this implementation does not do; that is unchanged here, and a supplied random is now ignored rather than refused.\u003c/li\u003e\n\u003cli\u003eLMS signature verification did not apply two of the checks RFC 8554 sec. 5.4.2 requires before a signature is processed. Step 2g refuses a signature whose LMS typecode is not the one from the public key, and without it the path computation took its height and tree digest from the parameter set the signature named rather than the key's, so a signature claiming a height-25 parameter set drove a 25-level computation against a height-5 key. Step 2i refuses a leaf number q outside the tree, and without it an out-of-range q flowed into the node arithmetic and was left for the candidate-root comparison to catch. Neither was a forgery - the domain separation between D_LEAF and D_INTR and the final comparison saw to that - but both are attacker-chosen work the specification says to refuse up front. Both are now checked, and a signature failing either is still reported as not verifying rather than thrown out of Signature.verify(). The catch around the signature decode in LMSSigner and HSSSigner has also been narrowed to the decode itself, as the corresponding SPI was corrected to do for github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2408\"\u003e#2408\u003c/a\u003e: past the parse the engine reports an inconsistent signature by returning false rather than by throwing, so the wider catch caught nothing while standing ready to turn a future internal error into a quiet false.\u003c/li\u003e\n\u003cli\u003eThe LMS and HSS key parameter classes now apply at construction the checks their decoders apply, so a key built directly cannot be one the decoder would refuse. LMSPrivateKeyParameters accepted an identifier of any length although the decoder reads exactly 16 bytes - such a key encoded but could not be read back - and left q, maxQ and the seed length unchecked; the seed is now required to be at least m bytes at decode as well, where a one-byte seed had been decoding silently and then deriving every one-time key from it. HSSPrivateKeyParameters checked neither its level count nor that it had been given a component key per level and a chaining signature per level below the root, and then indexed both lists, so a mismatch surfaced as IndexOutOfBoundsException - or, where a level happened to match, as a null chaining signature that only failed at signing time; the level is now checked after the reset that fills it in, since a null is legitimate on the way in. LMSPrivateKeyParameters.getInstance(byte[], byte[]) adopted the public key supplied beside the private one without comparing them, so a mismatched public key was simply reported by getPublicKey(); it now cross-checks the identifier, both parameter sets and, where the tree cache already holds it, the root, as the HSS entry point does. The decoders also now report a bad version or seed length as IOException rather than IllegalStateException, so a caller can catch one type for a malformed key, and the package-private LM-OTS public key decoder no longer declares throws Exception or dereferences an unrecognised typecode. The deprecated org.bouncycastle.pqc.crypto.lms copies carry the decoder corrections.\u003c/li\u003e\n\u003cli\u003eIn the LMS JCE layer, LMSKeyGenParameterSpec.fromNames knew all twenty LMS parameter-set names but only four of the sixteen LM-OTS ones, so none of the SP 800-208 n24 or SHAKE sets could be named; all sixteen are now present. KeyPairGenerator.initialize(int, SecureRandom) reports InvalidParameterException, which is what the JCA specifies and which extends the IllegalArgumentException it raised before, so existing catches still match. BCLMSPrivateKey.getIndex now takes the exhaustion check and the index read under the key's own monitor rather than as two separate calls, and two unused fields have gone from LMSSignatureSpi. Note that the LMS Signature claims its one-time key at the first update() rather than at sign(), so a Signature that is initialised and updated and then abandoned spends an index without producing a signature - the safe direction for a one-time scheme, and now documented on the SPI.\u003c/li\u003e\n\u003cli\u003eEvery other key pair generator that refuses a key size did the same thing the LMS one did above. KeyPairGenerator.initialize(int, SecureRandom) is documented to raise InvalidParameterException when the key size is not one the generator supports, and thirty of them raised a bare IllegalArgumentException instead, so a caller following the JCA and catching the documented type saw an exception escaping rather than a refusal. The ML-DSA, ML-KEM, SLH-DSA, Classic McEliece, FrodoKEM, NTRU and composite signature and KEM generators in the BC provider, and every generator in BCPQC, now raise InvalidParameterException - NewHope included, where the value is a key size it will not take rather than a mode of initialisation it does not offer. InvalidParameterException extends IllegalArgumentException, so callers written against the old behaviour go on catching it unchanged. The two RSA generators are corrected as well, and differently: theirs is a key size below a floor rather than a mode of initialisation they do not offer, and the refusal is raised by the lightweight RSAKeyGenerationParameters, which cannot name a java.security exception at all, so the RSA KeyPairGeneratorSpi now translates it - keeping the message verbatim and the original exception as the cause, through a new SecurityExceptions.invalidParameterException factory, since InvalidParameterException has no constructor that takes one. Of the 304 KeyPairGenerator services the two providers register, 299 now refuse a nonsense key size the way the JCA defines it and five accept it as a strength they can work with, with none left raising a bare IllegalArgumentException; that is asserted as a sweep over both providers rather than per algorithm, so a generator added later is covered without the test being touched. The jdk1.3 provider overlays of the four generators that have one carry the same change, and the jdk1.3 SecurityExceptions overlay gains the new factory along with the invalidAlgorithmParameterException one it had been missing.\u003c/li\u003e\n\u003cli\u003eKeyPairGenerator.initialize(AlgorithmParameterSpec, SecureRandom) had the same shape of problem as the int overload above, and only 44 of the 304 services the two providers register reported an unusable spec as the InvalidAlgorithmParameterException that method declares. The twenty-three PQC generators that resolve a parameter set by name - cmce, frodokem, mldsa, mlkem, slhdsa, aimer, bike, faest, falcon, haetae, hqc, mayo, mqom, ntru, ntruplus, both ntruprime variants, qruov, saber, sdith, smaugt, snova and sqisign, 230 services between them - case-folded the name they got back from the spec without checking it, so a spec with no getName() method, and a null spec, produced a NullPointerException from inside the fold; their own \u0026quot;is this name one I know\u0026quot; branch, which does report the declared exception, was unreachable. The two composite generators, whose parameter set is fixed by the algorithm name so that null is the only spec they accept, refused every other one with IllegalArgumentException. RSA answered correctly for a spec of the wrong type but not for one of the right type carrying values its lightweight parameters will not take - an even public exponent, or a key size below the floor - which is now translated the same way the int overload's is. All 304 services now report the declared exception, with the composites still taking the null spec that is right for them; note that InvalidAlgorithmParameterException is a checked exception and not an IllegalArgumentException, so a caller that was catching what these threw before has to catch the declared type instead.\u003c/li\u003e\n\u003cli\u003eAn HSS private key claimed the two records of its position under two different monitors. The top-level index and the bottom component key's one-time index q are independent records of the same position - the decoder requires them to agree, see the entry below - but generateLMSContext incremented the index under the HSS key's own monitor, released it, and only then claimed q under the component key's. A getEncoded() issued in between saw the index advanced and q not, and produced an encoding this implementation's own decoder rejects; and two threads meeting at a bottom-tree boundary could both pass the exhaustion test, take consecutive top-level indices and claim the same q, after which one of them was refused with \u0026quot;ots private key exhausted\u0026quot; by a key still reporting usages remaining, a top-level index had been spent with no signature made, and the two records stayed one apart for the rest of the key's life in that process - so it could no longer be encoded, cloned or sharded, and getIndex() and getUsagesRemaining() misreported by one. No one-time key was reused: the component key's claim is itself atomic, and the divergence runs index ahead of leaves, so the effect was on the key's usability rather than on the signatures it had made. Both records are now claimed under the one monitor, and the component key is claimed before the index is incremented so that an exhausted one leaves both untouched. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the same correction.\u003c/li\u003e\n\u003cli\u003eTimeStampToken parsed the attacker-controlled TSTInfo content of a time-stamp token (org.bouncycastle.tsp.TimeStampToken, reached from TimeStampResponse(byte[]) and (InputStream)) inside a try that caught only CMSException, so a well-formed RFC 3161 TimeStampResp whose embedded token carried a malformed TSTInfo - a SEQUENCE with fewer elements than the five mandatory fields, a non-SEQUENCE, truncated DER, or an unknown context tag - let an IllegalArgumentException or a NoSuchElementException escape the constructor's declared throws TSPException, IOException contract. A token signed by no signers or by more than one raised a bare IllegalArgumentException from the same constructor, before that try, for the same reason. Both are now reported as TSPException, matching the package-private TimeStampResponse(DLSequence) constructor and the existing getSignedAttributes guard in the same method; the signer-count refusal is a TSPValidationException, as the neighbouring check on the content type already was. Related, and the cause of the NoSuchElementException: asn1.tsp.TSTInfo read its five mandatory fields off the sequence with no bound on how many elements were actually there, so a short SEQUENCE left the enumeration to run out rather than being refused, and an oversize one was accepted with its extra elements absorbed into the optional slots. Decode now requires the five to ten elements RFC 3161 sec. 2.4.2 gives the type, which is what the sibling Accuracy and ArchiveTimeStamp decoders already did, so the failure is the IllegalArgumentException that getInstance is expected to raise (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2415\"\u003e#2415\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eNeither the HSS nor the XMSS^MT private key decoder checked its declared index against the traversal state stored beside it, although the two are independent records of the same position in the key and so can be compared. For HSS the records are the top-level index and the component keys' one-time indices q; for XMSS^MT they are the global index and the per-layer BDS states. A stored key whose index had been rolled back while its state stayed advanced - a partial write, a restore from backup, a buggy storage layer - was therefore accepted, and it then signed a second message under a one-time key the key had already used, producing a signature that verified, so nothing anywhere surfaced the reuse. RFC 8554 sec. 1 and RFC 8391 sec. 1.1 both require each one-time key to be used exactly once, and this is the failure those requirements exist to prevent; the single-tree XMSS decoder has tied its BDS state to its index since that state was first validated, and this brings the two multi-tree schemes into line. HSS decode now requires the declared index to equal the position the component q values imply - a level above the last contributes (q - 1) leaves of the levels beneath it, since its q has already advanced past the subtree it signed - and XMSS^MT decode now requires each present layer's BDS index to equal the leaf index that layer derives from the global index, allowing the one position where a layer has moved into a new subtree and its state legitimately still carries the previous subtree's final index. A layer with no state yet is unaffected, since those are built lazily at signing time. Related, and the same shape of omission: an XMSS or XMSS^MT private key encoding carries the tree root twice - the key's own root field and the root node of the BDS state stored beside it, which for XMSS^MT is the top layer's - and the two were never compared either. A corrupted root was accepted and then poisoned every signature the key made, because the root is hashed into the message digest: the signature did not verify and nothing indicated why. Decode now requires the two copies to agree. The BDS node values themselves are not checkable the way the LMS tree cache above is - a BDS authentication path, stack, retain or keep node does not have its children stored alongside it, so recomputing one means building a subtree, which is the work the state exists to avoid. Both checks are integer comparisons over the levels of the key, too small to measure against the surrounding decode, and both were verified not to reject any legitimate key by walking every index a key can reach: the full key space of the two-level HSS and the h=4/d=2, h=6/d=2, h=6/d=3, h=9/d=3 and h=8/d=4 XMSS^MT parameter sets, plus a three-level HSS key across a subtree boundary and an HSS shard. Since those node values cannot be recomputed, the encoded state now carries a checksum over itself instead, with the owning key's public seed hashed in front of it. Any corruption of the stored state is refused at decode rather than being loaded and then producing signatures that silently do not verify, and because the public seed is bound in, a state transplanted between two keys of the same parameter set is refused too, even though it is internally consistent and arrives with its own matching root. The public seed is bound rather than the secret seed or the PRF key deliberately: the state's own root and index are inside the encoding and so are already covered, hashing secret material would make the stored checksum a commitment to it for no gain in detection, and the PRF key does not influence the state at all. \u003cstrong\u003eThis is an error-detecting code and not integrity protection\u003c/strong\u003e - anyone able to rewrite the stored key recomputes it, so it establishes that the state is unchanged since it was written, never that it was correct when written, and the allocation bounds on the encoding remain the guard against a crafted one. It costs one SHA-256 over the state, measured at 5 to 8 microseconds each way for the h=10 and h=16 parameter sets, and 32 bytes of encoding. The state encoding was added earlier in this same cycle and has not been released, so the checksum is simply part of it rather than a new version: a state written by a 1.86 beta is rejected, which is recovered from by re-exporting the key. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the HSS check as well (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2414\"\u003e#2414\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eIn the XMSS and XMSS^MT JCE layer, KeyPairGenerator.initialize(int, SecureRandom) reports InvalidParameterException, which is what the JCA specifies and which extends the IllegalArgumentException it raised before, so existing catches still match. This is the XMSS counterpart of the same correction made to LMSKeyPairGeneratorSpi.\u003c/li\u003e\n\u003cli\u003eBCXMSSPrivateKey.getIndex and BCXMSSMTPrivateKey.getIndex took the exhaustion check and the index read as two separate calls on the key parameters. Each is atomic on its own, but the pair is not: a signature taken by another thread between them spends the last usage, so the check passes and the read that follows returns maxIndex + 1 - the one index past the end of the key, which is what the check exists to refuse, handed back as though it were the next one-time key to be used. Both reads are now taken under the key parameters' own monitor, the monitor their mutators hold, as BCLMSPrivateKey.getIndex was corrected to do. No one-time key is reused by this: the effect is on what the key reports about itself, not on the signatures it makes.\u003c/li\u003e\n\u003cli\u003eThe S/MIME example smoke test in the misc module (org.bouncycastle.mail.smime.examples.test.AllTests) drove SendSignedAndEncryptedMail against smtp.gmail.com, and that example finishes with Transport.send() under JavaMail's default settings, which have no connect timeout. Where outbound port 25 is refused the failure was swallowed and the test passed; where it is silently dropped, as on many home networks, the connect blocked and ./gradlew build hung in :misc:test indefinitely with \u0026quot;0 tests completed\u0026quot;. The test now delivers to an SMTP stub on a loopback port, with connect / read / write timeouts as a backstop, and asserts the message arrived (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2407\"\u003e#2407\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation took the traditional component public key bytes it feeds the KEM combiner from the recipient key's own encoding, while decapsulation recomputes the point from the private key and so always produced an uncompressed one. Section 4 of draft-ietf-lamps-pq-composite-kem requires an EC component to be carried as an uncompressed point, but a component key that encodes itself compressed - a BC EC key whose point format has been set through org.bouncycastle.jce.interfaces.ECPointEncoder, or a key from a provider that preserves a compressed encoding - was passed through as it came. Both sides then combined a different tradPK and derived different shared secrets, with no error reported on either: encapsulation and decapsulation both succeeded and the recipient simply could not decrypt. The EC component is now normalised to an uncompressed point wherever the engine serialises one, which covers the ephemeral key that forms the ciphertext as well. X25519 and X448 components have a single encoding and were unaffected, as were EC keys left in their default (uncompressed) format, whose shared secrets are unchanged. CompositePublicKey.getEncoded() took its component bytes the same way, so such a key also encoded to a composite key other implementations reject and whose bytes changed across an encode / decode / encode round trip - 1238 bytes rather than 1270 for MLKEM768-ECDH-P256, and for the composite ML-DSA keys sharing that method, 2006 rather than 2038 for MLDSA65-ECDSA-P256. It now normalises the component the same way. This is a write-side change only: a composite key carrying a compressed EC component is still decoded, since the component key factories accept either form, and continues to verify signatures as before - it simply re-encodes in the normalised form. The shared normalisation is org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil.getUncompressedSubjectPublicKeyBytes.\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation threw a NullPointerException, wrapped in an IllegalStateException out of KeyGenerator.generateKey(), when the SecureRandom it was given was null - which javax.crypto.KEM.newEncapsulator() documents as a request for the provider's default, and which KeyGenerator.init(spec, null) passes straight through. The three RSA-OAEP composites draw the traditional shared secret from that random directly, so they were the ones affected; the ECDH and X25519 / X448 composites escaped only because their component KeyPairGenerators default a random of their own. CompositeMLKEMEngine now defaults one through CryptoServicesRegistrar.getSecureRandom() on first use, as the composite KEM Cipher's wrap path already did, and as the KEM generators corrected earlier in this cycle now do. Related, the engine now also clears the ML-KEM component's shared secret alongside the traditional one on both the encapsulate and decapsulate paths - the copy handed back by getEncoded() was left in the heap - as section 3.5 of draft-ietf-lamps-pq-composite-kem requires.\u003c/li\u003e\n\u003cli\u003eCompositePublicKey.getAlgorithm() and CompositePrivateKey.getAlgorithm() returned null for all twelve Composite ML-KEM (draft-ietf-lamps-pq-composite-kem) parameter sets. Both classes resolved the name through the composite signature index only, which holds the composite ML-DSA OIDs, so a composite KEM key pair - generated, parsed from a certificate, or read from PKCS#8 - reported no algorithm at all, and the standard JCA idiom of reconstructing a key with KeyFactory.getInstance(key.getAlgorithm()) raised a NullPointerException. The lookup now falls back to the composite KEM index, so the name returned is the one the provider registers the algorithm under (e.g. MLKEM768-X25519-SHA3-256), matching the composite ML-DSA behaviour. The same single-index assumption made the CompositePublicKey(SubjectPublicKeyInfo) and CompositePrivateKey(PrivateKeyInfo) constructors reject a composite KEM key with \u0026quot;unable to create CompositePublicKey from SubjectPublicKeyInfo\u0026quot;; they now dispatch to the composite KEM key factory for those OIDs. Keys obtained through KeyFactory or through BouncyCastleProvider.getPublicKey / getPrivateKey were unaffected and are unchanged (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2404\"\u003e#2404\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe org.bouncycastle.jcajce.spec.KEMKDFSpec constructor stored a null otherInfo as given, so getOtherInfo() returned null, and three of the KDF branches KdfUtil.makeKeyBytes dispatches to - KMAC-128, KMAC-256 and SHAKE-256 - read the otherInfo length without a guard and threw NullPointerException out of the KEM operation, where the KDF2, KDF3 and HKDF branches tolerate a null through KDFParameters / HKDFParameters. The Builder of every spec in the package already mapped null to empty, so no provider path reached it, but the constructor is protected on a public class and KdfUtil is documented for callers building their own KEM integration; the deprecated KEMParameterSpec passes a null itself and escaped only because it also pins the KDF to null. The constructor now stores empty for a null, so getOtherInfo() never returns null, and a null and an explicitly empty otherInfo derive the same key.\u003c/li\u003e\n\u003cli\u003eQR-UOV signature verification accepted a signature encoding that was not canonical, so the encoding of a signature was not unique even after the trailing-byte fix of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e. Each F_q element of the signature is stored in ceil(log2 q) bits, one more bit pattern than the field has elements: q itself is representable and is arithmetically congruent to zero, so an element written as q verified exactly as the same element written as zero would, and the bits padding the last element out to the byte boundary were never read at all. Every zero element of a signature therefore carried a second encoding, and for the q = 7 parameter sets roughly one element in seven is zero - a single qruov_5_q7_L10 signature measured 256 spare bits, so on the order of 2^256 distinct byte strings verified for the one message and key. Verification now rejects any element outside [0, q) and any set padding bit; a signature produced by this or by the reference implementation is unaffected, as the KAT vectors of every parameter set confirm. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSNOVA signature verification ignored four bits inside the signature for any parameter set whose solution is an odd number of GF(16) nibbles - the SNOVA_24_5_5, SNOVA_25_8_3, SNOVA_29_6_5 and SNOVA_66_15_3 families, sixteen of the forty-four parameter sets. The last byte of the encoded solution carries a single nibble and the signer leaves the top four bits zero, but the decoder did not read them, so sixteen distinct byte strings verified for one signature. This is the same non-unique encoding github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e closed for bytes following the signature, applied inside it; the verifier now requires those bits to be zero. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSnovaPrivateKeyParameters did not validate the length of the private key encoding handed to it - the only one of the five schemes of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e that did not - and SnovaParameters.getPrivateKeyLength() reported the expanded (\u0026quot;ESK\u0026quot;) length even for a parameter set whose private key is the seed pair. A private key encoding reaches this constructor straight from a PKCS#8 blob, so a wrong length went undetected: a seed-form key with extra bytes appended was accepted and signed under a different derived key, and a short expanded-form key sized the signer's decode buffer negatively, throwing NegativeArraySizeException out of generateSignature() rather than being reported at construction. Related, the signing retry loop could not terminate: the vinegar values are derived from a single-byte counter, so only 256 distinct linear systems can be tried, and an expanded-form private key that is not a real central map is singular for all of them - generateSignature() then span forever rather than failing. The length is now checked at construction, getPrivateKeyLength() reports the length that parameter set's private key actually has, and the retry loop gives up after its 256 attempts as MAYO's does.\u003c/li\u003e\n\u003cli\u003eMayoSigner and MayoKeyPairGenerator did not clear several buffers holding secret key material that the MAYO reference implementation explicitly clears. Signing left the secret oil space O, the expanded L = (P1 + P1^t) * O + P2, and the M / VPV / Ox intermediates of the central map in place, having gone to the trouble of clearing eleven other buffers; key generation left the expanded seed, whose tail is the encoded oil space, and the P1 * O + P2 half of P; and the row-echelon step left the packed echelon form of the secret linear system and its pivot rows. Separately, if all 256 attempts at solving for the signature had given a rank-deficient system, signing emitted a signature built from the failed attempt's state instead of reporting the failure the reference returns, and AIMerSigner.generateSignature returned an empty array on failure, which a caller would hand on as though it were a signature. Both now throw.\u003c/li\u003e\n\u003cli\u003eFive PQC signature schemes - MAYO, SNOVA, QR-UOV, SQIsign and AIMer - returned the NIST crypto_sign \u0026quot;sm\u0026quot; signed-message envelope from generateSignature() rather than the signature. That envelope is an artefact of the reference KAT harness, which records the message alongside the signature so a vector file can be self-contained; it is not part of any of the five specifications, and no other BC signer emits it (Falcon's KAT test rebuilds the equivalent envelope in the test, which is where it belongs). Two consequences followed, both reaching the JCA Signature services of every parameter set of the five schemes in BouncyCastlePQCProvider. First, since the message was appended to the signature, verification had to skip whatever followed the signature proper, and it did so by checking only that the buffer was long enough - so any number of trailing bytes could be added to a valid signature, or the appended message replaced with unrelated data, and it still verified. A signature encoding was therefore not unique: anyone holding one valid signature could produce unlimited distinct byte strings that all verified for the same message and key, which breaks any use that treats the signature bytes as an identifier, deduplicates on them, or records them as evidence. Second, the envelope propagated into everything built on the operator layer: because ContentSigner hands the signature straight into the structure being signed, every X.509 certificate, CRL, CMS SignedData and TLS CertificateVerify BC produced with one of these algorithms carried a verbatim copy of the signed data inside its own signature field - a self-signed MAYO-1 certificate came to 3567 bytes where the same certificate is now 2020 - which no other implementation can parse as a signature, and which in a detached CMS signature meant the \u0026quot;detached\u0026quot; signature carried the content. generateSignature() now returns the bare signature, and verifySignature() requires exactly the parameter set's signature length, so appended or truncated data is rejected rather than ignored. \u003cstrong\u003eThis is a behavioural change for signatures produced by an earlier release\u003c/strong\u003e - MAYO and SNOVA from 1.84, QR-UOV, SQIsign and AIMer from 1.85 - which are no longer accepted in the envelope form they were emitted in; the signature bytes themselves are unchanged, so a stored value can be recovered by taking the leading signature-length bytes, or for AIMer, whose envelope was message || signature rather than signature || message, the trailing ones. The KAT tests now rebuild the envelope before comparing against the vector files, which continue to record it. Note that AIMer's verification had already been made length-exact during this cycle (see the entry below relating to github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2401\"\u003e#2401\u003c/a\u003e), so of the five only its envelope remained (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe MLS implementation did not bind an X.509 credential to the LeafNode's signature_key. LeafNode.verify() checked a leaf's signature against the signature_key declared in the leaf itself, while the X.509 credential's certificate chain was stored but never parsed or checked, so the certificate's public key was never required to match signature_key (RFC 9420 sec. 5.3). A leaf could therefore carry one party's certificate while being signed by an unrelated key and still be accepted under that party's identity through KeyPackage.verify() and the Group leaf-validation path. LeafNode.verify() now requires the end-entity certificate's subject public key, in the cipher suite's signature encoding, to equal signature_key for an X.509 credential, and rejects the leaf otherwise - including an empty chain or a certificate whose key type does not match the cipher suite; certificate-chain and identity validation to a trust anchor remain the application's responsibility per RFC 9420 sec. 5.3.1. A public org.bouncycastle.mls.codec.Certificate(byte[]) constructor and a Credential.getCertificates() accessor are added so callers can build and inspect X.509 credentials. Basic credentials are unaffected (CVE-2026-71885).\u003c/li\u003e\n\u003cli\u003eThe SecureRandom supplied to org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder.setSecureRandom() did not drive the content IV / nonce for any algorithm other than RC2. EnvelopedDataHelper.generateParameters passed the caller's SecureRandom to the AlgorithmParameterGenerator only in the RC2_CBC branch; every other content-encryption algorithm - AES-CBC, AES-GCM, AES-CCM, Camellia, ARIA, SEED and the rest - reached pGen.generateParameters() on an uninitialised generator, so the IV / nonce was drawn from a default SecureRandom and setSecureRandom() was silently ignored (the builder's javadoc states that random is used for IV/nonce generation). The generator is now initialised with the supplied random on the general path as well, so a caller who provides a specific randomness source - for a controlled or FIPS-approved DRBG, say - has it honoured for the content IV / nonce. The session-key generation path was unaffected and already used the supplied random. Because the content IV / nonce now comes from the supplied SecureRandom, the org.bouncycastle.crypto.util JournalingSecureRandom / JournaledAlgorithm reproducible-encryption support records it in the transcript: a resumed session reproduces the IV / nonce by regenerating it from the replayed randomness - build the resuming encryptor from the content-algorithm OID - rather than by reusing the AlgorithmIdentifier captured from the first encryption, which no longer keeps the transcript aligned.\u003c/li\u003e\n\u003cli\u003eThe NTRU LPRime, NTRU+ and SMAUG-T KEM generators threw a NullPointerException when constructed with a null SecureRandom, where every other KEM generator - including NTRU LPRime's own SNTRU Prime counterpart in the same package - defaults one through CryptoServicesRegistrar.getSecureRandom(). This is reachable from the lightweight API directly, and from javax.crypto.KEM, whose newEncapsulator() documents a null random as a request for the provider's default.\u003c/li\u003e\n\u003cli\u003eFrodoKEMEngine kept a single SHAKE instance in a field, so an engine reached concurrently produced wrong results. It is reached that way through org.bouncycastle.crypto.kems.FrodoKEMExtractor, which holds one engine for its lifetime: two threads extracting through one extractor interleaved the digest's absorb and squeeze phases, yielding shared secrets that silently did not match the sender's, or an IllegalStateException of \u0026quot;attempt to absorb while squeezing\u0026quot; from inside extractSecret. The digest is now built per call, as CMCEEngine's already was, which makes an extractor safe to share. Encapsulation was unaffected, since FrodoKEMGenerator builds an engine per call. Results for any single-threaded use are unchanged - the reference KAT vectors are byte-identical.\u003c/li\u003e\n\u003cli\u003eThe BCJSSE provider carried the TLS 1.2 coupling between the supported_groups extension and ECDSA over into TLS 1.3: an ECDSA signature scheme was treated as usable - offered in the signature_algorithms and signature_algorithms_cert extensions, and eligible when selecting the local credentials - only while the corresponding curve was among the named groups enabled for key exchange, both per context (a group unavailable for key agreement disabled the scheme outright) and per connection (the curve had to be in the supported_groups list about to be sent). RFC 8446 sec. 4.2.7 scopes supported_groups to key exchange only, with signature algorithms negotiated independently (sec. 4.2.3), so this incorrect restriction in TLS 1.3 has been removed. Ed25519, Ed448 and the RSA schemes were unaffected (as well as typical deployments using a default configuration for named groups).\u003c/li\u003e\n\u003cli\u003eThe bcmail module descriptor did not declare its javax.mail/javax.activation dependences, so a modular (module-path) consumer of the jar hit IllegalAccessError/module-resolution failures when the S/MIME classes touched the mail API. The descriptor now requires them optionally (requires static) under all four module names those libraries are known by - the automatic names mail and activation carried by the javax.mail:mail / javax.activation:activation artifacts, and the explicit names java.mail and java.activation carried by the newer com.sun.mail / com.sun.activation ones - a hard requires on any one name would break users of the others (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2389\"\u003e#2389\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFour type-coercion helpers in the OER / IEEE 1609.2 (ITS) decoder tested the wrong type in the identity fast path that lets a getInstance() factory return an argument that is already of the target type. org.bouncycastle.oer.its.ieee1609dot2.basetypes.UINT32.getInstance and org.bouncycastle.oer.its.etsi102941.basetypes.Version.getInstance guarded on UINT8 - a sibling of UINT32 under UintBase, and unrelated to Version - so passing a UINT8 threw ClassCastException, while passing an actual UINT32 or Version missed the fast path and fell through to ASN1Integer.getInstance, which rejects them: neither factory accepted its own type. org.bouncycastle.oer.its.etsi103097.EtsiTs103097DataEncryptedUnicast.getInstance guarded on its sibling EtsiTs103097DataEncrypted and then cast to the unicast type, so an EtsiTs103097DataEncrypted threw ClassCastException. org.bouncycastle.oer.OEROptional.getObject(Class) called value.getClass().isInstance(type) with the arguments transposed, which is always false because the argument is a java.lang.Class, so the cast path was dead and every optional field was resolved reflectively, failing with IllegalStateException for a target type with no static getInstance. Each guard now names the type it returns, matching the sibling UINT8 / UINT16 / UINT64 and EtsiTs103097DataEncrypted factories (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2373\"\u003e#2373\u003c/a\u003e).\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003eSee full diff in \u003ca href=\"https://github.com/bcgit/bc-java/commits\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003ecommonmark-java 0.29.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e[0.29.0] - 2026-06-20\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/42b4fb7adfe288ef13e9e27ab20aff7e91b0ab9d\"\u003e\u003ccode\u003e42b4fb7\u003c/code\u003e\u003c/a\u003e Prepare CHANGELOG for version 0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/b76e09d7a8362abb5f04e1d6b91dbd6da279a6fc\"\u003e\u003ccode\u003eb76e09d\u003c/code\u003e\u003c/a\u003e Limit how deep inline nodes may nest by default (100)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/49f65cb5cbec93cff713179990307145198e7061\"\u003e\u003ccode\u003e49f65cb\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing deeply nested emphasis\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/610f84b83e68c381e8f784ae4d044c80e1948b67\"\u003e\u003ccode\u003e610f84b\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological autolink email addresses\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/9f1d73897a56cbd74c39347af351a473e70297e1\"\u003e\u003ccode\u003e9f1d738\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological HTML block attributes\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/e13297e849995fdd582a85841067bff1d9c35ee5\"\u003e\u003ccode\u003ee13297e\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing pathological backticks\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/89d1bd3fa1524e8217ed61db5e8116c82434470f\"\u003e\u003ccode\u003e89d1bd3\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing with lots of \u003ccode\u003e\u0026lt;\u003c/...\n\n_Description has been truncated_","html_url":"https://github.com/amstaff666/openclaw-30754/pull/33","url":"https://dependabot.ecosyste.ms/api/v1/hosts/GitHub/repositories/amstaff666%2Fopenclaw-30754/issues/33","packages_url":"https://dependabot.ecosyste.ms/api/v1/issues/33/packages"}},{"old_version":"5.3.2","new_version":"5.5.0","update_type":"minor","path":null,"pr_created_at":"2026-09-10T17:54:11.000Z","version_change":"5.3.2 → 5.5.0","issue":{"uuid":"5415582546","node_id":"PR_kwDOTCTti88AAAABDCJjuQ","number":26,"state":"closed","title":"Bump the android-deps group across 1 directory with 16 updates","user":"dependabot[bot]","labels":["dependencies","java"],"assignees":[],"locked":false,"comments_count":1,"pull_request":true,"closed_at":"2026-09-11T17:45:27.000Z","author_association":null,"state_reason":null,"created_at":"2026-09-10T17:54:11.000Z","updated_at":"2026-09-11T17:45:29.000Z","time_to_close":85876,"merged_at":null,"merged_by":null,"closed_by":null,"dependency_metadata":{"prefix":"Bump","group_name":"android-deps","update_count":16,"packages":[{"name":"gradle-wrapper","old_version":"9.5.1","new_version":"9.7.1","repository_url":"https://github.com/gradle/gradle"},{"name":"org.bouncycastle:bcprov-jdk18on","old_version":"1.84","new_version":"1.85.2","repository_url":"https://github.com/bcgit/bc-java"},{"name":"org.commonmark:commonmark","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-autolink","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-strikethrough","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-tables","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-task-list-items","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.junit.vintage:junit-vintage-engine","old_version":"6.1.0","new_version":"6.1.3","repository_url":"https://github.com/junit-team/junit-framework"},{"name":"io.kotest:kotest-assertions-core-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"io.kotest:kotest-runner-junit5-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"com.squareup.okhttp3:mockwebserver","old_version":"5.3.2","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.squareup.okhttp3:okhttp","old_version":"5.3.2","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.android.application","old_version":"9.2.1","new_version":"9.4.0"},{"name":"com.android.test","old_version":"9.2.1","new_version":"9.4.0"},{"name":"org.jetbrains.kotlin.plugin.compose","old_version":"2.4.0","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"},{"name":"org.jetbrains.kotlin.plugin.serialization","old_version":"2.4.0","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"}],"path":null,"ecosystem":"maven"},"body":"Bumps the android-deps group with 16 updates in the /apps/android directory:\n\n| Package | From | To |\n| --- | --- | --- |\n| [gradle-wrapper](https://github.com/gradle/gradle) | `9.5.1` | `9.7.1` |\n| [org.bouncycastle:bcprov-jdk18on](https://github.com/bcgit/bc-java) | `1.84` | `1.85.2` |\n| [org.commonmark:commonmark](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-autolink](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-strikethrough](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-tables](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-task-list-items](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.junit.vintage:junit-vintage-engine](https://github.com/junit-team/junit-framework) | `6.1.0` | `6.1.3` |\n| [io.kotest:kotest-assertions-core-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [io.kotest:kotest-runner-junit5-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [com.squareup.okhttp3:mockwebserver](https://github.com/lysine-dev/okhttp) | `5.3.2` | `5.5.0` |\n| [com.squareup.okhttp3:okhttp](https://github.com/lysine-dev/okhttp) | `5.3.2` | `5.5.0` |\n| com.android.application | `9.2.1` | `9.4.0` |\n| com.android.test | `9.2.1` | `9.4.0` |\n| [org.jetbrains.kotlin.plugin.compose](https://github.com/JetBrains/kotlin) | `2.4.0` | `2.4.20` |\n| [org.jetbrains.kotlin.plugin.serialization](https://github.com/JetBrains/kotlin) | `2.4.0` | `2.4.20` |\n\n\nUpdates `gradle-wrapper` from 9.5.1 to 9.7.1\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/gradle/gradle/releases\"\u003egradle-wrapper's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e9.7.1\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.1.\u003c/p\u003e\n\u003cp\u003eThis is a patch release for 9.7.0. We recommend using 9.7.1 instead of 9.7.0.\u003c/p\u003e\n\u003cp\u003eHere are the highlights of 9.7.0 release:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIsolated Projects graduates to incubating\u003c/li\u003e\n\u003cli\u003eBroader Configuration Cache compatibility\u003c/li\u003e\n\u003cli\u003eResilient Sync helps you fix broken builds\u003c/li\u003e\n\u003cli\u003eMore source locations in problem reports\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003ca href=\"https://docs.gradle.org/9.7.1/release-notes.html\"\u003eRead the Release Notes\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eWe would like to thank the following community members for their contributions to this release of Gradle:\n\u003ca href=\"https://github.com/aSemy\"\u003eAdam\u003c/a\u003e,\n\u003ca href=\"https://github.com/Gautam-aman\"\u003eAman Gautam\u003c/a\u003e,\n\u003ca href=\"https://github.com/YukiCodepth\"\u003eAman Kumar\u003c/a\u003e,\n\u003ca href=\"https://github.com/adubrouski\"\u003eAnton Dubrouski\u003c/a\u003e,\n\u003ca href=\"https://github.com/liutikas\"\u003eAurimas\u003c/a\u003e,\n\u003ca href=\"https://github.com/gbhavya07\"\u003egbhavya07\u003c/a\u003e,\n\u003ca href=\"https://github.com/joshfriend\"\u003eJosh Friend\u003c/a\u003e,\n\u003ca href=\"https://github.com/nicklauslittle-gov\"\u003enicklauslittle-gov\u003c/a\u003e,\n\u003ca href=\"https://github.com/psoni674\"\u003ePragati\u003c/a\u003e,\n\u003ca href=\"https://github.com/Project516\"\u003eproject516\u003c/a\u003e,\n\u003ca href=\"https://github.com/Uomocapra\"\u003eQin Mi\u003c/a\u003e,\n\u003ca href=\"https://github.com/rkdfx\"\u003eRavi\u003c/a\u003e,\n\u003ca href=\"https://github.com/sk-reddy17\"\u003esk-reddy17\u003c/a\u003e,\n\u003ca href=\"https://github.com/Suvrat1629\"\u003eSuvrat Acharya\u003c/a\u003e,\n\u003ca href=\"https://github.com/ShreckYe\"\u003eYongshun Ye\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eUpgrade instructions\u003c/h2\u003e\n\u003cp\u003eSwitch your build to use Gradle 9.7.1 by updating your wrapper:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e./gradlew :wrapper --gradle-version=9.7.1 \u0026amp;\u0026amp; ./gradlew :wrapper\r\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eSee the Gradle \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/upgrading_version_9.html\"\u003e9.x upgrade guide\u003c/a\u003e to learn about deprecations, breaking changes and other considerations when upgrading.\u003c/p\u003e\n\u003cp\u003eFor Java, Groovy, Kotlin and Android compatibility, see the \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/compatibility.html\"\u003efull compatibility notes\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eReporting problems\u003c/h2\u003e\n\u003cp\u003eIf you find a problem with this release, please file a bug on \u003ca href=\"https://github.com/gradle/gradle/issues\"\u003eGitHub Issues\u003c/a\u003e adhering to our issue guidelines.\nIf you're not sure you're encountering a bug, please use the \u003ca href=\"https://discuss.gradle.org/c/help-discuss\"\u003eforum\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eWe hope you will build happiness with Gradle, and we look forward to your feedback via \u003ca href=\"https://twitter.com/gradle\"\u003eTwitter\u003c/a\u003e or on \u003ca href=\"https://github.com/gradle\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003e9.7.0\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.0.\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/92f0512e7f06d84621afba191f75e265363890cf\"\u003e\u003ccode\u003e92f0512\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38892\"\u003e#38892\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/820ee75a99a179bbffa41bcedc6477b685fabb9f\"\u003e\u003ccode\u003e820ee75\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/82c23f9bd2a89b4cc644e1f90a28a8668feb3dee\"\u003e\u003ccode\u003e82c23f9\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering problem in KTS (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38878\"\u003e#38878\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/ef11a7268fe8cc8d6ab849ec911aa11220180553\"\u003e\u003ccode\u003eef11a72\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering issue\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/bb0d8a974a71b1003efea41e4046e98855cd5ff8\"\u003e\u003ccode\u003ebb0d8a9\u003c/code\u003e\u003c/a\u003e Make relevant tests polyglot (run for multiple DSLs)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/336e129d7f95c03486acafc97abf59734acfed48\"\u003e\u003ccode\u003e336e129\u003c/code\u003e\u003c/a\u003e Update signing configuration (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38874\"\u003e#38874\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/4bdf0da2dad9884d089a6062a45ea7183e7d735d\"\u003e\u003ccode\u003e4bdf0da\u003c/code\u003e\u003c/a\u003e Update signing configuration\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/cd9b92c1b82856248cf1dc58b50378238bec7b52\"\u003e\u003ccode\u003ecd9b92c\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38839\"\u003e#38839\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/5f4e381964897ad8d6b99e5a7c77f26dba3259fb\"\u003e\u003ccode\u003e5f4e381\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/1e08ab551367aeb5fb48b26e72807e1d2b27c939\"\u003e\u003ccode\u003e1e08ab5\u003c/code\u003e\u003c/a\u003e Keep type-use annotations in extracted ABI classes (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38810\"\u003e#38810\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/gradle/gradle/compare/v9.5.1...v9.7.1\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.bouncycastle:bcprov-jdk18on` from 1.84 to 1.85.2\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.md\"\u003eorg.bouncycastle:bcprov-jdk18on's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch1\u003eBouncy Castle Crypto Package - Release Notes\u003c/h1\u003e\n\u003ch2\u003e1.0 Introduction\u003c/h2\u003e\n\u003cp\u003eThe Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. The package is organised so that it contains a light-weight API suitable for use in any environment (including the J2ME) with the additional infrastructure to conform the algorithms to the JCE framework.\u003c/p\u003e\n\u003ch2\u003e2.0 Release History\u003c/h2\u003e\n\u003cp\u003e\u003c!-- raw HTML omitted --\u003e\u003c!-- raw HTML omitted --\u003e\u003c/p\u003e\n\u003ch3\u003e2.1.1 Version\u003c/h3\u003e\n\u003cp\u003eRelease: 1.86\u003cbr /\u003e\nDate: 2026, TBD\u003c/p\u003e\n\u003ch3\u003e2.1.2 Defects Fixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) let a subkey inherit the primary key's Key Flags when its own Subkey Binding signature carried no Key Flags subpacket, which made the two capability decisions taken for one subkey disagree. OpenPGPCertificate.OpenPGPComponentKey.isSigningKey() reads the effective flags, which fell back to the primary key's direct-key or primary user ID self-signature, so a subkey bound with no flags of its own counted as signing-capable; verifyEmbeddedPrimaryKeyBinding reads the binding signature's own flags, found no signing capability there, and so skipped the embedded Primary Key Binding (cross-certification) signature that RFC 9580 sec. 5.2.1.8 and sec. 10.1.3 require of a subkey that can issue signatures. A data signature made by such a subkey was therefore attributed to the certificate and reported valid by OpenPGPSignature.OpenPGPDocumentSignature.isValid() with the cross-certification requirement never applied, where GnuPG refuses the same certificate and message as not cross-certified. An attacker holding a third party's public signing subkey - which is public material - could bind it to their own primary key with a Subkey Binding signature they are able to make, carrying no Key Flags and no embedded Primary Key Binding signature, which they cannot make without the subkey's private key, and have that party's genuine signatures verify as valid under the attacker's own identity: misattribution of a real signature rather than a forgery of a new one, since the signature still has to be one the subkey actually made. Key Flags are a statement about the key the carrying signature refers to (RFC 9580 sec. 5.2.3.29), so a subkey no longer inherits them from the certificate-wide signatures of the primary key: a Subkey Binding signature that omits the subpacket now leaves the subkey with no capabilities rather than the primary's, which makes the flags the cross-certification check consults the same flags every other decision consults. Preferences and the other subpackets a direct-key signature carries are inherited as before, and the primary key itself - whose flags legitimately come from its direct-key or user ID self-signature - is unaffected. The low-level PGPSignature / PGPPublicKeyRing API performs no binding checks by design and is unchanged.\u003c/li\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) used a version 6 key that carried no valid Direct Key signature, falling back to the primary user ID binding as it correctly does for a version 4 key. RFC 9580 sec. 5.2.3.10 requires the opposite: \u0026quot;An implementation MUST ensure that a valid Direct Key signature is present before using a version 6 key. This prevents certain attacks where an adversary strips a self-signature specifying a Key Expiration Time or certain preferences.\u0026quot; The certificate grammar says the same structurally, the Direct Key signature being mandatory in the version 6 structure of sec. 10.1.1 and optional in the version 4 one of sec. 10.1.3. Because a version 6 certificate carries its key expiration, features and algorithm preferences on the Direct Key signature - the convention the RFC recommends and the one OpenPGPKeyGenerator follows, its user ID certification carrying no expiration at all - removing that single signature packet from a published certificate silently dropped the expiration along with the preferences and features: OpenPGPCertificate.getSignatureChainFor fell back to the user ID binding, the primary key was still reported bound, and getEncryptionKeys() and getSigningKeys() went on returning the subkeys of a key whose owner had set it to expire. The primary key fingerprint is unchanged by the removal, so a relying party pinning the key by fingerprint still treats it as the same key, and no private key or hash collision is involved; the natural moment for the strip is the key refresh that RFC 9580 names as the reason to refetch a key at all - to learn about changes in expiration, features, preferences and revocation - which is exactly the update it defeats. This is a downgrade rather than a forgery, nothing being attributed to a key that did not authorise it, and the concerning direction is encryption, to a key meant to have been retired. OpenPGPCertificate.isBoundBy now requires a valid Direct Key self-signature on a version 6 primary key before any component of the certificate - the primary key, its subkeys or its identities - is treated as bound, so a version 6 certificate stripped of it offers no keys at all rather than an unexpiring set. Version 4 certificates are unaffected: there the key expiration legitimately lives on the user ID self-signature and the fallback is correct, so it stays. The revocation-only version 6 certificate of sec. 10.1.2, which legitimately carries no Direct Key signature, is unaffected as well - its key was already refused as revoked, and reading the revocation does not go through the binding check.\u003c/li\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) ignored the OpenPGPPolicy a caller had configured when it verified the signatures on an inline message. OpenPGPMessageInputStream took the policy it sanitizes each document signature against from the implementation's own default rather than from the processor the signature is being verified by, so a policy supplied through the documented OpenPGPApi(implementation, policy) / OpenPGPMessageProcessor(implementation, policy) constructor - which is how OpenPGPApi.decryptAndOrVerifyMessage() plumbs the configured policy through - had no bearing on whether a signature was accepted, although the same processor already applied it to the decompressed-size bound. A caller who hardened the policy beyond the default therefore had a signature that policy rejects handed back from getResult().getSignatures() with isTestedCorrect() true, while OpenPGPSignature.isValid(policy) on that same signature reported the rejection. Both verify paths, the one-pass and the prefixed-signature one, now read the configured policy; the detached-signature processor already did.\u003c/li\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) went on offering the subkeys of a certificate whose primary key had expired. OpenPGPCertificate's binding check evaluated only a subkey's own Subkey Binding signature, so a primary key whose Key Expiration Time (RFC 9580 sec. 5.2.3.13) had passed still handed out a longer-lived encryption or signing subkey from getEncryptionKeys() / getSigningKeys(), leaving the certificate contradicting itself - getExpirationTime() in the past and getPrimaryKey().isBoundAt() false, while isBoundAt() on the subkey answered true. An expired primary key can no longer certify, so the subkeys it bound are not usable with it either, which is how GnuPG and Sequoia both treat such a certificate; primary key revocation already propagated, since a revocation appears in the subkey's signature chain, but expiration is not carried there. Relatedly, a subkey no longer inherits the primary key's validity period at all - sec. 5.2.3.13 counts that period from the creation time of the key the carrying self-signature is made on, so re-basing the primary key's period on a subkey created later than it gave that subkey an expiration date later than the primary key's own.\u003c/li\u003e\n\u003cli\u003eOpenPGPSignature.OpenPGPDocumentSignature.isValidAt(Date) in the high-level OpenPGP API reported a data signature as valid at an evaluation time past the signature's own Signature Expiration Time (RFC 9580 sec. 5.2.3.18, hashed subpacket type 3). The method checked that the signature was correct and that the issuing key was bound and signing-capable at that date, but never consulted the signature's own expiration, so it disagreed with isEffectiveAt(Date) on the same object and with its own javadoc, which names being effective as one of the three criteria of a valid signature. Signature expiration is a separate axis from the issuing key's Key Expiration Time that the binding checks already cover, and GnuPG, GPGME, git and Sequoia all keep the two apart and treat a signature past its expiration as not good. isValid() and isValid(policy) evaluate at the signature's creation time, where a signature is always inside its own window, and are unchanged.\u003c/li\u003e\n\u003cli\u003eThe lightweight LMSSigner and HSSSigner refused a key wrapped in ParametersWithRandom, which is how BcContentSignerBuilder passes a key whenever setSecureRandom() has been called - so BcHssLmsContentSignerBuilder built a working signer until a random was set and then failed with \u0026quot;Incorrect Key Parameters\u0026quot;, and the two signers themselves raised ClassCastException on the same input. All three now unwrap it, as the promoted ML-DSA and SLH-DSA signers already did. The random is accepted and not used: LMS derives its message randomiser C from the key's seed and the one-time index, so it is deterministic and cannot repeat while q does not. Note SP 800-208 sec. 6.1 asks for C to come from an approved random bit generator, which this implementation does not do; that is unchanged here, and a supplied random is now ignored rather than refused.\u003c/li\u003e\n\u003cli\u003eLMS signature verification did not apply two of the checks RFC 8554 sec. 5.4.2 requires before a signature is processed. Step 2g refuses a signature whose LMS typecode is not the one from the public key, and without it the path computation took its height and tree digest from the parameter set the signature named rather than the key's, so a signature claiming a height-25 parameter set drove a 25-level computation against a height-5 key. Step 2i refuses a leaf number q outside the tree, and without it an out-of-range q flowed into the node arithmetic and was left for the candidate-root comparison to catch. Neither was a forgery - the domain separation between D_LEAF and D_INTR and the final comparison saw to that - but both are attacker-chosen work the specification says to refuse up front. Both are now checked, and a signature failing either is still reported as not verifying rather than thrown out of Signature.verify(). The catch around the signature decode in LMSSigner and HSSSigner has also been narrowed to the decode itself, as the corresponding SPI was corrected to do for github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2408\"\u003e#2408\u003c/a\u003e: past the parse the engine reports an inconsistent signature by returning false rather than by throwing, so the wider catch caught nothing while standing ready to turn a future internal error into a quiet false.\u003c/li\u003e\n\u003cli\u003eThe LMS and HSS key parameter classes now apply at construction the checks their decoders apply, so a key built directly cannot be one the decoder would refuse. LMSPrivateKeyParameters accepted an identifier of any length although the decoder reads exactly 16 bytes - such a key encoded but could not be read back - and left q, maxQ and the seed length unchecked; the seed is now required to be at least m bytes at decode as well, where a one-byte seed had been decoding silently and then deriving every one-time key from it. HSSPrivateKeyParameters checked neither its level count nor that it had been given a component key per level and a chaining signature per level below the root, and then indexed both lists, so a mismatch surfaced as IndexOutOfBoundsException - or, where a level happened to match, as a null chaining signature that only failed at signing time; the level is now checked after the reset that fills it in, since a null is legitimate on the way in. LMSPrivateKeyParameters.getInstance(byte[], byte[]) adopted the public key supplied beside the private one without comparing them, so a mismatched public key was simply reported by getPublicKey(); it now cross-checks the identifier, both parameter sets and, where the tree cache already holds it, the root, as the HSS entry point does. The decoders also now report a bad version or seed length as IOException rather than IllegalStateException, so a caller can catch one type for a malformed key, and the package-private LM-OTS public key decoder no longer declares throws Exception or dereferences an unrecognised typecode. The deprecated org.bouncycastle.pqc.crypto.lms copies carry the decoder corrections.\u003c/li\u003e\n\u003cli\u003eIn the LMS JCE layer, LMSKeyGenParameterSpec.fromNames knew all twenty LMS parameter-set names but only four of the sixteen LM-OTS ones, so none of the SP 800-208 n24 or SHAKE sets could be named; all sixteen are now present. KeyPairGenerator.initialize(int, SecureRandom) reports InvalidParameterException, which is what the JCA specifies and which extends the IllegalArgumentException it raised before, so existing catches still match. BCLMSPrivateKey.getIndex now takes the exhaustion check and the index read under the key's own monitor rather than as two separate calls, and two unused fields have gone from LMSSignatureSpi. Note that the LMS Signature claims its one-time key at the first update() rather than at sign(), so a Signature that is initialised and updated and then abandoned spends an index without producing a signature - the safe direction for a one-time scheme, and now documented on the SPI.\u003c/li\u003e\n\u003cli\u003eEvery other key pair generator that refuses a key size did the same thing the LMS one did above. KeyPairGenerator.initialize(int, SecureRandom) is documented to raise InvalidParameterException when the key size is not one the generator supports, and thirty of them raised a bare IllegalArgumentException instead, so a caller following the JCA and catching the documented type saw an exception escaping rather than a refusal. The ML-DSA, ML-KEM, SLH-DSA, Classic McEliece, FrodoKEM, NTRU and composite signature and KEM generators in the BC provider, and every generator in BCPQC, now raise InvalidParameterException - NewHope included, where the value is a key size it will not take rather than a mode of initialisation it does not offer. InvalidParameterException extends IllegalArgumentException, so callers written against the old behaviour go on catching it unchanged. The two RSA generators are corrected as well, and differently: theirs is a key size below a floor rather than a mode of initialisation they do not offer, and the refusal is raised by the lightweight RSAKeyGenerationParameters, which cannot name a java.security exception at all, so the RSA KeyPairGeneratorSpi now translates it - keeping the message verbatim and the original exception as the cause, through a new SecurityExceptions.invalidParameterException factory, since InvalidParameterException has no constructor that takes one. Of the 304 KeyPairGenerator services the two providers register, 299 now refuse a nonsense key size the way the JCA defines it and five accept it as a strength they can work with, with none left raising a bare IllegalArgumentException; that is asserted as a sweep over both providers rather than per algorithm, so a generator added later is covered without the test being touched. The jdk1.3 provider overlays of the four generators that have one carry the same change, and the jdk1.3 SecurityExceptions overlay gains the new factory along with the invalidAlgorithmParameterException one it had been missing.\u003c/li\u003e\n\u003cli\u003eKeyPairGenerator.initialize(AlgorithmParameterSpec, SecureRandom) had the same shape of problem as the int overload above, and only 44 of the 304 services the two providers register reported an unusable spec as the InvalidAlgorithmParameterException that method declares. The twenty-three PQC generators that resolve a parameter set by name - cmce, frodokem, mldsa, mlkem, slhdsa, aimer, bike, faest, falcon, haetae, hqc, mayo, mqom, ntru, ntruplus, both ntruprime variants, qruov, saber, sdith, smaugt, snova and sqisign, 230 services between them - case-folded the name they got back from the spec without checking it, so a spec with no getName() method, and a null spec, produced a NullPointerException from inside the fold; their own \u0026quot;is this name one I know\u0026quot; branch, which does report the declared exception, was unreachable. The two composite generators, whose parameter set is fixed by the algorithm name so that null is the only spec they accept, refused every other one with IllegalArgumentException. RSA answered correctly for a spec of the wrong type but not for one of the right type carrying values its lightweight parameters will not take - an even public exponent, or a key size below the floor - which is now translated the same way the int overload's is. All 304 services now report the declared exception, with the composites still taking the null spec that is right for them; note that InvalidAlgorithmParameterException is a checked exception and not an IllegalArgumentException, so a caller that was catching what these threw before has to catch the declared type instead.\u003c/li\u003e\n\u003cli\u003eAn HSS private key claimed the two records of its position under two different monitors. The top-level index and the bottom component key's one-time index q are independent records of the same position - the decoder requires them to agree, see the entry below - but generateLMSContext incremented the index under the HSS key's own monitor, released it, and only then claimed q under the component key's. A getEncoded() issued in between saw the index advanced and q not, and produced an encoding this implementation's own decoder rejects; and two threads meeting at a bottom-tree boundary could both pass the exhaustion test, take consecutive top-level indices and claim the same q, after which one of them was refused with \u0026quot;ots private key exhausted\u0026quot; by a key still reporting usages remaining, a top-level index had been spent with no signature made, and the two records stayed one apart for the rest of the key's life in that process - so it could no longer be encoded, cloned or sharded, and getIndex() and getUsagesRemaining() misreported by one. No one-time key was reused: the component key's claim is itself atomic, and the divergence runs index ahead of leaves, so the effect was on the key's usability rather than on the signatures it had made. Both records are now claimed under the one monitor, and the component key is claimed before the index is incremented so that an exhausted one leaves both untouched. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the same correction.\u003c/li\u003e\n\u003cli\u003eTimeStampToken parsed the attacker-controlled TSTInfo content of a time-stamp token (org.bouncycastle.tsp.TimeStampToken, reached from TimeStampResponse(byte[]) and (InputStream)) inside a try that caught only CMSException, so a well-formed RFC 3161 TimeStampResp whose embedded token carried a malformed TSTInfo - a SEQUENCE with fewer elements than the five mandatory fields, a non-SEQUENCE, truncated DER, or an unknown context tag - let an IllegalArgumentException or a NoSuchElementException escape the constructor's declared throws TSPException, IOException contract. A token signed by no signers or by more than one raised a bare IllegalArgumentException from the same constructor, before that try, for the same reason. Both are now reported as TSPException, matching the package-private TimeStampResponse(DLSequence) constructor and the existing getSignedAttributes guard in the same method; the signer-count refusal is a TSPValidationException, as the neighbouring check on the content type already was. Related, and the cause of the NoSuchElementException: asn1.tsp.TSTInfo read its five mandatory fields off the sequence with no bound on how many elements were actually there, so a short SEQUENCE left the enumeration to run out rather than being refused, and an oversize one was accepted with its extra elements absorbed into the optional slots. Decode now requires the five to ten elements RFC 3161 sec. 2.4.2 gives the type, which is what the sibling Accuracy and ArchiveTimeStamp decoders already did, so the failure is the IllegalArgumentException that getInstance is expected to raise (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2415\"\u003e#2415\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eNeither the HSS nor the XMSS^MT private key decoder checked its declared index against the traversal state stored beside it, although the two are independent records of the same position in the key and so can be compared. For HSS the records are the top-level index and the component keys' one-time indices q; for XMSS^MT they are the global index and the per-layer BDS states. A stored key whose index had been rolled back while its state stayed advanced - a partial write, a restore from backup, a buggy storage layer - was therefore accepted, and it then signed a second message under a one-time key the key had already used, producing a signature that verified, so nothing anywhere surfaced the reuse. RFC 8554 sec. 1 and RFC 8391 sec. 1.1 both require each one-time key to be used exactly once, and this is the failure those requirements exist to prevent; the single-tree XMSS decoder has tied its BDS state to its index since that state was first validated, and this brings the two multi-tree schemes into line. HSS decode now requires the declared index to equal the position the component q values imply - a level above the last contributes (q - 1) leaves of the levels beneath it, since its q has already advanced past the subtree it signed - and XMSS^MT decode now requires each present layer's BDS index to equal the leaf index that layer derives from the global index, allowing the one position where a layer has moved into a new subtree and its state legitimately still carries the previous subtree's final index. A layer with no state yet is unaffected, since those are built lazily at signing time. Related, and the same shape of omission: an XMSS or XMSS^MT private key encoding carries the tree root twice - the key's own root field and the root node of the BDS state stored beside it, which for XMSS^MT is the top layer's - and the two were never compared either. A corrupted root was accepted and then poisoned every signature the key made, because the root is hashed into the message digest: the signature did not verify and nothing indicated why. Decode now requires the two copies to agree. The BDS node values themselves are not checkable the way the LMS tree cache above is - a BDS authentication path, stack, retain or keep node does not have its children stored alongside it, so recomputing one means building a subtree, which is the work the state exists to avoid. Both checks are integer comparisons over the levels of the key, too small to measure against the surrounding decode, and both were verified not to reject any legitimate key by walking every index a key can reach: the full key space of the two-level HSS and the h=4/d=2, h=6/d=2, h=6/d=3, h=9/d=3 and h=8/d=4 XMSS^MT parameter sets, plus a three-level HSS key across a subtree boundary and an HSS shard. Since those node values cannot be recomputed, the encoded state now carries a checksum over itself instead, with the owning key's public seed hashed in front of it. Any corruption of the stored state is refused at decode rather than being loaded and then producing signatures that silently do not verify, and because the public seed is bound in, a state transplanted between two keys of the same parameter set is refused too, even though it is internally consistent and arrives with its own matching root. The public seed is bound rather than the secret seed or the PRF key deliberately: the state's own root and index are inside the encoding and so are already covered, hashing secret material would make the stored checksum a commitment to it for no gain in detection, and the PRF key does not influence the state at all. \u003cstrong\u003eThis is an error-detecting code and not integrity protection\u003c/strong\u003e - anyone able to rewrite the stored key recomputes it, so it establishes that the state is unchanged since it was written, never that it was correct when written, and the allocation bounds on the encoding remain the guard against a crafted one. It costs one SHA-256 over the state, measured at 5 to 8 microseconds each way for the h=10 and h=16 parameter sets, and 32 bytes of encoding. The state encoding was added earlier in this same cycle and has not been released, so the checksum is simply part of it rather than a new version: a state written by a 1.86 beta is rejected, which is recovered from by re-exporting the key. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the HSS check as well (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2414\"\u003e#2414\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eIn the XMSS and XMSS^MT JCE layer, KeyPairGenerator.initialize(int, SecureRandom) reports InvalidParameterException, which is what the JCA specifies and which extends the IllegalArgumentException it raised before, so existing catches still match. This is the XMSS counterpart of the same correction made to LMSKeyPairGeneratorSpi.\u003c/li\u003e\n\u003cli\u003eBCXMSSPrivateKey.getIndex and BCXMSSMTPrivateKey.getIndex took the exhaustion check and the index read as two separate calls on the key parameters. Each is atomic on its own, but the pair is not: a signature taken by another thread between them spends the last usage, so the check passes and the read that follows returns maxIndex + 1 - the one index past the end of the key, which is what the check exists to refuse, handed back as though it were the next one-time key to be used. Both reads are now taken under the key parameters' own monitor, the monitor their mutators hold, as BCLMSPrivateKey.getIndex was corrected to do. No one-time key is reused by this: the effect is on what the key reports about itself, not on the signatures it makes.\u003c/li\u003e\n\u003cli\u003eThe S/MIME example smoke test in the misc module (org.bouncycastle.mail.smime.examples.test.AllTests) drove SendSignedAndEncryptedMail against smtp.gmail.com, and that example finishes with Transport.send() under JavaMail's default settings, which have no connect timeout. Where outbound port 25 is refused the failure was swallowed and the test passed; where it is silently dropped, as on many home networks, the connect blocked and ./gradlew build hung in :misc:test indefinitely with \u0026quot;0 tests completed\u0026quot;. The test now delivers to an SMTP stub on a loopback port, with connect / read / write timeouts as a backstop, and asserts the message arrived (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2407\"\u003e#2407\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation took the traditional component public key bytes it feeds the KEM combiner from the recipient key's own encoding, while decapsulation recomputes the point from the private key and so always produced an uncompressed one. Section 4 of draft-ietf-lamps-pq-composite-kem requires an EC component to be carried as an uncompressed point, but a component key that encodes itself compressed - a BC EC key whose point format has been set through org.bouncycastle.jce.interfaces.ECPointEncoder, or a key from a provider that preserves a compressed encoding - was passed through as it came. Both sides then combined a different tradPK and derived different shared secrets, with no error reported on either: encapsulation and decapsulation both succeeded and the recipient simply could not decrypt. The EC component is now normalised to an uncompressed point wherever the engine serialises one, which covers the ephemeral key that forms the ciphertext as well. X25519 and X448 components have a single encoding and were unaffected, as were EC keys left in their default (uncompressed) format, whose shared secrets are unchanged. CompositePublicKey.getEncoded() took its component bytes the same way, so such a key also encoded to a composite key other implementations reject and whose bytes changed across an encode / decode / encode round trip - 1238 bytes rather than 1270 for MLKEM768-ECDH-P256, and for the composite ML-DSA keys sharing that method, 2006 rather than 2038 for MLDSA65-ECDSA-P256. It now normalises the component the same way. This is a write-side change only: a composite key carrying a compressed EC component is still decoded, since the component key factories accept either form, and continues to verify signatures as before - it simply re-encodes in the normalised form. The shared normalisation is org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil.getUncompressedSubjectPublicKeyBytes.\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation threw a NullPointerException, wrapped in an IllegalStateException out of KeyGenerator.generateKey(), when the SecureRandom it was given was null - which javax.crypto.KEM.newEncapsulator() documents as a request for the provider's default, and which KeyGenerator.init(spec, null) passes straight through. The three RSA-OAEP composites draw the traditional shared secret from that random directly, so they were the ones affected; the ECDH and X25519 / X448 composites escaped only because their component KeyPairGenerators default a random of their own. CompositeMLKEMEngine now defaults one through CryptoServicesRegistrar.getSecureRandom() on first use, as the composite KEM Cipher's wrap path already did, and as the KEM generators corrected earlier in this cycle now do. Related, the engine now also clears the ML-KEM component's shared secret alongside the traditional one on both the encapsulate and decapsulate paths - the copy handed back by getEncoded() was left in the heap - as section 3.5 of draft-ietf-lamps-pq-composite-kem requires.\u003c/li\u003e\n\u003cli\u003eCompositePublicKey.getAlgorithm() and CompositePrivateKey.getAlgorithm() returned null for all twelve Composite ML-KEM (draft-ietf-lamps-pq-composite-kem) parameter sets. Both classes resolved the name through the composite signature index only, which holds the composite ML-DSA OIDs, so a composite KEM key pair - generated, parsed from a certificate, or read from PKCS#8 - reported no algorithm at all, and the standard JCA idiom of reconstructing a key with KeyFactory.getInstance(key.getAlgorithm()) raised a NullPointerException. The lookup now falls back to the composite KEM index, so the name returned is the one the provider registers the algorithm under (e.g. MLKEM768-X25519-SHA3-256), matching the composite ML-DSA behaviour. The same single-index assumption made the CompositePublicKey(SubjectPublicKeyInfo) and CompositePrivateKey(PrivateKeyInfo) constructors reject a composite KEM key with \u0026quot;unable to create CompositePublicKey from SubjectPublicKeyInfo\u0026quot;; they now dispatch to the composite KEM key factory for those OIDs. Keys obtained through KeyFactory or through BouncyCastleProvider.getPublicKey / getPrivateKey were unaffected and are unchanged (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2404\"\u003e#2404\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe org.bouncycastle.jcajce.spec.KEMKDFSpec constructor stored a null otherInfo as given, so getOtherInfo() returned null, and three of the KDF branches KdfUtil.makeKeyBytes dispatches to - KMAC-128, KMAC-256 and SHAKE-256 - read the otherInfo length without a guard and threw NullPointerException out of the KEM operation, where the KDF2, KDF3 and HKDF branches tolerate a null through KDFParameters / HKDFParameters. The Builder of every spec in the package already mapped null to empty, so no provider path reached it, but the constructor is protected on a public class and KdfUtil is documented for callers building their own KEM integration; the deprecated KEMParameterSpec passes a null itself and escaped only because it also pins the KDF to null. The constructor now stores empty for a null, so getOtherInfo() never returns null, and a null and an explicitly empty otherInfo derive the same key.\u003c/li\u003e\n\u003cli\u003eQR-UOV signature verification accepted a signature encoding that was not canonical, so the encoding of a signature was not unique even after the trailing-byte fix of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e. Each F_q element of the signature is stored in ceil(log2 q) bits, one more bit pattern than the field has elements: q itself is representable and is arithmetically congruent to zero, so an element written as q verified exactly as the same element written as zero would, and the bits padding the last element out to the byte boundary were never read at all. Every zero element of a signature therefore carried a second encoding, and for the q = 7 parameter sets roughly one element in seven is zero - a single qruov_5_q7_L10 signature measured 256 spare bits, so on the order of 2^256 distinct byte strings verified for the one message and key. Verification now rejects any element outside [0, q) and any set padding bit; a signature produced by this or by the reference implementation is unaffected, as the KAT vectors of every parameter set confirm. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSNOVA signature verification ignored four bits inside the signature for any parameter set whose solution is an odd number of GF(16) nibbles - the SNOVA_24_5_5, SNOVA_25_8_3, SNOVA_29_6_5 and SNOVA_66_15_3 families, sixteen of the forty-four parameter sets. The last byte of the encoded solution carries a single nibble and the signer leaves the top four bits zero, but the decoder did not read them, so sixteen distinct byte strings verified for one signature. This is the same non-unique encoding github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e closed for bytes following the signature, applied inside it; the verifier now requires those bits to be zero. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSnovaPrivateKeyParameters did not validate the length of the private key encoding handed to it - the only one of the five schemes of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e that did not - and SnovaParameters.getPrivateKeyLength() reported the expanded (\u0026quot;ESK\u0026quot;) length even for a parameter set whose private key is the seed pair. A private key encoding reaches this constructor straight from a PKCS#8 blob, so a wrong length went undetected: a seed-form key with extra bytes appended was accepted and signed under a different derived key, and a short expanded-form key sized the signer's decode buffer negatively, throwing NegativeArraySizeException out of generateSignature() rather than being reported at construction. Related, the signing retry loop could not terminate: the vinegar values are derived from a single-byte counter, so only 256 distinct linear systems can be tried, and an expanded-form private key that is not a real central map is singular for all of them - generateSignature() then span forever rather than failing. The length is now checked at construction, getPrivateKeyLength() reports the length that parameter set's private key actually has, and the retry loop gives up after its 256 attempts as MAYO's does.\u003c/li\u003e\n\u003cli\u003eMayoSigner and MayoKeyPairGenerator did not clear several buffers holding secret key material that the MAYO reference implementation explicitly clears. Signing left the secret oil space O, the expanded L = (P1 + P1^t) * O + P2, and the M / VPV / Ox intermediates of the central map in place, having gone to the trouble of clearing eleven other buffers; key generation left the expanded seed, whose tail is the encoded oil space, and the P1 * O + P2 half of P; and the row-echelon step left the packed echelon form of the secret linear system and its pivot rows. Separately, if all 256 attempts at solving for the signature had given a rank-deficient system, signing emitted a signature built from the failed attempt's state instead of reporting the failure the reference returns, and AIMerSigner.generateSignature returned an empty array on failure, which a caller would hand on as though it were a signature. Both now throw.\u003c/li\u003e\n\u003cli\u003eFive PQC signature schemes - MAYO, SNOVA, QR-UOV, SQIsign and AIMer - returned the NIST crypto_sign \u0026quot;sm\u0026quot; signed-message envelope from generateSignature() rather than the signature. That envelope is an artefact of the reference KAT harness, which records the message alongside the signature so a vector file can be self-contained; it is not part of any of the five specifications, and no other BC signer emits it (Falcon's KAT test rebuilds the equivalent envelope in the test, which is where it belongs). Two consequences followed, both reaching the JCA Signature services of every parameter set of the five schemes in BouncyCastlePQCProvider. First, since the message was appended to the signature, verification had to skip whatever followed the signature proper, and it did so by checking only that the buffer was long enough - so any number of trailing bytes could be added to a valid signature, or the appended message replaced with unrelated data, and it still verified. A signature encoding was therefore not unique: anyone holding one valid signature could produce unlimited distinct byte strings that all verified for the same message and key, which breaks any use that treats the signature bytes as an identifier, deduplicates on them, or records them as evidence. Second, the envelope propagated into everything built on the operator layer: because ContentSigner hands the signature straight into the structure being signed, every X.509 certificate, CRL, CMS SignedData and TLS CertificateVerify BC produced with one of these algorithms carried a verbatim copy of the signed data inside its own signature field - a self-signed MAYO-1 certificate came to 3567 bytes where the same certificate is now 2020 - which no other implementation can parse as a signature, and which in a detached CMS signature meant the \u0026quot;detached\u0026quot; signature carried the content. generateSignature() now returns the bare signature, and verifySignature() requires exactly the parameter set's signature length, so appended or truncated data is rejected rather than ignored. \u003cstrong\u003eThis is a behavioural change for signatures produced by an earlier release\u003c/strong\u003e - MAYO and SNOVA from 1.84, QR-UOV, SQIsign and AIMer from 1.85 - which are no longer accepted in the envelope form they were emitted in; the signature bytes themselves are unchanged, so a stored value can be recovered by taking the leading signature-length bytes, or for AIMer, whose envelope was message || signature rather than signature || message, the trailing ones. The KAT tests now rebuild the envelope before comparing against the vector files, which continue to record it. Note that AIMer's verification had already been made length-exact during this cycle (see the entry below relating to github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2401\"\u003e#2401\u003c/a\u003e), so of the five only its envelope remained (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe MLS implementation did not bind an X.509 credential to the LeafNode's signature_key. LeafNode.verify() checked a leaf's signature against the signature_key declared in the leaf itself, while the X.509 credential's certificate chain was stored but never parsed or checked, so the certificate's public key was never required to match signature_key (RFC 9420 sec. 5.3). A leaf could therefore carry one party's certificate while being signed by an unrelated key and still be accepted under that party's identity through KeyPackage.verify() and the Group leaf-validation path. LeafNode.verify() now requires the end-entity certificate's subject public key, in the cipher suite's signature encoding, to equal signature_key for an X.509 credential, and rejects the leaf otherwise - including an empty chain or a certificate whose key type does not match the cipher suite; certificate-chain and identity validation to a trust anchor remain the application's responsibility per RFC 9420 sec. 5.3.1. A public org.bouncycastle.mls.codec.Certificate(byte[]) constructor and a Credential.getCertificates() accessor are added so callers can build and inspect X.509 credentials. Basic credentials are unaffected.\u003c/li\u003e\n\u003cli\u003eThe SecureRandom supplied to org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder.setSecureRandom() did not drive the content IV / nonce for any algorithm other than RC2. EnvelopedDataHelper.generateParameters passed the caller's SecureRandom to the AlgorithmParameterGenerator only in the RC2_CBC branch; every other content-encryption algorithm - AES-CBC, AES-GCM, AES-CCM, Camellia, ARIA, SEED and the rest - reached pGen.generateParameters() on an uninitialised generator, so the IV / nonce was drawn from a default SecureRandom and setSecureRandom() was silently ignored (the builder's javadoc states that random is used for IV/nonce generation). The generator is now initialised with the supplied random on the general path as well, so a caller who provides a specific randomness source - for a controlled or FIPS-approved DRBG, say - has it honoured for the content IV / nonce. The session-key generation path was unaffected and already used the supplied random. Because the content IV / nonce now comes from the supplied SecureRandom, the org.bouncycastle.crypto.util JournalingSecureRandom / JournaledAlgorithm reproducible-encryption support records it in the transcript: a resumed session reproduces the IV / nonce by regenerating it from the replayed randomness - build the resuming encryptor from the content-algorithm OID - rather than by reusing the AlgorithmIdentifier captured from the first encryption, which no longer keeps the transcript aligned.\u003c/li\u003e\n\u003cli\u003eThe NTRU LPRime, NTRU+ and SMAUG-T KEM generators threw a NullPointerException when constructed with a null SecureRandom, where every other KEM generator - including NTRU LPRime's own SNTRU Prime counterpart in the same package - defaults one through CryptoServicesRegistrar.getSecureRandom(). This is reachable from the lightweight API directly, and from javax.crypto.KEM, whose newEncapsulator() documents a null random as a request for the provider's default.\u003c/li\u003e\n\u003cli\u003eFrodoKEMEngine kept a single SHAKE instance in a field, so an engine reached concurrently produced wrong results. It is reached that way through org.bouncycastle.crypto.kems.FrodoKEMExtractor, which holds one engine for its lifetime: two threads extracting through one extractor interleaved the digest's absorb and squeeze phases, yielding shared secrets that silently did not match the sender's, or an IllegalStateException of \u0026quot;attempt to absorb while squeezing\u0026quot; from inside extractSecret. The digest is now built per call, as CMCEEngine's already was, which makes an extractor safe to share. Encapsulation was unaffected, since FrodoKEMGenerator builds an engine per call. Results for any single-threaded use are unchanged - the reference KAT vectors are byte-identical.\u003c/li\u003e\n\u003cli\u003eThe BCJSSE provider carried the TLS 1.2 coupling between the supported_groups extension and ECDSA over into TLS 1.3: an ECDSA signature scheme was treated as usable - offered in the signature_algorithms and signature_algorithms_cert extensions, and eligible when selecting the local credentials - only while the corresponding curve was among the named groups enabled for key exchange, both per context (a group unavailable for key agreement disabled the scheme outright) and per connection (the curve had to be in the supported_groups list about to be sent). RFC 8446 sec. 4.2.7 scopes supported_groups to key exchange only, with signature algorithms negotiated independently (sec. 4.2.3), so this incorrect restriction in TLS 1.3 has been removed. Ed25519, Ed448 and the RSA schemes were unaffected (as well as typical deployments using a default configuration for named groups).\u003c/li\u003e\n\u003cli\u003eThe bcmail module descriptor did not declare its javax.mail/javax.activation dependences, so a modular (module-path) consumer of the jar hit IllegalAccessError/module-resolution failures when the S/MIME classes touched the mail API. The descriptor now requires them optionally (requires static) under all four module names those libraries are known by - the automatic names mail and activation carried by the javax.mail:mail / javax.activation:activation artifacts, and the explicit names java.mail and java.activation carried by the newer com.sun.mail / com.sun.activation ones - a hard requires on any one name would break users of the others (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2389\"\u003e#2389\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFour type-coercion helpers in the OER / IEEE 1609.2 (ITS) decoder tested the wrong type in the identity fast path that lets a getInstance() factory return an argument that is already of the target type. org.bouncycastle.oer.its.ieee1609dot2.basetypes.UINT32.getInstance and org.bouncycastle.oer.its.etsi102941.basetypes.Version.getInstance guarded on UINT8 - a sibling of UINT32 under UintBase, and unrelated to Version - so passing a UINT8 threw ClassCastException, while passing an actual UINT32 or Version missed the fast path and fell through to ASN1Integer.getInstance, which rejects them: neither factory accepted its own type. org.bouncycastle.oer.its.etsi103097.EtsiTs103097DataEncryptedUnicast.getInstance guarded on its sibling EtsiTs103097DataEncrypted and then cast to the unicast type, so an EtsiTs103097DataEncrypted threw ClassCastException. org.bouncycastle.oer.OEROptional.getObject(Class) called value.getClass().isInstance(type) with the arguments transposed, which is always false because the argument is a java.lang.Class, so the cast path was dead and every optional field was resolved reflectively, failing with IllegalStateException for a target type with no static getInstance. Each guard now names the type it returns, matching the sibling UINT8 / UINT16 / UINT64 and EtsiTs103097DataEncrypted factories (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2373\"\u003e#2373\u003c/a\u003e).\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003eSee full diff in \u003ca href=\"https://github.com/bcgit/bc-java/commits\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003ecommonmark-java 0.29.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e[0.29.0] - 2026-06-20\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/42b4fb7adfe288ef13e9e27ab20aff7e91b0ab9d\"\u003e\u003ccode\u003e42b4fb7\u003c/code\u003e\u003c/a\u003e Prepare CHANGELOG for version 0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/b76e09d7a8362abb5f04e1d6b91dbd6da279a6fc\"\u003e\u003ccode\u003eb76e09d\u003c/code\u003e\u003c/a\u003e Limit how deep inline nodes may nest by default (100)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/49f65cb5cbec93cff713179990307145198e7061\"\u003e\u003ccode\u003e49f65cb\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing deeply nested emphasis\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/610f84b83e68c381e8f784ae4d044c80e1948b67\"\u003e\u003ccode\u003e610f84b\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological autolink email addresses\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/9f1d73897a56cbd74c39347af351a473e70297e1\"\u003e\u003ccode\u003e9f1d738\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological HTML block attributes\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/e13297e849995fdd582a85841067bff1d9c35ee5\"\u003e\u003ccode\u003ee13297e\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing pathological backticks\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/89d1bd3fa1524e8217ed61db5e8116c82434470f\"\u003e\u003ccode\u003e89d1bd3\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing with lots of \u003ccode\u003e\u0026lt;\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/commonmark/commonmark-java/compare/commonmark-parent-0.28.0...commonmark-parent-0.30.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark-ext-autolink` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:...\n\n_Description has been truncated_","html_url":"https://github.com/brahminib/support-claw/pull/26","url":"https://dependabot.ecosyste.ms/api/v1/hosts/GitHub/repositories/brahminib%2Fsupport-claw/issues/26","packages_url":"https://dependabot.ecosyste.ms/api/v1/issues/26/packages"}},{"old_version":"5.3.2","new_version":"5.5.0","update_type":"minor","path":null,"pr_created_at":"2026-09-10T10:41:20.000Z","version_change":"5.3.2 → 5.5.0","issue":{"uuid":"5411138290","node_id":"PR_kwDOTMZbOc8AAAABC-kAMA","number":16,"state":"open","title":"Bump the android-deps group across 1 directory with 21 updates","user":"dependabot[bot]","labels":["dependencies","java"],"assignees":[],"locked":false,"comments_count":1,"pull_request":true,"closed_at":null,"author_association":null,"state_reason":null,"created_at":"2026-09-10T10:41:20.000Z","updated_at":"2026-09-10T10:42:28.000Z","time_to_close":null,"merged_at":null,"merged_by":null,"closed_by":null,"dependency_metadata":{"prefix":"Bump","group_name":"android-deps","update_count":21,"packages":[{"name":"gradle-wrapper","old_version":"9.4.1","new_version":"9.7.1","repository_url":"https://github.com/gradle/gradle"},{"name":"androidx.core:core-ktx","old_version":"1.18.0","new_version":"1.19.0"},{"name":"org.bouncycastle:bcprov-jdk18on","old_version":"1.84","new_version":"1.85.2","repository_url":"https://github.com/bcgit/bc-java"},{"name":"org.commonmark:commonmark","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-autolink","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-strikethrough","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-tables","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-task-list-items","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"dnsjava:dnsjava","old_version":"3.6.4","new_version":"3.6.5","repository_url":"https://github.com/dnsjava/dnsjava"},{"name":"org.junit.vintage:junit-vintage-engine","old_version":"6.0.3","new_version":"6.1.3","repository_url":"https://github.com/junit-team/junit-framework"},{"name":"io.kotest:kotest-assertions-core-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"io.kotest:kotest-runner-junit5-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"org.jetbrains.kotlinx:kotlinx-coroutines-android","old_version":"1.10.2","new_version":"1.11.0","repository_url":"https://github.com/Kotlin/kotlinx.coroutines"},{"name":"org.jetbrains.kotlinx:kotlinx-coroutines-test","old_version":"1.10.2","new_version":"1.11.0","repository_url":"https://github.com/Kotlin/kotlinx.coroutines"},{"name":"com.google.android.material:material","old_version":"1.13.0","new_version":"1.14.0","repository_url":"https://github.com/material-components/material-components-android"},{"name":"com.squareup.okhttp3:mockwebserver","old_version":"5.3.2","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.squareup.okhttp3:okhttp","old_version":"5.3.2","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.android.application","old_version":"9.2.0","new_version":"9.4.0"},{"name":"com.android.test","old_version":"9.2.0","new_version":"9.4.0"},{"name":"org.jetbrains.kotlin.plugin.compose","old_version":"2.3.21","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"},{"name":"org.jetbrains.kotlin.plugin.serialization","old_version":"2.3.21","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"}],"path":null,"ecosystem":"maven"},"body":"Bumps the android-deps group with 21 updates in the /apps/android directory:\n\n| Package | From | To |\n| --- | --- | --- |\n| [gradle-wrapper](https://github.com/gradle/gradle) | `9.4.1` | `9.7.1` |\n| androidx.core:core-ktx | `1.18.0` | `1.19.0` |\n| [org.bouncycastle:bcprov-jdk18on](https://github.com/bcgit/bc-java) | `1.84` | `1.85.2` |\n| [org.commonmark:commonmark](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-autolink](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-strikethrough](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-tables](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-task-list-items](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [dnsjava:dnsjava](https://github.com/dnsjava/dnsjava) | `3.6.4` | `3.6.5` |\n| [org.junit.vintage:junit-vintage-engine](https://github.com/junit-team/junit-framework) | `6.0.3` | `6.1.3` |\n| [io.kotest:kotest-assertions-core-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [io.kotest:kotest-runner-junit5-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [org.jetbrains.kotlinx:kotlinx-coroutines-android](https://github.com/Kotlin/kotlinx.coroutines) | `1.10.2` | `1.11.0` |\n| [org.jetbrains.kotlinx:kotlinx-coroutines-test](https://github.com/Kotlin/kotlinx.coroutines) | `1.10.2` | `1.11.0` |\n| [com.google.android.material:material](https://github.com/material-components/material-components-android) | `1.13.0` | `1.14.0` |\n| [com.squareup.okhttp3:mockwebserver](https://github.com/lysine-dev/okhttp) | `5.3.2` | `5.5.0` |\n| [com.squareup.okhttp3:okhttp](https://github.com/lysine-dev/okhttp) | `5.3.2` | `5.5.0` |\n| com.android.application | `9.2.0` | `9.4.0` |\n| com.android.test | `9.2.0` | `9.4.0` |\n| [org.jetbrains.kotlin.plugin.compose](https://github.com/JetBrains/kotlin) | `2.3.21` | `2.4.20` |\n| [org.jetbrains.kotlin.plugin.serialization](https://github.com/JetBrains/kotlin) | `2.3.21` | `2.4.20` |\n\n\nUpdates `gradle-wrapper` from 9.4.1 to 9.7.1\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/gradle/gradle/releases\"\u003egradle-wrapper's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e9.7.1\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.1.\u003c/p\u003e\n\u003cp\u003eThis is a patch release for 9.7.0. We recommend using 9.7.1 instead of 9.7.0.\u003c/p\u003e\n\u003cp\u003eHere are the highlights of 9.7.0 release:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIsolated Projects graduates to incubating\u003c/li\u003e\n\u003cli\u003eBroader Configuration Cache compatibility\u003c/li\u003e\n\u003cli\u003eResilient Sync helps you fix broken builds\u003c/li\u003e\n\u003cli\u003eMore source locations in problem reports\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003ca href=\"https://docs.gradle.org/9.7.1/release-notes.html\"\u003eRead the Release Notes\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eWe would like to thank the following community members for their contributions to this release of Gradle:\n\u003ca href=\"https://github.com/aSemy\"\u003eAdam\u003c/a\u003e,\n\u003ca href=\"https://github.com/Gautam-aman\"\u003eAman Gautam\u003c/a\u003e,\n\u003ca href=\"https://github.com/YukiCodepth\"\u003eAman Kumar\u003c/a\u003e,\n\u003ca href=\"https://github.com/adubrouski\"\u003eAnton Dubrouski\u003c/a\u003e,\n\u003ca href=\"https://github.com/liutikas\"\u003eAurimas\u003c/a\u003e,\n\u003ca href=\"https://github.com/gbhavya07\"\u003egbhavya07\u003c/a\u003e,\n\u003ca href=\"https://github.com/joshfriend\"\u003eJosh Friend\u003c/a\u003e,\n\u003ca href=\"https://github.com/nicklauslittle-gov\"\u003enicklauslittle-gov\u003c/a\u003e,\n\u003ca href=\"https://github.com/psoni674\"\u003ePragati\u003c/a\u003e,\n\u003ca href=\"https://github.com/Project516\"\u003eproject516\u003c/a\u003e,\n\u003ca href=\"https://github.com/Uomocapra\"\u003eQin Mi\u003c/a\u003e,\n\u003ca href=\"https://github.com/rkdfx\"\u003eRavi\u003c/a\u003e,\n\u003ca href=\"https://github.com/sk-reddy17\"\u003esk-reddy17\u003c/a\u003e,\n\u003ca href=\"https://github.com/Suvrat1629\"\u003eSuvrat Acharya\u003c/a\u003e,\n\u003ca href=\"https://github.com/ShreckYe\"\u003eYongshun Ye\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eUpgrade instructions\u003c/h2\u003e\n\u003cp\u003eSwitch your build to use Gradle 9.7.1 by updating your wrapper:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e./gradlew :wrapper --gradle-version=9.7.1 \u0026amp;\u0026amp; ./gradlew :wrapper\r\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eSee the Gradle \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/upgrading_version_9.html\"\u003e9.x upgrade guide\u003c/a\u003e to learn about deprecations, breaking changes and other considerations when upgrading.\u003c/p\u003e\n\u003cp\u003eFor Java, Groovy, Kotlin and Android compatibility, see the \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/compatibility.html\"\u003efull compatibility notes\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eReporting problems\u003c/h2\u003e\n\u003cp\u003eIf you find a problem with this release, please file a bug on \u003ca href=\"https://github.com/gradle/gradle/issues\"\u003eGitHub Issues\u003c/a\u003e adhering to our issue guidelines.\nIf you're not sure you're encountering a bug, please use the \u003ca href=\"https://discuss.gradle.org/c/help-discuss\"\u003eforum\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eWe hope you will build happiness with Gradle, and we look forward to your feedback via \u003ca href=\"https://twitter.com/gradle\"\u003eTwitter\u003c/a\u003e or on \u003ca href=\"https://github.com/gradle\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003e9.7.0\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.0.\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/92f0512e7f06d84621afba191f75e265363890cf\"\u003e\u003ccode\u003e92f0512\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38892\"\u003e#38892\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/820ee75a99a179bbffa41bcedc6477b685fabb9f\"\u003e\u003ccode\u003e820ee75\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/82c23f9bd2a89b4cc644e1f90a28a8668feb3dee\"\u003e\u003ccode\u003e82c23f9\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering problem in KTS (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38878\"\u003e#38878\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/ef11a7268fe8cc8d6ab849ec911aa11220180553\"\u003e\u003ccode\u003eef11a72\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering issue\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/bb0d8a974a71b1003efea41e4046e98855cd5ff8\"\u003e\u003ccode\u003ebb0d8a9\u003c/code\u003e\u003c/a\u003e Make relevant tests polyglot (run for multiple DSLs)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/336e129d7f95c03486acafc97abf59734acfed48\"\u003e\u003ccode\u003e336e129\u003c/code\u003e\u003c/a\u003e Update signing configuration (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38874\"\u003e#38874\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/4bdf0da2dad9884d089a6062a45ea7183e7d735d\"\u003e\u003ccode\u003e4bdf0da\u003c/code\u003e\u003c/a\u003e Update signing configuration\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/cd9b92c1b82856248cf1dc58b50378238bec7b52\"\u003e\u003ccode\u003ecd9b92c\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38839\"\u003e#38839\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/5f4e381964897ad8d6b99e5a7c77f26dba3259fb\"\u003e\u003ccode\u003e5f4e381\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/1e08ab551367aeb5fb48b26e72807e1d2b27c939\"\u003e\u003ccode\u003e1e08ab5\u003c/code\u003e\u003c/a\u003e Keep type-use annotations in extracted ABI classes (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38810\"\u003e#38810\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/gradle/gradle/compare/v9.4.1...v9.7.1\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `androidx.core:core-ktx` from 1.18.0 to 1.19.0\n\nUpdates `org.bouncycastle:bcprov-jdk18on` from 1.84 to 1.85.2\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.md\"\u003eorg.bouncycastle:bcprov-jdk18on's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch1\u003eBouncy Castle Crypto Package - Release Notes\u003c/h1\u003e\n\u003ch2\u003e1.0 Introduction\u003c/h2\u003e\n\u003cp\u003eThe Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. The package is organised so that it contains a light-weight API suitable for use in any environment (including the J2ME) with the additional infrastructure to conform the algorithms to the JCE framework.\u003c/p\u003e\n\u003ch2\u003e2.0 Release History\u003c/h2\u003e\n\u003cp\u003e\u003c!-- raw HTML omitted --\u003e\u003c!-- raw HTML omitted --\u003e\u003c/p\u003e\n\u003ch3\u003e2.1.1 Version\u003c/h3\u003e\n\u003cp\u003eRelease: 1.86\u003cbr /\u003e\nDate: 2026, TBD\u003c/p\u003e\n\u003ch3\u003e2.1.2 Defects Fixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) let a subkey inherit the primary key's Key Flags when its own Subkey Binding signature carried no Key Flags subpacket, which made the two capability decisions taken for one subkey disagree. OpenPGPCertificate.OpenPGPComponentKey.isSigningKey() reads the effective flags, which fell back to the primary key's direct-key or primary user ID self-signature, so a subkey bound with no flags of its own counted as signing-capable; verifyEmbeddedPrimaryKeyBinding reads the binding signature's own flags, found no signing capability there, and so skipped the embedded Primary Key Binding (cross-certification) signature that RFC 9580 sec. 5.2.1.8 and sec. 10.1.3 require of a subkey that can issue signatures. A data signature made by such a subkey was therefore attributed to the certificate and reported valid by OpenPGPSignature.OpenPGPDocumentSignature.isValid() with the cross-certification requirement never applied, where GnuPG refuses the same certificate and message as not cross-certified. An attacker holding a third party's public signing subkey - which is public material - could bind it to their own primary key with a Subkey Binding signature they are able to make, carrying no Key Flags and no embedded Primary Key Binding signature, which they cannot make without the subkey's private key, and have that party's genuine signatures verify as valid under the attacker's own identity: misattribution of a real signature rather than a forgery of a new one, since the signature still has to be one the subkey actually made. Key Flags are a statement about the key the carrying signature refers to (RFC 9580 sec. 5.2.3.29), so a subkey no longer inherits them from the certificate-wide signatures of the primary key: a Subkey Binding signature that omits the subpacket now leaves the subkey with no capabilities rather than the primary's, which makes the flags the cross-certification check consults the same flags every other decision consults. Preferences and the other subpackets a direct-key signature carries are inherited as before, and the primary key itself - whose flags legitimately come from its direct-key or user ID self-signature - is unaffected. The low-level PGPSignature / PGPPublicKeyRing API performs no binding checks by design and is unchanged.\u003c/li\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) used a version 6 key that carried no valid Direct Key signature, falling back to the primary user ID binding as it correctly does for a version 4 key. RFC 9580 sec. 5.2.3.10 requires the opposite: \u0026quot;An implementation MUST ensure that a valid Direct Key signature is present before using a version 6 key. This prevents certain attacks where an adversary strips a self-signature specifying a Key Expiration Time or certain preferences.\u0026quot; The certificate grammar says the same structurally, the Direct Key signature being mandatory in the version 6 structure of sec. 10.1.1 and optional in the version 4 one of sec. 10.1.3. Because a version 6 certificate carries its key expiration, features and algorithm preferences on the Direct Key signature - the convention the RFC recommends and the one OpenPGPKeyGenerator follows, its user ID certification carrying no expiration at all - removing that single signature packet from a published certificate silently dropped the expiration along with the preferences and features: OpenPGPCertificate.getSignatureChainFor fell back to the user ID binding, the primary key was still reported bound, and getEncryptionKeys() and getSigningKeys() went on returning the subkeys of a key whose owner had set it to expire. The primary key fingerprint is unchanged by the removal, so a relying party pinning the key by fingerprint still treats it as the same key, and no private key or hash collision is involved; the natural moment for the strip is the key refresh that RFC 9580 names as the reason to refetch a key at all - to learn about changes in expiration, features, preferences and revocation - which is exactly the update it defeats. This is a downgrade rather than a forgery, nothing being attributed to a key that did not authorise it, and the concerning direction is encryption, to a key meant to have been retired. OpenPGPCertificate.isBoundBy now requires a valid Direct Key self-signature on a version 6 primary key before any component of the certificate - the primary key, its subkeys or its identities - is treated as bound, so a version 6 certificate stripped of it offers no keys at all rather than an unexpiring set. Version 4 certificates are unaffected: there the key expiration legitimately lives on the user ID self-signature and the fallback is correct, so it stays. The revocation-only version 6 certificate of sec. 10.1.2, which legitimately carries no Direct Key signature, is unaffected as well - its key was already refused as revoked, and reading the revocation does not go through the binding check.\u003c/li\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) ignored the OpenPGPPolicy a caller had configured when it verified the signatures on an inline message. OpenPGPMessageInputStream took the policy it sanitizes each document signature against from the implementation's own default rather than from the processor the signature is being verified by, so a policy supplied through the documented OpenPGPApi(implementation, policy) / OpenPGPMessageProcessor(implementation, policy) constructor - which is how OpenPGPApi.decryptAndOrVerifyMessage() plumbs the configured policy through - had no bearing on whether a signature was accepted, although the same processor already applied it to the decompressed-size bound. A caller who hardened the policy beyond the default therefore had a signature that policy rejects handed back from getResult().getSignatures() with isTestedCorrect() true, while OpenPGPSignature.isValid(policy) on that same signature reported the rejection. Both verify paths, the one-pass and the prefixed-signature one, now read the configured policy; the detached-signature processor already did.\u003c/li\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) went on offering the subkeys of a certificate whose primary key had expired. OpenPGPCertificate's binding check evaluated only a subkey's own Subkey Binding signature, so a primary key whose Key Expiration Time (RFC 9580 sec. 5.2.3.13) had passed still handed out a longer-lived encryption or signing subkey from getEncryptionKeys() / getSigningKeys(), leaving the certificate contradicting itself - getExpirationTime() in the past and getPrimaryKey().isBoundAt() false, while isBoundAt() on the subkey answered true. An expired primary key can no longer certify, so the subkeys it bound are not usable with it either, which is how GnuPG and Sequoia both treat such a certificate; primary key revocation already propagated, since a revocation appears in the subkey's signature chain, but expiration is not carried there. Relatedly, a subkey no longer inherits the primary key's validity period at all - sec. 5.2.3.13 counts that period from the creation time of the key the carrying self-signature is made on, so re-basing the primary key's period on a subkey created later than it gave that subkey an expiration date later than the primary key's own.\u003c/li\u003e\n\u003cli\u003eOpenPGPSignature.OpenPGPDocumentSignature.isValidAt(Date) in the high-level OpenPGP API reported a data signature as valid at an evaluation time past the signature's own Signature Expiration Time (RFC 9580 sec. 5.2.3.18, hashed subpacket type 3). The method checked that the signature was correct and that the issuing key was bound and signing-capable at that date, but never consulted the signature's own expiration, so it disagreed with isEffectiveAt(Date) on the same object and with its own javadoc, which names being effective as one of the three criteria of a valid signature. Signature expiration is a separate axis from the issuing key's Key Expiration Time that the binding checks already cover, and GnuPG, GPGME, git and Sequoia all keep the two apart and treat a signature past its expiration as not good. isValid() and isValid(policy) evaluate at the signature's creation time, where a signature is always inside its own window, and are unchanged.\u003c/li\u003e\n\u003cli\u003eThe lightweight LMSSigner and HSSSigner refused a key wrapped in ParametersWithRandom, which is how BcContentSignerBuilder passes a key whenever setSecureRandom() has been called - so BcHssLmsContentSignerBuilder built a working signer until a random was set and then failed with \u0026quot;Incorrect Key Parameters\u0026quot;, and the two signers themselves raised ClassCastException on the same input. All three now unwrap it, as the promoted ML-DSA and SLH-DSA signers already did. The random is accepted and not used: LMS derives its message randomiser C from the key's seed and the one-time index, so it is deterministic and cannot repeat while q does not. Note SP 800-208 sec. 6.1 asks for C to come from an approved random bit generator, which this implementation does not do; that is unchanged here, and a supplied random is now ignored rather than refused.\u003c/li\u003e\n\u003cli\u003eLMS signature verification did not apply two of the checks RFC 8554 sec. 5.4.2 requires before a signature is processed. Step 2g refuses a signature whose LMS typecode is not the one from the public key, and without it the path computation took its height and tree digest from the parameter set the signature named rather than the key's, so a signature claiming a height-25 parameter set drove a 25-level computation against a height-5 key. Step 2i refuses a leaf number q outside the tree, and without it an out-of-range q flowed into the node arithmetic and was left for the candidate-root comparison to catch. Neither was a forgery - the domain separation between D_LEAF and D_INTR and the final comparison saw to that - but both are attacker-chosen work the specification says to refuse up front. Both are now checked, and a signature failing either is still reported as not verifying rather than thrown out of Signature.verify(). The catch around the signature decode in LMSSigner and HSSSigner has also been narrowed to the decode itself, as the corresponding SPI was corrected to do for github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2408\"\u003e#2408\u003c/a\u003e: past the parse the engine reports an inconsistent signature by returning false rather than by throwing, so the wider catch caught nothing while standing ready to turn a future internal error into a quiet false.\u003c/li\u003e\n\u003cli\u003eThe LMS and HSS key parameter classes now apply at construction the checks their decoders apply, so a key built directly cannot be one the decoder would refuse. LMSPrivateKeyParameters accepted an identifier of any length although the decoder reads exactly 16 bytes - such a key encoded but could not be read back - and left q, maxQ and the seed length unchecked; the seed is now required to be at least m bytes at decode as well, where a one-byte seed had been decoding silently and then deriving every one-time key from it. HSSPrivateKeyParameters checked neither its level count nor that it had been given a component key per level and a chaining signature per level below the root, and then indexed both lists, so a mismatch surfaced as IndexOutOfBoundsException - or, where a level happened to match, as a null chaining signature that only failed at signing time; the level is now checked after the reset that fills it in, since a null is legitimate on the way in. LMSPrivateKeyParameters.getInstance(byte[], byte[]) adopted the public key supplied beside the private one without comparing them, so a mismatched public key was simply reported by getPublicKey(); it now cross-checks the identifier, both parameter sets and, where the tree cache already holds it, the root, as the HSS entry point does. The decoders also now report a bad version or seed length as IOException rather than IllegalStateException, so a caller can catch one type for a malformed key, and the package-private LM-OTS public key decoder no longer declares throws Exception or dereferences an unrecognised typecode. The deprecated org.bouncycastle.pqc.crypto.lms copies carry the decoder corrections.\u003c/li\u003e\n\u003cli\u003eIn the LMS JCE layer, LMSKeyGenParameterSpec.fromNames knew all twenty LMS parameter-set names but only four of the sixteen LM-OTS ones, so none of the SP 800-208 n24 or SHAKE sets could be named; all sixteen are now present. KeyPairGenerator.initialize(int, SecureRandom) reports InvalidParameterException, which is what the JCA specifies and which extends the IllegalArgumentException it raised before, so existing catches still match. BCLMSPrivateKey.getIndex now takes the exhaustion check and the index read under the key's own monitor rather than as two separate calls, and two unused fields have gone from LMSSignatureSpi. Note that the LMS Signature claims its one-time key at the first update() rather than at sign(), so a Signature that is initialised and updated and then abandoned spends an index without producing a signature - the safe direction for a one-time scheme, and now documented on the SPI.\u003c/li\u003e\n\u003cli\u003eEvery other key pair generator that refuses a key size did the same thing the LMS one did above. KeyPairGenerator.initialize(int, SecureRandom) is documented to raise InvalidParameterException when the key size is not one the generator supports, and thirty of them raised a bare IllegalArgumentException instead, so a caller following the JCA and catching the documented type saw an exception escaping rather than a refusal. The ML-DSA, ML-KEM, SLH-DSA, Classic McEliece, FrodoKEM, NTRU and composite signature and KEM generators in the BC provider, and every generator in BCPQC, now raise InvalidParameterException - NewHope included, where the value is a key size it will not take rather than a mode of initialisation it does not offer. InvalidParameterException extends IllegalArgumentException, so callers written against the old behaviour go on catching it unchanged. The two RSA generators are corrected as well, and differently: theirs is a key size below a floor rather than a mode of initialisation they do not offer, and the refusal is raised by the lightweight RSAKeyGenerationParameters, which cannot name a java.security exception at all, so the RSA KeyPairGeneratorSpi now translates it - keeping the message verbatim and the original exception as the cause, through a new SecurityExceptions.invalidParameterException factory, since InvalidParameterException has no constructor that takes one. Of the 304 KeyPairGenerator services the two providers register, 299 now refuse a nonsense key size the way the JCA defines it and five accept it as a strength they can work with, with none left raising a bare IllegalArgumentException; that is asserted as a sweep over both providers rather than per algorithm, so a generator added later is covered without the test being touched. The jdk1.3 provider overlays of the four generators that have one carry the same change, and the jdk1.3 SecurityExceptions overlay gains the new factory along with the invalidAlgorithmParameterException one it had been missing.\u003c/li\u003e\n\u003cli\u003eKeyPairGenerator.initialize(AlgorithmParameterSpec, SecureRandom) had the same shape of problem as the int overload above, and only 44 of the 304 services the two providers register reported an unusable spec as the InvalidAlgorithmParameterException that method declares. The twenty-three PQC generators that resolve a parameter set by name - cmce, frodokem, mldsa, mlkem, slhdsa, aimer, bike, faest, falcon, haetae, hqc, mayo, mqom, ntru, ntruplus, both ntruprime variants, qruov, saber, sdith, smaugt, snova and sqisign, 230 services between them - case-folded the name they got back from the spec without checking it, so a spec with no getName() method, and a null spec, produced a NullPointerException from inside the fold; their own \u0026quot;is this name one I know\u0026quot; branch, which does report the declared exception, was unreachable. The two composite generators, whose parameter set is fixed by the algorithm name so that null is the only spec they accept, refused every other one with IllegalArgumentException. RSA answered correctly for a spec of the wrong type but not for one of the right type carrying values its lightweight parameters will not take - an even public exponent, or a key size below the floor - which is now translated the same way the int overload's is. All 304 services now report the declared exception, with the composites still taking the null spec that is right for them; note that InvalidAlgorithmParameterException is a checked exception and not an IllegalArgumentException, so a caller that was catching what these threw before has to catch the declared type instead.\u003c/li\u003e\n\u003cli\u003eAn HSS private key claimed the two records of its position under two different monitors. The top-level index and the bottom component key's one-time index q are independent records of the same position - the decoder requires them to agree, see the entry below - but generateLMSContext incremented the index under the HSS key's own monitor, released it, and only then claimed q under the component key's. A getEncoded() issued in between saw the index advanced and q not, and produced an encoding this implementation's own decoder rejects; and two threads meeting at a bottom-tree boundary could both pass the exhaustion test, take consecutive top-level indices and claim the same q, after which one of them was refused with \u0026quot;ots private key exhausted\u0026quot; by a key still reporting usages remaining, a top-level index had been spent with no signature made, and the two records stayed one apart for the rest of the key's life in that process - so it could no longer be encoded, cloned or sharded, and getIndex() and getUsagesRemaining() misreported by one. No one-time key was reused: the component key's claim is itself atomic, and the divergence runs index ahead of leaves, so the effect was on the key's usability rather than on the signatures it had made. Both records are now claimed under the one monitor, and the component key is claimed before the index is incremented so that an exhausted one leaves both untouched. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the same correction.\u003c/li\u003e\n\u003cli\u003eTimeStampToken parsed the attacker-controlled TSTInfo content of a time-stamp token (org.bouncycastle.tsp.TimeStampToken, reached from TimeStampResponse(byte[]) and (InputStream)) inside a try that caught only CMSException, so a well-formed RFC 3161 TimeStampResp whose embedded token carried a malformed TSTInfo - a SEQUENCE with fewer elements than the five mandatory fields, a non-SEQUENCE, truncated DER, or an unknown context tag - let an IllegalArgumentException or a NoSuchElementException escape the constructor's declared throws TSPException, IOException contract. A token signed by no signers or by more than one raised a bare IllegalArgumentException from the same constructor, before that try, for the same reason. Both are now reported as TSPException, matching the package-private TimeStampResponse(DLSequence) constructor and the existing getSignedAttributes guard in the same method; the signer-count refusal is a TSPValidationException, as the neighbouring check on the content type already was. Related, and the cause of the NoSuchElementException: asn1.tsp.TSTInfo read its five mandatory fields off the sequence with no bound on how many elements were actually there, so a short SEQUENCE left the enumeration to run out rather than being refused, and an oversize one was accepted with its extra elements absorbed into the optional slots. Decode now requires the five to ten elements RFC 3161 sec. 2.4.2 gives the type, which is what the sibling Accuracy and ArchiveTimeStamp decoders already did, so the failure is the IllegalArgumentException that getInstance is expected to raise (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2415\"\u003e#2415\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eNeither the HSS nor the XMSS^MT private key decoder checked its declared index against the traversal state stored beside it, although the two are independent records of the same position in the key and so can be compared. For HSS the records are the top-level index and the component keys' one-time indices q; for XMSS^MT they are the global index and the per-layer BDS states. A stored key whose index had been rolled back while its state stayed advanced - a partial write, a restore from backup, a buggy storage layer - was therefore accepted, and it then signed a second message under a one-time key the key had already used, producing a signature that verified, so nothing anywhere surfaced the reuse. RFC 8554 sec. 1 and RFC 8391 sec. 1.1 both require each one-time key to be used exactly once, and this is the failure those requirements exist to prevent; the single-tree XMSS decoder has tied its BDS state to its index since that state was first validated, and this brings the two multi-tree schemes into line. HSS decode now requires the declared index to equal the position the component q values imply - a level above the last contributes (q - 1) leaves of the levels beneath it, since its q has already advanced past the subtree it signed - and XMSS^MT decode now requires each present layer's BDS index to equal the leaf index that layer derives from the global index, allowing the one position where a layer has moved into a new subtree and its state legitimately still carries the previous subtree's final index. A layer with no state yet is unaffected, since those are built lazily at signing time. Related, and the same shape of omission: an XMSS or XMSS^MT private key encoding carries the tree root twice - the key's own root field and the root node of the BDS state stored beside it, which for XMSS^MT is the top layer's - and the two were never compared either. A corrupted root was accepted and then poisoned every signature the key made, because the root is hashed into the message digest: the signature did not verify and nothing indicated why. Decode now requires the two copies to agree. The BDS node values themselves are not checkable the way the LMS tree cache above is - a BDS authentication path, stack, retain or keep node does not have its children stored alongside it, so recomputing one means building a subtree, which is the work the state exists to avoid. Both checks are integer comparisons over the levels of the key, too small to measure against the surrounding decode, and both were verified not to reject any legitimate key by walking every index a key can reach: the full key space of the two-level HSS and the h=4/d=2, h=6/d=2, h=6/d=3, h=9/d=3 and h=8/d=4 XMSS^MT parameter sets, plus a three-level HSS key across a subtree boundary and an HSS shard. Since those node values cannot be recomputed, the encoded state now carries a checksum over itself instead, with the owning key's public seed hashed in front of it. Any corruption of the stored state is refused at decode rather than being loaded and then producing signatures that silently do not verify, and because the public seed is bound in, a state transplanted between two keys of the same parameter set is refused too, even though it is internally consistent and arrives with its own matching root. The public seed is bound rather than the secret seed or the PRF key deliberately: the state's own root and index are inside the encoding and so are already covered, hashing secret material would make the stored checksum a commitment to it for no gain in detection, and the PRF key does not influence the state at all. \u003cstrong\u003eThis is an error-detecting code and not integrity protection\u003c/strong\u003e - anyone able to rewrite the stored key recomputes it, so it establishes that the state is unchanged since it was written, never that it was correct when written, and the allocation bounds on the encoding remain the guard against a crafted one. It costs one SHA-256 over the state, measured at 5 to 8 microseconds each way for the h=10 and h=16 parameter sets, and 32 bytes of encoding. The state encoding was added earlier in this same cycle and has not been released, so the checksum is simply part of it rather than a new version: a state written by a 1.86 beta is rejected, which is recovered from by re-exporting the key. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the HSS check as well (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2414\"\u003e#2414\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eIn the XMSS and XMSS^MT JCE layer, KeyPairGenerator.initialize(int, SecureRandom) reports InvalidParameterException, which is what the JCA specifies and which extends the IllegalArgumentException it raised before, so existing catches still match. This is the XMSS counterpart of the same correction made to LMSKeyPairGeneratorSpi.\u003c/li\u003e\n\u003cli\u003eBCXMSSPrivateKey.getIndex and BCXMSSMTPrivateKey.getIndex took the exhaustion check and the index read as two separate calls on the key parameters. Each is atomic on its own, but the pair is not: a signature taken by another thread between them spends the last usage, so the check passes and the read that follows returns maxIndex + 1 - the one index past the end of the key, which is what the check exists to refuse, handed back as though it were the next one-time key to be used. Both reads are now taken under the key parameters' own monitor, the monitor their mutators hold, as BCLMSPrivateKey.getIndex was corrected to do. No one-time key is reused by this: the effect is on what the key reports about itself, not on the signatures it makes.\u003c/li\u003e\n\u003cli\u003eThe S/MIME example smoke test in the misc module (org.bouncycastle.mail.smime.examples.test.AllTests) drove SendSignedAndEncryptedMail against smtp.gmail.com, and that example finishes with Transport.send() under JavaMail's default settings, which have no connect timeout. Where outbound port 25 is refused the failure was swallowed and the test passed; where it is silently dropped, as on many home networks, the connect blocked and ./gradlew build hung in :misc:test indefinitely with \u0026quot;0 tests completed\u0026quot;. The test now delivers to an SMTP stub on a loopback port, with connect / read / write timeouts as a backstop, and asserts the message arrived (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2407\"\u003e#2407\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation took the traditional component public key bytes it feeds the KEM combiner from the recipient key's own encoding, while decapsulation recomputes the point from the private key and so always produced an uncompressed one. Section 4 of draft-ietf-lamps-pq-composite-kem requires an EC component to be carried as an uncompressed point, but a component key that encodes itself compressed - a BC EC key whose point format has been set through org.bouncycastle.jce.interfaces.ECPointEncoder, or a key from a provider that preserves a compressed encoding - was passed through as it came. Both sides then combined a different tradPK and derived different shared secrets, with no error reported on either: encapsulation and decapsulation both succeeded and the recipient simply could not decrypt. The EC component is now normalised to an uncompressed point wherever the engine serialises one, which covers the ephemeral key that forms the ciphertext as well. X25519 and X448 components have a single encoding and were unaffected, as were EC keys left in their default (uncompressed) format, whose shared secrets are unchanged. CompositePublicKey.getEncoded() took its component bytes the same way, so such a key also encoded to a composite key other implementations reject and whose bytes changed across an encode / decode / encode round trip - 1238 bytes rather than 1270 for MLKEM768-ECDH-P256, and for the composite ML-DSA keys sharing that method, 2006 rather than 2038 for MLDSA65-ECDSA-P256. It now normalises the component the same way. This is a write-side change only: a composite key carrying a compressed EC component is still decoded, since the component key factories accept either form, and continues to verify signatures as before - it simply re-encodes in the normalised form. The shared normalisation is org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil.getUncompressedSubjectPublicKeyBytes.\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation threw a NullPointerException, wrapped in an IllegalStateException out of KeyGenerator.generateKey(), when the SecureRandom it was given was null - which javax.crypto.KEM.newEncapsulator() documents as a request for the provider's default, and which KeyGenerator.init(spec, null) passes straight through. The three RSA-OAEP composites draw the traditional shared secret from that random directly, so they were the ones affected; the ECDH and X25519 / X448 composites escaped only because their component KeyPairGenerators default a random of their own. CompositeMLKEMEngine now defaults one through CryptoServicesRegistrar.getSecureRandom() on first use, as the composite KEM Cipher's wrap path already did, and as the KEM generators corrected earlier in this cycle now do. Related, the engine now also clears the ML-KEM component's shared secret alongside the traditional one on both the encapsulate and decapsulate paths - the copy handed back by getEncoded() was left in the heap - as section 3.5 of draft-ietf-lamps-pq-composite-kem requires.\u003c/li\u003e\n\u003cli\u003eCompositePublicKey.getAlgorithm() and CompositePrivateKey.getAlgorithm() returned null for all twelve Composite ML-KEM (draft-ietf-lamps-pq-composite-kem) parameter sets. Both classes resolved the name through the composite signature index only, which holds the composite ML-DSA OIDs, so a composite KEM key pair - generated, parsed from a certificate, or read from PKCS#8 - reported no algorithm at all, and the standard JCA idiom of reconstructing a key with KeyFactory.getInstance(key.getAlgorithm()) raised a NullPointerException. The lookup now falls back to the composite KEM index, so the name returned is the one the provider registers the algorithm under (e.g. MLKEM768-X25519-SHA3-256), matching the composite ML-DSA behaviour. The same single-index assumption made the CompositePublicKey(SubjectPublicKeyInfo) and CompositePrivateKey(PrivateKeyInfo) constructors reject a composite KEM key with \u0026quot;unable to create CompositePublicKey from SubjectPublicKeyInfo\u0026quot;; they now dispatch to the composite KEM key factory for those OIDs. Keys obtained through KeyFactory or through BouncyCastleProvider.getPublicKey / getPrivateKey were unaffected and are unchanged (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2404\"\u003e#2404\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe org.bouncycastle.jcajce.spec.KEMKDFSpec constructor stored a null otherInfo as given, so getOtherInfo() returned null, and three of the KDF branches KdfUtil.makeKeyBytes dispatches to - KMAC-128, KMAC-256 and SHAKE-256 - read the otherInfo length without a guard and threw NullPointerException out of the KEM operation, where the KDF2, KDF3 and HKDF branches tolerate a null through KDFParameters / HKDFParameters. The Builder of every spec in the package already mapped null to empty, so no provider path reached it, but the constructor is protected on a public class and KdfUtil is documented for callers building their own KEM integration; the deprecated KEMParameterSpec passes a null itself and escaped only because it also pins the KDF to null. The constructor now stores empty for a null, so getOtherInfo() never returns null, and a null and an explicitly empty otherInfo derive the same key.\u003c/li\u003e\n\u003cli\u003eQR-UOV signature verification accepted a signature encoding that was not canonical, so the encoding of a signature was not unique even after the trailing-byte fix of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e. Each F_q element of the signature is stored in ceil(log2 q) bits, one more bit pattern than the field has elements: q itself is representable and is arithmetically congruent to zero, so an element written as q verified exactly as the same element written as zero would, and the bits padding the last element out to the byte boundary were never read at all. Every zero element of a signature therefore carried a second encoding, and for the q = 7 parameter sets roughly one element in seven is zero - a single qruov_5_q7_L10 signature measured 256 spare bits, so on the order of 2^256 distinct byte strings verified for the one message and key. Verification now rejects any element outside [0, q) and any set padding bit; a signature produced by this or by the reference implementation is unaffected, as the KAT vectors of every parameter set confirm. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSNOVA signature verification ignored four bits inside the signature for any parameter set whose solution is an odd number of GF(16) nibbles - the SNOVA_24_5_5, SNOVA_25_8_3, SNOVA_29_6_5 and SNOVA_66_15_3 families, sixteen of the forty-four parameter sets. The last byte of the encoded solution carries a single nibble and the signer leaves the top four bits zero, but the decoder did not read them, so sixteen distinct byte strings verified for one signature. This is the same non-unique encoding github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e closed for bytes following the signature, applied inside it; the verifier now requires those bits to be zero. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSnovaPrivateKeyParameters did not validate the length of the private key encoding handed to it - the only one of the five schemes of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e that did not - and SnovaParameters.getPrivateKeyLength() reported the expanded (\u0026quot;ESK\u0026quot;) length even for a parameter set whose private key is the seed pair. A private key encoding reaches this constructor straight from a PKCS#8 blob, so a wrong length went undetected: a seed-form key with extra bytes appended was accepted and signed under a different derived key, and a short expanded-form key sized the signer's decode buffer negatively, throwing NegativeArraySizeException out of generateSignature() rather than being reported at construction. Related, the signing retry loop could not terminate: the vinegar values are derived from a single-byte counter, so only 256 distinct linear systems can be tried, and an expanded-form private key that is not a real central map is singular for all of them - generateSignature() then span forever rather than failing. The length is now checked at construction, getPrivateKeyLength() reports the length that parameter set's private key actually has, and the retry loop gives up after its 256 attempts as MAYO's does.\u003c/li\u003e\n\u003cli\u003eMayoSigner and MayoKeyPairGenerator did not clear several buffers holding secret key material that the MAYO reference implementation explicitly clears. Signing left the secret oil space O, the expanded L = (P1 + P1^t) * O + P2, and the M / VPV / Ox intermediates of the central map in place, having gone to the trouble of clearing eleven other buffers; key generation left the expanded seed, whose tail is the encoded oil space, and the P1 * O + P2 half of P; and the row-echelon step left the packed echelon form of the secret linear system and its pivot rows. Separately, if all 256 attempts at solving for the signature had given a rank-deficient system, signing emitted a signature built from the failed attempt's state instead of reporting the failure the reference returns, and AIMerSigner.generateSignature returned an empty array on failure, which a caller would hand on as though it were a signature. Both now throw.\u003c/li\u003e\n\u003cli\u003eFive PQC signature schemes - MAYO, SNOVA, QR-UOV, SQIsign and AIMer - returned the NIST crypto_sign \u0026quot;sm\u0026quot; signed-message envelope from generateSignature() rather than the signature. That envelope is an artefact of the reference KAT harness, which records the message alongside the signature so a vector file can be self-contained; it is not part of any of the five specifications, and no other BC signer emits it (Falcon's KAT test rebuilds the equivalent envelope in the test, which is where it belongs). Two consequences followed, both reaching the JCA Signature services of every parameter set of the five schemes in BouncyCastlePQCProvider. First, since the message was appended to the signature, verification had to skip whatever followed the signature proper, and it did so by checking only that the buffer was long enough - so any number of trailing bytes could be added to a valid signature, or the appended message replaced with unrelated data, and it still verified. A signature encoding was therefore not unique: anyone holding one valid signature could produce unlimited distinct byte strings that all verified for the same message and key, which breaks any use that treats the signature bytes as an identifier, deduplicates on them, or records them as evidence. Second, the envelope propagated into everything built on the operator layer: because ContentSigner hands the signature straight into the structure being signed, every X.509 certificate, CRL, CMS SignedData and TLS CertificateVerify BC produced with one of these algorithms carried a verbatim copy of the signed data inside its own signature field - a self-signed MAYO-1 certificate came to 3567 bytes where the same certificate is now 2020 - which no other implementation can parse as a signature, and which in a detached CMS signature meant the \u0026quot;detached\u0026quot; signature carried the content. generateSignature() now returns the bare signature, and verifySignature() requires exactly the parameter set's signature length, so appended or truncated data is rejected rather than ignored. \u003cstrong\u003eThis is a behavioural change for signatures produced by an earlier release\u003c/strong\u003e - MAYO and SNOVA from 1.84, QR-UOV, SQIsign and AIMer from 1.85 - which are no longer accepted in the envelope form they were emitted in; the signature bytes themselves are unchanged, so a stored value can be recovered by taking the leading signature-length bytes, or for AIMer, whose envelope was message || signature rather than signature || message, the trailing ones. The KAT tests now rebuild the envelope before comparing against the vector files, which continue to record it. Note that AIMer's verification had already been made length-exact during this cycle (see the entry below relating to github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2401\"\u003e#2401\u003c/a\u003e), so of the five only its envelope remained (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe MLS implementation did not bind an X.509 credential to the LeafNode's signature_key. LeafNode.verify() checked a leaf's signature against the signature_key declared in the leaf itself, while the X.509 credential's certificate chain was stored but never parsed or checked, so the certificate's public key was never required to match signature_key (RFC 9420 sec. 5.3). A leaf could therefore carry one party's certificate while being signed by an unrelated key and still be accepted under that party's identity through KeyPackage.verify() and the Group leaf-validation path. LeafNode.verify() now requires the end-entity certificate's subject public key, in the cipher suite's signature encoding, to equal signature_key for an X.509 credential, and rejects the leaf otherwise - including an empty chain or a certificate whose key type does not match the cipher suite; certificate-chain and identity validation to a trust anchor remain the application's responsibility per RFC 9420 sec. 5.3.1. A public org.bouncycastle.mls.codec.Certificate(byte[]) constructor and a Credential.getCertificates() accessor are added so callers can build and inspect X.509 credentials. Basic credentials are unaffected.\u003c/li\u003e\n\u003cli\u003eThe SecureRandom supplied to org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder.setSecureRandom() did not drive the content IV / nonce for any algorithm other than RC2. EnvelopedDataHelper.generateParameters passed the caller's SecureRandom to the AlgorithmParameterGenerator only in the RC2_CBC branch; every other content-encryption algorithm - AES-CBC, AES-GCM, AES-CCM, Camellia, ARIA, SEED and the rest - reached pGen.generateParameters() on an uninitialised generator, so the IV / nonce was drawn from a default SecureRandom and setSecureRandom() was silently ignored (the builder's javadoc states that random is used for IV/nonce generation). The generator is now initialised with the supplied random on the general path as well, so a caller who provides a specific randomness source - for a controlled or FIPS-approved DRBG, say - has it honoured for the content IV / nonce. The session-key generation path was unaffected and already used the supplied random. Because the content IV / nonce now comes from the supplied SecureRandom, the org.bouncycastle.crypto.util JournalingSecureRandom / JournaledAlgorithm reproducible-encryption support records it in the transcript: a resumed session reproduces the IV / nonce by regenerating it from the replayed randomness - build the resuming encryptor from the content-algorithm OID - rather than by reusing the AlgorithmIdentifier captured from the first encryption, which no longer keeps the transcript aligned.\u003c/li\u003e\n\u003cli\u003eThe NTRU LPRime, NTRU+ and SMAUG-T KEM generators threw a NullPointerException when constructed with a null SecureRandom, where every other KEM generator - including NTRU LPRime's own SNTRU Prime counterpart in the same package - defaults one through CryptoServicesRegistrar.getSecureRandom(). This is reachable from the lightweight API directly, and from javax.crypto.KEM, whose newEncapsulator() documents a null random as a request for the provider's default.\u003c/li\u003e\n\u003cli\u003eFrodoKEMEngine kept a single SHAKE instance in a field, so an engine reached concurrently produced wrong results. It is reached that way through org.bouncycastle.crypto.kems.FrodoKEMExtractor, which holds one engine for its lifetime: two threads extracting through one extractor interleaved the digest's absorb and squeeze phases, yielding shared secrets that silently did not match the sender's, or an IllegalStateException of \u0026quot;attempt to absorb while squeezing\u0026quot; from inside extractSecret. The digest is now built per call, as CMCEEngine's already was, which makes an extractor safe to share. Encapsulation was unaffected, since FrodoKEMGenerator builds an engine per call. Results for any single-threaded use are unchanged - the reference KAT vectors are byte-identical.\u003c/li\u003e\n\u003cli\u003eThe BCJSSE provider carried the TLS 1.2 coupling between the supported_groups extension and ECDSA over into TLS 1.3: an ECDSA signature scheme was treated as usable - offered in the signature_algorithms and signature_algorithms_cert extensions, and eligible when selecting the local credentials - only while the corresponding curve was among the named groups enabled for key exchange, both per context (a group unavailable for key agreement disabled the scheme outright) and per connection (the curve had to be in the supported_groups list about to be sent). RFC 8446 sec. 4.2.7 scopes supported_groups to key exchange only, with signature algorithms negotiated independently (sec. 4.2.3), so this incorrect restriction in TLS 1.3 has been removed. Ed25519, Ed448 and the RSA schemes were unaffected (as well as typical deployments using a default configuration for named groups).\u003c/li\u003e\n\u003cli\u003eThe bcmail module descriptor did not declare its javax.mail/javax.activation dependences, so a modular (module-path) consumer of the jar hit IllegalAccessError/module-resolution failures when the S/MIME classes touched the mail API. The descriptor now requires them optionally (requires static) under all four module names those libraries are known by - the automatic names mail and activation carried by the javax.mail:mail / javax.activation:activation artifacts, and the explicit names java.mail and java.activation carried by the newer com.sun.mail / com.sun.activation ones - a hard requires on any one name would break users of the others (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2389\"\u003e#2389\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFour type-coercion helpers in the OER / IEEE 1609.2 (ITS) decoder tested the wrong type in the identity fast path that lets a getInstance() factory return an argument that is already of the target type. org.bouncycastle.oer.its.ieee1609dot2.basetypes.UINT32.getInstance and org.bouncycastle.oer.its.etsi102941.basetypes.Version.getInstance guarded on UINT8 - a sibling of UINT32 under UintBase, and unrelated to Version - so passing a UINT8 threw ClassCastException, while passing an actual UINT32 or Version missed the fast path and fell through to ASN1Integer.getInstance, which rejects them: neither factory accepted its own type. org.bouncycastle.oer.its.etsi103097.EtsiTs103097DataEncryptedUnicast.getInstance guarded on its sibling EtsiTs103097DataEncrypted and then cast to the unicast type, so an EtsiTs103097DataEncrypted threw ClassCastException. org.bouncycastle.oer.OEROptional.getObject(Class) called value.getClass().isInstance(type) with the arguments transposed, which is always false because the argument is a java.lang.Class, so the cast path was dead and every optional field was resolved reflectively, failing with IllegalStateException for a target type with no static getInstance. Each guard now names the type it returns, matching the sibling UINT8 / UINT16 / UINT64 and EtsiTs103097DataEncrypted factories (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2373\"\u003e#2373\u003c/a\u003e).\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003eSee full diff in \u003ca href=\"https://github.com/bcgit/bc-java/commits\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003ecommonmark-java 0.29.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e[0.29.0] - 2026-06-20\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/42b4fb7adfe288ef13e9e27ab20aff7e91b0ab9d\"\u003e\u003ccode\u003e42b4fb7\u003c/code\u003e\u003c/a\u003e Prepare CHANGELOG for version 0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/b76e09d7a8362abb5f04e1d6b91dbd6da279a6fc\"\u003e\u003ccode\u003eb76e09d\u003c/code\u003e\u003c/a\u003e Limit how deep inline nodes may nest by default (100)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/49f65cb5cbec93cff713179990307145198e7061\"\u003e\u003ccode\u003e49f65cb\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing deeply nested emphasis\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/610f84b83e68c381e8f784ae4d044c80e1948b67\"\u003e\u003ccode\u003e610f84b\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological autolink email addresses\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/9f1d73897a56cbd74c39347af351a473e70297e1\"\u003e\u003ccode\u003e9f1d738\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological HTML block attributes\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/e13297e849995fdd582a85841067bff1d9c35ee5\"\u003e\u003ccode\u003ee13297e\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing pathological backticks\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-j...\n\n_Description has been truncated_","html_url":"https://github.com/SevenAILab/geo-demo/pull/16","url":"https://dependabot.ecosyste.ms/api/v1/hosts/GitHub/repositories/SevenAILab%2Fgeo-demo/issues/16","packages_url":"https://dependabot.ecosyste.ms/api/v1/issues/16/packages"}},{"old_version":"5.4.0","new_version":"5.5.0","update_type":"minor","path":null,"pr_created_at":"2026-09-10T05:53:15.000Z","version_change":"5.4.0 → 5.5.0","issue":{"uuid":"5408368480","node_id":"PR_kwDOTa7xfM8AAAABC8URIQ","number":23,"state":"open","title":"Bump the android-deps group across 1 directory with 21 updates","user":"dependabot[bot]","labels":["dependencies","java"],"assignees":[],"locked":false,"comments_count":1,"pull_request":true,"closed_at":null,"author_association":null,"state_reason":null,"created_at":"2026-09-10T05:53:15.000Z","updated_at":"2026-09-10T06:09:40.000Z","time_to_close":null,"merged_at":null,"merged_by":null,"closed_by":null,"dependency_metadata":{"prefix":"Bump","group_name":"android-deps","update_count":21,"packages":[{"name":"gradle-wrapper","old_version":"9.6.1","new_version":"9.7.1","repository_url":"https://github.com/gradle/gradle"},{"name":"androidx.appcompat:appcompat","old_version":"1.7.1","new_version":"1.8.0"},{"name":"org.bouncycastle:bcprov-jdk18on","old_version":"1.85","new_version":"1.85.2","repository_url":"https://github.com/bcgit/bc-java"},{"name":"org.commonmark:commonmark","old_version":"0.29.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-autolink","old_version":"0.29.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-strikethrough","old_version":"0.29.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-tables","old_version":"0.29.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-task-list-items","old_version":"0.29.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"io.coil-kt.coil3:coil-compose","old_version":"3.5.0","new_version":"3.6.2","repository_url":"https://github.com/coil-kt/coil"},{"name":"io.coil-kt.coil3:coil-svg","old_version":"3.5.0","new_version":"3.6.2","repository_url":"https://github.com/coil-kt/coil"},{"name":"org.junit.vintage:junit-vintage-engine","old_version":"6.1.2","new_version":"6.1.3","repository_url":"https://github.com/junit-team/junit-framework"},{"name":"io.kotest:kotest-assertions-core-jvm","old_version":"6.2.2","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"io.kotest:kotest-runner-junit5-jvm","old_version":"6.2.2","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"com.squareup.okhttp3:mockwebserver","old_version":"5.4.0","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.squareup.okhttp3:okhttp","old_version":"5.4.0","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.android.application","old_version":"9.3.0","new_version":"9.4.0"},{"name":"com.android.library","old_version":"9.3.0","new_version":"9.4.0"},{"name":"com.android.test","old_version":"9.3.0","new_version":"9.4.0"},{"name":"org.jetbrains.kotlin.plugin.compose","old_version":"2.4.0","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"},{"name":"org.jetbrains.kotlin.plugin.serialization","old_version":"2.4.0","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"},{"name":"com.google.devtools.ksp","old_version":"2.3.10","new_version":"2.3.11","repository_url":"https://github.com/google/ksp"}],"path":null,"ecosystem":"maven"},"body":"Bumps the android-deps group with 21 updates in the /apps/android directory:\n\n| Package | From | To |\n| --- | --- | --- |\n| [gradle-wrapper](https://github.com/gradle/gradle) | `9.6.1` | `9.7.1` |\n| androidx.appcompat:appcompat | `1.7.1` | `1.8.0` |\n| [org.bouncycastle:bcprov-jdk18on](https://github.com/bcgit/bc-java) | `1.85` | `1.85.2` |\n| [org.commonmark:commonmark](https://github.com/commonmark/commonmark-java) | `0.29.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-autolink](https://github.com/commonmark/commonmark-java) | `0.29.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-strikethrough](https://github.com/commonmark/commonmark-java) | `0.29.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-tables](https://github.com/commonmark/commonmark-java) | `0.29.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-task-list-items](https://github.com/commonmark/commonmark-java) | `0.29.0` | `0.30.0` |\n| [io.coil-kt.coil3:coil-compose](https://github.com/coil-kt/coil) | `3.5.0` | `3.6.2` |\n| [io.coil-kt.coil3:coil-svg](https://github.com/coil-kt/coil) | `3.5.0` | `3.6.2` |\n| [org.junit.vintage:junit-vintage-engine](https://github.com/junit-team/junit-framework) | `6.1.2` | `6.1.3` |\n| [io.kotest:kotest-assertions-core-jvm](https://github.com/kotest/kotest) | `6.2.2` | `6.2.4` |\n| [io.kotest:kotest-runner-junit5-jvm](https://github.com/kotest/kotest) | `6.2.2` | `6.2.4` |\n| [com.squareup.okhttp3:mockwebserver](https://github.com/lysine-dev/okhttp) | `5.4.0` | `5.5.0` |\n| [com.squareup.okhttp3:okhttp](https://github.com/lysine-dev/okhttp) | `5.4.0` | `5.5.0` |\n| com.android.application | `9.3.0` | `9.4.0` |\n| com.android.library | `9.3.0` | `9.4.0` |\n| com.android.test | `9.3.0` | `9.4.0` |\n| [org.jetbrains.kotlin.plugin.compose](https://github.com/JetBrains/kotlin) | `2.4.0` | `2.4.20` |\n| [org.jetbrains.kotlin.plugin.serialization](https://github.com/JetBrains/kotlin) | `2.4.0` | `2.4.20` |\n| [com.google.devtools.ksp](https://github.com/google/ksp) | `2.3.10` | `2.3.11` |\n\n\nUpdates `gradle-wrapper` from 9.6.1 to 9.7.1\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/gradle/gradle/releases\"\u003egradle-wrapper's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e9.7.1\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.1.\u003c/p\u003e\n\u003cp\u003eThis is a patch release for 9.7.0. We recommend using 9.7.1 instead of 9.7.0.\u003c/p\u003e\n\u003cp\u003eHere are the highlights of 9.7.0 release:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIsolated Projects graduates to incubating\u003c/li\u003e\n\u003cli\u003eBroader Configuration Cache compatibility\u003c/li\u003e\n\u003cli\u003eResilient Sync helps you fix broken builds\u003c/li\u003e\n\u003cli\u003eMore source locations in problem reports\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003ca href=\"https://docs.gradle.org/9.7.1/release-notes.html\"\u003eRead the Release Notes\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eWe would like to thank the following community members for their contributions to this release of Gradle:\n\u003ca href=\"https://github.com/aSemy\"\u003eAdam\u003c/a\u003e,\n\u003ca href=\"https://github.com/Gautam-aman\"\u003eAman Gautam\u003c/a\u003e,\n\u003ca href=\"https://github.com/YukiCodepth\"\u003eAman Kumar\u003c/a\u003e,\n\u003ca href=\"https://github.com/adubrouski\"\u003eAnton Dubrouski\u003c/a\u003e,\n\u003ca href=\"https://github.com/liutikas\"\u003eAurimas\u003c/a\u003e,\n\u003ca href=\"https://github.com/gbhavya07\"\u003egbhavya07\u003c/a\u003e,\n\u003ca href=\"https://github.com/joshfriend\"\u003eJosh Friend\u003c/a\u003e,\n\u003ca href=\"https://github.com/nicklauslittle-gov\"\u003enicklauslittle-gov\u003c/a\u003e,\n\u003ca href=\"https://github.com/psoni674\"\u003ePragati\u003c/a\u003e,\n\u003ca href=\"https://github.com/Project516\"\u003eproject516\u003c/a\u003e,\n\u003ca href=\"https://github.com/Uomocapra\"\u003eQin Mi\u003c/a\u003e,\n\u003ca href=\"https://github.com/rkdfx\"\u003eRavi\u003c/a\u003e,\n\u003ca href=\"https://github.com/sk-reddy17\"\u003esk-reddy17\u003c/a\u003e,\n\u003ca href=\"https://github.com/Suvrat1629\"\u003eSuvrat Acharya\u003c/a\u003e,\n\u003ca href=\"https://github.com/ShreckYe\"\u003eYongshun Ye\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eUpgrade instructions\u003c/h2\u003e\n\u003cp\u003eSwitch your build to use Gradle 9.7.1 by updating your wrapper:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e./gradlew :wrapper --gradle-version=9.7.1 \u0026amp;\u0026amp; ./gradlew :wrapper\r\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eSee the Gradle \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/upgrading_version_9.html\"\u003e9.x upgrade guide\u003c/a\u003e to learn about deprecations, breaking changes and other considerations when upgrading.\u003c/p\u003e\n\u003cp\u003eFor Java, Groovy, Kotlin and Android compatibility, see the \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/compatibility.html\"\u003efull compatibility notes\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eReporting problems\u003c/h2\u003e\n\u003cp\u003eIf you find a problem with this release, please file a bug on \u003ca href=\"https://github.com/gradle/gradle/issues\"\u003eGitHub Issues\u003c/a\u003e adhering to our issue guidelines.\nIf you're not sure you're encountering a bug, please use the \u003ca href=\"https://discuss.gradle.org/c/help-discuss\"\u003eforum\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eWe hope you will build happiness with Gradle, and we look forward to your feedback via \u003ca href=\"https://twitter.com/gradle\"\u003eTwitter\u003c/a\u003e or on \u003ca href=\"https://github.com/gradle\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003e9.7.0\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.0.\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/92f0512e7f06d84621afba191f75e265363890cf\"\u003e\u003ccode\u003e92f0512\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38892\"\u003e#38892\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/820ee75a99a179bbffa41bcedc6477b685fabb9f\"\u003e\u003ccode\u003e820ee75\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/82c23f9bd2a89b4cc644e1f90a28a8668feb3dee\"\u003e\u003ccode\u003e82c23f9\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering problem in KTS (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38878\"\u003e#38878\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/ef11a7268fe8cc8d6ab849ec911aa11220180553\"\u003e\u003ccode\u003eef11a72\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering issue\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/bb0d8a974a71b1003efea41e4046e98855cd5ff8\"\u003e\u003ccode\u003ebb0d8a9\u003c/code\u003e\u003c/a\u003e Make relevant tests polyglot (run for multiple DSLs)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/336e129d7f95c03486acafc97abf59734acfed48\"\u003e\u003ccode\u003e336e129\u003c/code\u003e\u003c/a\u003e Update signing configuration (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38874\"\u003e#38874\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/4bdf0da2dad9884d089a6062a45ea7183e7d735d\"\u003e\u003ccode\u003e4bdf0da\u003c/code\u003e\u003c/a\u003e Update signing configuration\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/cd9b92c1b82856248cf1dc58b50378238bec7b52\"\u003e\u003ccode\u003ecd9b92c\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38839\"\u003e#38839\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/5f4e381964897ad8d6b99e5a7c77f26dba3259fb\"\u003e\u003ccode\u003e5f4e381\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/1e08ab551367aeb5fb48b26e72807e1d2b27c939\"\u003e\u003ccode\u003e1e08ab5\u003c/code\u003e\u003c/a\u003e Keep type-use annotations in extracted ABI classes (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38810\"\u003e#38810\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/gradle/gradle/compare/v9.6.1...v9.7.1\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `androidx.appcompat:appcompat` from 1.7.1 to 1.8.0\n\nUpdates `org.bouncycastle:bcprov-jdk18on` from 1.85 to 1.85.2\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.md\"\u003eorg.bouncycastle:bcprov-jdk18on's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch1\u003eBouncy Castle Crypto Package - Release Notes\u003c/h1\u003e\n\u003ch2\u003e1.0 Introduction\u003c/h2\u003e\n\u003cp\u003eThe Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. The package is organised so that it contains a light-weight API suitable for use in any environment (including the J2ME) with the additional infrastructure to conform the algorithms to the JCE framework.\u003c/p\u003e\n\u003ch2\u003e2.0 Release History\u003c/h2\u003e\n\u003cp\u003e\u003c!-- raw HTML omitted --\u003e\u003c!-- raw HTML omitted --\u003e\u003c/p\u003e\n\u003ch3\u003e2.1.1 Version\u003c/h3\u003e\n\u003cp\u003eRelease: 1.86\u003cbr /\u003e\nDate: 2026, TBD\u003c/p\u003e\n\u003ch3\u003e2.1.2 Defects Fixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) let a subkey inherit the primary key's Key Flags when its own Subkey Binding signature carried no Key Flags subpacket, which made the two capability decisions taken for one subkey disagree. OpenPGPCertificate.OpenPGPComponentKey.isSigningKey() reads the effective flags, which fell back to the primary key's direct-key or primary user ID self-signature, so a subkey bound with no flags of its own counted as signing-capable; verifyEmbeddedPrimaryKeyBinding reads the binding signature's own flags, found no signing capability there, and so skipped the embedded Primary Key Binding (cross-certification) signature that RFC 9580 sec. 5.2.1.8 and sec. 10.1.3 require of a subkey that can issue signatures. A data signature made by such a subkey was therefore attributed to the certificate and reported valid by OpenPGPSignature.OpenPGPDocumentSignature.isValid() with the cross-certification requirement never applied, where GnuPG refuses the same certificate and message as not cross-certified. An attacker holding a third party's public signing subkey - which is public material - could bind it to their own primary key with a Subkey Binding signature they are able to make, carrying no Key Flags and no embedded Primary Key Binding signature, which they cannot make without the subkey's private key, and have that party's genuine signatures verify as valid under the attacker's own identity: misattribution of a real signature rather than a forgery of a new one, since the signature still has to be one the subkey actually made. Key Flags are a statement about the key the carrying signature refers to (RFC 9580 sec. 5.2.3.29), so a subkey no longer inherits them from the certificate-wide signatures of the primary key: a Subkey Binding signature that omits the subpacket now leaves the subkey with no capabilities rather than the primary's, which makes the flags the cross-certification check consults the same flags every other decision consults. Preferences and the other subpackets a direct-key signature carries are inherited as before, and the primary key itself - whose flags legitimately come from its direct-key or user ID self-signature - is unaffected. The low-level PGPSignature / PGPPublicKeyRing API performs no binding checks by design and is unchanged.\u003c/li\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) used a version 6 key that carried no valid Direct Key signature, falling back to the primary user ID binding as it correctly does for a version 4 key. RFC 9580 sec. 5.2.3.10 requires the opposite: \u0026quot;An implementation MUST ensure that a valid Direct Key signature is present before using a version 6 key. This prevents certain attacks where an adversary strips a self-signature specifying a Key Expiration Time or certain preferences.\u0026quot; The certificate grammar says the same structurally, the Direct Key signature being mandatory in the version 6 structure of sec. 10.1.1 and optional in the version 4 one of sec. 10.1.3. Because a version 6 certificate carries its key expiration, features and algorithm preferences on the Direct Key signature - the convention the RFC recommends and the one OpenPGPKeyGenerator follows, its user ID certification carrying no expiration at all - removing that single signature packet from a published certificate silently dropped the expiration along with the preferences and features: OpenPGPCertificate.getSignatureChainFor fell back to the user ID binding, the primary key was still reported bound, and getEncryptionKeys() and getSigningKeys() went on returning the subkeys of a key whose owner had set it to expire. The primary key fingerprint is unchanged by the removal, so a relying party pinning the key by fingerprint still treats it as the same key, and no private key or hash collision is involved; the natural moment for the strip is the key refresh that RFC 9580 names as the reason to refetch a key at all - to learn about changes in expiration, features, preferences and revocation - which is exactly the update it defeats. This is a downgrade rather than a forgery, nothing being attributed to a key that did not authorise it, and the concerning direction is encryption, to a key meant to have been retired. OpenPGPCertificate.isBoundBy now requires a valid Direct Key self-signature on a version 6 primary key before any component of the certificate - the primary key, its subkeys or its identities - is treated as bound, so a version 6 certificate stripped of it offers no keys at all rather than an unexpiring set. Version 4 certificates are unaffected: there the key expiration legitimately lives on the user ID self-signature and the fallback is correct, so it stays. The revocation-only version 6 certificate of sec. 10.1.2, which legitimately carries no Direct Key signature, is unaffected as well - its key was already refused as revoked, and reading the revocation does not go through the binding check.\u003c/li\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) ignored the OpenPGPPolicy a caller had configured when it verified the signatures on an inline message. OpenPGPMessageInputStream took the policy it sanitizes each document signature against from the implementation's own default rather than from the processor the signature is being verified by, so a policy supplied through the documented OpenPGPApi(implementation, policy) / OpenPGPMessageProcessor(implementation, policy) constructor - which is how OpenPGPApi.decryptAndOrVerifyMessage() plumbs the configured policy through - had no bearing on whether a signature was accepted, although the same processor already applied it to the decompressed-size bound. A caller who hardened the policy beyond the default therefore had a signature that policy rejects handed back from getResult().getSignatures() with isTestedCorrect() true, while OpenPGPSignature.isValid(policy) on that same signature reported the rejection. Both verify paths, the one-pass and the prefixed-signature one, now read the configured policy; the detached-signature processor already did.\u003c/li\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) went on offering the subkeys of a certificate whose primary key had expired. OpenPGPCertificate's binding check evaluated only a subkey's own Subkey Binding signature, so a primary key whose Key Expiration Time (RFC 9580 sec. 5.2.3.13) had passed still handed out a longer-lived encryption or signing subkey from getEncryptionKeys() / getSigningKeys(), leaving the certificate contradicting itself - getExpirationTime() in the past and getPrimaryKey().isBoundAt() false, while isBoundAt() on the subkey answered true. An expired primary key can no longer certify, so the subkeys it bound are not usable with it either, which is how GnuPG and Sequoia both treat such a certificate; primary key revocation already propagated, since a revocation appears in the subkey's signature chain, but expiration is not carried there. Relatedly, a subkey no longer inherits the primary key's validity period at all - sec. 5.2.3.13 counts that period from the creation time of the key the carrying self-signature is made on, so re-basing the primary key's period on a subkey created later than it gave that subkey an expiration date later than the primary key's own.\u003c/li\u003e\n\u003cli\u003eOpenPGPSignature.OpenPGPDocumentSignature.isValidAt(Date) in the high-level OpenPGP API reported a data signature as valid at an evaluation time past the signature's own Signature Expiration Time (RFC 9580 sec. 5.2.3.18, hashed subpacket type 3). The method checked that the signature was correct and that the issuing key was bound and signing-capable at that date, but never consulted the signature's own expiration, so it disagreed with isEffectiveAt(Date) on the same object and with its own javadoc, which names being effective as one of the three criteria of a valid signature. Signature expiration is a separate axis from the issuing key's Key Expiration Time that the binding checks already cover, and GnuPG, GPGME, git and Sequoia all keep the two apart and treat a signature past its expiration as not good. isValid() and isValid(policy) evaluate at the signature's creation time, where a signature is always inside its own window, and are unchanged.\u003c/li\u003e\n\u003cli\u003eThe lightweight LMSSigner and HSSSigner refused a key wrapped in ParametersWithRandom, which is how BcContentSignerBuilder passes a key whenever setSecureRandom() has been called - so BcHssLmsContentSignerBuilder built a working signer until a random was set and then failed with \u0026quot;Incorrect Key Parameters\u0026quot;, and the two signers themselves raised ClassCastException on the same input. All three now unwrap it, as the promoted ML-DSA and SLH-DSA signers already did. The random is accepted and not used: LMS derives its message randomiser C from the key's seed and the one-time index, so it is deterministic and cannot repeat while q does not. Note SP 800-208 sec. 6.1 asks for C to come from an approved random bit generator, which this implementation does not do; that is unchanged here, and a supplied random is now ignored rather than refused.\u003c/li\u003e\n\u003cli\u003eLMS signature verification did not apply two of the checks RFC 8554 sec. 5.4.2 requires before a signature is processed. Step 2g refuses a signature whose LMS typecode is not the one from the public key, and without it the path computation took its height and tree digest from the parameter set the signature named rather than the key's, so a signature claiming a height-25 parameter set drove a 25-level computation against a height-5 key. Step 2i refuses a leaf number q outside the tree, and without it an out-of-range q flowed into the node arithmetic and was left for the candidate-root comparison to catch. Neither was a forgery - the domain separation between D_LEAF and D_INTR and the final comparison saw to that - but both are attacker-chosen work the specification says to refuse up front. Both are now checked, and a signature failing either is still reported as not verifying rather than thrown out of Signature.verify(). The catch around the signature decode in LMSSigner and HSSSigner has also been narrowed to the decode itself, as the corresponding SPI was corrected to do for github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2408\"\u003e#2408\u003c/a\u003e: past the parse the engine reports an inconsistent signature by returning false rather than by throwing, so the wider catch caught nothing while standing ready to turn a future internal error into a quiet false.\u003c/li\u003e\n\u003cli\u003eThe LMS and HSS key parameter classes now apply at construction the checks their decoders apply, so a key built directly cannot be one the decoder would refuse. LMSPrivateKeyParameters accepted an identifier of any length although the decoder reads exactly 16 bytes - such a key encoded but could not be read back - and left q, maxQ and the seed length unchecked; the seed is now required to be at least m bytes at decode as well, where a one-byte seed had been decoding silently and then deriving every one-time key from it. HSSPrivateKeyParameters checked neither its level count nor that it had been given a component key per level and a chaining signature per level below the root, and then indexed both lists, so a mismatch surfaced as IndexOutOfBoundsException - or, where a level happened to match, as a null chaining signature that only failed at signing time; the level is now checked after the reset that fills it in, since a null is legitimate on the way in. LMSPrivateKeyParameters.getInstance(byte[], byte[]) adopted the public key supplied beside the private one without comparing them, so a mismatched public key was simply reported by getPublicKey(); it now cross-checks the identifier, both parameter sets and, where the tree cache already holds it, the root, as the HSS entry point does. The decoders also now report a bad version or seed length as IOException rather than IllegalStateException, so a caller can catch one type for a malformed key, and the package-private LM-OTS public key decoder no longer declares throws Exception or dereferences an unrecognised typecode. The deprecated org.bouncycastle.pqc.crypto.lms copies carry the decoder corrections.\u003c/li\u003e\n\u003cli\u003eIn the LMS JCE layer, LMSKeyGenParameterSpec.fromNames knew all twenty LMS parameter-set names but only four of the sixteen LM-OTS ones, so none of the SP 800-208 n24 or SHAKE sets could be named; all sixteen are now present. KeyPairGenerator.initialize(int, SecureRandom) reports InvalidParameterException, which is what the JCA specifies and which extends the IllegalArgumentException it raised before, so existing catches still match. BCLMSPrivateKey.getIndex now takes the exhaustion check and the index read under the key's own monitor rather than as two separate calls, and two unused fields have gone from LMSSignatureSpi. Note that the LMS Signature claims its one-time key at the first update() rather than at sign(), so a Signature that is initialised and updated and then abandoned spends an index without producing a signature - the safe direction for a one-time scheme, and now documented on the SPI.\u003c/li\u003e\n\u003cli\u003eEvery other key pair generator that refuses a key size did the same thing the LMS one did above. KeyPairGenerator.initialize(int, SecureRandom) is documented to raise InvalidParameterException when the key size is not one the generator supports, and thirty of them raised a bare IllegalArgumentException instead, so a caller following the JCA and catching the documented type saw an exception escaping rather than a refusal. The ML-DSA, ML-KEM, SLH-DSA, Classic McEliece, FrodoKEM, NTRU and composite signature and KEM generators in the BC provider, and every generator in BCPQC, now raise InvalidParameterException - NewHope included, where the value is a key size it will not take rather than a mode of initialisation it does not offer. InvalidParameterException extends IllegalArgumentException, so callers written against the old behaviour go on catching it unchanged. The two RSA generators are corrected as well, and differently: theirs is a key size below a floor rather than a mode of initialisation they do not offer, and the refusal is raised by the lightweight RSAKeyGenerationParameters, which cannot name a java.security exception at all, so the RSA KeyPairGeneratorSpi now translates it - keeping the message verbatim and the original exception as the cause, through a new SecurityExceptions.invalidParameterException factory, since InvalidParameterException has no constructor that takes one. Of the 304 KeyPairGenerator services the two providers register, 299 now refuse a nonsense key size the way the JCA defines it and five accept it as a strength they can work with, with none left raising a bare IllegalArgumentException; that is asserted as a sweep over both providers rather than per algorithm, so a generator added later is covered without the test being touched. The jdk1.3 provider overlays of the four generators that have one carry the same change, and the jdk1.3 SecurityExceptions overlay gains the new factory along with the invalidAlgorithmParameterException one it had been missing.\u003c/li\u003e\n\u003cli\u003eKeyPairGenerator.initialize(AlgorithmParameterSpec, SecureRandom) had the same shape of problem as the int overload above, and only 44 of the 304 services the two providers register reported an unusable spec as the InvalidAlgorithmParameterException that method declares. The twenty-three PQC generators that resolve a parameter set by name - cmce, frodokem, mldsa, mlkem, slhdsa, aimer, bike, faest, falcon, haetae, hqc, mayo, mqom, ntru, ntruplus, both ntruprime variants, qruov, saber, sdith, smaugt, snova and sqisign, 230 services between them - case-folded the name they got back from the spec without checking it, so a spec with no getName() method, and a null spec, produced a NullPointerException from inside the fold; their own \u0026quot;is this name one I know\u0026quot; branch, which does report the declared exception, was unreachable. The two composite generators, whose parameter set is fixed by the algorithm name so that null is the only spec they accept, refused every other one with IllegalArgumentException. RSA answered correctly for a spec of the wrong type but not for one of the right type carrying values its lightweight parameters will not take - an even public exponent, or a key size below the floor - which is now translated the same way the int overload's is. All 304 services now report the declared exception, with the composites still taking the null spec that is right for them; note that InvalidAlgorithmParameterException is a checked exception and not an IllegalArgumentException, so a caller that was catching what these threw before has to catch the declared type instead.\u003c/li\u003e\n\u003cli\u003eAn HSS private key claimed the two records of its position under two different monitors. The top-level index and the bottom component key's one-time index q are independent records of the same position - the decoder requires them to agree, see the entry below - but generateLMSContext incremented the index under the HSS key's own monitor, released it, and only then claimed q under the component key's. A getEncoded() issued in between saw the index advanced and q not, and produced an encoding this implementation's own decoder rejects; and two threads meeting at a bottom-tree boundary could both pass the exhaustion test, take consecutive top-level indices and claim the same q, after which one of them was refused with \u0026quot;ots private key exhausted\u0026quot; by a key still reporting usages remaining, a top-level index had been spent with no signature made, and the two records stayed one apart for the rest of the key's life in that process - so it could no longer be encoded, cloned or sharded, and getIndex() and getUsagesRemaining() misreported by one. No one-time key was reused: the component key's claim is itself atomic, and the divergence runs index ahead of leaves, so the effect was on the key's usability rather than on the signatures it had made. Both records are now claimed under the one monitor, and the component key is claimed before the index is incremented so that an exhausted one leaves both untouched. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the same correction.\u003c/li\u003e\n\u003cli\u003eTimeStampToken parsed the attacker-controlled TSTInfo content of a time-stamp token (org.bouncycastle.tsp.TimeStampToken, reached from TimeStampResponse(byte[]) and (InputStream)) inside a try that caught only CMSException, so a well-formed RFC 3161 TimeStampResp whose embedded token carried a malformed TSTInfo - a SEQUENCE with fewer elements than the five mandatory fields, a non-SEQUENCE, truncated DER, or an unknown context tag - let an IllegalArgumentException or a NoSuchElementException escape the constructor's declared throws TSPException, IOException contract. A token signed by no signers or by more than one raised a bare IllegalArgumentException from the same constructor, before that try, for the same reason. Both are now reported as TSPException, matching the package-private TimeStampResponse(DLSequence) constructor and the existing getSignedAttributes guard in the same method; the signer-count refusal is a TSPValidationException, as the neighbouring check on the content type already was. Related, and the cause of the NoSuchElementException: asn1.tsp.TSTInfo read its five mandatory fields off the sequence with no bound on how many elements were actually there, so a short SEQUENCE left the enumeration to run out rather than being refused, and an oversize one was accepted with its extra elements absorbed into the optional slots. Decode now requires the five to ten elements RFC 3161 sec. 2.4.2 gives the type, which is what the sibling Accuracy and ArchiveTimeStamp decoders already did, so the failure is the IllegalArgumentException that getInstance is expected to raise (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2415\"\u003e#2415\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eNeither the HSS nor the XMSS^MT private key decoder checked its declared index against the traversal state stored beside it, although the two are independent records of the same position in the key and so can be compared. For HSS the records are the top-level index and the component keys' one-time indices q; for XMSS^MT they are the global index and the per-layer BDS states. A stored key whose index had been rolled back while its state stayed advanced - a partial write, a restore from backup, a buggy storage layer - was therefore accepted, and it then signed a second message under a one-time key the key had already used, producing a signature that verified, so nothing anywhere surfaced the reuse. RFC 8554 sec. 1 and RFC 8391 sec. 1.1 both require each one-time key to be used exactly once, and this is the failure those requirements exist to prevent; the single-tree XMSS decoder has tied its BDS state to its index since that state was first validated, and this brings the two multi-tree schemes into line. HSS decode now requires the declared index to equal the position the component q values imply - a level above the last contributes (q - 1) leaves of the levels beneath it, since its q has already advanced past the subtree it signed - and XMSS^MT decode now requires each present layer's BDS index to equal the leaf index that layer derives from the global index, allowing the one position where a layer has moved into a new subtree and its state legitimately still carries the previous subtree's final index. A layer with no state yet is unaffected, since those are built lazily at signing time. Related, and the same shape of omission: an XMSS or XMSS^MT private key encoding carries the tree root twice - the key's own root field and the root node of the BDS state stored beside it, which for XMSS^MT is the top layer's - and the two were never compared either. A corrupted root was accepted and then poisoned every signature the key made, because the root is hashed into the message digest: the signature did not verify and nothing indicated why. Decode now requires the two copies to agree. The BDS node values themselves are not checkable the way the LMS tree cache above is - a BDS authentication path, stack, retain or keep node does not have its children stored alongside it, so recomputing one means building a subtree, which is the work the state exists to avoid. Both checks are integer comparisons over the levels of the key, too small to measure against the surrounding decode, and both were verified not to reject any legitimate key by walking every index a key can reach: the full key space of the two-level HSS and the h=4/d=2, h=6/d=2, h=6/d=3, h=9/d=3 and h=8/d=4 XMSS^MT parameter sets, plus a three-level HSS key across a subtree boundary and an HSS shard. Since those node values cannot be recomputed, the encoded state now carries a checksum over itself instead, with the owning key's public seed hashed in front of it. Any corruption of the stored state is refused at decode rather than being loaded and then producing signatures that silently do not verify, and because the public seed is bound in, a state transplanted between two keys of the same parameter set is refused too, even though it is internally consistent and arrives with its own matching root. The public seed is bound rather than the secret seed or the PRF key deliberately: the state's own root and index are inside the encoding and so are already covered, hashing secret material would make the stored checksum a commitment to it for no gain in detection, and the PRF key does not influence the state at all. \u003cstrong\u003eThis is an error-detecting code and not integrity protection\u003c/strong\u003e - anyone able to rewrite the stored key recomputes it, so it establishes that the state is unchanged since it was written, never that it was correct when written, and the allocation bounds on the encoding remain the guard against a crafted one. It costs one SHA-256 over the state, measured at 5 to 8 microseconds each way for the h=10 and h=16 parameter sets, and 32 bytes of encoding. The state encoding was added earlier in this same cycle and has not been released, so the checksum is simply part of it rather than a new version: a state written by a 1.86 beta is rejected, which is recovered from by re-exporting the key. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the HSS check as well (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2414\"\u003e#2414\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eIn the XMSS and XMSS^MT JCE layer, KeyPairGenerator.initialize(int, SecureRandom) reports InvalidParameterException, which is what the JCA specifies and which extends the IllegalArgumentException it raised before, so existing catches still match. This is the XMSS counterpart of the same correction made to LMSKeyPairGeneratorSpi.\u003c/li\u003e\n\u003cli\u003eBCXMSSPrivateKey.getIndex and BCXMSSMTPrivateKey.getIndex took the exhaustion check and the index read as two separate calls on the key parameters. Each is atomic on its own, but the pair is not: a signature taken by another thread between them spends the last usage, so the check passes and the read that follows returns maxIndex + 1 - the one index past the end of the key, which is what the check exists to refuse, handed back as though it were the next one-time key to be used. Both reads are now taken under the key parameters' own monitor, the monitor their mutators hold, as BCLMSPrivateKey.getIndex was corrected to do. No one-time key is reused by this: the effect is on what the key reports about itself, not on the signatures it makes.\u003c/li\u003e\n\u003cli\u003eThe S/MIME example smoke test in the misc module (org.bouncycastle.mail.smime.examples.test.AllTests) drove SendSignedAndEncryptedMail against smtp.gmail.com, and that example finishes with Transport.send() under JavaMail's default settings, which have no connect timeout. Where outbound port 25 is refused the failure was swallowed and the test passed; where it is silently dropped, as on many home networks, the connect blocked and ./gradlew build hung in :misc:test indefinitely with \u0026quot;0 tests completed\u0026quot;. The test now delivers to an SMTP stub on a loopback port, with connect / read / write timeouts as a backstop, and asserts the message arrived (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2407\"\u003e#2407\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation took the traditional component public key bytes it feeds the KEM combiner from the recipient key's own encoding, while decapsulation recomputes the point from the private key and so always produced an uncompressed one. Section 4 of draft-ietf-lamps-pq-composite-kem requires an EC component to be carried as an uncompressed point, but a component key that encodes itself compressed - a BC EC key whose point format has been set through org.bouncycastle.jce.interfaces.ECPointEncoder, or a key from a provider that preserves a compressed encoding - was passed through as it came. Both sides then combined a different tradPK and derived different shared secrets, with no error reported on either: encapsulation and decapsulation both succeeded and the recipient simply could not decrypt. The EC component is now normalised to an uncompressed point wherever the engine serialises one, which covers the ephemeral key that forms the ciphertext as well. X25519 and X448 components have a single encoding and were unaffected, as were EC keys left in their default (uncompressed) format, whose shared secrets are unchanged. CompositePublicKey.getEncoded() took its component bytes the same way, so such a key also encoded to a composite key other implementations reject and whose bytes changed across an encode / decode / encode round trip - 1238 bytes rather than 1270 for MLKEM768-ECDH-P256, and for the composite ML-DSA keys sharing that method, 2006 rather than 2038 for MLDSA65-ECDSA-P256. It now normalises the component the same way. This is a write-side change only: a composite key carrying a compressed EC component is still decoded, since the component key factories accept either form, and continues to verify signatures as before - it simply re-encodes in the normalised form. The shared normalisation is org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil.getUncompressedSubjectPublicKeyBytes.\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation threw a NullPointerException, wrapped in an IllegalStateException out of KeyGenerator.generateKey(), when the SecureRandom it was given was null - which javax.crypto.KEM.newEncapsulator() documents as a request for the provider's default, and which KeyGenerator.init(spec, null) passes straight through. The three RSA-OAEP composites draw the traditional shared secret from that random directly, so they were the ones affected; the ECDH and X25519 / X448 composites escaped only because their component KeyPairGenerators default a random of their own. CompositeMLKEMEngine now defaults one through CryptoServicesRegistrar.getSecureRandom() on first use, as the composite KEM Cipher's wrap path already did, and as the KEM generators corrected earlier in this cycle now do. Related, the engine now also clears the ML-KEM component's shared secret alongside the traditional one on both the encapsulate and decapsulate paths - the copy handed back by getEncoded() was left in the heap - as section 3.5 of draft-ietf-lamps-pq-composite-kem requires.\u003c/li\u003e\n\u003cli\u003eCompositePublicKey.getAlgorithm() and CompositePrivateKey.getAlgorithm() returned null for all twelve Composite ML-KEM (draft-ietf-lamps-pq-composite-kem) parameter sets. Both classes resolved the name through the composite signature index only, which holds the composite ML-DSA OIDs, so a composite KEM key pair - generated, parsed from a certificate, or read from PKCS#8 - reported no algorithm at all, and the standard JCA idiom of reconstructing a key with KeyFactory.getInstance(key.getAlgorithm()) raised a NullPointerException. The lookup now falls back to the composite KEM index, so the name returned is the one the provider registers the algorithm under (e.g. MLKEM768-X25519-SHA3-256), matching the composite ML-DSA behaviour. The same single-index assumption made the CompositePublicKey(SubjectPublicKeyInfo) and CompositePrivateKey(PrivateKeyInfo) constructors reject a composite KEM key with \u0026quot;unable to create CompositePublicKey from SubjectPublicKeyInfo\u0026quot;; they now dispatch to the composite KEM key factory for those OIDs. Keys obtained through KeyFactory or through BouncyCastleProvider.getPublicKey / getPrivateKey were unaffected and are unchanged (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2404\"\u003e#2404\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe org.bouncycastle.jcajce.spec.KEMKDFSpec constructor stored a null otherInfo as given, so getOtherInfo() returned null, and three of the KDF branches KdfUtil.makeKeyBytes dispatches to - KMAC-128, KMAC-256 and SHAKE-256 - read the otherInfo length without a guard and threw NullPointerException out of the KEM operation, where the KDF2, KDF3 and HKDF branches tolerate a null through KDFParameters / HKDFParameters. The Builder of every spec in the package already mapped null to empty, so no provider path reached it, but the constructor is protected on a public class and KdfUtil is documented for callers building their own KEM integration; the deprecated KEMParameterSpec passes a null itself and escaped only because it also pins the KDF to null. The constructor now stores empty for a null, so getOtherInfo() never returns null, and a null and an explicitly empty otherInfo derive the same key.\u003c/li\u003e\n\u003cli\u003eQR-UOV signature verification accepted a signature encoding that was not canonical, so the encoding of a signature was not unique even after the trailing-byte fix of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e. Each F_q element of the signature is stored in ceil(log2 q) bits, one more bit pattern than the field has elements: q itself is representable and is arithmetically congruent to zero, so an element written as q verified exactly as the same element written as zero would, and the bits padding the last element out to the byte boundary were never read at all. Every zero element of a signature therefore carried a second encoding, and for the q = 7 parameter sets roughly one element in seven is zero - a single qruov_5_q7_L10 signature measured 256 spare bits, so on the order of 2^256 distinct byte strings verified for the one message and key. Verification now rejects any element outside [0, q) and any set padding bit; a signature produced by this or by the reference implementation is unaffected, as the KAT vectors of every parameter set confirm. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSNOVA signature verification ignored four bits inside the signature for any parameter set whose solution is an odd number of GF(16) nibbles - the SNOVA_24_5_5, SNOVA_25_8_3, SNOVA_29_6_5 and SNOVA_66_15_3 families, sixteen of the forty-four parameter sets. The last byte of the encoded solution carries a single nibble and the signer leaves the top four bits zero, but the decoder did not read them, so sixteen distinct byte strings verified for one signature. This is the same non-unique encoding github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e closed for bytes following the signature, applied inside it; the verifier now requires those bits to be zero. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSnovaPrivateKeyParameters did not validate the length of the private key encoding handed to it - the only one of the five schemes of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e that did not - and SnovaParameters.getPrivateKeyLength() reported the expanded (\u0026quot;ESK\u0026quot;) length even for a parameter set whose private key is the seed pair. A private key encoding reaches this constructor straight from a PKCS#8 blob, so a wrong length went undetected: a seed-form key with extra bytes appended was accepted and signed under a different derived key, and a short expanded-form key sized the signer's decode buffer negatively, throwing NegativeArraySizeException out of generateSignature() rather than being reported at construction. Related, the signing retry loop could not terminate: the vinegar values are derived from a single-byte counter, so only 256 distinct linear systems can be tried, and an expanded-form private key that is not a real central map is singular for all of them - generateSignature() then span forever rather than failing. The length is now checked at construction, getPrivateKeyLength() reports the length that parameter set's private key actually has, and the retry loop gives up after its 256 attempts as MAYO's does.\u003c/li\u003e\n\u003cli\u003eMayoSigner and MayoKeyPairGenerator did not clear several buffers holding secret key material that the MAYO reference implementation explicitly clears. Signing left the secret oil space O, the expanded L = (P1 + P1^t) * O + P2, and the M / VPV / Ox intermediates of the central map in place, having gone to the trouble of clearing eleven other buffers; key generation left the expanded seed, whose tail is the encoded oil space, and the P1 * O + P2 half of P; and the row-echelon step left the packed echelon form of the secret linear system and its pivot rows. Separately, if all 256 attempts at solving for the signature had given a rank-deficient system, signing emitted a signature built from the failed attempt's state instead of reporting the failure the reference returns, and AIMerSigner.generateSignature returned an empty array on failure, which a caller would hand on as though it were a signature. Both now throw.\u003c/li\u003e\n\u003cli\u003eFive PQC signature schemes - MAYO, SNOVA, QR-UOV, SQIsign and AIMer - returned the NIST crypto_sign \u0026quot;sm\u0026quot; signed-message envelope from generateSignature() rather than the signature. That envelope is an artefact of the reference KAT harness, which records the message alongside the signature so a vector file can be self-contained; it is not part of any of the five specifications, and no other BC signer emits it (Falcon's KAT test rebuilds the equivalent envelope in the test, which is where it belongs). Two consequences followed, both reaching the JCA Signature services of every parameter set of the five schemes in BouncyCastlePQCProvider. First, since the message was appended to the signature, verification had to skip whatever followed the signature proper, and it did so by checking only that the buffer was long enough - so any number of trailing bytes could be added to a valid signature, or the appended message replaced with unrelated data, and it still verified. A signature encoding was therefore not unique: anyone holding one valid signature could produce unlimited distinct byte strings that all verified for the same message and key, which breaks any use that treats the signature bytes as an identifier, deduplicates on them, or records them as evidence. Second, the envelope propagated into everything built on the operator layer: because ContentSigner hands the signature straight into the structure being signed, every X.509 certificate, CRL, CMS SignedData and TLS CertificateVerify BC produced with one of these algorithms carried a verbatim copy of the signed data inside its own signature field - a self-signed MAYO-1 certificate came to 3567 bytes where the same certificate is now 2020 - which no other implementation can parse as a signature, and which in a detached CMS signature meant the \u0026quot;detached\u0026quot; signature carried the content. generateSignature() now returns the bare signature, and verifySignature() requires exactly the parameter set's signature length, so appended or truncated data is rejected rather than ignored. \u003cstrong\u003eThis is a behavioural change for signatures produced by an earlier release\u003c/strong\u003e - MAYO and SNOVA from 1.84, QR-UOV, SQIsign and AIMer from 1.85 - which are no longer accepted in the envelope form they were emitted in; the signature bytes themselves are unchanged, so a stored value can be recovered by taking the leading signature-length bytes, or for AIMer, whose envelope was message || signature rather than signature || message, the trailing ones. The KAT tests now rebuild the envelope before comparing against the vector files, which continue to record it. Note that AIMer's verification had already been made length-exact during this cycle (see the entry below relating to github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2401\"\u003e#2401\u003c/a\u003e), so of the five only its envelope remained (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe MLS implementation did not bind an X.509 credential to the LeafNode's signature_key. LeafNode.verify() checked a leaf's signature against the signature_key declared in the leaf itself, while the X.509 credential's certificate chain was stored but never parsed or checked, so the certificate's public key was never required to match signature_key (RFC 9420 sec. 5.3). A leaf could therefore carry one party's certificate while being signed by an unrelated key and still be accepted under that party's identity through KeyPackage.verify() and the Group leaf-validation path. LeafNode.verify() now requires the end-entity certificate's subject public key, in the cipher suite's signature encoding, to equal signature_key for an X.509 credential, and rejects the leaf otherwise - including an empty chain or a certificate whose key type does not match the cipher suite; certificate-chain and identity validation to a trust anchor remain the application's responsibility per RFC 9420 sec. 5.3.1. A public org.bouncycastle.mls.codec.Certificate(byte[]) constructor and a Credential.getCertificates() accessor are added so callers can build and inspect X.509 credentials. Basic credentials are unaffected.\u003c/li\u003e\n\u003cli\u003eThe SecureRandom supplied to org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder.setSecureRandom() did not drive the content IV / nonce for any algorithm other than RC2. EnvelopedDataHelper.generateParameters passed the caller's SecureRandom to the AlgorithmParameterGenerator only in the RC2_CBC branch; every other content-encryption algorithm - AES-CBC, AES-GCM, AES-CCM, Camellia, ARIA, SEED and the rest - reached pGen.generateParameters() on an uninitialised generator, so the IV / nonce was drawn from a default SecureRandom and setSecureRandom() was silently ignored (the builder's javadoc states that random is used for IV/nonce generation). The generator is now initialised with the supplied random on the general path as well, so a caller who provides a specific randomness source - for a controlled or FIPS-approved DRBG, say - has it honoured for the content IV / nonce. The session-key generation path was unaffected and already used the supplied random. Because the content IV / nonce now comes from the supplied SecureRandom, the org.bouncycastle.crypto.util JournalingSecureRandom / JournaledAlgorithm reproducible-encryption support records it in the transcript: a resumed session reproduces the IV / nonce by regenerating it from the replayed randomness - build the resuming encryptor from the content-algorithm OID - rather than by reusing the AlgorithmIdentifier captured from the first encryption, which no longer keeps the transcript aligned.\u003c/li\u003e\n\u003cli\u003eThe NTRU LPRime, NTRU+ and SMAUG-T KEM generators threw a NullPointerException when constructed with a null SecureRandom, where every other KEM generator - including NTRU LPRime's own SNTRU Prime counterpart in the same package - defaults one through CryptoServicesRegistrar.getSecureRandom(). This is reachable from the lightweight API directly, and from javax.crypto.KEM, whose newEncapsulator() documents a null random as a request for the provider's default.\u003c/li\u003e\n\u003cli\u003eFrodoKEMEngine kept a single SHAKE instance in a field, so an engine reached concurrently produced wrong results. It is reached that way through org.bouncycastle.crypto.kems.FrodoKEMExtractor, which holds one engine for its lifetime: two threads extracting through one extractor interleaved the digest's absorb and squeeze phases, yielding shared secrets that silently did not match the sender's, or an IllegalStateException of \u0026quot;attempt to absorb while squeezing\u0026quot; from inside extractSecret. The digest is now built per call, as CMCEEngine's already was, which makes an extractor safe to share. Encapsulation was unaffected, since FrodoKEMGenerator builds an engine per call. Results for any single-threaded use are unchanged - the reference KAT vectors are byte-identical.\u003c/li\u003e\n\u003cli\u003eThe BCJSSE provider carried the TLS 1.2 coupling between the supported_groups extension and ECDSA over into TLS 1.3: an ECDSA signature scheme was treated as usable - offered in the signature_algorithms and signature_algorithms_cert extensions, and eligible when selecting the local credentials - only while the corresponding curve was among the named groups enabled for key exchange, both per context (a group unavailable for key agreement disabled the scheme outright) and per connection (the curve had to be in the supported_groups list about to be sent). RFC 8446 sec. 4.2.7 scopes supported_groups to key exchange only, with signature algorithms negotiated independently (sec. 4.2.3), so this incorrect restriction in TLS 1.3 has been removed. Ed25519, Ed448 and the RSA schemes were unaffected (as well as typical deployments using a default configuration for named groups).\u003c/li\u003e\n\u003cli\u003eThe bcmail module descriptor did not declare its javax.mail/javax.activation dependences, so a modular (module-path) consumer of the jar hit IllegalAccessError/module-resolution failures when the S/MIME classes touched the mail API. The descriptor now requires them optionally (requires static) under all four module names those libraries are known by - the automatic names mail and activation carried by the javax.mail:mail / javax.activation:activation artifacts, and the explicit names java.mail and java.activation carried by the newer com.sun.mail / com.sun.activation ones - a hard requires on any one name would break users of the others (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2389\"\u003e#2389\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFour type-coercion helpers in the OER / IEEE 1609.2 (ITS) decoder tested the wrong type in the identity fast path that lets a getInstance() factory return an argument that is already of the target type. org.bouncycastle.oer.its.ieee1609dot2.basetypes.UINT32.getInstance and org.bouncycastle.oer.its.etsi102941.basetypes.Version.getInstance guarded on UINT8 - a sibling of UINT32 under UintBase, and unrelated to Version - so passing a UINT8 threw ClassCastException, while passing an actual UINT32 or Version missed the fast path and fell through to ASN1Integer.getInstance, which rejects them: neither factory accepted its own type. org.bouncycastle.oer.its.etsi103097.EtsiTs103097DataEncryptedUnicast.getInstance guarded on its sibling EtsiTs103097DataEncrypted and then cast to the unicast type, so an EtsiTs103097DataEncrypted threw ClassCastException. org.bouncycastle.oer.OEROptional.getObject(Class) called value.getClass().isInstance(type) with the arguments transposed, which is always false because the argument is a java.lang.Class, so the cast path was dead and every optional field was resolved reflectively, failing with IllegalStateException for a target type with no static getInstance. Each guard now names the type it returns, matching the sibling UINT8 / UINT16 / UINT64 and EtsiTs103097DataEncrypted factories (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2373\"\u003e#2373\u003c/a\u003e).\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003eSee full diff in \u003ca href=\"https://github.com/bcgit/bc-java/commits\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark` from 0.29.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/blockquote\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/blockquote\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/42b4fb7adfe288ef13e9e27ab20aff7e91b0ab9d\"\u003e\u003ccode\u003e42b4fb7\u003c/code\u003e\u003c/a\u003e Prepare CHANGELOG for version 0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/b76e09d7a8362abb5f04e1d6b91dbd6da279a6fc\"\u003e\u003ccode\u003eb76e09d\u003c/code\u003e\u003c/a\u003e Limit how deep inline nodes may nest by default (100)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/49f65cb5cbec93cff713179990307145198e7061\"\u003e\u003ccode\u003e49f65cb\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing deeply nested emphasis\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/610f84b83e68c381e8f784ae4d044c80e1948b67\"\u003e\u003ccode\u003e610f84b\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological autolink email addresses\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/9f1d73897a56cbd74c39347af351a473e70297e1\"\u003e\u003ccode\u003e9f1d738\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological HTML block attributes\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/e13297e849995fdd582a85841067bff1d9c35ee5\"\u003e\u003ccode\u003ee13297e\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing pathological backticks\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/89d1bd3fa1524e8217ed61db5e8116c82434470f\"\u003e\u003ccode\u003e89d1bd3\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing with lots of \u003ccode\u003e\u0026lt;\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/commonmark/commonmark-java/compare/commonmark-parent-0.29.0...commonmark-parent-0.30.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark-ext-autolink` from 0.29.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark-ext-autolink's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/blockquote\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003e...\n\n_Description has been truncated_","html_url":"https://github.com/essentiaMarco/openclaw-slim/pull/23","url":"https://dependabot.ecosyste.ms/api/v1/hosts/GitHub/repositories/essentiaMarco%2Fopenclaw-slim/issues/23","packages_url":"https://dependabot.ecosyste.ms/api/v1/issues/23/packages"}},{"old_version":"5.3.2","new_version":"5.5.0","update_type":"minor","path":null,"pr_created_at":"2026-09-09T23:32:25.000Z","version_change":"5.3.2 → 5.5.0","issue":{"uuid":"5405831278","node_id":"PR_kwDOS7tr488AAAABC6SmLQ","number":43,"state":"closed","title":"chore(deps): bump the android-deps group across 1 directory with 21 updates","user":"dependabot[bot]","labels":["dependencies","java"],"assignees":[],"locked":false,"comments_count":1,"pull_request":true,"closed_at":"2026-09-11T23:24:55.000Z","author_association":null,"state_reason":null,"created_at":"2026-09-09T23:32:25.000Z","updated_at":"2026-09-11T23:24:57.000Z","time_to_close":172350,"merged_at":null,"merged_by":null,"closed_by":null,"dependency_metadata":{"prefix":"chore(deps): bump","group_name":"android-deps","update_count":21,"packages":[{"name":"gradle-wrapper","old_version":"9.4.1","new_version":"9.7.1","repository_url":"https://github.com/gradle/gradle"},{"name":"androidx.core:core-ktx","old_version":"1.18.0","new_version":"1.19.0"},{"name":"org.bouncycastle:bcprov-jdk18on","old_version":"1.84","new_version":"1.85.2","repository_url":"https://github.com/bcgit/bc-java"},{"name":"org.commonmark:commonmark","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-autolink","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-strikethrough","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-tables","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-task-list-items","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"dnsjava:dnsjava","old_version":"3.6.4","new_version":"3.6.5","repository_url":"https://github.com/dnsjava/dnsjava"},{"name":"org.junit.vintage:junit-vintage-engine","old_version":"6.0.3","new_version":"6.1.3","repository_url":"https://github.com/junit-team/junit-framework"},{"name":"io.kotest:kotest-assertions-core-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"io.kotest:kotest-runner-junit5-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"org.jetbrains.kotlinx:kotlinx-coroutines-android","old_version":"1.10.2","new_version":"1.11.0","repository_url":"https://github.com/Kotlin/kotlinx.coroutines"},{"name":"org.jetbrains.kotlinx:kotlinx-coroutines-test","old_version":"1.10.2","new_version":"1.11.0","repository_url":"https://github.com/Kotlin/kotlinx.coroutines"},{"name":"com.google.android.material:material","old_version":"1.13.0","new_version":"1.14.0","repository_url":"https://github.com/material-components/material-components-android"},{"name":"com.squareup.okhttp3:mockwebserver","old_version":"5.3.2","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.squareup.okhttp3:okhttp","old_version":"5.3.2","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.android.application","old_version":"9.2.0","new_version":"9.4.0"},{"name":"com.android.test","old_version":"9.2.0","new_version":"9.4.0"},{"name":"org.jetbrains.kotlin.plugin.compose","old_version":"2.3.21","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"},{"name":"org.jetbrains.kotlin.plugin.serialization","old_version":"2.3.21","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"}],"path":null,"ecosystem":"maven"},"body":"Bumps the android-deps group with 21 updates in the /apps/android directory:\n\n| Package | From | To |\n| --- | --- | --- |\n| [gradle-wrapper](https://github.com/gradle/gradle) | `9.4.1` | `9.7.1` |\n| androidx.core:core-ktx | `1.18.0` | `1.19.0` |\n| [org.bouncycastle:bcprov-jdk18on](https://github.com/bcgit/bc-java) | `1.84` | `1.85.2` |\n| [org.commonmark:commonmark](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-autolink](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-strikethrough](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-tables](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-task-list-items](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [dnsjava:dnsjava](https://github.com/dnsjava/dnsjava) | `3.6.4` | `3.6.5` |\n| [org.junit.vintage:junit-vintage-engine](https://github.com/junit-team/junit-framework) | `6.0.3` | `6.1.3` |\n| [io.kotest:kotest-assertions-core-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [io.kotest:kotest-runner-junit5-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [org.jetbrains.kotlinx:kotlinx-coroutines-android](https://github.com/Kotlin/kotlinx.coroutines) | `1.10.2` | `1.11.0` |\n| [org.jetbrains.kotlinx:kotlinx-coroutines-test](https://github.com/Kotlin/kotlinx.coroutines) | `1.10.2` | `1.11.0` |\n| [com.google.android.material:material](https://github.com/material-components/material-components-android) | `1.13.0` | `1.14.0` |\n| [com.squareup.okhttp3:mockwebserver](https://github.com/lysine-dev/okhttp) | `5.3.2` | `5.5.0` |\n| [com.squareup.okhttp3:okhttp](https://github.com/lysine-dev/okhttp) | `5.3.2` | `5.5.0` |\n| com.android.application | `9.2.0` | `9.4.0` |\n| com.android.test | `9.2.0` | `9.4.0` |\n| [org.jetbrains.kotlin.plugin.compose](https://github.com/JetBrains/kotlin) | `2.3.21` | `2.4.20` |\n| [org.jetbrains.kotlin.plugin.serialization](https://github.com/JetBrains/kotlin) | `2.3.21` | `2.4.20` |\n\n\nUpdates `gradle-wrapper` from 9.4.1 to 9.7.1\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/gradle/gradle/releases\"\u003egradle-wrapper's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e9.7.1\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.1.\u003c/p\u003e\n\u003cp\u003eThis is a patch release for 9.7.0. We recommend using 9.7.1 instead of 9.7.0.\u003c/p\u003e\n\u003cp\u003eHere are the highlights of 9.7.0 release:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIsolated Projects graduates to incubating\u003c/li\u003e\n\u003cli\u003eBroader Configuration Cache compatibility\u003c/li\u003e\n\u003cli\u003eResilient Sync helps you fix broken builds\u003c/li\u003e\n\u003cli\u003eMore source locations in problem reports\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003ca href=\"https://docs.gradle.org/9.7.1/release-notes.html\"\u003eRead the Release Notes\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eWe would like to thank the following community members for their contributions to this release of Gradle:\n\u003ca href=\"https://github.com/aSemy\"\u003eAdam\u003c/a\u003e,\n\u003ca href=\"https://github.com/Gautam-aman\"\u003eAman Gautam\u003c/a\u003e,\n\u003ca href=\"https://github.com/YukiCodepth\"\u003eAman Kumar\u003c/a\u003e,\n\u003ca href=\"https://github.com/adubrouski\"\u003eAnton Dubrouski\u003c/a\u003e,\n\u003ca href=\"https://github.com/liutikas\"\u003eAurimas\u003c/a\u003e,\n\u003ca href=\"https://github.com/gbhavya07\"\u003egbhavya07\u003c/a\u003e,\n\u003ca href=\"https://github.com/joshfriend\"\u003eJosh Friend\u003c/a\u003e,\n\u003ca href=\"https://github.com/nicklauslittle-gov\"\u003enicklauslittle-gov\u003c/a\u003e,\n\u003ca href=\"https://github.com/psoni674\"\u003ePragati\u003c/a\u003e,\n\u003ca href=\"https://github.com/Project516\"\u003eproject516\u003c/a\u003e,\n\u003ca href=\"https://github.com/Uomocapra\"\u003eQin Mi\u003c/a\u003e,\n\u003ca href=\"https://github.com/rkdfx\"\u003eRavi\u003c/a\u003e,\n\u003ca href=\"https://github.com/sk-reddy17\"\u003esk-reddy17\u003c/a\u003e,\n\u003ca href=\"https://github.com/Suvrat1629\"\u003eSuvrat Acharya\u003c/a\u003e,\n\u003ca href=\"https://github.com/ShreckYe\"\u003eYongshun Ye\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eUpgrade instructions\u003c/h2\u003e\n\u003cp\u003eSwitch your build to use Gradle 9.7.1 by updating your wrapper:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e./gradlew :wrapper --gradle-version=9.7.1 \u0026amp;\u0026amp; ./gradlew :wrapper\r\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eSee the Gradle \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/upgrading_version_9.html\"\u003e9.x upgrade guide\u003c/a\u003e to learn about deprecations, breaking changes and other considerations when upgrading.\u003c/p\u003e\n\u003cp\u003eFor Java, Groovy, Kotlin and Android compatibility, see the \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/compatibility.html\"\u003efull compatibility notes\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eReporting problems\u003c/h2\u003e\n\u003cp\u003eIf you find a problem with this release, please file a bug on \u003ca href=\"https://github.com/gradle/gradle/issues\"\u003eGitHub Issues\u003c/a\u003e adhering to our issue guidelines.\nIf you're not sure you're encountering a bug, please use the \u003ca href=\"https://discuss.gradle.org/c/help-discuss\"\u003eforum\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eWe hope you will build happiness with Gradle, and we look forward to your feedback via \u003ca href=\"https://twitter.com/gradle\"\u003eTwitter\u003c/a\u003e or on \u003ca href=\"https://github.com/gradle\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003e9.7.0\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.0.\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/92f0512e7f06d84621afba191f75e265363890cf\"\u003e\u003ccode\u003e92f0512\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38892\"\u003e#38892\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/820ee75a99a179bbffa41bcedc6477b685fabb9f\"\u003e\u003ccode\u003e820ee75\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/82c23f9bd2a89b4cc644e1f90a28a8668feb3dee\"\u003e\u003ccode\u003e82c23f9\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering problem in KTS (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38878\"\u003e#38878\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/ef11a7268fe8cc8d6ab849ec911aa11220180553\"\u003e\u003ccode\u003eef11a72\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering issue\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/bb0d8a974a71b1003efea41e4046e98855cd5ff8\"\u003e\u003ccode\u003ebb0d8a9\u003c/code\u003e\u003c/a\u003e Make relevant tests polyglot (run for multiple DSLs)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/336e129d7f95c03486acafc97abf59734acfed48\"\u003e\u003ccode\u003e336e129\u003c/code\u003e\u003c/a\u003e Update signing configuration (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38874\"\u003e#38874\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/4bdf0da2dad9884d089a6062a45ea7183e7d735d\"\u003e\u003ccode\u003e4bdf0da\u003c/code\u003e\u003c/a\u003e Update signing configuration\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/cd9b92c1b82856248cf1dc58b50378238bec7b52\"\u003e\u003ccode\u003ecd9b92c\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38839\"\u003e#38839\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/5f4e381964897ad8d6b99e5a7c77f26dba3259fb\"\u003e\u003ccode\u003e5f4e381\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/1e08ab551367aeb5fb48b26e72807e1d2b27c939\"\u003e\u003ccode\u003e1e08ab5\u003c/code\u003e\u003c/a\u003e Keep type-use annotations in extracted ABI classes (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38810\"\u003e#38810\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/gradle/gradle/compare/v9.4.1...v9.7.1\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `androidx.core:core-ktx` from 1.18.0 to 1.19.0\n\nUpdates `org.bouncycastle:bcprov-jdk18on` from 1.84 to 1.85.2\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.md\"\u003eorg.bouncycastle:bcprov-jdk18on's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch1\u003eBouncy Castle Crypto Package - Release Notes\u003c/h1\u003e\n\u003ch2\u003e1.0 Introduction\u003c/h2\u003e\n\u003cp\u003eThe Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. The package is organised so that it contains a light-weight API suitable for use in any environment (including the J2ME) with the additional infrastructure to conform the algorithms to the JCE framework.\u003c/p\u003e\n\u003ch2\u003e2.0 Release History\u003c/h2\u003e\n\u003cp\u003e\u003c!-- raw HTML omitted --\u003e\u003c!-- raw HTML omitted --\u003e\u003c/p\u003e\n\u003ch3\u003e2.1.1 Version\u003c/h3\u003e\n\u003cp\u003eRelease: 1.86\u003cbr /\u003e\nDate: 2026, TBD\u003c/p\u003e\n\u003ch3\u003e2.1.2 Defects Fixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) let a subkey inherit the primary key's Key Flags when its own Subkey Binding signature carried no Key Flags subpacket, which made the two capability decisions taken for one subkey disagree. OpenPGPCertificate.OpenPGPComponentKey.isSigningKey() reads the effective flags, which fell back to the primary key's direct-key or primary user ID self-signature, so a subkey bound with no flags of its own counted as signing-capable; verifyEmbeddedPrimaryKeyBinding reads the binding signature's own flags, found no signing capability there, and so skipped the embedded Primary Key Binding (cross-certification) signature that RFC 9580 sec. 5.2.1.8 and sec. 10.1.3 require of a subkey that can issue signatures. A data signature made by such a subkey was therefore attributed to the certificate and reported valid by OpenPGPSignature.OpenPGPDocumentSignature.isValid() with the cross-certification requirement never applied, where GnuPG refuses the same certificate and message as not cross-certified. An attacker holding a third party's public signing subkey - which is public material - could bind it to their own primary key with a Subkey Binding signature they are able to make, carrying no Key Flags and no embedded Primary Key Binding signature, which they cannot make without the subkey's private key, and have that party's genuine signatures verify as valid under the attacker's own identity: misattribution of a real signature rather than a forgery of a new one, since the signature still has to be one the subkey actually made. Key Flags are a statement about the key the carrying signature refers to (RFC 9580 sec. 5.2.3.29), so a subkey no longer inherits them from the certificate-wide signatures of the primary key: a Subkey Binding signature that omits the subpacket now leaves the subkey with no capabilities rather than the primary's, which makes the flags the cross-certification check consults the same flags every other decision consults. Preferences and the other subpackets a direct-key signature carries are inherited as before, and the primary key itself - whose flags legitimately come from its direct-key or user ID self-signature - is unaffected. The low-level PGPSignature / PGPPublicKeyRing API performs no binding checks by design and is unchanged.\u003c/li\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) used a version 6 key that carried no valid Direct Key signature, falling back to the primary user ID binding as it correctly does for a version 4 key. RFC 9580 sec. 5.2.3.10 requires the opposite: \u0026quot;An implementation MUST ensure that a valid Direct Key signature is present before using a version 6 key. This prevents certain attacks where an adversary strips a self-signature specifying a Key Expiration Time or certain preferences.\u0026quot; The certificate grammar says the same structurally, the Direct Key signature being mandatory in the version 6 structure of sec. 10.1.1 and optional in the version 4 one of sec. 10.1.3. Because a version 6 certificate carries its key expiration, features and algorithm preferences on the Direct Key signature - the convention the RFC recommends and the one OpenPGPKeyGenerator follows, its user ID certification carrying no expiration at all - removing that single signature packet from a published certificate silently dropped the expiration along with the preferences and features: OpenPGPCertificate.getSignatureChainFor fell back to the user ID binding, the primary key was still reported bound, and getEncryptionKeys() and getSigningKeys() went on returning the subkeys of a key whose owner had set it to expire. The primary key fingerprint is unchanged by the removal, so a relying party pinning the key by fingerprint still treats it as the same key, and no private key or hash collision is involved; the natural moment for the strip is the key refresh that RFC 9580 names as the reason to refetch a key at all - to learn about changes in expiration, features, preferences and revocation - which is exactly the update it defeats. This is a downgrade rather than a forgery, nothing being attributed to a key that did not authorise it, and the concerning direction is encryption, to a key meant to have been retired. OpenPGPCertificate.isBoundBy now requires a valid Direct Key self-signature on a version 6 primary key before any component of the certificate - the primary key, its subkeys or its identities - is treated as bound, so a version 6 certificate stripped of it offers no keys at all rather than an unexpiring set. Version 4 certificates are unaffected: there the key expiration legitimately lives on the user ID self-signature and the fallback is correct, so it stays. The revocation-only version 6 certificate of sec. 10.1.2, which legitimately carries no Direct Key signature, is unaffected as well - its key was already refused as revoked, and reading the revocation does not go through the binding check.\u003c/li\u003e\n\u003cli\u003eThe lightweight LMSSigner and HSSSigner refused a key wrapped in ParametersWithRandom, which is how BcContentSignerBuilder passes a key whenever setSecureRandom() has been called - so BcHssLmsContentSignerBuilder built a working signer until a random was set and then failed with \u0026quot;Incorrect Key Parameters\u0026quot;, and the two signers themselves raised ClassCastException on the same input. All three now unwrap it, as the promoted ML-DSA and SLH-DSA signers already did. The random is accepted and not used: LMS derives its message randomiser C from the key's seed and the one-time index, so it is deterministic and cannot repeat while q does not. Note SP 800-208 sec. 6.1 asks for C to come from an approved random bit generator, which this implementation does not do; that is unchanged here, and a supplied random is now ignored rather than refused.\u003c/li\u003e\n\u003cli\u003eLMS signature verification did not apply two of the checks RFC 8554 sec. 5.4.2 requires before a signature is processed. Step 2g refuses a signature whose LMS typecode is not the one from the public key, and without it the path computation took its height and tree digest from the parameter set the signature named rather than the key's, so a signature claiming a height-25 parameter set drove a 25-level computation against a height-5 key. Step 2i refuses a leaf number q outside the tree, and without it an out-of-range q flowed into the node arithmetic and was left for the candidate-root comparison to catch. Neither was a forgery - the domain separation between D_LEAF and D_INTR and the final comparison saw to that - but both are attacker-chosen work the specification says to refuse up front. Both are now checked, and a signature failing either is still reported as not verifying rather than thrown out of Signature.verify(). The catch around the signature decode in LMSSigner and HSSSigner has also been narrowed to the decode itself, as the corresponding SPI was corrected to do for github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2408\"\u003e#2408\u003c/a\u003e: past the parse the engine reports an inconsistent signature by returning false rather than by throwing, so the wider catch caught nothing while standing ready to turn a future internal error into a quiet false.\u003c/li\u003e\n\u003cli\u003eThe LMS and HSS key parameter classes now apply at construction the checks their decoders apply, so a key built directly cannot be one the decoder would refuse. LMSPrivateKeyParameters accepted an identifier of any length although the decoder reads exactly 16 bytes - such a key encoded but could not be read back - and left q, maxQ and the seed length unchecked; the seed is now required to be at least m bytes at decode as well, where a one-byte seed had been decoding silently and then deriving every one-time key from it. HSSPrivateKeyParameters checked neither its level count nor that it had been given a component key per level and a chaining signature per level below the root, and then indexed both lists, so a mismatch surfaced as IndexOutOfBoundsException - or, where a level happened to match, as a null chaining signature that only failed at signing time; the level is now checked after the reset that fills it in, since a null is legitimate on the way in. LMSPrivateKeyParameters.getInstance(byte[], byte[]) adopted the public key supplied beside the private one without comparing them, so a mismatched public key was simply reported by getPublicKey(); it now cross-checks the identifier, both parameter sets and, where the tree cache already holds it, the root, as the HSS entry point does. The decoders also now report a bad version or seed length as IOException rather than IllegalStateException, so a caller can catch one type for a malformed key, and the package-private LM-OTS public key decoder no longer declares throws Exception or dereferences an unrecognised typecode. The deprecated org.bouncycastle.pqc.crypto.lms copies carry the decoder corrections.\u003c/li\u003e\n\u003cli\u003eIn the LMS JCE layer, LMSKeyGenParameterSpec.fromNames knew all twenty LMS parameter-set names but only four of the sixteen LM-OTS ones, so none of the SP 800-208 n24 or SHAKE sets could be named; all sixteen are now present. KeyPairGenerator.initialize(int, SecureRandom) reports InvalidParameterException, which is what the JCA specifies and which extends the IllegalArgumentException it raised before, so existing catches still match. BCLMSPrivateKey.getIndex now takes the exhaustion check and the index read under the key's own monitor rather than as two separate calls, and two unused fields have gone from LMSSignatureSpi. Note that the LMS Signature claims its one-time key at the first update() rather than at sign(), so a Signature that is initialised and updated and then abandoned spends an index without producing a signature - the safe direction for a one-time scheme, and now documented on the SPI.\u003c/li\u003e\n\u003cli\u003eEvery other key pair generator that refuses a key size did the same thing the LMS one did above. KeyPairGenerator.initialize(int, SecureRandom) is documented to raise InvalidParameterException when the key size is not one the generator supports, and thirty of them raised a bare IllegalArgumentException instead, so a caller following the JCA and catching the documented type saw an exception escaping rather than a refusal. The ML-DSA, ML-KEM, SLH-DSA, Classic McEliece, FrodoKEM, NTRU and composite signature and KEM generators in the BC provider, and every generator in BCPQC, now raise InvalidParameterException - NewHope included, where the value is a key size it will not take rather than a mode of initialisation it does not offer. InvalidParameterException extends IllegalArgumentException, so callers written against the old behaviour go on catching it unchanged. The two RSA generators are corrected as well, and differently: theirs is a key size below a floor rather than a mode of initialisation they do not offer, and the refusal is raised by the lightweight RSAKeyGenerationParameters, which cannot name a java.security exception at all, so the RSA KeyPairGeneratorSpi now translates it - keeping the message verbatim and the original exception as the cause, through a new SecurityExceptions.invalidParameterException factory, since InvalidParameterException has no constructor that takes one. Of the 304 KeyPairGenerator services the two providers register, 299 now refuse a nonsense key size the way the JCA defines it and five accept it as a strength they can work with, with none left raising a bare IllegalArgumentException; that is asserted as a sweep over both providers rather than per algorithm, so a generator added later is covered without the test being touched. The jdk1.3 provider overlays of the four generators that have one carry the same change, and the jdk1.3 SecurityExceptions overlay gains the new factory along with the invalidAlgorithmParameterException one it had been missing.\u003c/li\u003e\n\u003cli\u003eKeyPairGenerator.initialize(AlgorithmParameterSpec, SecureRandom) had the same shape of problem as the int overload above, and only 44 of the 304 services the two providers register reported an unusable spec as the InvalidAlgorithmParameterException that method declares. The twenty-three PQC generators that resolve a parameter set by name - cmce, frodokem, mldsa, mlkem, slhdsa, aimer, bike, faest, falcon, haetae, hqc, mayo, mqom, ntru, ntruplus, both ntruprime variants, qruov, saber, sdith, smaugt, snova and sqisign, 230 services between them - case-folded the name they got back from the spec without checking it, so a spec with no getName() method, and a null spec, produced a NullPointerException from inside the fold; their own \u0026quot;is this name one I know\u0026quot; branch, which does report the declared exception, was unreachable. The two composite generators, whose parameter set is fixed by the algorithm name so that null is the only spec they accept, refused every other one with IllegalArgumentException. RSA answered correctly for a spec of the wrong type but not for one of the right type carrying values its lightweight parameters will not take - an even public exponent, or a key size below the floor - which is now translated the same way the int overload's is. All 304 services now report the declared exception, with the composites still taking the null spec that is right for them; note that InvalidAlgorithmParameterException is a checked exception and not an IllegalArgumentException, so a caller that was catching what these threw before has to catch the declared type instead.\u003c/li\u003e\n\u003cli\u003eAn HSS private key claimed the two records of its position under two different monitors. The top-level index and the bottom component key's one-time index q are independent records of the same position - the decoder requires them to agree, see the entry below - but generateLMSContext incremented the index under the HSS key's own monitor, released it, and only then claimed q under the component key's. A getEncoded() issued in between saw the index advanced and q not, and produced an encoding this implementation's own decoder rejects; and two threads meeting at a bottom-tree boundary could both pass the exhaustion test, take consecutive top-level indices and claim the same q, after which one of them was refused with \u0026quot;ots private key exhausted\u0026quot; by a key still reporting usages remaining, a top-level index had been spent with no signature made, and the two records stayed one apart for the rest of the key's life in that process - so it could no longer be encoded, cloned or sharded, and getIndex() and getUsagesRemaining() misreported by one. No one-time key was reused: the component key's claim is itself atomic, and the divergence runs index ahead of leaves, so the effect was on the key's usability rather than on the signatures it had made. Both records are now claimed under the one monitor, and the component key is claimed before the index is incremented so that an exhausted one leaves both untouched. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the same correction.\u003c/li\u003e\n\u003cli\u003eTimeStampToken parsed the attacker-controlled TSTInfo content of a time-stamp token (org.bouncycastle.tsp.TimeStampToken, reached from TimeStampResponse(byte[]) and (InputStream)) inside a try that caught only CMSException, so a well-formed RFC 3161 TimeStampResp whose embedded token carried a malformed TSTInfo - a SEQUENCE with fewer elements than the five mandatory fields, a non-SEQUENCE, truncated DER, or an unknown context tag - let an IllegalArgumentException or a NoSuchElementException escape the constructor's declared throws TSPException, IOException contract. A token signed by no signers or by more than one raised a bare IllegalArgumentException from the same constructor, before that try, for the same reason. Both are now reported as TSPException, matching the package-private TimeStampResponse(DLSequence) constructor and the existing getSignedAttributes guard in the same method; the signer-count refusal is a TSPValidationException, as the neighbouring check on the content type already was. Related, and the cause of the NoSuchElementException: asn1.tsp.TSTInfo read its five mandatory fields off the sequence with no bound on how many elements were actually there, so a short SEQUENCE left the enumeration to run out rather than being refused, and an oversize one was accepted with its extra elements absorbed into the optional slots. Decode now requires the five to ten elements RFC 3161 sec. 2.4.2 gives the type, which is what the sibling Accuracy and ArchiveTimeStamp decoders already did, so the failure is the IllegalArgumentException that getInstance is expected to raise (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2415\"\u003e#2415\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eNeither the HSS nor the XMSS^MT private key decoder checked its declared index against the traversal state stored beside it, although the two are independent records of the same position in the key and so can be compared. For HSS the records are the top-level index and the component keys' one-time indices q; for XMSS^MT they are the global index and the per-layer BDS states. A stored key whose index had been rolled back while its state stayed advanced - a partial write, a restore from backup, a buggy storage layer - was therefore accepted, and it then signed a second message under a one-time key the key had already used, producing a signature that verified, so nothing anywhere surfaced the reuse. RFC 8554 sec. 1 and RFC 8391 sec. 1.1 both require each one-time key to be used exactly once, and this is the failure those requirements exist to prevent; the single-tree XMSS decoder has tied its BDS state to its index since that state was first validated, and this brings the two multi-tree schemes into line. HSS decode now requires the declared index to equal the position the component q values imply - a level above the last contributes (q - 1) leaves of the levels beneath it, since its q has already advanced past the subtree it signed - and XMSS^MT decode now requires each present layer's BDS index to equal the leaf index that layer derives from the global index, allowing the one position where a layer has moved into a new subtree and its state legitimately still carries the previous subtree's final index. A layer with no state yet is unaffected, since those are built lazily at signing time. Related, and the same shape of omission: an XMSS or XMSS^MT private key encoding carries the tree root twice - the key's own root field and the root node of the BDS state stored beside it, which for XMSS^MT is the top layer's - and the two were never compared either. A corrupted root was accepted and then poisoned every signature the key made, because the root is hashed into the message digest: the signature did not verify and nothing indicated why. Decode now requires the two copies to agree. The BDS node values themselves are not checkable the way the LMS tree cache above is - a BDS authentication path, stack, retain or keep node does not have its children stored alongside it, so recomputing one means building a subtree, which is the work the state exists to avoid. Both checks are integer comparisons over the levels of the key, too small to measure against the surrounding decode, and both were verified not to reject any legitimate key by walking every index a key can reach: the full key space of the two-level HSS and the h=4/d=2, h=6/d=2, h=6/d=3, h=9/d=3 and h=8/d=4 XMSS^MT parameter sets, plus a three-level HSS key across a subtree boundary and an HSS shard. Since those node values cannot be recomputed, the encoded state now carries a checksum over itself instead, with the owning key's public seed hashed in front of it. Any corruption of the stored state is refused at decode rather than being loaded and then producing signatures that silently do not verify, and because the public seed is bound in, a state transplanted between two keys of the same parameter set is refused too, even though it is internally consistent and arrives with its own matching root. The public seed is bound rather than the secret seed or the PRF key deliberately: the state's own root and index are inside the encoding and so are already covered, hashing secret material would make the stored checksum a commitment to it for no gain in detection, and the PRF key does not influence the state at all. \u003cstrong\u003eThis is an error-detecting code and not integrity protection\u003c/strong\u003e - anyone able to rewrite the stored key recomputes it, so it establishes that the state is unchanged since it was written, never that it was correct when written, and the allocation bounds on the encoding remain the guard against a crafted one. It costs one SHA-256 over the state, measured at 5 to 8 microseconds each way for the h=10 and h=16 parameter sets, and 32 bytes of encoding. The state encoding was added earlier in this same cycle and has not been released, so the checksum is simply part of it rather than a new version: a state written by a 1.86 beta is rejected, which is recovered from by re-exporting the key. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the HSS check as well (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2414\"\u003e#2414\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe S/MIME example smoke test in the misc module (org.bouncycastle.mail.smime.examples.test.AllTests) drove SendSignedAndEncryptedMail against smtp.gmail.com, and that example finishes with Transport.send() under JavaMail's default settings, which have no connect timeout. Where outbound port 25 is refused the failure was swallowed and the test passed; where it is silently dropped, as on many home networks, the connect blocked and ./gradlew build hung in :misc:test indefinitely with \u0026quot;0 tests completed\u0026quot;. The test now delivers to an SMTP stub on a loopback port, with connect / read / write timeouts as a backstop, and asserts the message arrived (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2407\"\u003e#2407\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation took the traditional component public key bytes it feeds the KEM combiner from the recipient key's own encoding, while decapsulation recomputes the point from the private key and so always produced an uncompressed one. Section 4 of draft-ietf-lamps-pq-composite-kem requires an EC component to be carried as an uncompressed point, but a component key that encodes itself compressed - a BC EC key whose point format has been set through org.bouncycastle.jce.interfaces.ECPointEncoder, or a key from a provider that preserves a compressed encoding - was passed through as it came. Both sides then combined a different tradPK and derived different shared secrets, with no error reported on either: encapsulation and decapsulation both succeeded and the recipient simply could not decrypt. The EC component is now normalised to an uncompressed point wherever the engine serialises one, which covers the ephemeral key that forms the ciphertext as well. X25519 and X448 components have a single encoding and were unaffected, as were EC keys left in their default (uncompressed) format, whose shared secrets are unchanged. CompositePublicKey.getEncoded() took its component bytes the same way, so such a key also encoded to a composite key other implementations reject and whose bytes changed across an encode / decode / encode round trip - 1238 bytes rather than 1270 for MLKEM768-ECDH-P256, and for the composite ML-DSA keys sharing that method, 2006 rather than 2038 for MLDSA65-ECDSA-P256. It now normalises the component the same way. This is a write-side change only: a composite key carrying a compressed EC component is still decoded, since the component key factories accept either form, and continues to verify signatures as before - it simply re-encodes in the normalised form. The shared normalisation is org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil.getUncompressedSubjectPublicKeyBytes.\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation threw a NullPointerException, wrapped in an IllegalStateException out of KeyGenerator.generateKey(), when the SecureRandom it was given was null - which javax.crypto.KEM.newEncapsulator() documents as a request for the provider's default, and which KeyGenerator.init(spec, null) passes straight through. The three RSA-OAEP composites draw the traditional shared secret from that random directly, so they were the ones affected; the ECDH and X25519 / X448 composites escaped only because their component KeyPairGenerators default a random of their own. CompositeMLKEMEngine now defaults one through CryptoServicesRegistrar.getSecureRandom() on first use, as the composite KEM Cipher's wrap path already did, and as the KEM generators corrected earlier in this cycle now do. Related, the engine now also clears the ML-KEM component's shared secret alongside the traditional one on both the encapsulate and decapsulate paths - the copy handed back by getEncoded() was left in the heap - as section 3.5 of draft-ietf-lamps-pq-composite-kem requires.\u003c/li\u003e\n\u003cli\u003eCompositePublicKey.getAlgorithm() and CompositePrivateKey.getAlgorithm() returned null for all twelve Composite ML-KEM (draft-ietf-lamps-pq-composite-kem) parameter sets. Both classes resolved the name through the composite signature index only, which holds the composite ML-DSA OIDs, so a composite KEM key pair - generated, parsed from a certificate, or read from PKCS#8 - reported no algorithm at all, and the standard JCA idiom of reconstructing a key with KeyFactory.getInstance(key.getAlgorithm()) raised a NullPointerException. The lookup now falls back to the composite KEM index, so the name returned is the one the provider registers the algorithm under (e.g. MLKEM768-X25519-SHA3-256), matching the composite ML-DSA behaviour. The same single-index assumption made the CompositePublicKey(SubjectPublicKeyInfo) and CompositePrivateKey(PrivateKeyInfo) constructors reject a composite KEM key with \u0026quot;unable to create CompositePublicKey from SubjectPublicKeyInfo\u0026quot;; they now dispatch to the composite KEM key factory for those OIDs. Keys obtained through KeyFactory or through BouncyCastleProvider.getPublicKey / getPrivateKey were unaffected and are unchanged (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2404\"\u003e#2404\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe org.bouncycastle.jcajce.spec.KEMKDFSpec constructor stored a null otherInfo as given, so getOtherInfo() returned null, and three of the KDF branches KdfUtil.makeKeyBytes dispatches to - KMAC-128, KMAC-256 and SHAKE-256 - read the otherInfo length without a guard and threw NullPointerException out of the KEM operation, where the KDF2, KDF3 and HKDF branches tolerate a null through KDFParameters / HKDFParameters. The Builder of every spec in the package already mapped null to empty, so no provider path reached it, but the constructor is protected on a public class and KdfUtil is documented for callers building their own KEM integration; the deprecated KEMParameterSpec passes a null itself and escaped only because it also pins the KDF to null. The constructor now stores empty for a null, so getOtherInfo() never returns null, and a null and an explicitly empty otherInfo derive the same key.\u003c/li\u003e\n\u003cli\u003eQR-UOV signature verification accepted a signature encoding that was not canonical, so the encoding of a signature was not unique even after the trailing-byte fix of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e. Each F_q element of the signature is stored in ceil(log2 q) bits, one more bit pattern than the field has elements: q itself is representable and is arithmetically congruent to zero, so an element written as q verified exactly as the same element written as zero would, and the bits padding the last element out to the byte boundary were never read at all. Every zero element of a signature therefore carried a second encoding, and for the q = 7 parameter sets roughly one element in seven is zero - a single qruov_5_q7_L10 signature measured 256 spare bits, so on the order of 2^256 distinct byte strings verified for the one message and key. Verification now rejects any element outside [0, q) and any set padding bit; a signature produced by this or by the reference implementation is unaffected, as the KAT vectors of every parameter set confirm. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSNOVA signature verification ignored four bits inside the signature for any parameter set whose solution is an odd number of GF(16) nibbles - the SNOVA_24_5_5, SNOVA_25_8_3, SNOVA_29_6_5 and SNOVA_66_15_3 families, sixteen of the forty-four parameter sets. The last byte of the encoded solution carries a single nibble and the signer leaves the top four bits zero, but the decoder did not read them, so sixteen distinct byte strings verified for one signature. This is the same non-unique encoding github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e closed for bytes following the signature, applied inside it; the verifier now requires those bits to be zero. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSnovaPrivateKeyParameters did not validate the length of the private key encoding handed to it - the only one of the five schemes of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e that did not - and SnovaParameters.getPrivateKeyLength() reported the expanded (\u0026quot;ESK\u0026quot;) length even for a parameter set whose private key is the seed pair. A private key encoding reaches this constructor straight from a PKCS#8 blob, so a wrong length went undetected: a seed-form key with extra bytes appended was accepted and signed under a different derived key, and a short expanded-form key sized the signer's decode buffer negatively, throwing NegativeArraySizeException out of generateSignature() rather than being reported at construction. Related, the signing retry loop could not terminate: the vinegar values are derived from a single-byte counter, so only 256 distinct linear systems can be tried, and an expanded-form private key that is not a real central map is singular for all of them - generateSignature() then span forever rather than failing. The length is now checked at construction, getPrivateKeyLength() reports the length that parameter set's private key actually has, and the retry loop gives up after its 256 attempts as MAYO's does.\u003c/li\u003e\n\u003cli\u003eMayoSigner and MayoKeyPairGenerator did not clear several buffers holding secret key material that the MAYO reference implementation explicitly clears. Signing left the secret oil space O, the expanded L = (P1 + P1^t) * O + P2, and the M / VPV / Ox intermediates of the central map in place, having gone to the trouble of clearing eleven other buffers; key generation left the expanded seed, whose tail is the encoded oil space, and the P1 * O + P2 half of P; and the row-echelon step left the packed echelon form of the secret linear system and its pivot rows. Separately, if all 256 attempts at solving for the signature had given a rank-deficient system, signing emitted a signature built from the failed attempt's state instead of reporting the failure the reference returns, and AIMerSigner.generateSignature returned an empty array on failure, which a caller would hand on as though it were a signature. Both now throw.\u003c/li\u003e\n\u003cli\u003eFive PQC signature schemes - MAYO, SNOVA, QR-UOV, SQIsign and AIMer - returned the NIST crypto_sign \u0026quot;sm\u0026quot; signed-message envelope from generateSignature() rather than the signature. That envelope is an artefact of the reference KAT harness, which records the message alongside the signature so a vector file can be self-contained; it is not part of any of the five specifications, and no other BC signer emits it (Falcon's KAT test rebuilds the equivalent envelope in the test, which is where it belongs). Two consequences followed, both reaching the JCA Signature services of every parameter set of the five schemes in BouncyCastlePQCProvider. First, since the message was appended to the signature, verification had to skip whatever followed the signature proper, and it did so by checking only that the buffer was long enough - so any number of trailing bytes could be added to a valid signature, or the appended message replaced with unrelated data, and it still verified. A signature encoding was therefore not unique: anyone holding one valid signature could produce unlimited distinct byte strings that all verified for the same message and key, which breaks any use that treats the signature bytes as an identifier, deduplicates on them, or records them as evidence. Second, the envelope propagated into everything built on the operator layer: because ContentSigner hands the signature straight into the structure being signed, every X.509 certificate, CRL, CMS SignedData and TLS CertificateVerify BC produced with one of these algorithms carried a verbatim copy of the signed data inside its own signature field - a self-signed MAYO-1 certificate came to 3567 bytes where the same certificate is now 2020 - which no other implementation can parse as a signature, and which in a detached CMS signature meant the \u0026quot;detached\u0026quot; signature carried the content. generateSignature() now returns the bare signature, and verifySignature() requires exactly the parameter set's signature length, so appended or truncated data is rejected rather than ignored. \u003cstrong\u003eThis is a behavioural change for signatures produced by an earlier release\u003c/strong\u003e - MAYO and SNOVA from 1.84, QR-UOV, SQIsign and AIMer from 1.85 - which are no longer accepted in the envelope form they were emitted in; the signature bytes themselves are unchanged, so a stored value can be recovered by taking the leading signature-length bytes, or for AIMer, whose envelope was message || signature rather than signature || message, the trailing ones. The KAT tests now rebuild the envelope before comparing against the vector files, which continue to record it. Note that AIMer's verification had already been made length-exact during this cycle (see the entry below relating to github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2401\"\u003e#2401\u003c/a\u003e), so of the five only its envelope remained (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe MLS implementation did not bind an X.509 credential to the LeafNode's signature_key. LeafNode.verify() checked a leaf's signature against the signature_key declared in the leaf itself, while the X.509 credential's certificate chain was stored but never parsed or checked, so the certificate's public key was never required to match signature_key (RFC 9420 sec. 5.3). A leaf could therefore carry one party's certificate while being signed by an unrelated key and still be accepted under that party's identity through KeyPackage.verify() and the Group leaf-validation path. LeafNode.verify() now requires the end-entity certificate's subject public key, in the cipher suite's signature encoding, to equal signature_key for an X.509 credential, and rejects the leaf otherwise - including an empty chain or a certificate whose key type does not match the cipher suite; certificate-chain and identity validation to a trust anchor remain the application's responsibility per RFC 9420 sec. 5.3.1. A public org.bouncycastle.mls.codec.Certificate(byte[]) constructor and a Credential.getCertificates() accessor are added so callers can build and inspect X.509 credentials. Basic credentials are unaffected.\u003c/li\u003e\n\u003cli\u003eThe SecureRandom supplied to org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder.setSecureRandom() did not drive the content IV / nonce for any algorithm other than RC2. EnvelopedDataHelper.generateParameters passed the caller's SecureRandom to the AlgorithmParameterGenerator only in the RC2_CBC branch; every other content-encryption algorithm - AES-CBC, AES-GCM, AES-CCM, Camellia, ARIA, SEED and the rest - reached pGen.generateParameters() on an uninitialised generator, so the IV / nonce was drawn from a default SecureRandom and setSecureRandom() was silently ignored (the builder's javadoc states that random is used for IV/nonce generation). The generator is now initialised with the supplied random on the general path as well, so a caller who provides a specific randomness source - for a controlled or FIPS-approved DRBG, say - has it honoured for the content IV / nonce. The session-key generation path was unaffected and already used the supplied random. Because the content IV / nonce now comes from the supplied SecureRandom, the org.bouncycastle.crypto.util JournalingSecureRandom / JournaledAlgorithm reproducible-encryption support records it in the transcript: a resumed session reproduces the IV / nonce by regenerating it from the replayed randomness - build the resuming encryptor from the content-algorithm OID - rather than by reusing the AlgorithmIdentifier captured from the first encryption, which no longer keeps the transcript aligned.\u003c/li\u003e\n\u003cli\u003eThe NTRU LPRime, NTRU+ and SMAUG-T KEM generators threw a NullPointerException when constructed with a null SecureRandom, where every other KEM generator - including NTRU LPRime's own SNTRU Prime counterpart in the same package - defaults one through CryptoServicesRegistrar.getSecureRandom(). This is reachable from the lightweight API directly, and from javax.crypto.KEM, whose newEncapsulator() documents a null random as a request for the provider's default.\u003c/li\u003e\n\u003cli\u003eFrodoKEMEngine kept a single SHAKE instance in a field, so an engine reached concurrently produced wrong results. It is reached that way through org.bouncycastle.crypto.kems.FrodoKEMExtractor, which holds one engine for its lifetime: two threads extracting through one extractor interleaved the digest's absorb and squeeze phases, yielding shared secrets that silently did not match the sender's, or an IllegalStateException of \u0026quot;attempt to absorb while squeezing\u0026quot; from inside extractSecret. The digest is now built per call, as CMCEEngine's already was, which makes an extractor safe to share. Encapsulation was unaffected, since FrodoKEMGenerator builds an engine per call. Results for any single-threaded use are unchanged - the reference KAT vectors are byte-identical.\u003c/li\u003e\n\u003cli\u003eThe BCJSSE provider carried the TLS 1.2 coupling between the supported_groups extension and ECDSA over into TLS 1.3: an ECDSA signature scheme was treated as usable - offered in the signature_algorithms and signature_algorithms_cert extensions, and eligible when selecting the local credentials - only while the corresponding curve was among the named groups enabled for key exchange, both per context (a group unavailable for key agreement disabled the scheme outright) and per connection (the curve had to be in the supported_groups list about to be sent). RFC 8446 sec. 4.2.7 scopes supported_groups to key exchange only, with signature algorithms negotiated independently (sec. 4.2.3), so this incorrect restriction in TLS 1.3 has been removed. Ed25519, Ed448 and the RSA schemes were unaffected (as well as typical deployments using a default configuration for named groups).\u003c/li\u003e\n\u003cli\u003eThe bcmail module descriptor did not declare its javax.mail/javax.activation dependences, so a modular (module-path) consumer of the jar hit IllegalAccessError/module-resolution failures when the S/MIME classes touched the mail API. The descriptor now requires them optionally (requires static) under all four module names those libraries are known by - the automatic names mail and activation carried by the javax.mail:mail / javax.activation:activation artifacts, and the explicit names java.mail and java.activation carried by the newer com.sun.mail / com.sun.activation ones - a hard requires on any one name would break users of the others (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2389\"\u003e#2389\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFour type-coercion helpers in the OER / IEEE 1609.2 (ITS) decoder tested the wrong type in the identity fast path that lets a getInstance() factory return an argument that is already of the target type. org.bouncycastle.oer.its.ieee1609dot2.basetypes.UINT32.getInstance and org.bouncycastle.oer.its.etsi102941.basetypes.Version.getInstance guarded on UINT8 - a sibling of UINT32 under UintBase, and unrelated to Version - so passing a UINT8 threw ClassCastException, while passing an actual UINT32 or Version missed the fast path and fell through to ASN1Integer.getInstance, which rejects them: neither factory accepted its own type. org.bouncycastle.oer.its.etsi103097.EtsiTs103097DataEncryptedUnicast.getInstance guarded on its sibling EtsiTs103097DataEncrypted and then cast to the unicast type, so an EtsiTs103097DataEncrypted threw ClassCastException. org.bouncycastle.oer.OEROptional.getObject(Class) called value.getClass().isInstance(type) with the arguments transposed, which is always false because the argument is a java.lang.Class, so the cast path was dead and every optional field was resolved reflectively, failing with IllegalStateException for a target type with no static getInstance. Each guard now names the type it returns, matching the sibling UINT8 / UINT16 / UINT64 and EtsiTs103097DataEncrypted factories (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2373\"\u003e#2373\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eDefaultAlgorithmNameFinder and DefaultSignatureNameFinder had no entries at all for the ShangMi algorithms, so an SM2 signature AlgorithmIdentifier that DefaultSignatureAlgorithmIdentifierFinder itself produces came back named only by its OID string - getAlgorithmName(GMObjectIdentifiers.sm2sign_with_sm3) returned \u0026quot;1.2.156.10197.1.501\u0026quot; and hasAlgorithmName returned false. Both finders now name sm2sign_with_sm3 as SM3WITHSM2 and sm2sign_with_sha256 as SHA256WITHSM2, and DefaultAlgorithmNameFinder additionally names the sm3 digest. All three resolve through the BC provider, as Signature and MessageDigest respectively. The remaining GM arc - the SM4 cipher modes, the sm2encrypt variants, and the SM1 / SM6 / SSF33 ciphers BC does not implement - is still unnamed (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2377\"\u003e#2377\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe RFC 4998 evidence-record classes compared the digest AlgorithmIdentifier named by a time-stamp authority with the one their own DigestCalculator uses, and did so with AlgorithmIdentifier.equals(), which compares the encodings. A TSA that names SHA-256 with an explicit NULL parameters field - DigiCert among them - therefore failed against BC's own calculator, which names it with the parameters absent, and ERSArchiveTimeStampGenerator.generateArchiveTimeStamp rejected the response with \u0026quot;time stamp imprint for wrong algorithm\u0026quot;. Both spellings name the same digest and RFC 5754 sec. 2 requires a receiver to accept either, while requiring that identifiers be generated with the parameters absent, which BC already does. The three affected comparisons - the two in ERSArchiveTimeStampGenerator and the digest check in ERSEvidenceRecord.renew - now use the new AlgorithmIdentifier.areEquivalent, which matches on the algorithm and treats an absent parameters field and NULL as the same, and the consistency check across an evidence record's archive time stamp chain uses it too. An identifier carrying an actual parameter structure is never equivalent to one carrying none (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2379\"\u003e#2379\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eEDIPartyName.toASN1Primitive emitted the nameAssigner and partyName DirectoryStrings without their context tags, so an EDIPartyName built through its public constructor could not be parsed back by EDIPartyName.getInstance, which correctly requires them. RFC 5280 sec. 4.2.1.6 tags both members [0] and [1], and those tags are explicit despite the module's IMPLICIT TAGS because DirectoryString is a CHOICE, which X.680 does not allow to be tagged implicitly - the decoder already had this right. The encoder now matches it. Note the type was added during the 1.85 cycle and GeneralName validates its ediPartyName alternative through it, so a GeneralName carrying an untagged ediPartyName - including one BC itself produced - is rejected where 1.84 passed it through unexamined; the untagged form is not read leniently (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2380\"\u003e#2380\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eRSASSA-PSS could not be used with a RIPEMD digest through the JCA API. Nothing registered the RIPEMD PSS signatures, so Signature.getInstance(\u0026quot;RIPEMD160WITHRSAANDMGF1\u0026quot;) raised NoSuchAlgorithmException, and the generic RSASSA-PSS route with an explicit PSSParameterSpec failed too: org.bouncycastle.jcajce.provider.util.DigestFactory.getDigest returned null for a RIPEMD name, and isSameDigest - an allow-list of the SHA families and MD5 - reported two identical RIPEMD names as different digests, so the spec was rejected with \u0026quot;digest algorithm for MGF should be the same as for PSS parameters\u0026quot;. isSameDigest now answers true for equal names whatever the digest, which also covers Whirlpool, SM3, GOST3411 and anything else outside that allow-list; DigestFactory recognises RIPEMD128, RIPEMD160 and RIPEMD256 by name and OID; the three PSS signatures are registered with MGF1 over the same digest and a salt of the digest length; and DefaultSignatureAlgorithmIdentifierFinder gains the matching RIPEMD*WITHRSAANDMGF1 entries with their RSASSA-PSS-params, so the operator/JcaContentSignerBuilder path works as well. Note BC continues to require the PSS hash and the MGF1 hash to be the same, which RFC 8017 does not itself demand (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2381\"\u003e#2381\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe opt-in key-size validation on CMS key-transport recipients (org.bouncycastle.cms.jcajce.JceKeyTransRecipient.setKeySizeValidation(true)) never ran for a message using RFC 9709 CEK derivation (id-alg-cek-hkdf-sha256): the branch that should have selected the actual content-encryption algorithm carried in the KDF AlgorithmIdentifier's parameters compared the encrypted-key byte array against the id-alg-cek-hkdf-sha256 object identifier - a comparison that is always false - so the check fell through to a key-size lookup on the outer KDF OID, which has no registered key size, and silently checked nothing. A key-transport EnvelopedData/AuthEnvelopedData whose transported (and HKDF-derived) content-encryption key did not match the key size of the advertised content-encryption algorithm was therefore accepted even with validation enabled. The recipient now dispatches on the content-encryption AlgorithmIdentifier's algorithm OID, so key-size validation of RFC 9709 messages checks the recovered key against the inner content-encryption algorithm. Messages with a matching key size, non-HKDF messages, and recipients that do not enable validation are unaffected.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003eSee full diff in \u003ca href=\"https://github.com/bcgit/bc-java/commits\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003ecommonmark-java 0.29.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e[0.29.0] - 2026-06-20\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/comm...\n\n_Description has been truncated_","html_url":"https://github.com/greench-ai/GreenchClaw/pull/43","url":"https://dependabot.ecosyste.ms/api/v1/hosts/GitHub/repositories/greench-ai%2FGreenchClaw/issues/43","packages_url":"https://dependabot.ecosyste.ms/api/v1/issues/43/packages"}},{"old_version":"5.3.2","new_version":"5.5.0","update_type":"minor","path":null,"pr_created_at":"2026-09-09T22:22:36.000Z","version_change":"5.3.2 → 5.5.0","issue":{"uuid":"5405355443","node_id":"PR_kwDOUIXVxs8AAAABC56M1A","number":11,"state":"closed","title":"chore(deps): bump the android-deps group across 1 directory with 16 updates","user":"dependabot[bot]","labels":["dependencies","java"],"assignees":[],"locked":false,"comments_count":1,"pull_request":true,"closed_at":"2026-09-11T22:18:04.000Z","author_association":null,"state_reason":null,"created_at":"2026-09-09T22:22:36.000Z","updated_at":"2026-09-11T22:18:08.000Z","time_to_close":172528,"merged_at":null,"merged_by":null,"closed_by":null,"dependency_metadata":{"prefix":"chore(deps): bump","group_name":"android-deps","update_count":16,"packages":[{"name":"gradle-wrapper","old_version":"9.5.1","new_version":"9.7.1","repository_url":"https://github.com/gradle/gradle"},{"name":"org.bouncycastle:bcprov-jdk18on","old_version":"1.84","new_version":"1.85.2","repository_url":"https://github.com/bcgit/bc-java"},{"name":"org.commonmark:commonmark","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-autolink","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-strikethrough","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-tables","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-task-list-items","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.junit.vintage:junit-vintage-engine","old_version":"6.1.0","new_version":"6.1.3","repository_url":"https://github.com/junit-team/junit-framework"},{"name":"io.kotest:kotest-assertions-core-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"io.kotest:kotest-runner-junit5-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"com.squareup.okhttp3:mockwebserver","old_version":"5.3.2","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.squareup.okhttp3:okhttp","old_version":"5.3.2","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.android.application","old_version":"9.2.1","new_version":"9.4.0"},{"name":"com.android.test","old_version":"9.2.1","new_version":"9.4.0"},{"name":"org.jetbrains.kotlin.plugin.compose","old_version":"2.4.0","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"},{"name":"org.jetbrains.kotlin.plugin.serialization","old_version":"2.4.0","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"}],"path":null,"ecosystem":"maven"},"body":"Bumps the android-deps group with 16 updates in the /apps/android directory:\n\n| Package | From | To |\n| --- | --- | --- |\n| [gradle-wrapper](https://github.com/gradle/gradle) | `9.5.1` | `9.7.1` |\n| [org.bouncycastle:bcprov-jdk18on](https://github.com/bcgit/bc-java) | `1.84` | `1.85.2` |\n| [org.commonmark:commonmark](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-autolink](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-strikethrough](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-tables](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-task-list-items](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.junit.vintage:junit-vintage-engine](https://github.com/junit-team/junit-framework) | `6.1.0` | `6.1.3` |\n| [io.kotest:kotest-assertions-core-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [io.kotest:kotest-runner-junit5-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [com.squareup.okhttp3:mockwebserver](https://github.com/lysine-dev/okhttp) | `5.3.2` | `5.5.0` |\n| [com.squareup.okhttp3:okhttp](https://github.com/lysine-dev/okhttp) | `5.3.2` | `5.5.0` |\n| com.android.application | `9.2.1` | `9.4.0` |\n| com.android.test | `9.2.1` | `9.4.0` |\n| [org.jetbrains.kotlin.plugin.compose](https://github.com/JetBrains/kotlin) | `2.4.0` | `2.4.20` |\n| [org.jetbrains.kotlin.plugin.serialization](https://github.com/JetBrains/kotlin) | `2.4.0` | `2.4.20` |\n\n\nUpdates `gradle-wrapper` from 9.5.1 to 9.7.1\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/gradle/gradle/releases\"\u003egradle-wrapper's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e9.7.1\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.1.\u003c/p\u003e\n\u003cp\u003eThis is a patch release for 9.7.0. We recommend using 9.7.1 instead of 9.7.0.\u003c/p\u003e\n\u003cp\u003eHere are the highlights of 9.7.0 release:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIsolated Projects graduates to incubating\u003c/li\u003e\n\u003cli\u003eBroader Configuration Cache compatibility\u003c/li\u003e\n\u003cli\u003eResilient Sync helps you fix broken builds\u003c/li\u003e\n\u003cli\u003eMore source locations in problem reports\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003ca href=\"https://docs.gradle.org/9.7.1/release-notes.html\"\u003eRead the Release Notes\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eWe would like to thank the following community members for their contributions to this release of Gradle:\n\u003ca href=\"https://github.com/aSemy\"\u003eAdam\u003c/a\u003e,\n\u003ca href=\"https://github.com/Gautam-aman\"\u003eAman Gautam\u003c/a\u003e,\n\u003ca href=\"https://github.com/YukiCodepth\"\u003eAman Kumar\u003c/a\u003e,\n\u003ca href=\"https://github.com/adubrouski\"\u003eAnton Dubrouski\u003c/a\u003e,\n\u003ca href=\"https://github.com/liutikas\"\u003eAurimas\u003c/a\u003e,\n\u003ca href=\"https://github.com/gbhavya07\"\u003egbhavya07\u003c/a\u003e,\n\u003ca href=\"https://github.com/joshfriend\"\u003eJosh Friend\u003c/a\u003e,\n\u003ca href=\"https://github.com/nicklauslittle-gov\"\u003enicklauslittle-gov\u003c/a\u003e,\n\u003ca href=\"https://github.com/psoni674\"\u003ePragati\u003c/a\u003e,\n\u003ca href=\"https://github.com/Project516\"\u003eproject516\u003c/a\u003e,\n\u003ca href=\"https://github.com/Uomocapra\"\u003eQin Mi\u003c/a\u003e,\n\u003ca href=\"https://github.com/rkdfx\"\u003eRavi\u003c/a\u003e,\n\u003ca href=\"https://github.com/sk-reddy17\"\u003esk-reddy17\u003c/a\u003e,\n\u003ca href=\"https://github.com/Suvrat1629\"\u003eSuvrat Acharya\u003c/a\u003e,\n\u003ca href=\"https://github.com/ShreckYe\"\u003eYongshun Ye\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eUpgrade instructions\u003c/h2\u003e\n\u003cp\u003eSwitch your build to use Gradle 9.7.1 by updating your wrapper:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e./gradlew :wrapper --gradle-version=9.7.1 \u0026amp;\u0026amp; ./gradlew :wrapper\r\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eSee the Gradle \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/upgrading_version_9.html\"\u003e9.x upgrade guide\u003c/a\u003e to learn about deprecations, breaking changes and other considerations when upgrading.\u003c/p\u003e\n\u003cp\u003eFor Java, Groovy, Kotlin and Android compatibility, see the \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/compatibility.html\"\u003efull compatibility notes\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eReporting problems\u003c/h2\u003e\n\u003cp\u003eIf you find a problem with this release, please file a bug on \u003ca href=\"https://github.com/gradle/gradle/issues\"\u003eGitHub Issues\u003c/a\u003e adhering to our issue guidelines.\nIf you're not sure you're encountering a bug, please use the \u003ca href=\"https://discuss.gradle.org/c/help-discuss\"\u003eforum\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eWe hope you will build happiness with Gradle, and we look forward to your feedback via \u003ca href=\"https://twitter.com/gradle\"\u003eTwitter\u003c/a\u003e or on \u003ca href=\"https://github.com/gradle\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003e9.7.0\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.0.\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/92f0512e7f06d84621afba191f75e265363890cf\"\u003e\u003ccode\u003e92f0512\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38892\"\u003e#38892\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/820ee75a99a179bbffa41bcedc6477b685fabb9f\"\u003e\u003ccode\u003e820ee75\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/82c23f9bd2a89b4cc644e1f90a28a8668feb3dee\"\u003e\u003ccode\u003e82c23f9\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering problem in KTS (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38878\"\u003e#38878\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/ef11a7268fe8cc8d6ab849ec911aa11220180553\"\u003e\u003ccode\u003eef11a72\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering issue\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/bb0d8a974a71b1003efea41e4046e98855cd5ff8\"\u003e\u003ccode\u003ebb0d8a9\u003c/code\u003e\u003c/a\u003e Make relevant tests polyglot (run for multiple DSLs)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/336e129d7f95c03486acafc97abf59734acfed48\"\u003e\u003ccode\u003e336e129\u003c/code\u003e\u003c/a\u003e Update signing configuration (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38874\"\u003e#38874\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/4bdf0da2dad9884d089a6062a45ea7183e7d735d\"\u003e\u003ccode\u003e4bdf0da\u003c/code\u003e\u003c/a\u003e Update signing configuration\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/cd9b92c1b82856248cf1dc58b50378238bec7b52\"\u003e\u003ccode\u003ecd9b92c\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38839\"\u003e#38839\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/5f4e381964897ad8d6b99e5a7c77f26dba3259fb\"\u003e\u003ccode\u003e5f4e381\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/1e08ab551367aeb5fb48b26e72807e1d2b27c939\"\u003e\u003ccode\u003e1e08ab5\u003c/code\u003e\u003c/a\u003e Keep type-use annotations in extracted ABI classes (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38810\"\u003e#38810\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/gradle/gradle/compare/v9.5.1...v9.7.1\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.bouncycastle:bcprov-jdk18on` from 1.84 to 1.85.2\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.md\"\u003eorg.bouncycastle:bcprov-jdk18on's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch1\u003eBouncy Castle Crypto Package - Release Notes\u003c/h1\u003e\n\u003ch2\u003e1.0 Introduction\u003c/h2\u003e\n\u003cp\u003eThe Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. The package is organised so that it contains a light-weight API suitable for use in any environment (including the J2ME) with the additional infrastructure to conform the algorithms to the JCE framework.\u003c/p\u003e\n\u003ch2\u003e2.0 Release History\u003c/h2\u003e\n\u003cp\u003e\u003c!-- raw HTML omitted --\u003e\u003c!-- raw HTML omitted --\u003e\u003c/p\u003e\n\u003ch3\u003e2.1.1 Version\u003c/h3\u003e\n\u003cp\u003eRelease: 1.86\u003cbr /\u003e\nDate: 2026, TBD\u003c/p\u003e\n\u003ch3\u003e2.1.2 Defects Fixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) let a subkey inherit the primary key's Key Flags when its own Subkey Binding signature carried no Key Flags subpacket, which made the two capability decisions taken for one subkey disagree. OpenPGPCertificate.OpenPGPComponentKey.isSigningKey() reads the effective flags, which fell back to the primary key's direct-key or primary user ID self-signature, so a subkey bound with no flags of its own counted as signing-capable; verifyEmbeddedPrimaryKeyBinding reads the binding signature's own flags, found no signing capability there, and so skipped the embedded Primary Key Binding (cross-certification) signature that RFC 9580 sec. 5.2.1.8 and sec. 10.1.3 require of a subkey that can issue signatures. A data signature made by such a subkey was therefore attributed to the certificate and reported valid by OpenPGPSignature.OpenPGPDocumentSignature.isValid() with the cross-certification requirement never applied, where GnuPG refuses the same certificate and message as not cross-certified. An attacker holding a third party's public signing subkey - which is public material - could bind it to their own primary key with a Subkey Binding signature they are able to make, carrying no Key Flags and no embedded Primary Key Binding signature, which they cannot make without the subkey's private key, and have that party's genuine signatures verify as valid under the attacker's own identity: misattribution of a real signature rather than a forgery of a new one, since the signature still has to be one the subkey actually made. Key Flags are a statement about the key the carrying signature refers to (RFC 9580 sec. 5.2.3.29), so a subkey no longer inherits them from the certificate-wide signatures of the primary key: a Subkey Binding signature that omits the subpacket now leaves the subkey with no capabilities rather than the primary's, which makes the flags the cross-certification check consults the same flags every other decision consults. Preferences and the other subpackets a direct-key signature carries are inherited as before, and the primary key itself - whose flags legitimately come from its direct-key or user ID self-signature - is unaffected. The low-level PGPSignature / PGPPublicKeyRing API performs no binding checks by design and is unchanged.\u003c/li\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) used a version 6 key that carried no valid Direct Key signature, falling back to the primary user ID binding as it correctly does for a version 4 key. RFC 9580 sec. 5.2.3.10 requires the opposite: \u0026quot;An implementation MUST ensure that a valid Direct Key signature is present before using a version 6 key. This prevents certain attacks where an adversary strips a self-signature specifying a Key Expiration Time or certain preferences.\u0026quot; The certificate grammar says the same structurally, the Direct Key signature being mandatory in the version 6 structure of sec. 10.1.1 and optional in the version 4 one of sec. 10.1.3. Because a version 6 certificate carries its key expiration, features and algorithm preferences on the Direct Key signature - the convention the RFC recommends and the one OpenPGPKeyGenerator follows, its user ID certification carrying no expiration at all - removing that single signature packet from a published certificate silently dropped the expiration along with the preferences and features: OpenPGPCertificate.getSignatureChainFor fell back to the user ID binding, the primary key was still reported bound, and getEncryptionKeys() and getSigningKeys() went on returning the subkeys of a key whose owner had set it to expire. The primary key fingerprint is unchanged by the removal, so a relying party pinning the key by fingerprint still treats it as the same key, and no private key or hash collision is involved; the natural moment for the strip is the key refresh that RFC 9580 names as the reason to refetch a key at all - to learn about changes in expiration, features, preferences and revocation - which is exactly the update it defeats. This is a downgrade rather than a forgery, nothing being attributed to a key that did not authorise it, and the concerning direction is encryption, to a key meant to have been retired. OpenPGPCertificate.isBoundBy now requires a valid Direct Key self-signature on a version 6 primary key before any component of the certificate - the primary key, its subkeys or its identities - is treated as bound, so a version 6 certificate stripped of it offers no keys at all rather than an unexpiring set. Version 4 certificates are unaffected: there the key expiration legitimately lives on the user ID self-signature and the fallback is correct, so it stays. The revocation-only version 6 certificate of sec. 10.1.2, which legitimately carries no Direct Key signature, is unaffected as well - its key was already refused as revoked, and reading the revocation does not go through the binding check.\u003c/li\u003e\n\u003cli\u003eThe lightweight LMSSigner and HSSSigner refused a key wrapped in ParametersWithRandom, which is how BcContentSignerBuilder passes a key whenever setSecureRandom() has been called - so BcHssLmsContentSignerBuilder built a working signer until a random was set and then failed with \u0026quot;Incorrect Key Parameters\u0026quot;, and the two signers themselves raised ClassCastException on the same input. All three now unwrap it, as the promoted ML-DSA and SLH-DSA signers already did. The random is accepted and not used: LMS derives its message randomiser C from the key's seed and the one-time index, so it is deterministic and cannot repeat while q does not. Note SP 800-208 sec. 6.1 asks for C to come from an approved random bit generator, which this implementation does not do; that is unchanged here, and a supplied random is now ignored rather than refused.\u003c/li\u003e\n\u003cli\u003eLMS signature verification did not apply two of the checks RFC 8554 sec. 5.4.2 requires before a signature is processed. Step 2g refuses a signature whose LMS typecode is not the one from the public key, and without it the path computation took its height and tree digest from the parameter set the signature named rather than the key's, so a signature claiming a height-25 parameter set drove a 25-level computation against a height-5 key. Step 2i refuses a leaf number q outside the tree, and without it an out-of-range q flowed into the node arithmetic and was left for the candidate-root comparison to catch. Neither was a forgery - the domain separation between D_LEAF and D_INTR and the final comparison saw to that - but both are attacker-chosen work the specification says to refuse up front. Both are now checked, and a signature failing either is still reported as not verifying rather than thrown out of Signature.verify(). The catch around the signature decode in LMSSigner and HSSSigner has also been narrowed to the decode itself, as the corresponding SPI was corrected to do for github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2408\"\u003e#2408\u003c/a\u003e: past the parse the engine reports an inconsistent signature by returning false rather than by throwing, so the wider catch caught nothing while standing ready to turn a future internal error into a quiet false.\u003c/li\u003e\n\u003cli\u003eThe LMS and HSS key parameter classes now apply at construction the checks their decoders apply, so a key built directly cannot be one the decoder would refuse. LMSPrivateKeyParameters accepted an identifier of any length although the decoder reads exactly 16 bytes - such a key encoded but could not be read back - and left q, maxQ and the seed length unchecked; the seed is now required to be at least m bytes at decode as well, where a one-byte seed had been decoding silently and then deriving every one-time key from it. HSSPrivateKeyParameters checked neither its level count nor that it had been given a component key per level and a chaining signature per level below the root, and then indexed both lists, so a mismatch surfaced as IndexOutOfBoundsException - or, where a level happened to match, as a null chaining signature that only failed at signing time; the level is now checked after the reset that fills it in, since a null is legitimate on the way in. LMSPrivateKeyParameters.getInstance(byte[], byte[]) adopted the public key supplied beside the private one without comparing them, so a mismatched public key was simply reported by getPublicKey(); it now cross-checks the identifier, both parameter sets and, where the tree cache already holds it, the root, as the HSS entry point does. The decoders also now report a bad version or seed length as IOException rather than IllegalStateException, so a caller can catch one type for a malformed key, and the package-private LM-OTS public key decoder no longer declares throws Exception or dereferences an unrecognised typecode. The deprecated org.bouncycastle.pqc.crypto.lms copies carry the decoder corrections.\u003c/li\u003e\n\u003cli\u003eIn the LMS JCE layer, LMSKeyGenParameterSpec.fromNames knew all twenty LMS parameter-set names but only four of the sixteen LM-OTS ones, so none of the SP 800-208 n24 or SHAKE sets could be named; all sixteen are now present. KeyPairGenerator.initialize(int, SecureRandom) reports InvalidParameterException, which is what the JCA specifies and which extends the IllegalArgumentException it raised before, so existing catches still match. BCLMSPrivateKey.getIndex now takes the exhaustion check and the index read under the key's own monitor rather than as two separate calls, and two unused fields have gone from LMSSignatureSpi. Note that the LMS Signature claims its one-time key at the first update() rather than at sign(), so a Signature that is initialised and updated and then abandoned spends an index without producing a signature - the safe direction for a one-time scheme, and now documented on the SPI.\u003c/li\u003e\n\u003cli\u003eEvery other key pair generator that refuses a key size did the same thing the LMS one did above. KeyPairGenerator.initialize(int, SecureRandom) is documented to raise InvalidParameterException when the key size is not one the generator supports, and thirty of them raised a bare IllegalArgumentException instead, so a caller following the JCA and catching the documented type saw an exception escaping rather than a refusal. The ML-DSA, ML-KEM, SLH-DSA, Classic McEliece, FrodoKEM, NTRU and composite signature and KEM generators in the BC provider, and every generator in BCPQC, now raise InvalidParameterException - NewHope included, where the value is a key size it will not take rather than a mode of initialisation it does not offer. InvalidParameterException extends IllegalArgumentException, so callers written against the old behaviour go on catching it unchanged. The two RSA generators are corrected as well, and differently: theirs is a key size below a floor rather than a mode of initialisation they do not offer, and the refusal is raised by the lightweight RSAKeyGenerationParameters, which cannot name a java.security exception at all, so the RSA KeyPairGeneratorSpi now translates it - keeping the message verbatim and the original exception as the cause, through a new SecurityExceptions.invalidParameterException factory, since InvalidParameterException has no constructor that takes one. Of the 304 KeyPairGenerator services the two providers register, 299 now refuse a nonsense key size the way the JCA defines it and five accept it as a strength they can work with, with none left raising a bare IllegalArgumentException; that is asserted as a sweep over both providers rather than per algorithm, so a generator added later is covered without the test being touched. The jdk1.3 provider overlays of the four generators that have one carry the same change, and the jdk1.3 SecurityExceptions overlay gains the new factory along with the invalidAlgorithmParameterException one it had been missing.\u003c/li\u003e\n\u003cli\u003eKeyPairGenerator.initialize(AlgorithmParameterSpec, SecureRandom) had the same shape of problem as the int overload above, and only 44 of the 304 services the two providers register reported an unusable spec as the InvalidAlgorithmParameterException that method declares. The twenty-three PQC generators that resolve a parameter set by name - cmce, frodokem, mldsa, mlkem, slhdsa, aimer, bike, faest, falcon, haetae, hqc, mayo, mqom, ntru, ntruplus, both ntruprime variants, qruov, saber, sdith, smaugt, snova and sqisign, 230 services between them - case-folded the name they got back from the spec without checking it, so a spec with no getName() method, and a null spec, produced a NullPointerException from inside the fold; their own \u0026quot;is this name one I know\u0026quot; branch, which does report the declared exception, was unreachable. The two composite generators, whose parameter set is fixed by the algorithm name so that null is the only spec they accept, refused every other one with IllegalArgumentException. RSA answered correctly for a spec of the wrong type but not for one of the right type carrying values its lightweight parameters will not take - an even public exponent, or a key size below the floor - which is now translated the same way the int overload's is. All 304 services now report the declared exception, with the composites still taking the null spec that is right for them; note that InvalidAlgorithmParameterException is a checked exception and not an IllegalArgumentException, so a caller that was catching what these threw before has to catch the declared type instead.\u003c/li\u003e\n\u003cli\u003eAn HSS private key claimed the two records of its position under two different monitors. The top-level index and the bottom component key's one-time index q are independent records of the same position - the decoder requires them to agree, see the entry below - but generateLMSContext incremented the index under the HSS key's own monitor, released it, and only then claimed q under the component key's. A getEncoded() issued in between saw the index advanced and q not, and produced an encoding this implementation's own decoder rejects; and two threads meeting at a bottom-tree boundary could both pass the exhaustion test, take consecutive top-level indices and claim the same q, after which one of them was refused with \u0026quot;ots private key exhausted\u0026quot; by a key still reporting usages remaining, a top-level index had been spent with no signature made, and the two records stayed one apart for the rest of the key's life in that process - so it could no longer be encoded, cloned or sharded, and getIndex() and getUsagesRemaining() misreported by one. No one-time key was reused: the component key's claim is itself atomic, and the divergence runs index ahead of leaves, so the effect was on the key's usability rather than on the signatures it had made. Both records are now claimed under the one monitor, and the component key is claimed before the index is incremented so that an exhausted one leaves both untouched. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the same correction.\u003c/li\u003e\n\u003cli\u003eTimeStampToken parsed the attacker-controlled TSTInfo content of a time-stamp token (org.bouncycastle.tsp.TimeStampToken, reached from TimeStampResponse(byte[]) and (InputStream)) inside a try that caught only CMSException, so a well-formed RFC 3161 TimeStampResp whose embedded token carried a malformed TSTInfo - a SEQUENCE with fewer elements than the five mandatory fields, a non-SEQUENCE, truncated DER, or an unknown context tag - let an IllegalArgumentException or a NoSuchElementException escape the constructor's declared throws TSPException, IOException contract. A token signed by no signers or by more than one raised a bare IllegalArgumentException from the same constructor, before that try, for the same reason. Both are now reported as TSPException, matching the package-private TimeStampResponse(DLSequence) constructor and the existing getSignedAttributes guard in the same method; the signer-count refusal is a TSPValidationException, as the neighbouring check on the content type already was. Related, and the cause of the NoSuchElementException: asn1.tsp.TSTInfo read its five mandatory fields off the sequence with no bound on how many elements were actually there, so a short SEQUENCE left the enumeration to run out rather than being refused, and an oversize one was accepted with its extra elements absorbed into the optional slots. Decode now requires the five to ten elements RFC 3161 sec. 2.4.2 gives the type, which is what the sibling Accuracy and ArchiveTimeStamp decoders already did, so the failure is the IllegalArgumentException that getInstance is expected to raise (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2415\"\u003e#2415\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eNeither the HSS nor the XMSS^MT private key decoder checked its declared index against the traversal state stored beside it, although the two are independent records of the same position in the key and so can be compared. For HSS the records are the top-level index and the component keys' one-time indices q; for XMSS^MT they are the global index and the per-layer BDS states. A stored key whose index had been rolled back while its state stayed advanced - a partial write, a restore from backup, a buggy storage layer - was therefore accepted, and it then signed a second message under a one-time key the key had already used, producing a signature that verified, so nothing anywhere surfaced the reuse. RFC 8554 sec. 1 and RFC 8391 sec. 1.1 both require each one-time key to be used exactly once, and this is the failure those requirements exist to prevent; the single-tree XMSS decoder has tied its BDS state to its index since that state was first validated, and this brings the two multi-tree schemes into line. HSS decode now requires the declared index to equal the position the component q values imply - a level above the last contributes (q - 1) leaves of the levels beneath it, since its q has already advanced past the subtree it signed - and XMSS^MT decode now requires each present layer's BDS index to equal the leaf index that layer derives from the global index, allowing the one position where a layer has moved into a new subtree and its state legitimately still carries the previous subtree's final index. A layer with no state yet is unaffected, since those are built lazily at signing time. Related, and the same shape of omission: an XMSS or XMSS^MT private key encoding carries the tree root twice - the key's own root field and the root node of the BDS state stored beside it, which for XMSS^MT is the top layer's - and the two were never compared either. A corrupted root was accepted and then poisoned every signature the key made, because the root is hashed into the message digest: the signature did not verify and nothing indicated why. Decode now requires the two copies to agree. The BDS node values themselves are not checkable the way the LMS tree cache above is - a BDS authentication path, stack, retain or keep node does not have its children stored alongside it, so recomputing one means building a subtree, which is the work the state exists to avoid. Both checks are integer comparisons over the levels of the key, too small to measure against the surrounding decode, and both were verified not to reject any legitimate key by walking every index a key can reach: the full key space of the two-level HSS and the h=4/d=2, h=6/d=2, h=6/d=3, h=9/d=3 and h=8/d=4 XMSS^MT parameter sets, plus a three-level HSS key across a subtree boundary and an HSS shard. Since those node values cannot be recomputed, the encoded state now carries a checksum over itself instead, with the owning key's public seed hashed in front of it. Any corruption of the stored state is refused at decode rather than being loaded and then producing signatures that silently do not verify, and because the public seed is bound in, a state transplanted between two keys of the same parameter set is refused too, even though it is internally consistent and arrives with its own matching root. The public seed is bound rather than the secret seed or the PRF key deliberately: the state's own root and index are inside the encoding and so are already covered, hashing secret material would make the stored checksum a commitment to it for no gain in detection, and the PRF key does not influence the state at all. \u003cstrong\u003eThis is an error-detecting code and not integrity protection\u003c/strong\u003e - anyone able to rewrite the stored key recomputes it, so it establishes that the state is unchanged since it was written, never that it was correct when written, and the allocation bounds on the encoding remain the guard against a crafted one. It costs one SHA-256 over the state, measured at 5 to 8 microseconds each way for the h=10 and h=16 parameter sets, and 32 bytes of encoding. The state encoding was added earlier in this same cycle and has not been released, so the checksum is simply part of it rather than a new version: a state written by a 1.86 beta is rejected, which is recovered from by re-exporting the key. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the HSS check as well (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2414\"\u003e#2414\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe S/MIME example smoke test in the misc module (org.bouncycastle.mail.smime.examples.test.AllTests) drove SendSignedAndEncryptedMail against smtp.gmail.com, and that example finishes with Transport.send() under JavaMail's default settings, which have no connect timeout. Where outbound port 25 is refused the failure was swallowed and the test passed; where it is silently dropped, as on many home networks, the connect blocked and ./gradlew build hung in :misc:test indefinitely with \u0026quot;0 tests completed\u0026quot;. The test now delivers to an SMTP stub on a loopback port, with connect / read / write timeouts as a backstop, and asserts the message arrived (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2407\"\u003e#2407\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation took the traditional component public key bytes it feeds the KEM combiner from the recipient key's own encoding, while decapsulation recomputes the point from the private key and so always produced an uncompressed one. Section 4 of draft-ietf-lamps-pq-composite-kem requires an EC component to be carried as an uncompressed point, but a component key that encodes itself compressed - a BC EC key whose point format has been set through org.bouncycastle.jce.interfaces.ECPointEncoder, or a key from a provider that preserves a compressed encoding - was passed through as it came. Both sides then combined a different tradPK and derived different shared secrets, with no error reported on either: encapsulation and decapsulation both succeeded and the recipient simply could not decrypt. The EC component is now normalised to an uncompressed point wherever the engine serialises one, which covers the ephemeral key that forms the ciphertext as well. X25519 and X448 components have a single encoding and were unaffected, as were EC keys left in their default (uncompressed) format, whose shared secrets are unchanged. CompositePublicKey.getEncoded() took its component bytes the same way, so such a key also encoded to a composite key other implementations reject and whose bytes changed across an encode / decode / encode round trip - 1238 bytes rather than 1270 for MLKEM768-ECDH-P256, and for the composite ML-DSA keys sharing that method, 2006 rather than 2038 for MLDSA65-ECDSA-P256. It now normalises the component the same way. This is a write-side change only: a composite key carrying a compressed EC component is still decoded, since the component key factories accept either form, and continues to verify signatures as before - it simply re-encodes in the normalised form. The shared normalisation is org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil.getUncompressedSubjectPublicKeyBytes.\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation threw a NullPointerException, wrapped in an IllegalStateException out of KeyGenerator.generateKey(), when the SecureRandom it was given was null - which javax.crypto.KEM.newEncapsulator() documents as a request for the provider's default, and which KeyGenerator.init(spec, null) passes straight through. The three RSA-OAEP composites draw the traditional shared secret from that random directly, so they were the ones affected; the ECDH and X25519 / X448 composites escaped only because their component KeyPairGenerators default a random of their own. CompositeMLKEMEngine now defaults one through CryptoServicesRegistrar.getSecureRandom() on first use, as the composite KEM Cipher's wrap path already did, and as the KEM generators corrected earlier in this cycle now do. Related, the engine now also clears the ML-KEM component's shared secret alongside the traditional one on both the encapsulate and decapsulate paths - the copy handed back by getEncoded() was left in the heap - as section 3.5 of draft-ietf-lamps-pq-composite-kem requires.\u003c/li\u003e\n\u003cli\u003eCompositePublicKey.getAlgorithm() and CompositePrivateKey.getAlgorithm() returned null for all twelve Composite ML-KEM (draft-ietf-lamps-pq-composite-kem) parameter sets. Both classes resolved the name through the composite signature index only, which holds the composite ML-DSA OIDs, so a composite KEM key pair - generated, parsed from a certificate, or read from PKCS#8 - reported no algorithm at all, and the standard JCA idiom of reconstructing a key with KeyFactory.getInstance(key.getAlgorithm()) raised a NullPointerException. The lookup now falls back to the composite KEM index, so the name returned is the one the provider registers the algorithm under (e.g. MLKEM768-X25519-SHA3-256), matching the composite ML-DSA behaviour. The same single-index assumption made the CompositePublicKey(SubjectPublicKeyInfo) and CompositePrivateKey(PrivateKeyInfo) constructors reject a composite KEM key with \u0026quot;unable to create CompositePublicKey from SubjectPublicKeyInfo\u0026quot;; they now dispatch to the composite KEM key factory for those OIDs. Keys obtained through KeyFactory or through BouncyCastleProvider.getPublicKey / getPrivateKey were unaffected and are unchanged (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2404\"\u003e#2404\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe org.bouncycastle.jcajce.spec.KEMKDFSpec constructor stored a null otherInfo as given, so getOtherInfo() returned null, and three of the KDF branches KdfUtil.makeKeyBytes dispatches to - KMAC-128, KMAC-256 and SHAKE-256 - read the otherInfo length without a guard and threw NullPointerException out of the KEM operation, where the KDF2, KDF3 and HKDF branches tolerate a null through KDFParameters / HKDFParameters. The Builder of every spec in the package already mapped null to empty, so no provider path reached it, but the constructor is protected on a public class and KdfUtil is documented for callers building their own KEM integration; the deprecated KEMParameterSpec passes a null itself and escaped only because it also pins the KDF to null. The constructor now stores empty for a null, so getOtherInfo() never returns null, and a null and an explicitly empty otherInfo derive the same key.\u003c/li\u003e\n\u003cli\u003eQR-UOV signature verification accepted a signature encoding that was not canonical, so the encoding of a signature was not unique even after the trailing-byte fix of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e. Each F_q element of the signature is stored in ceil(log2 q) bits, one more bit pattern than the field has elements: q itself is representable and is arithmetically congruent to zero, so an element written as q verified exactly as the same element written as zero would, and the bits padding the last element out to the byte boundary were never read at all. Every zero element of a signature therefore carried a second encoding, and for the q = 7 parameter sets roughly one element in seven is zero - a single qruov_5_q7_L10 signature measured 256 spare bits, so on the order of 2^256 distinct byte strings verified for the one message and key. Verification now rejects any element outside [0, q) and any set padding bit; a signature produced by this or by the reference implementation is unaffected, as the KAT vectors of every parameter set confirm. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSNOVA signature verification ignored four bits inside the signature for any parameter set whose solution is an odd number of GF(16) nibbles - the SNOVA_24_5_5, SNOVA_25_8_3, SNOVA_29_6_5 and SNOVA_66_15_3 families, sixteen of the forty-four parameter sets. The last byte of the encoded solution carries a single nibble and the signer leaves the top four bits zero, but the decoder did not read them, so sixteen distinct byte strings verified for one signature. This is the same non-unique encoding github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e closed for bytes following the signature, applied inside it; the verifier now requires those bits to be zero. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSnovaPrivateKeyParameters did not validate the length of the private key encoding handed to it - the only one of the five schemes of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e that did not - and SnovaParameters.getPrivateKeyLength() reported the expanded (\u0026quot;ESK\u0026quot;) length even for a parameter set whose private key is the seed pair. A private key encoding reaches this constructor straight from a PKCS#8 blob, so a wrong length went undetected: a seed-form key with extra bytes appended was accepted and signed under a different derived key, and a short expanded-form key sized the signer's decode buffer negatively, throwing NegativeArraySizeException out of generateSignature() rather than being reported at construction. Related, the signing retry loop could not terminate: the vinegar values are derived from a single-byte counter, so only 256 distinct linear systems can be tried, and an expanded-form private key that is not a real central map is singular for all of them - generateSignature() then span forever rather than failing. The length is now checked at construction, getPrivateKeyLength() reports the length that parameter set's private key actually has, and the retry loop gives up after its 256 attempts as MAYO's does.\u003c/li\u003e\n\u003cli\u003eMayoSigner and MayoKeyPairGenerator did not clear several buffers holding secret key material that the MAYO reference implementation explicitly clears. Signing left the secret oil space O, the expanded L = (P1 + P1^t) * O + P2, and the M / VPV / Ox intermediates of the central map in place, having gone to the trouble of clearing eleven other buffers; key generation left the expanded seed, whose tail is the encoded oil space, and the P1 * O + P2 half of P; and the row-echelon step left the packed echelon form of the secret linear system and its pivot rows. Separately, if all 256 attempts at solving for the signature had given a rank-deficient system, signing emitted a signature built from the failed attempt's state instead of reporting the failure the reference returns, and AIMerSigner.generateSignature returned an empty array on failure, which a caller would hand on as though it were a signature. Both now throw.\u003c/li\u003e\n\u003cli\u003eFive PQC signature schemes - MAYO, SNOVA, QR-UOV, SQIsign and AIMer - returned the NIST crypto_sign \u0026quot;sm\u0026quot; signed-message envelope from generateSignature() rather than the signature. That envelope is an artefact of the reference KAT harness, which records the message alongside the signature so a vector file can be self-contained; it is not part of any of the five specifications, and no other BC signer emits it (Falcon's KAT test rebuilds the equivalent envelope in the test, which is where it belongs). Two consequences followed, both reaching the JCA Signature services of every parameter set of the five schemes in BouncyCastlePQCProvider. First, since the message was appended to the signature, verification had to skip whatever followed the signature proper, and it did so by checking only that the buffer was long enough - so any number of trailing bytes could be added to a valid signature, or the appended message replaced with unrelated data, and it still verified. A signature encoding was therefore not unique: anyone holding one valid signature could produce unlimited distinct byte strings that all verified for the same message and key, which breaks any use that treats the signature bytes as an identifier, deduplicates on them, or records them as evidence. Second, the envelope propagated into everything built on the operator layer: because ContentSigner hands the signature straight into the structure being signed, every X.509 certificate, CRL, CMS SignedData and TLS CertificateVerify BC produced with one of these algorithms carried a verbatim copy of the signed data inside its own signature field - a self-signed MAYO-1 certificate came to 3567 bytes where the same certificate is now 2020 - which no other implementation can parse as a signature, and which in a detached CMS signature meant the \u0026quot;detached\u0026quot; signature carried the content. generateSignature() now returns the bare signature, and verifySignature() requires exactly the parameter set's signature length, so appended or truncated data is rejected rather than ignored. \u003cstrong\u003eThis is a behavioural change for signatures produced by an earlier release\u003c/strong\u003e - MAYO and SNOVA from 1.84, QR-UOV, SQIsign and AIMer from 1.85 - which are no longer accepted in the envelope form they were emitted in; the signature bytes themselves are unchanged, so a stored value can be recovered by taking the leading signature-length bytes, or for AIMer, whose envelope was message || signature rather than signature || message, the trailing ones. The KAT tests now rebuild the envelope before comparing against the vector files, which continue to record it. Note that AIMer's verification had already been made length-exact during this cycle (see the entry below relating to github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2401\"\u003e#2401\u003c/a\u003e), so of the five only its envelope remained (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe MLS implementation did not bind an X.509 credential to the LeafNode's signature_key. LeafNode.verify() checked a leaf's signature against the signature_key declared in the leaf itself, while the X.509 credential's certificate chain was stored but never parsed or checked, so the certificate's public key was never required to match signature_key (RFC 9420 sec. 5.3). A leaf could therefore carry one party's certificate while being signed by an unrelated key and still be accepted under that party's identity through KeyPackage.verify() and the Group leaf-validation path. LeafNode.verify() now requires the end-entity certificate's subject public key, in the cipher suite's signature encoding, to equal signature_key for an X.509 credential, and rejects the leaf otherwise - including an empty chain or a certificate whose key type does not match the cipher suite; certificate-chain and identity validation to a trust anchor remain the application's responsibility per RFC 9420 sec. 5.3.1. A public org.bouncycastle.mls.codec.Certificate(byte[]) constructor and a Credential.getCertificates() accessor are added so callers can build and inspect X.509 credentials. Basic credentials are unaffected.\u003c/li\u003e\n\u003cli\u003eThe SecureRandom supplied to org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder.setSecureRandom() did not drive the content IV / nonce for any algorithm other than RC2. EnvelopedDataHelper.generateParameters passed the caller's SecureRandom to the AlgorithmParameterGenerator only in the RC2_CBC branch; every other content-encryption algorithm - AES-CBC, AES-GCM, AES-CCM, Camellia, ARIA, SEED and the rest - reached pGen.generateParameters() on an uninitialised generator, so the IV / nonce was drawn from a default SecureRandom and setSecureRandom() was silently ignored (the builder's javadoc states that random is used for IV/nonce generation). The generator is now initialised with the supplied random on the general path as well, so a caller who provides a specific randomness source - for a controlled or FIPS-approved DRBG, say - has it honoured for the content IV / nonce. The session-key generation path was unaffected and already used the supplied random. Because the content IV / nonce now comes from the supplied SecureRandom, the org.bouncycastle.crypto.util JournalingSecureRandom / JournaledAlgorithm reproducible-encryption support records it in the transcript: a resumed session reproduces the IV / nonce by regenerating it from the replayed randomness - build the resuming encryptor from the content-algorithm OID - rather than by reusing the AlgorithmIdentifier captured from the first encryption, which no longer keeps the transcript aligned.\u003c/li\u003e\n\u003cli\u003eThe NTRU LPRime, NTRU+ and SMAUG-T KEM generators threw a NullPointerException when constructed with a null SecureRandom, where every other KEM generator - including NTRU LPRime's own SNTRU Prime counterpart in the same package - defaults one through CryptoServicesRegistrar.getSecureRandom(). This is reachable from the lightweight API directly, and from javax.crypto.KEM, whose newEncapsulator() documents a null random as a request for the provider's default.\u003c/li\u003e\n\u003cli\u003eFrodoKEMEngine kept a single SHAKE instance in a field, so an engine reached concurrently produced wrong results. It is reached that way through org.bouncycastle.crypto.kems.FrodoKEMExtractor, which holds one engine for its lifetime: two threads extracting through one extractor interleaved the digest's absorb and squeeze phases, yielding shared secrets that silently did not match the sender's, or an IllegalStateException of \u0026quot;attempt to absorb while squeezing\u0026quot; from inside extractSecret. The digest is now built per call, as CMCEEngine's already was, which makes an extractor safe to share. Encapsulation was unaffected, since FrodoKEMGenerator builds an engine per call. Results for any single-threaded use are unchanged - the reference KAT vectors are byte-identical.\u003c/li\u003e\n\u003cli\u003eThe BCJSSE provider carried the TLS 1.2 coupling between the supported_groups extension and ECDSA over into TLS 1.3: an ECDSA signature scheme was treated as usable - offered in the signature_algorithms and signature_algorithms_cert extensions, and eligible when selecting the local credentials - only while the corresponding curve was among the named groups enabled for key exchange, both per context (a group unavailable for key agreement disabled the scheme outright) and per connection (the curve had to be in the supported_groups list about to be sent). RFC 8446 sec. 4.2.7 scopes supported_groups to key exchange only, with signature algorithms negotiated independently (sec. 4.2.3), so this incorrect restriction in TLS 1.3 has been removed. Ed25519, Ed448 and the RSA schemes were unaffected (as well as typical deployments using a default configuration for named groups).\u003c/li\u003e\n\u003cli\u003eThe bcmail module descriptor did not declare its javax.mail/javax.activation dependences, so a modular (module-path) consumer of the jar hit IllegalAccessError/module-resolution failures when the S/MIME classes touched the mail API. The descriptor now requires them optionally (requires static) under all four module names those libraries are known by - the automatic names mail and activation carried by the javax.mail:mail / javax.activation:activation artifacts, and the explicit names java.mail and java.activation carried by the newer com.sun.mail / com.sun.activation ones - a hard requires on any one name would break users of the others (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2389\"\u003e#2389\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFour type-coercion helpers in the OER / IEEE 1609.2 (ITS) decoder tested the wrong type in the identity fast path that lets a getInstance() factory return an argument that is already of the target type. org.bouncycastle.oer.its.ieee1609dot2.basetypes.UINT32.getInstance and org.bouncycastle.oer.its.etsi102941.basetypes.Version.getInstance guarded on UINT8 - a sibling of UINT32 under UintBase, and unrelated to Version - so passing a UINT8 threw ClassCastException, while passing an actual UINT32 or Version missed the fast path and fell through to ASN1Integer.getInstance, which rejects them: neither factory accepted its own type. org.bouncycastle.oer.its.etsi103097.EtsiTs103097DataEncryptedUnicast.getInstance guarded on its sibling EtsiTs103097DataEncrypted and then cast to the unicast type, so an EtsiTs103097DataEncrypted threw ClassCastException. org.bouncycastle.oer.OEROptional.getObject(Class) called value.getClass().isInstance(type) with the arguments transposed, which is always false because the argument is a java.lang.Class, so the cast path was dead and every optional field was resolved reflectively, failing with IllegalStateException for a target type with no static getInstance. Each guard now names the type it returns, matching the sibling UINT8 / UINT16 / UINT64 and EtsiTs103097DataEncrypted factories (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2373\"\u003e#2373\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eDefaultAlgorithmNameFinder and DefaultSignatureNameFinder had no entries at all for the ShangMi algorithms, so an SM2 signature AlgorithmIdentifier that DefaultSignatureAlgorithmIdentifierFinder itself produces came back named only by its OID string - getAlgorithmName(GMObjectIdentifiers.sm2sign_with_sm3) returned \u0026quot;1.2.156.10197.1.501\u0026quot; and hasAlgorithmName returned false. Both finders now name sm2sign_with_sm3 as SM3WITHSM2 and sm2sign_with_sha256 as SHA256WITHSM2, and DefaultAlgorithmNameFinder additionally names the sm3 digest. All three resolve through the BC provider, as Signature and MessageDigest respectively. The remaining GM arc - the SM4 cipher modes, the sm2encrypt variants, and the SM1 / SM6 / SSF33 ciphers BC does not implement - is still unnamed (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2377\"\u003e#2377\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe RFC 4998 evidence-record classes compared the digest AlgorithmIdentifier named by a time-stamp authority with the one their own DigestCalculator uses, and did so with AlgorithmIdentifier.equals(), which compares the encodings. A TSA that names SHA-256 with an explicit NULL parameters field - DigiCert among them - therefore failed against BC's own calculator, which names it with the parameters absent, and ERSArchiveTimeStampGenerator.generateArchiveTimeStamp rejected the response with \u0026quot;time stamp imprint for wrong algorithm\u0026quot;. Both spellings name the same digest and RFC 5754 sec. 2 requires a receiver to accept either, while requiring that identifiers be generated with the parameters absent, which BC already does. The three affected comparisons - the two in ERSArchiveTimeStampGenerator and the digest check in ERSEvidenceRecord.renew - now use the new AlgorithmIdentifier.areEquivalent, which matches on the algorithm and treats an absent parameters field and NULL as the same, and the consistency check across an evidence record's archive time stamp chain uses it too. An identifier carrying an actual parameter structure is never equivalent to one carrying none (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2379\"\u003e#2379\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eEDIPartyName.toASN1Primitive emitted the nameAssigner and partyName DirectoryStrings without their context tags, so an EDIPartyName built through its public constructor could not be parsed back by EDIPartyName.getInstance, which correctly requires them. RFC 5280 sec. 4.2.1.6 tags both members [0] and [1], and those tags are explicit despite the module's IMPLICIT TAGS because DirectoryString is a CHOICE, which X.680 does not allow to be tagged implicitly - the decoder already had this right. The encoder now matches it. Note the type was added during the 1.85 cycle and GeneralName validates its ediPartyName alternative through it, so a GeneralName carrying an untagged ediPartyName - including one BC itself produced - is rejected where 1.84 passed it through unexamined; the untagged form is not read leniently (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2380\"\u003e#2380\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eRSASSA-PSS could not be used with a RIPEMD digest through the JCA API. Nothing registered the RIPEMD PSS signatures, so Signature.getInstance(\u0026quot;RIPEMD160WITHRSAANDMGF1\u0026quot;) raised NoSuchAlgorithmException, and the generic RSASSA-PSS route with an explicit PSSParameterSpec failed too: org.bouncycastle.jcajce.provider.util.DigestFactory.getDigest returned null for a RIPEMD name, and isSameDigest - an allow-list of the SHA families and MD5 - reported two identical RIPEMD names as different digests, so the spec was rejected with \u0026quot;digest algorithm for MGF should be the same as for PSS parameters\u0026quot;. isSameDigest now answers true for equal names whatever the digest, which also covers Whirlpool, SM3, GOST3411 and anything else outside that allow-list; DigestFactory recognises RIPEMD128, RIPEMD160 and RIPEMD256 by name and OID; the three PSS signatures are registered with MGF1 over the same digest and a salt of the digest length; and DefaultSignatureAlgorithmIdentifierFinder gains the matching RIPEMD*WITHRSAANDMGF1 entries with their RSASSA-PSS-params, so the operator/JcaContentSignerBuilder path works as well. Note BC continues to require the PSS hash and the MGF1 hash to be the same, which RFC 8017 does not itself demand (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2381\"\u003e#2381\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe opt-in key-size validation on CMS key-transport recipients (org.bouncycastle.cms.jcajce.JceKeyTransRecipient.setKeySizeValidation(true)) never ran for a message using RFC 9709 CEK derivation (id-alg-cek-hkdf-sha256): the branch that should have selected the actual content-encryption algorithm carried in the KDF AlgorithmIdentifier's parameters compared the encrypted-key byte array against the id-alg-cek-hkdf-sha256 object identifier - a comparison that is always false - so the check fell through to a key-size lookup on the outer KDF OID, which has no registered key size, and silently checked nothing. A key-transport EnvelopedData/AuthEnvelopedData whose transported (and HKDF-derived) content-encryption key did not match the key size of the advertised content-encryption algorithm was therefore accepted even with validation enabled. The recipient now dispatches on the content-encryption AlgorithmIdentifier's algorithm OID, so key-size validation of RFC 9709 messages checks the recovered key against the inner content-encryption algorithm. Messages with a matching key size, non-HKDF messages, and recipients that do not enable validation are unaffected.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003eSee full diff in \u003ca href=\"https://github.com/bcgit/bc-java/commits\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003ecommonmark-java 0.29.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e[0.29.0] - 2026-06-20\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/42b4fb7adfe288ef13e9e27ab20aff7e91b0ab9d\"\u003e\u003ccode\u003e42b4fb7\u003c/code\u003e\u003c/a\u003e Prepare CHANGELOG for version 0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/b76e09d7a8362abb5f04e1d6b91dbd6da279a6fc\"\u003e\u003ccode\u003eb76e09d\u003c/code\u003e\u003c/a\u003e Limit how deep inline nodes may nest by default (100)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/49f65cb5cbec93cff713179990307145198e7061\"\u003e\u003ccode\u003e49f65cb\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing deeply nested emphasis\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/c...\n\n_Description has been truncated_","html_url":"https://github.com/engsathiago/EVE-Agent/pull/11","url":"https://dependabot.ecosyste.ms/api/v1/hosts/GitHub/repositories/engsathiago%2FEVE-Agent/issues/11","packages_url":"https://dependabot.ecosyste.ms/api/v1/issues/11/packages"}},{"old_version":"5.3.2","new_version":"5.5.0","update_type":"minor","path":null,"pr_created_at":"2026-09-09T21:32:45.000Z","version_change":"5.3.2 → 5.5.0","issue":{"uuid":"5404956375","node_id":"PR_kwDOTCWVXc8AAAABC5loaQ","number":41,"state":"closed","title":"chore(deps): bump the android-deps group across 1 directory with 21 updates","user":"dependabot[bot]","labels":["dependencies","java"],"assignees":[],"locked":false,"comments_count":1,"pull_request":true,"closed_at":"2026-09-11T21:25:00.000Z","author_association":null,"state_reason":null,"created_at":"2026-09-09T21:32:45.000Z","updated_at":"2026-09-11T21:25:02.000Z","time_to_close":172335,"merged_at":null,"merged_by":null,"closed_by":null,"dependency_metadata":{"prefix":"chore(deps): bump","group_name":"android-deps","update_count":21,"packages":[{"name":"gradle-wrapper","old_version":"9.4.1","new_version":"9.7.1","repository_url":"https://github.com/gradle/gradle"},{"name":"androidx.core:core-ktx","old_version":"1.18.0","new_version":"1.19.0"},{"name":"org.bouncycastle:bcprov-jdk18on","old_version":"1.84","new_version":"1.85.2","repository_url":"https://github.com/bcgit/bc-java"},{"name":"org.commonmark:commonmark","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-autolink","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-strikethrough","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-tables","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-task-list-items","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"dnsjava:dnsjava","old_version":"3.6.4","new_version":"3.6.5","repository_url":"https://github.com/dnsjava/dnsjava"},{"name":"org.junit.vintage:junit-vintage-engine","old_version":"6.0.3","new_version":"6.1.3","repository_url":"https://github.com/junit-team/junit-framework"},{"name":"io.kotest:kotest-assertions-core-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"io.kotest:kotest-runner-junit5-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"org.jetbrains.kotlinx:kotlinx-coroutines-android","old_version":"1.10.2","new_version":"1.11.0","repository_url":"https://github.com/Kotlin/kotlinx.coroutines"},{"name":"org.jetbrains.kotlinx:kotlinx-coroutines-test","old_version":"1.10.2","new_version":"1.11.0","repository_url":"https://github.com/Kotlin/kotlinx.coroutines"},{"name":"com.google.android.material:material","old_version":"1.13.0","new_version":"1.14.0","repository_url":"https://github.com/material-components/material-components-android"},{"name":"com.squareup.okhttp3:mockwebserver","old_version":"5.3.2","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.squareup.okhttp3:okhttp","old_version":"5.3.2","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.android.application","old_version":"9.2.0","new_version":"9.4.0"},{"name":"com.android.test","old_version":"9.2.0","new_version":"9.4.0"},{"name":"org.jetbrains.kotlin.plugin.compose","old_version":"2.3.21","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"},{"name":"org.jetbrains.kotlin.plugin.serialization","old_version":"2.3.21","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"}],"path":null,"ecosystem":"maven"},"body":"Bumps the android-deps group with 21 updates in the /apps/android directory:\n\n| Package | From | To |\n| --- | --- | --- |\n| [gradle-wrapper](https://github.com/gradle/gradle) | `9.4.1` | `9.7.1` |\n| androidx.core:core-ktx | `1.18.0` | `1.19.0` |\n| [org.bouncycastle:bcprov-jdk18on](https://github.com/bcgit/bc-java) | `1.84` | `1.85.2` |\n| [org.commonmark:commonmark](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-autolink](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-strikethrough](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-tables](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-task-list-items](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [dnsjava:dnsjava](https://github.com/dnsjava/dnsjava) | `3.6.4` | `3.6.5` |\n| [org.junit.vintage:junit-vintage-engine](https://github.com/junit-team/junit-framework) | `6.0.3` | `6.1.3` |\n| [io.kotest:kotest-assertions-core-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [io.kotest:kotest-runner-junit5-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [org.jetbrains.kotlinx:kotlinx-coroutines-android](https://github.com/Kotlin/kotlinx.coroutines) | `1.10.2` | `1.11.0` |\n| [org.jetbrains.kotlinx:kotlinx-coroutines-test](https://github.com/Kotlin/kotlinx.coroutines) | `1.10.2` | `1.11.0` |\n| [com.google.android.material:material](https://github.com/material-components/material-components-android) | `1.13.0` | `1.14.0` |\n| [com.squareup.okhttp3:mockwebserver](https://github.com/lysine-dev/okhttp) | `5.3.2` | `5.5.0` |\n| [com.squareup.okhttp3:okhttp](https://github.com/lysine-dev/okhttp) | `5.3.2` | `5.5.0` |\n| com.android.application | `9.2.0` | `9.4.0` |\n| com.android.test | `9.2.0` | `9.4.0` |\n| [org.jetbrains.kotlin.plugin.compose](https://github.com/JetBrains/kotlin) | `2.3.21` | `2.4.20` |\n| [org.jetbrains.kotlin.plugin.serialization](https://github.com/JetBrains/kotlin) | `2.3.21` | `2.4.20` |\n\n\nUpdates `gradle-wrapper` from 9.4.1 to 9.7.1\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/gradle/gradle/releases\"\u003egradle-wrapper's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e9.7.1\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.1.\u003c/p\u003e\n\u003cp\u003eThis is a patch release for 9.7.0. We recommend using 9.7.1 instead of 9.7.0.\u003c/p\u003e\n\u003cp\u003eHere are the highlights of 9.7.0 release:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIsolated Projects graduates to incubating\u003c/li\u003e\n\u003cli\u003eBroader Configuration Cache compatibility\u003c/li\u003e\n\u003cli\u003eResilient Sync helps you fix broken builds\u003c/li\u003e\n\u003cli\u003eMore source locations in problem reports\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003ca href=\"https://docs.gradle.org/9.7.1/release-notes.html\"\u003eRead the Release Notes\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eWe would like to thank the following community members for their contributions to this release of Gradle:\n\u003ca href=\"https://github.com/aSemy\"\u003eAdam\u003c/a\u003e,\n\u003ca href=\"https://github.com/Gautam-aman\"\u003eAman Gautam\u003c/a\u003e,\n\u003ca href=\"https://github.com/YukiCodepth\"\u003eAman Kumar\u003c/a\u003e,\n\u003ca href=\"https://github.com/adubrouski\"\u003eAnton Dubrouski\u003c/a\u003e,\n\u003ca href=\"https://github.com/liutikas\"\u003eAurimas\u003c/a\u003e,\n\u003ca href=\"https://github.com/gbhavya07\"\u003egbhavya07\u003c/a\u003e,\n\u003ca href=\"https://github.com/joshfriend\"\u003eJosh Friend\u003c/a\u003e,\n\u003ca href=\"https://github.com/nicklauslittle-gov\"\u003enicklauslittle-gov\u003c/a\u003e,\n\u003ca href=\"https://github.com/psoni674\"\u003ePragati\u003c/a\u003e,\n\u003ca href=\"https://github.com/Project516\"\u003eproject516\u003c/a\u003e,\n\u003ca href=\"https://github.com/Uomocapra\"\u003eQin Mi\u003c/a\u003e,\n\u003ca href=\"https://github.com/rkdfx\"\u003eRavi\u003c/a\u003e,\n\u003ca href=\"https://github.com/sk-reddy17\"\u003esk-reddy17\u003c/a\u003e,\n\u003ca href=\"https://github.com/Suvrat1629\"\u003eSuvrat Acharya\u003c/a\u003e,\n\u003ca href=\"https://github.com/ShreckYe\"\u003eYongshun Ye\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eUpgrade instructions\u003c/h2\u003e\n\u003cp\u003eSwitch your build to use Gradle 9.7.1 by updating your wrapper:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e./gradlew :wrapper --gradle-version=9.7.1 \u0026amp;\u0026amp; ./gradlew :wrapper\r\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eSee the Gradle \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/upgrading_version_9.html\"\u003e9.x upgrade guide\u003c/a\u003e to learn about deprecations, breaking changes and other considerations when upgrading.\u003c/p\u003e\n\u003cp\u003eFor Java, Groovy, Kotlin and Android compatibility, see the \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/compatibility.html\"\u003efull compatibility notes\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eReporting problems\u003c/h2\u003e\n\u003cp\u003eIf you find a problem with this release, please file a bug on \u003ca href=\"https://github.com/gradle/gradle/issues\"\u003eGitHub Issues\u003c/a\u003e adhering to our issue guidelines.\nIf you're not sure you're encountering a bug, please use the \u003ca href=\"https://discuss.gradle.org/c/help-discuss\"\u003eforum\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eWe hope you will build happiness with Gradle, and we look forward to your feedback via \u003ca href=\"https://twitter.com/gradle\"\u003eTwitter\u003c/a\u003e or on \u003ca href=\"https://github.com/gradle\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003e9.7.0\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.0.\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/92f0512e7f06d84621afba191f75e265363890cf\"\u003e\u003ccode\u003e92f0512\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38892\"\u003e#38892\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/820ee75a99a179bbffa41bcedc6477b685fabb9f\"\u003e\u003ccode\u003e820ee75\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/82c23f9bd2a89b4cc644e1f90a28a8668feb3dee\"\u003e\u003ccode\u003e82c23f9\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering problem in KTS (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38878\"\u003e#38878\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/ef11a7268fe8cc8d6ab849ec911aa11220180553\"\u003e\u003ccode\u003eef11a72\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering issue\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/bb0d8a974a71b1003efea41e4046e98855cd5ff8\"\u003e\u003ccode\u003ebb0d8a9\u003c/code\u003e\u003c/a\u003e Make relevant tests polyglot (run for multiple DSLs)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/336e129d7f95c03486acafc97abf59734acfed48\"\u003e\u003ccode\u003e336e129\u003c/code\u003e\u003c/a\u003e Update signing configuration (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38874\"\u003e#38874\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/4bdf0da2dad9884d089a6062a45ea7183e7d735d\"\u003e\u003ccode\u003e4bdf0da\u003c/code\u003e\u003c/a\u003e Update signing configuration\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/cd9b92c1b82856248cf1dc58b50378238bec7b52\"\u003e\u003ccode\u003ecd9b92c\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38839\"\u003e#38839\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/5f4e381964897ad8d6b99e5a7c77f26dba3259fb\"\u003e\u003ccode\u003e5f4e381\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/1e08ab551367aeb5fb48b26e72807e1d2b27c939\"\u003e\u003ccode\u003e1e08ab5\u003c/code\u003e\u003c/a\u003e Keep type-use annotations in extracted ABI classes (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38810\"\u003e#38810\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/gradle/gradle/compare/v9.4.1...v9.7.1\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `androidx.core:core-ktx` from 1.18.0 to 1.19.0\n\nUpdates `org.bouncycastle:bcprov-jdk18on` from 1.84 to 1.85.2\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.md\"\u003eorg.bouncycastle:bcprov-jdk18on's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch1\u003eBouncy Castle Crypto Package - Release Notes\u003c/h1\u003e\n\u003ch2\u003e1.0 Introduction\u003c/h2\u003e\n\u003cp\u003eThe Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. The package is organised so that it contains a light-weight API suitable for use in any environment (including the J2ME) with the additional infrastructure to conform the algorithms to the JCE framework.\u003c/p\u003e\n\u003ch2\u003e2.0 Release History\u003c/h2\u003e\n\u003cp\u003e\u003c!-- raw HTML omitted --\u003e\u003c!-- raw HTML omitted --\u003e\u003c/p\u003e\n\u003ch3\u003e2.1.1 Version\u003c/h3\u003e\n\u003cp\u003eRelease: 1.86\u003cbr /\u003e\nDate: 2026, TBD\u003c/p\u003e\n\u003ch3\u003e2.1.2 Defects Fixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) let a subkey inherit the primary key's Key Flags when its own Subkey Binding signature carried no Key Flags subpacket, which made the two capability decisions taken for one subkey disagree. OpenPGPCertificate.OpenPGPComponentKey.isSigningKey() reads the effective flags, which fell back to the primary key's direct-key or primary user ID self-signature, so a subkey bound with no flags of its own counted as signing-capable; verifyEmbeddedPrimaryKeyBinding reads the binding signature's own flags, found no signing capability there, and so skipped the embedded Primary Key Binding (cross-certification) signature that RFC 9580 sec. 5.2.1.8 and sec. 10.1.3 require of a subkey that can issue signatures. A data signature made by such a subkey was therefore attributed to the certificate and reported valid by OpenPGPSignature.OpenPGPDocumentSignature.isValid() with the cross-certification requirement never applied, where GnuPG refuses the same certificate and message as not cross-certified. An attacker holding a third party's public signing subkey - which is public material - could bind it to their own primary key with a Subkey Binding signature they are able to make, carrying no Key Flags and no embedded Primary Key Binding signature, which they cannot make without the subkey's private key, and have that party's genuine signatures verify as valid under the attacker's own identity: misattribution of a real signature rather than a forgery of a new one, since the signature still has to be one the subkey actually made. Key Flags are a statement about the key the carrying signature refers to (RFC 9580 sec. 5.2.3.29), so a subkey no longer inherits them from the certificate-wide signatures of the primary key: a Subkey Binding signature that omits the subpacket now leaves the subkey with no capabilities rather than the primary's, which makes the flags the cross-certification check consults the same flags every other decision consults. Preferences and the other subpackets a direct-key signature carries are inherited as before, and the primary key itself - whose flags legitimately come from its direct-key or user ID self-signature - is unaffected. The low-level PGPSignature / PGPPublicKeyRing API performs no binding checks by design and is unchanged.\u003c/li\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) used a version 6 key that carried no valid Direct Key signature, falling back to the primary user ID binding as it correctly does for a version 4 key. RFC 9580 sec. 5.2.3.10 requires the opposite: \u0026quot;An implementation MUST ensure that a valid Direct Key signature is present before using a version 6 key. This prevents certain attacks where an adversary strips a self-signature specifying a Key Expiration Time or certain preferences.\u0026quot; The certificate grammar says the same structurally, the Direct Key signature being mandatory in the version 6 structure of sec. 10.1.1 and optional in the version 4 one of sec. 10.1.3. Because a version 6 certificate carries its key expiration, features and algorithm preferences on the Direct Key signature - the convention the RFC recommends and the one OpenPGPKeyGenerator follows, its user ID certification carrying no expiration at all - removing that single signature packet from a published certificate silently dropped the expiration along with the preferences and features: OpenPGPCertificate.getSignatureChainFor fell back to the user ID binding, the primary key was still reported bound, and getEncryptionKeys() and getSigningKeys() went on returning the subkeys of a key whose owner had set it to expire. The primary key fingerprint is unchanged by the removal, so a relying party pinning the key by fingerprint still treats it as the same key, and no private key or hash collision is involved; the natural moment for the strip is the key refresh that RFC 9580 names as the reason to refetch a key at all - to learn about changes in expiration, features, preferences and revocation - which is exactly the update it defeats. This is a downgrade rather than a forgery, nothing being attributed to a key that did not authorise it, and the concerning direction is encryption, to a key meant to have been retired. OpenPGPCertificate.isBoundBy now requires a valid Direct Key self-signature on a version 6 primary key before any component of the certificate - the primary key, its subkeys or its identities - is treated as bound, so a version 6 certificate stripped of it offers no keys at all rather than an unexpiring set. Version 4 certificates are unaffected: there the key expiration legitimately lives on the user ID self-signature and the fallback is correct, so it stays. The revocation-only version 6 certificate of sec. 10.1.2, which legitimately carries no Direct Key signature, is unaffected as well - its key was already refused as revoked, and reading the revocation does not go through the binding check.\u003c/li\u003e\n\u003cli\u003eThe lightweight LMSSigner and HSSSigner refused a key wrapped in ParametersWithRandom, which is how BcContentSignerBuilder passes a key whenever setSecureRandom() has been called - so BcHssLmsContentSignerBuilder built a working signer until a random was set and then failed with \u0026quot;Incorrect Key Parameters\u0026quot;, and the two signers themselves raised ClassCastException on the same input. All three now unwrap it, as the promoted ML-DSA and SLH-DSA signers already did. The random is accepted and not used: LMS derives its message randomiser C from the key's seed and the one-time index, so it is deterministic and cannot repeat while q does not. Note SP 800-208 sec. 6.1 asks for C to come from an approved random bit generator, which this implementation does not do; that is unchanged here, and a supplied random is now ignored rather than refused.\u003c/li\u003e\n\u003cli\u003eLMS signature verification did not apply two of the checks RFC 8554 sec. 5.4.2 requires before a signature is processed. Step 2g refuses a signature whose LMS typecode is not the one from the public key, and without it the path computation took its height and tree digest from the parameter set the signature named rather than the key's, so a signature claiming a height-25 parameter set drove a 25-level computation against a height-5 key. Step 2i refuses a leaf number q outside the tree, and without it an out-of-range q flowed into the node arithmetic and was left for the candidate-root comparison to catch. Neither was a forgery - the domain separation between D_LEAF and D_INTR and the final comparison saw to that - but both are attacker-chosen work the specification says to refuse up front. Both are now checked, and a signature failing either is still reported as not verifying rather than thrown out of Signature.verify(). The catch around the signature decode in LMSSigner and HSSSigner has also been narrowed to the decode itself, as the corresponding SPI was corrected to do for github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2408\"\u003e#2408\u003c/a\u003e: past the parse the engine reports an inconsistent signature by returning false rather than by throwing, so the wider catch caught nothing while standing ready to turn a future internal error into a quiet false.\u003c/li\u003e\n\u003cli\u003eThe LMS and HSS key parameter classes now apply at construction the checks their decoders apply, so a key built directly cannot be one the decoder would refuse. LMSPrivateKeyParameters accepted an identifier of any length although the decoder reads exactly 16 bytes - such a key encoded but could not be read back - and left q, maxQ and the seed length unchecked; the seed is now required to be at least m bytes at decode as well, where a one-byte seed had been decoding silently and then deriving every one-time key from it. HSSPrivateKeyParameters checked neither its level count nor that it had been given a component key per level and a chaining signature per level below the root, and then indexed both lists, so a mismatch surfaced as IndexOutOfBoundsException - or, where a level happened to match, as a null chaining signature that only failed at signing time; the level is now checked after the reset that fills it in, since a null is legitimate on the way in. LMSPrivateKeyParameters.getInstance(byte[], byte[]) adopted the public key supplied beside the private one without comparing them, so a mismatched public key was simply reported by getPublicKey(); it now cross-checks the identifier, both parameter sets and, where the tree cache already holds it, the root, as the HSS entry point does. The decoders also now report a bad version or seed length as IOException rather than IllegalStateException, so a caller can catch one type for a malformed key, and the package-private LM-OTS public key decoder no longer declares throws Exception or dereferences an unrecognised typecode. The deprecated org.bouncycastle.pqc.crypto.lms copies carry the decoder corrections.\u003c/li\u003e\n\u003cli\u003eIn the LMS JCE layer, LMSKeyGenParameterSpec.fromNames knew all twenty LMS parameter-set names but only four of the sixteen LM-OTS ones, so none of the SP 800-208 n24 or SHAKE sets could be named; all sixteen are now present. KeyPairGenerator.initialize(int, SecureRandom) reports InvalidParameterException, which is what the JCA specifies and which extends the IllegalArgumentException it raised before, so existing catches still match. BCLMSPrivateKey.getIndex now takes the exhaustion check and the index read under the key's own monitor rather than as two separate calls, and two unused fields have gone from LMSSignatureSpi. Note that the LMS Signature claims its one-time key at the first update() rather than at sign(), so a Signature that is initialised and updated and then abandoned spends an index without producing a signature - the safe direction for a one-time scheme, and now documented on the SPI.\u003c/li\u003e\n\u003cli\u003eEvery other key pair generator that refuses a key size did the same thing the LMS one did above. KeyPairGenerator.initialize(int, SecureRandom) is documented to raise InvalidParameterException when the key size is not one the generator supports, and thirty of them raised a bare IllegalArgumentException instead, so a caller following the JCA and catching the documented type saw an exception escaping rather than a refusal. The ML-DSA, ML-KEM, SLH-DSA, Classic McEliece, FrodoKEM, NTRU and composite signature and KEM generators in the BC provider, and every generator in BCPQC, now raise InvalidParameterException - NewHope included, where the value is a key size it will not take rather than a mode of initialisation it does not offer. InvalidParameterException extends IllegalArgumentException, so callers written against the old behaviour go on catching it unchanged. The two RSA generators are corrected as well, and differently: theirs is a key size below a floor rather than a mode of initialisation they do not offer, and the refusal is raised by the lightweight RSAKeyGenerationParameters, which cannot name a java.security exception at all, so the RSA KeyPairGeneratorSpi now translates it - keeping the message verbatim and the original exception as the cause, through a new SecurityExceptions.invalidParameterException factory, since InvalidParameterException has no constructor that takes one. Of the 304 KeyPairGenerator services the two providers register, 299 now refuse a nonsense key size the way the JCA defines it and five accept it as a strength they can work with, with none left raising a bare IllegalArgumentException; that is asserted as a sweep over both providers rather than per algorithm, so a generator added later is covered without the test being touched. The jdk1.3 provider overlays of the four generators that have one carry the same change, and the jdk1.3 SecurityExceptions overlay gains the new factory along with the invalidAlgorithmParameterException one it had been missing.\u003c/li\u003e\n\u003cli\u003eKeyPairGenerator.initialize(AlgorithmParameterSpec, SecureRandom) had the same shape of problem as the int overload above, and only 44 of the 304 services the two providers register reported an unusable spec as the InvalidAlgorithmParameterException that method declares. The twenty-three PQC generators that resolve a parameter set by name - cmce, frodokem, mldsa, mlkem, slhdsa, aimer, bike, faest, falcon, haetae, hqc, mayo, mqom, ntru, ntruplus, both ntruprime variants, qruov, saber, sdith, smaugt, snova and sqisign, 230 services between them - case-folded the name they got back from the spec without checking it, so a spec with no getName() method, and a null spec, produced a NullPointerException from inside the fold; their own \u0026quot;is this name one I know\u0026quot; branch, which does report the declared exception, was unreachable. The two composite generators, whose parameter set is fixed by the algorithm name so that null is the only spec they accept, refused every other one with IllegalArgumentException. RSA answered correctly for a spec of the wrong type but not for one of the right type carrying values its lightweight parameters will not take - an even public exponent, or a key size below the floor - which is now translated the same way the int overload's is. All 304 services now report the declared exception, with the composites still taking the null spec that is right for them; note that InvalidAlgorithmParameterException is a checked exception and not an IllegalArgumentException, so a caller that was catching what these threw before has to catch the declared type instead.\u003c/li\u003e\n\u003cli\u003eAn HSS private key claimed the two records of its position under two different monitors. The top-level index and the bottom component key's one-time index q are independent records of the same position - the decoder requires them to agree, see the entry below - but generateLMSContext incremented the index under the HSS key's own monitor, released it, and only then claimed q under the component key's. A getEncoded() issued in between saw the index advanced and q not, and produced an encoding this implementation's own decoder rejects; and two threads meeting at a bottom-tree boundary could both pass the exhaustion test, take consecutive top-level indices and claim the same q, after which one of them was refused with \u0026quot;ots private key exhausted\u0026quot; by a key still reporting usages remaining, a top-level index had been spent with no signature made, and the two records stayed one apart for the rest of the key's life in that process - so it could no longer be encoded, cloned or sharded, and getIndex() and getUsagesRemaining() misreported by one. No one-time key was reused: the component key's claim is itself atomic, and the divergence runs index ahead of leaves, so the effect was on the key's usability rather than on the signatures it had made. Both records are now claimed under the one monitor, and the component key is claimed before the index is incremented so that an exhausted one leaves both untouched. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the same correction.\u003c/li\u003e\n\u003cli\u003eTimeStampToken parsed the attacker-controlled TSTInfo content of a time-stamp token (org.bouncycastle.tsp.TimeStampToken, reached from TimeStampResponse(byte[]) and (InputStream)) inside a try that caught only CMSException, so a well-formed RFC 3161 TimeStampResp whose embedded token carried a malformed TSTInfo - a SEQUENCE with fewer elements than the five mandatory fields, a non-SEQUENCE, truncated DER, or an unknown context tag - let an IllegalArgumentException or a NoSuchElementException escape the constructor's declared throws TSPException, IOException contract. A token signed by no signers or by more than one raised a bare IllegalArgumentException from the same constructor, before that try, for the same reason. Both are now reported as TSPException, matching the package-private TimeStampResponse(DLSequence) constructor and the existing getSignedAttributes guard in the same method; the signer-count refusal is a TSPValidationException, as the neighbouring check on the content type already was. Related, and the cause of the NoSuchElementException: asn1.tsp.TSTInfo read its five mandatory fields off the sequence with no bound on how many elements were actually there, so a short SEQUENCE left the enumeration to run out rather than being refused, and an oversize one was accepted with its extra elements absorbed into the optional slots. Decode now requires the five to ten elements RFC 3161 sec. 2.4.2 gives the type, which is what the sibling Accuracy and ArchiveTimeStamp decoders already did, so the failure is the IllegalArgumentException that getInstance is expected to raise (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2415\"\u003e#2415\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eNeither the HSS nor the XMSS^MT private key decoder checked its declared index against the traversal state stored beside it, although the two are independent records of the same position in the key and so can be compared. For HSS the records are the top-level index and the component keys' one-time indices q; for XMSS^MT they are the global index and the per-layer BDS states. A stored key whose index had been rolled back while its state stayed advanced - a partial write, a restore from backup, a buggy storage layer - was therefore accepted, and it then signed a second message under a one-time key the key had already used, producing a signature that verified, so nothing anywhere surfaced the reuse. RFC 8554 sec. 1 and RFC 8391 sec. 1.1 both require each one-time key to be used exactly once, and this is the failure those requirements exist to prevent; the single-tree XMSS decoder has tied its BDS state to its index since that state was first validated, and this brings the two multi-tree schemes into line. HSS decode now requires the declared index to equal the position the component q values imply - a level above the last contributes (q - 1) leaves of the levels beneath it, since its q has already advanced past the subtree it signed - and XMSS^MT decode now requires each present layer's BDS index to equal the leaf index that layer derives from the global index, allowing the one position where a layer has moved into a new subtree and its state legitimately still carries the previous subtree's final index. A layer with no state yet is unaffected, since those are built lazily at signing time. Related, and the same shape of omission: an XMSS or XMSS^MT private key encoding carries the tree root twice - the key's own root field and the root node of the BDS state stored beside it, which for XMSS^MT is the top layer's - and the two were never compared either. A corrupted root was accepted and then poisoned every signature the key made, because the root is hashed into the message digest: the signature did not verify and nothing indicated why. Decode now requires the two copies to agree. The BDS node values themselves are not checkable the way the LMS tree cache above is - a BDS authentication path, stack, retain or keep node does not have its children stored alongside it, so recomputing one means building a subtree, which is the work the state exists to avoid. Both checks are integer comparisons over the levels of the key, too small to measure against the surrounding decode, and both were verified not to reject any legitimate key by walking every index a key can reach: the full key space of the two-level HSS and the h=4/d=2, h=6/d=2, h=6/d=3, h=9/d=3 and h=8/d=4 XMSS^MT parameter sets, plus a three-level HSS key across a subtree boundary and an HSS shard. Since those node values cannot be recomputed, the encoded state now carries a checksum over itself instead, with the owning key's public seed hashed in front of it. Any corruption of the stored state is refused at decode rather than being loaded and then producing signatures that silently do not verify, and because the public seed is bound in, a state transplanted between two keys of the same parameter set is refused too, even though it is internally consistent and arrives with its own matching root. The public seed is bound rather than the secret seed or the PRF key deliberately: the state's own root and index are inside the encoding and so are already covered, hashing secret material would make the stored checksum a commitment to it for no gain in detection, and the PRF key does not influence the state at all. \u003cstrong\u003eThis is an error-detecting code and not integrity protection\u003c/strong\u003e - anyone able to rewrite the stored key recomputes it, so it establishes that the state is unchanged since it was written, never that it was correct when written, and the allocation bounds on the encoding remain the guard against a crafted one. It costs one SHA-256 over the state, measured at 5 to 8 microseconds each way for the h=10 and h=16 parameter sets, and 32 bytes of encoding. The state encoding was added earlier in this same cycle and has not been released, so the checksum is simply part of it rather than a new version: a state written by a 1.86 beta is rejected, which is recovered from by re-exporting the key. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the HSS check as well (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2414\"\u003e#2414\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe S/MIME example smoke test in the misc module (org.bouncycastle.mail.smime.examples.test.AllTests) drove SendSignedAndEncryptedMail against smtp.gmail.com, and that example finishes with Transport.send() under JavaMail's default settings, which have no connect timeout. Where outbound port 25 is refused the failure was swallowed and the test passed; where it is silently dropped, as on many home networks, the connect blocked and ./gradlew build hung in :misc:test indefinitely with \u0026quot;0 tests completed\u0026quot;. The test now delivers to an SMTP stub on a loopback port, with connect / read / write timeouts as a backstop, and asserts the message arrived (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2407\"\u003e#2407\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation took the traditional component public key bytes it feeds the KEM combiner from the recipient key's own encoding, while decapsulation recomputes the point from the private key and so always produced an uncompressed one. Section 4 of draft-ietf-lamps-pq-composite-kem requires an EC component to be carried as an uncompressed point, but a component key that encodes itself compressed - a BC EC key whose point format has been set through org.bouncycastle.jce.interfaces.ECPointEncoder, or a key from a provider that preserves a compressed encoding - was passed through as it came. Both sides then combined a different tradPK and derived different shared secrets, with no error reported on either: encapsulation and decapsulation both succeeded and the recipient simply could not decrypt. The EC component is now normalised to an uncompressed point wherever the engine serialises one, which covers the ephemeral key that forms the ciphertext as well. X25519 and X448 components have a single encoding and were unaffected, as were EC keys left in their default (uncompressed) format, whose shared secrets are unchanged. CompositePublicKey.getEncoded() took its component bytes the same way, so such a key also encoded to a composite key other implementations reject and whose bytes changed across an encode / decode / encode round trip - 1238 bytes rather than 1270 for MLKEM768-ECDH-P256, and for the composite ML-DSA keys sharing that method, 2006 rather than 2038 for MLDSA65-ECDSA-P256. It now normalises the component the same way. This is a write-side change only: a composite key carrying a compressed EC component is still decoded, since the component key factories accept either form, and continues to verify signatures as before - it simply re-encodes in the normalised form. The shared normalisation is org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil.getUncompressedSubjectPublicKeyBytes.\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation threw a NullPointerException, wrapped in an IllegalStateException out of KeyGenerator.generateKey(), when the SecureRandom it was given was null - which javax.crypto.KEM.newEncapsulator() documents as a request for the provider's default, and which KeyGenerator.init(spec, null) passes straight through. The three RSA-OAEP composites draw the traditional shared secret from that random directly, so they were the ones affected; the ECDH and X25519 / X448 composites escaped only because their component KeyPairGenerators default a random of their own. CompositeMLKEMEngine now defaults one through CryptoServicesRegistrar.getSecureRandom() on first use, as the composite KEM Cipher's wrap path already did, and as the KEM generators corrected earlier in this cycle now do. Related, the engine now also clears the ML-KEM component's shared secret alongside the traditional one on both the encapsulate and decapsulate paths - the copy handed back by getEncoded() was left in the heap - as section 3.5 of draft-ietf-lamps-pq-composite-kem requires.\u003c/li\u003e\n\u003cli\u003eCompositePublicKey.getAlgorithm() and CompositePrivateKey.getAlgorithm() returned null for all twelve Composite ML-KEM (draft-ietf-lamps-pq-composite-kem) parameter sets. Both classes resolved the name through the composite signature index only, which holds the composite ML-DSA OIDs, so a composite KEM key pair - generated, parsed from a certificate, or read from PKCS#8 - reported no algorithm at all, and the standard JCA idiom of reconstructing a key with KeyFactory.getInstance(key.getAlgorithm()) raised a NullPointerException. The lookup now falls back to the composite KEM index, so the name returned is the one the provider registers the algorithm under (e.g. MLKEM768-X25519-SHA3-256), matching the composite ML-DSA behaviour. The same single-index assumption made the CompositePublicKey(SubjectPublicKeyInfo) and CompositePrivateKey(PrivateKeyInfo) constructors reject a composite KEM key with \u0026quot;unable to create CompositePublicKey from SubjectPublicKeyInfo\u0026quot;; they now dispatch to the composite KEM key factory for those OIDs. Keys obtained through KeyFactory or through BouncyCastleProvider.getPublicKey / getPrivateKey were unaffected and are unchanged (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2404\"\u003e#2404\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe org.bouncycastle.jcajce.spec.KEMKDFSpec constructor stored a null otherInfo as given, so getOtherInfo() returned null, and three of the KDF branches KdfUtil.makeKeyBytes dispatches to - KMAC-128, KMAC-256 and SHAKE-256 - read the otherInfo length without a guard and threw NullPointerException out of the KEM operation, where the KDF2, KDF3 and HKDF branches tolerate a null through KDFParameters / HKDFParameters. The Builder of every spec in the package already mapped null to empty, so no provider path reached it, but the constructor is protected on a public class and KdfUtil is documented for callers building their own KEM integration; the deprecated KEMParameterSpec passes a null itself and escaped only because it also pins the KDF to null. The constructor now stores empty for a null, so getOtherInfo() never returns null, and a null and an explicitly empty otherInfo derive the same key.\u003c/li\u003e\n\u003cli\u003eQR-UOV signature verification accepted a signature encoding that was not canonical, so the encoding of a signature was not unique even after the trailing-byte fix of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e. Each F_q element of the signature is stored in ceil(log2 q) bits, one more bit pattern than the field has elements: q itself is representable and is arithmetically congruent to zero, so an element written as q verified exactly as the same element written as zero would, and the bits padding the last element out to the byte boundary were never read at all. Every zero element of a signature therefore carried a second encoding, and for the q = 7 parameter sets roughly one element in seven is zero - a single qruov_5_q7_L10 signature measured 256 spare bits, so on the order of 2^256 distinct byte strings verified for the one message and key. Verification now rejects any element outside [0, q) and any set padding bit; a signature produced by this or by the reference implementation is unaffected, as the KAT vectors of every parameter set confirm. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSNOVA signature verification ignored four bits inside the signature for any parameter set whose solution is an odd number of GF(16) nibbles - the SNOVA_24_5_5, SNOVA_25_8_3, SNOVA_29_6_5 and SNOVA_66_15_3 families, sixteen of the forty-four parameter sets. The last byte of the encoded solution carries a single nibble and the signer leaves the top four bits zero, but the decoder did not read them, so sixteen distinct byte strings verified for one signature. This is the same non-unique encoding github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e closed for bytes following the signature, applied inside it; the verifier now requires those bits to be zero. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSnovaPrivateKeyParameters did not validate the length of the private key encoding handed to it - the only one of the five schemes of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e that did not - and SnovaParameters.getPrivateKeyLength() reported the expanded (\u0026quot;ESK\u0026quot;) length even for a parameter set whose private key is the seed pair. A private key encoding reaches this constructor straight from a PKCS#8 blob, so a wrong length went undetected: a seed-form key with extra bytes appended was accepted and signed under a different derived key, and a short expanded-form key sized the signer's decode buffer negatively, throwing NegativeArraySizeException out of generateSignature() rather than being reported at construction. Related, the signing retry loop could not terminate: the vinegar values are derived from a single-byte counter, so only 256 distinct linear systems can be tried, and an expanded-form private key that is not a real central map is singular for all of them - generateSignature() then span forever rather than failing. The length is now checked at construction, getPrivateKeyLength() reports the length that parameter set's private key actually has, and the retry loop gives up after its 256 attempts as MAYO's does.\u003c/li\u003e\n\u003cli\u003eMayoSigner and MayoKeyPairGenerator did not clear several buffers holding secret key material that the MAYO reference implementation explicitly clears. Signing left the secret oil space O, the expanded L = (P1 + P1^t) * O + P2, and the M / VPV / Ox intermediates of the central map in place, having gone to the trouble of clearing eleven other buffers; key generation left the expanded seed, whose tail is the encoded oil space, and the P1 * O + P2 half of P; and the row-echelon step left the packed echelon form of the secret linear system and its pivot rows. Separately, if all 256 attempts at solving for the signature had given a rank-deficient system, signing emitted a signature built from the failed attempt's state instead of reporting the failure the reference returns, and AIMerSigner.generateSignature returned an empty array on failure, which a caller would hand on as though it were a signature. Both now throw.\u003c/li\u003e\n\u003cli\u003eFive PQC signature schemes - MAYO, SNOVA, QR-UOV, SQIsign and AIMer - returned the NIST crypto_sign \u0026quot;sm\u0026quot; signed-message envelope from generateSignature() rather than the signature. That envelope is an artefact of the reference KAT harness, which records the message alongside the signature so a vector file can be self-contained; it is not part of any of the five specifications, and no other BC signer emits it (Falcon's KAT test rebuilds the equivalent envelope in the test, which is where it belongs). Two consequences followed, both reaching the JCA Signature services of every parameter set of the five schemes in BouncyCastlePQCProvider. First, since the message was appended to the signature, verification had to skip whatever followed the signature proper, and it did so by checking only that the buffer was long enough - so any number of trailing bytes could be added to a valid signature, or the appended message replaced with unrelated data, and it still verified. A signature encoding was therefore not unique: anyone holding one valid signature could produce unlimited distinct byte strings that all verified for the same message and key, which breaks any use that treats the signature bytes as an identifier, deduplicates on them, or records them as evidence. Second, the envelope propagated into everything built on the operator layer: because ContentSigner hands the signature straight into the structure being signed, every X.509 certificate, CRL, CMS SignedData and TLS CertificateVerify BC produced with one of these algorithms carried a verbatim copy of the signed data inside its own signature field - a self-signed MAYO-1 certificate came to 3567 bytes where the same certificate is now 2020 - which no other implementation can parse as a signature, and which in a detached CMS signature meant the \u0026quot;detached\u0026quot; signature carried the content. generateSignature() now returns the bare signature, and verifySignature() requires exactly the parameter set's signature length, so appended or truncated data is rejected rather than ignored. \u003cstrong\u003eThis is a behavioural change for signatures produced by an earlier release\u003c/strong\u003e - MAYO and SNOVA from 1.84, QR-UOV, SQIsign and AIMer from 1.85 - which are no longer accepted in the envelope form they were emitted in; the signature bytes themselves are unchanged, so a stored value can be recovered by taking the leading signature-length bytes, or for AIMer, whose envelope was message || signature rather than signature || message, the trailing ones. The KAT tests now rebuild the envelope before comparing against the vector files, which continue to record it. Note that AIMer's verification had already been made length-exact during this cycle (see the entry below relating to github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2401\"\u003e#2401\u003c/a\u003e), so of the five only its envelope remained (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe MLS implementation did not bind an X.509 credential to the LeafNode's signature_key. LeafNode.verify() checked a leaf's signature against the signature_key declared in the leaf itself, while the X.509 credential's certificate chain was stored but never parsed or checked, so the certificate's public key was never required to match signature_key (RFC 9420 sec. 5.3). A leaf could therefore carry one party's certificate while being signed by an unrelated key and still be accepted under that party's identity through KeyPackage.verify() and the Group leaf-validation path. LeafNode.verify() now requires the end-entity certificate's subject public key, in the cipher suite's signature encoding, to equal signature_key for an X.509 credential, and rejects the leaf otherwise - including an empty chain or a certificate whose key type does not match the cipher suite; certificate-chain and identity validation to a trust anchor remain the application's responsibility per RFC 9420 sec. 5.3.1. A public org.bouncycastle.mls.codec.Certificate(byte[]) constructor and a Credential.getCertificates() accessor are added so callers can build and inspect X.509 credentials. Basic credentials are unaffected.\u003c/li\u003e\n\u003cli\u003eThe SecureRandom supplied to org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder.setSecureRandom() did not drive the content IV / nonce for any algorithm other than RC2. EnvelopedDataHelper.generateParameters passed the caller's SecureRandom to the AlgorithmParameterGenerator only in the RC2_CBC branch; every other content-encryption algorithm - AES-CBC, AES-GCM, AES-CCM, Camellia, ARIA, SEED and the rest - reached pGen.generateParameters() on an uninitialised generator, so the IV / nonce was drawn from a default SecureRandom and setSecureRandom() was silently ignored (the builder's javadoc states that random is used for IV/nonce generation). The generator is now initialised with the supplied random on the general path as well, so a caller who provides a specific randomness source - for a controlled or FIPS-approved DRBG, say - has it honoured for the content IV / nonce. The session-key generation path was unaffected and already used the supplied random. Because the content IV / nonce now comes from the supplied SecureRandom, the org.bouncycastle.crypto.util JournalingSecureRandom / JournaledAlgorithm reproducible-encryption support records it in the transcript: a resumed session reproduces the IV / nonce by regenerating it from the replayed randomness - build the resuming encryptor from the content-algorithm OID - rather than by reusing the AlgorithmIdentifier captured from the first encryption, which no longer keeps the transcript aligned.\u003c/li\u003e\n\u003cli\u003eThe NTRU LPRime, NTRU+ and SMAUG-T KEM generators threw a NullPointerException when constructed with a null SecureRandom, where every other KEM generator - including NTRU LPRime's own SNTRU Prime counterpart in the same package - defaults one through CryptoServicesRegistrar.getSecureRandom(). This is reachable from the lightweight API directly, and from javax.crypto.KEM, whose newEncapsulator() documents a null random as a request for the provider's default.\u003c/li\u003e\n\u003cli\u003eFrodoKEMEngine kept a single SHAKE instance in a field, so an engine reached concurrently produced wrong results. It is reached that way through org.bouncycastle.crypto.kems.FrodoKEMExtractor, which holds one engine for its lifetime: two threads extracting through one extractor interleaved the digest's absorb and squeeze phases, yielding shared secrets that silently did not match the sender's, or an IllegalStateException of \u0026quot;attempt to absorb while squeezing\u0026quot; from inside extractSecret. The digest is now built per call, as CMCEEngine's already was, which makes an extractor safe to share. Encapsulation was unaffected, since FrodoKEMGenerator builds an engine per call. Results for any single-threaded use are unchanged - the reference KAT vectors are byte-identical.\u003c/li\u003e\n\u003cli\u003eThe BCJSSE provider carried the TLS 1.2 coupling between the supported_groups extension and ECDSA over into TLS 1.3: an ECDSA signature scheme was treated as usable - offered in the signature_algorithms and signature_algorithms_cert extensions, and eligible when selecting the local credentials - only while the corresponding curve was among the named groups enabled for key exchange, both per context (a group unavailable for key agreement disabled the scheme outright) and per connection (the curve had to be in the supported_groups list about to be sent). RFC 8446 sec. 4.2.7 scopes supported_groups to key exchange only, with signature algorithms negotiated independently (sec. 4.2.3), so this incorrect restriction in TLS 1.3 has been removed. Ed25519, Ed448 and the RSA schemes were unaffected (as well as typical deployments using a default configuration for named groups).\u003c/li\u003e\n\u003cli\u003eThe bcmail module descriptor did not declare its javax.mail/javax.activation dependences, so a modular (module-path) consumer of the jar hit IllegalAccessError/module-resolution failures when the S/MIME classes touched the mail API. The descriptor now requires them optionally (requires static) under all four module names those libraries are known by - the automatic names mail and activation carried by the javax.mail:mail / javax.activation:activation artifacts, and the explicit names java.mail and java.activation carried by the newer com.sun.mail / com.sun.activation ones - a hard requires on any one name would break users of the others (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2389\"\u003e#2389\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFour type-coercion helpers in the OER / IEEE 1609.2 (ITS) decoder tested the wrong type in the identity fast path that lets a getInstance() factory return an argument that is already of the target type. org.bouncycastle.oer.its.ieee1609dot2.basetypes.UINT32.getInstance and org.bouncycastle.oer.its.etsi102941.basetypes.Version.getInstance guarded on UINT8 - a sibling of UINT32 under UintBase, and unrelated to Version - so passing a UINT8 threw ClassCastException, while passing an actual UINT32 or Version missed the fast path and fell through to ASN1Integer.getInstance, which rejects them: neither factory accepted its own type. org.bouncycastle.oer.its.etsi103097.EtsiTs103097DataEncryptedUnicast.getInstance guarded on its sibling EtsiTs103097DataEncrypted and then cast to the unicast type, so an EtsiTs103097DataEncrypted threw ClassCastException. org.bouncycastle.oer.OEROptional.getObject(Class) called value.getClass().isInstance(type) with the arguments transposed, which is always false because the argument is a java.lang.Class, so the cast path was dead and every optional field was resolved reflectively, failing with IllegalStateException for a target type with no static getInstance. Each guard now names the type it returns, matching the sibling UINT8 / UINT16 / UINT64 and EtsiTs103097DataEncrypted factories (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2373\"\u003e#2373\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eDefaultAlgorithmNameFinder and DefaultSignatureNameFinder had no entries at all for the ShangMi algorithms, so an SM2 signature AlgorithmIdentifier that DefaultSignatureAlgorithmIdentifierFinder itself produces came back named only by its OID string - getAlgorithmName(GMObjectIdentifiers.sm2sign_with_sm3) returned \u0026quot;1.2.156.10197.1.501\u0026quot; and hasAlgorithmName returned false. Both finders now name sm2sign_with_sm3 as SM3WITHSM2 and sm2sign_with_sha256 as SHA256WITHSM2, and DefaultAlgorithmNameFinder additionally names the sm3 digest. All three resolve through the BC provider, as Signature and MessageDigest respectively. The remaining GM arc - the SM4 cipher modes, the sm2encrypt variants, and the SM1 / SM6 / SSF33 ciphers BC does not implement - is still unnamed (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2377\"\u003e#2377\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe RFC 4998 evidence-record classes compared the digest AlgorithmIdentifier named by a time-stamp authority with the one their own DigestCalculator uses, and did so with AlgorithmIdentifier.equals(), which compares the encodings. A TSA that names SHA-256 with an explicit NULL parameters field - DigiCert among them - therefore failed against BC's own calculator, which names it with the parameters absent, and ERSArchiveTimeStampGenerator.generateArchiveTimeStamp rejected the response with \u0026quot;time stamp imprint for wrong algorithm\u0026quot;. Both spellings name the same digest and RFC 5754 sec. 2 requires a receiver to accept either, while requiring that identifiers be generated with the parameters absent, which BC already does. The three affected comparisons - the two in ERSArchiveTimeStampGenerator and the digest check in ERSEvidenceRecord.renew - now use the new AlgorithmIdentifier.areEquivalent, which matches on the algorithm and treats an absent parameters field and NULL as the same, and the consistency check across an evidence record's archive time stamp chain uses it too. An identifier carrying an actual parameter structure is never equivalent to one carrying none (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2379\"\u003e#2379\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eEDIPartyName.toASN1Primitive emitted the nameAssigner and partyName DirectoryStrings without their context tags, so an EDIPartyName built through its public constructor could not be parsed back by EDIPartyName.getInstance, which correctly requires them. RFC 5280 sec. 4.2.1.6 tags both members [0] and [1], and those tags are explicit despite the module's IMPLICIT TAGS because DirectoryString is a CHOICE, which X.680 does not allow to be tagged implicitly - the decoder already had this right. The encoder now matches it. Note the type was added during the 1.85 cycle and GeneralName validates its ediPartyName alternative through it, so a GeneralName carrying an untagged ediPartyName - including one BC itself produced - is rejected where 1.84 passed it through unexamined; the untagged form is not read leniently (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2380\"\u003e#2380\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eRSASSA-PSS could not be used with a RIPEMD digest through the JCA API. Nothing registered the RIPEMD PSS signatures, so Signature.getInstance(\u0026quot;RIPEMD160WITHRSAANDMGF1\u0026quot;) raised NoSuchAlgorithmException, and the generic RSASSA-PSS route with an explicit PSSParameterSpec failed too: org.bouncycastle.jcajce.provider.util.DigestFactory.getDigest returned null for a RIPEMD name, and isSameDigest - an allow-list of the SHA families and MD5 - reported two identical RIPEMD names as different digests, so the spec was rejected with \u0026quot;digest algorithm for MGF should be the same as for PSS parameters\u0026quot;. isSameDigest now answers true for equal names whatever the digest, which also covers Whirlpool, SM3, GOST3411 and anything else outside that allow-list; DigestFactory recognises RIPEMD128, RIPEMD160 and RIPEMD256 by name and OID; the three PSS signatures are registered with MGF1 over the same digest and a salt of the digest length; and DefaultSignatureAlgorithmIdentifierFinder gains the matching RIPEMD*WITHRSAANDMGF1 entries with their RSASSA-PSS-params, so the operator/JcaContentSignerBuilder path works as well. Note BC continues to require the PSS hash and the MGF1 hash to be the same, which RFC 8017 does not itself demand (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2381\"\u003e#2381\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe opt-in key-size validation on CMS key-transport recipients (org.bouncycastle.cms.jcajce.JceKeyTransRecipient.setKeySizeValidation(true)) never ran for a message using RFC 9709 CEK derivation (id-alg-cek-hkdf-sha256): the branch that should have selected the actual content-encryption algorithm carried in the KDF AlgorithmIdentifier's parameters compared the encrypted-key byte array against the id-alg-cek-hkdf-sha256 object identifier - a comparison that is always false - so the check fell through to a key-size lookup on the outer KDF OID, which has no registered key size, and silently checked nothing. A key-transport EnvelopedData/AuthEnvelopedData whose transported (and HKDF-derived) content-encryption key did not match the key size of the advertised content-encryption algorithm was therefore accepted even with validation enabled. The recipient now dispatches on the content-encryption AlgorithmIdentifier's algorithm OID, so key-size validation of RFC 9709 messages checks the recovered key against the inner content-encryption algorithm. Messages with a matching key size, non-HKDF messages, and recipients that do not enable validation are unaffected.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003eSee full diff in \u003ca href=\"https://github.com/bcgit/bc-java/commits\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003ecommonmark-java 0.29.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e[0.29.0] - 2026-06-20\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/comm...\n\n_Description has been truncated_","html_url":"https://github.com/stevewow/openclaw/pull/41","url":"https://dependabot.ecosyste.ms/api/v1/hosts/GitHub/repositories/stevewow%2Fopenclaw/issues/41","packages_url":"https://dependabot.ecosyste.ms/api/v1/issues/41/packages"}},{"old_version":"5.4.0","new_version":"5.5.0","update_type":"minor","path":null,"pr_created_at":"2026-09-09T21:11:02.000Z","version_change":"5.4.0 → 5.5.0","issue":{"uuid":"5404784348","node_id":"PR_kwDOTdoxEM8AAAABC5c9bA","number":13,"state":"closed","title":"Bump the android-deps group across 1 directory with 17 updates","user":"dependabot[bot]","labels":["dependencies","java"],"assignees":[],"locked":false,"comments_count":1,"pull_request":true,"closed_at":"2026-09-11T21:07:46.000Z","author_association":null,"state_reason":null,"created_at":"2026-09-09T21:11:02.000Z","updated_at":"2026-09-11T21:07:48.000Z","time_to_close":172604,"merged_at":null,"merged_by":null,"closed_by":null,"dependency_metadata":{"prefix":"Bump","group_name":"android-deps","update_count":17,"packages":[{"name":"gradle-wrapper","old_version":"9.6.1","new_version":"9.7.1","repository_url":"https://github.com/gradle/gradle"},{"name":"org.bouncycastle:bcprov-jdk18on","old_version":"1.84","new_version":"1.85.2","repository_url":"https://github.com/bcgit/bc-java"},{"name":"org.commonmark:commonmark","old_version":"0.29.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-autolink","old_version":"0.29.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-strikethrough","old_version":"0.29.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-tables","old_version":"0.29.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-task-list-items","old_version":"0.29.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.junit.vintage:junit-vintage-engine","old_version":"6.1.1","new_version":"6.1.3","repository_url":"https://github.com/junit-team/junit-framework"},{"name":"io.kotest:kotest-assertions-core-jvm","old_version":"6.2.1","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"io.kotest:kotest-runner-junit5-jvm","old_version":"6.2.1","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"com.squareup.okhttp3:mockwebserver","old_version":"5.4.0","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.squareup.okhttp3:okhttp","old_version":"5.4.0","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.android.application","old_version":"9.2.1","new_version":"9.4.0"},{"name":"com.android.test","old_version":"9.2.1","new_version":"9.4.0"},{"name":"org.jetbrains.kotlin.plugin.compose","old_version":"2.4.0","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"},{"name":"org.jetbrains.kotlin.plugin.serialization","old_version":"2.4.0","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"},{"name":"com.google.devtools.ksp","old_version":"2.3.9","new_version":"2.3.11","repository_url":"https://github.com/google/ksp"}],"path":null,"ecosystem":"maven"},"body":"Bumps the android-deps group with 17 updates in the /apps/android directory:\n\n| Package | From | To |\n| --- | --- | --- |\n| [gradle-wrapper](https://github.com/gradle/gradle) | `9.6.1` | `9.7.1` |\n| [org.bouncycastle:bcprov-jdk18on](https://github.com/bcgit/bc-java) | `1.84` | `1.85.2` |\n| [org.commonmark:commonmark](https://github.com/commonmark/commonmark-java) | `0.29.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-autolink](https://github.com/commonmark/commonmark-java) | `0.29.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-strikethrough](https://github.com/commonmark/commonmark-java) | `0.29.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-tables](https://github.com/commonmark/commonmark-java) | `0.29.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-task-list-items](https://github.com/commonmark/commonmark-java) | `0.29.0` | `0.30.0` |\n| [org.junit.vintage:junit-vintage-engine](https://github.com/junit-team/junit-framework) | `6.1.1` | `6.1.3` |\n| [io.kotest:kotest-assertions-core-jvm](https://github.com/kotest/kotest) | `6.2.1` | `6.2.4` |\n| [io.kotest:kotest-runner-junit5-jvm](https://github.com/kotest/kotest) | `6.2.1` | `6.2.4` |\n| [com.squareup.okhttp3:mockwebserver](https://github.com/lysine-dev/okhttp) | `5.4.0` | `5.5.0` |\n| [com.squareup.okhttp3:okhttp](https://github.com/lysine-dev/okhttp) | `5.4.0` | `5.5.0` |\n| com.android.application | `9.2.1` | `9.4.0` |\n| com.android.test | `9.2.1` | `9.4.0` |\n| [org.jetbrains.kotlin.plugin.compose](https://github.com/JetBrains/kotlin) | `2.4.0` | `2.4.20` |\n| [org.jetbrains.kotlin.plugin.serialization](https://github.com/JetBrains/kotlin) | `2.4.0` | `2.4.20` |\n| [com.google.devtools.ksp](https://github.com/google/ksp) | `2.3.9` | `2.3.11` |\n\n\nUpdates `gradle-wrapper` from 9.6.1 to 9.7.1\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/gradle/gradle/releases\"\u003egradle-wrapper's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e9.7.1\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.1.\u003c/p\u003e\n\u003cp\u003eThis is a patch release for 9.7.0. We recommend using 9.7.1 instead of 9.7.0.\u003c/p\u003e\n\u003cp\u003eHere are the highlights of 9.7.0 release:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIsolated Projects graduates to incubating\u003c/li\u003e\n\u003cli\u003eBroader Configuration Cache compatibility\u003c/li\u003e\n\u003cli\u003eResilient Sync helps you fix broken builds\u003c/li\u003e\n\u003cli\u003eMore source locations in problem reports\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003ca href=\"https://docs.gradle.org/9.7.1/release-notes.html\"\u003eRead the Release Notes\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eWe would like to thank the following community members for their contributions to this release of Gradle:\n\u003ca href=\"https://github.com/aSemy\"\u003eAdam\u003c/a\u003e,\n\u003ca href=\"https://github.com/Gautam-aman\"\u003eAman Gautam\u003c/a\u003e,\n\u003ca href=\"https://github.com/YukiCodepth\"\u003eAman Kumar\u003c/a\u003e,\n\u003ca href=\"https://github.com/adubrouski\"\u003eAnton Dubrouski\u003c/a\u003e,\n\u003ca href=\"https://github.com/liutikas\"\u003eAurimas\u003c/a\u003e,\n\u003ca href=\"https://github.com/gbhavya07\"\u003egbhavya07\u003c/a\u003e,\n\u003ca href=\"https://github.com/joshfriend\"\u003eJosh Friend\u003c/a\u003e,\n\u003ca href=\"https://github.com/nicklauslittle-gov\"\u003enicklauslittle-gov\u003c/a\u003e,\n\u003ca href=\"https://github.com/psoni674\"\u003ePragati\u003c/a\u003e,\n\u003ca href=\"https://github.com/Project516\"\u003eproject516\u003c/a\u003e,\n\u003ca href=\"https://github.com/Uomocapra\"\u003eQin Mi\u003c/a\u003e,\n\u003ca href=\"https://github.com/rkdfx\"\u003eRavi\u003c/a\u003e,\n\u003ca href=\"https://github.com/sk-reddy17\"\u003esk-reddy17\u003c/a\u003e,\n\u003ca href=\"https://github.com/Suvrat1629\"\u003eSuvrat Acharya\u003c/a\u003e,\n\u003ca href=\"https://github.com/ShreckYe\"\u003eYongshun Ye\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eUpgrade instructions\u003c/h2\u003e\n\u003cp\u003eSwitch your build to use Gradle 9.7.1 by updating your wrapper:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e./gradlew :wrapper --gradle-version=9.7.1 \u0026amp;\u0026amp; ./gradlew :wrapper\r\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eSee the Gradle \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/upgrading_version_9.html\"\u003e9.x upgrade guide\u003c/a\u003e to learn about deprecations, breaking changes and other considerations when upgrading.\u003c/p\u003e\n\u003cp\u003eFor Java, Groovy, Kotlin and Android compatibility, see the \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/compatibility.html\"\u003efull compatibility notes\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eReporting problems\u003c/h2\u003e\n\u003cp\u003eIf you find a problem with this release, please file a bug on \u003ca href=\"https://github.com/gradle/gradle/issues\"\u003eGitHub Issues\u003c/a\u003e adhering to our issue guidelines.\nIf you're not sure you're encountering a bug, please use the \u003ca href=\"https://discuss.gradle.org/c/help-discuss\"\u003eforum\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eWe hope you will build happiness with Gradle, and we look forward to your feedback via \u003ca href=\"https://twitter.com/gradle\"\u003eTwitter\u003c/a\u003e or on \u003ca href=\"https://github.com/gradle\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003e9.7.0\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.0.\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/92f0512e7f06d84621afba191f75e265363890cf\"\u003e\u003ccode\u003e92f0512\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38892\"\u003e#38892\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/820ee75a99a179bbffa41bcedc6477b685fabb9f\"\u003e\u003ccode\u003e820ee75\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/82c23f9bd2a89b4cc644e1f90a28a8668feb3dee\"\u003e\u003ccode\u003e82c23f9\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering problem in KTS (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38878\"\u003e#38878\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/ef11a7268fe8cc8d6ab849ec911aa11220180553\"\u003e\u003ccode\u003eef11a72\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering issue\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/bb0d8a974a71b1003efea41e4046e98855cd5ff8\"\u003e\u003ccode\u003ebb0d8a9\u003c/code\u003e\u003c/a\u003e Make relevant tests polyglot (run for multiple DSLs)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/336e129d7f95c03486acafc97abf59734acfed48\"\u003e\u003ccode\u003e336e129\u003c/code\u003e\u003c/a\u003e Update signing configuration (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38874\"\u003e#38874\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/4bdf0da2dad9884d089a6062a45ea7183e7d735d\"\u003e\u003ccode\u003e4bdf0da\u003c/code\u003e\u003c/a\u003e Update signing configuration\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/cd9b92c1b82856248cf1dc58b50378238bec7b52\"\u003e\u003ccode\u003ecd9b92c\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38839\"\u003e#38839\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/5f4e381964897ad8d6b99e5a7c77f26dba3259fb\"\u003e\u003ccode\u003e5f4e381\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/1e08ab551367aeb5fb48b26e72807e1d2b27c939\"\u003e\u003ccode\u003e1e08ab5\u003c/code\u003e\u003c/a\u003e Keep type-use annotations in extracted ABI classes (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38810\"\u003e#38810\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/gradle/gradle/compare/v9.6.1...v9.7.1\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.bouncycastle:bcprov-jdk18on` from 1.84 to 1.85.2\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.md\"\u003eorg.bouncycastle:bcprov-jdk18on's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch1\u003eBouncy Castle Crypto Package - Release Notes\u003c/h1\u003e\n\u003ch2\u003e1.0 Introduction\u003c/h2\u003e\n\u003cp\u003eThe Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. The package is organised so that it contains a light-weight API suitable for use in any environment (including the J2ME) with the additional infrastructure to conform the algorithms to the JCE framework.\u003c/p\u003e\n\u003ch2\u003e2.0 Release History\u003c/h2\u003e\n\u003cp\u003e\u003c!-- raw HTML omitted --\u003e\u003c!-- raw HTML omitted --\u003e\u003c/p\u003e\n\u003ch3\u003e2.1.1 Version\u003c/h3\u003e\n\u003cp\u003eRelease: 1.86\u003cbr /\u003e\nDate: 2026, TBD\u003c/p\u003e\n\u003ch3\u003e2.1.2 Defects Fixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) let a subkey inherit the primary key's Key Flags when its own Subkey Binding signature carried no Key Flags subpacket, which made the two capability decisions taken for one subkey disagree. OpenPGPCertificate.OpenPGPComponentKey.isSigningKey() reads the effective flags, which fell back to the primary key's direct-key or primary user ID self-signature, so a subkey bound with no flags of its own counted as signing-capable; verifyEmbeddedPrimaryKeyBinding reads the binding signature's own flags, found no signing capability there, and so skipped the embedded Primary Key Binding (cross-certification) signature that RFC 9580 sec. 5.2.1.8 and sec. 10.1.3 require of a subkey that can issue signatures. A data signature made by such a subkey was therefore attributed to the certificate and reported valid by OpenPGPSignature.OpenPGPDocumentSignature.isValid() with the cross-certification requirement never applied, where GnuPG refuses the same certificate and message as not cross-certified. An attacker holding a third party's public signing subkey - which is public material - could bind it to their own primary key with a Subkey Binding signature they are able to make, carrying no Key Flags and no embedded Primary Key Binding signature, which they cannot make without the subkey's private key, and have that party's genuine signatures verify as valid under the attacker's own identity: misattribution of a real signature rather than a forgery of a new one, since the signature still has to be one the subkey actually made. Key Flags are a statement about the key the carrying signature refers to (RFC 9580 sec. 5.2.3.29), so a subkey no longer inherits them from the certificate-wide signatures of the primary key: a Subkey Binding signature that omits the subpacket now leaves the subkey with no capabilities rather than the primary's, which makes the flags the cross-certification check consults the same flags every other decision consults. Preferences and the other subpackets a direct-key signature carries are inherited as before, and the primary key itself - whose flags legitimately come from its direct-key or user ID self-signature - is unaffected. The low-level PGPSignature / PGPPublicKeyRing API performs no binding checks by design and is unchanged.\u003c/li\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) used a version 6 key that carried no valid Direct Key signature, falling back to the primary user ID binding as it correctly does for a version 4 key. RFC 9580 sec. 5.2.3.10 requires the opposite: \u0026quot;An implementation MUST ensure that a valid Direct Key signature is present before using a version 6 key. This prevents certain attacks where an adversary strips a self-signature specifying a Key Expiration Time or certain preferences.\u0026quot; The certificate grammar says the same structurally, the Direct Key signature being mandatory in the version 6 structure of sec. 10.1.1 and optional in the version 4 one of sec. 10.1.3. Because a version 6 certificate carries its key expiration, features and algorithm preferences on the Direct Key signature - the convention the RFC recommends and the one OpenPGPKeyGenerator follows, its user ID certification carrying no expiration at all - removing that single signature packet from a published certificate silently dropped the expiration along with the preferences and features: OpenPGPCertificate.getSignatureChainFor fell back to the user ID binding, the primary key was still reported bound, and getEncryptionKeys() and getSigningKeys() went on returning the subkeys of a key whose owner had set it to expire. The primary key fingerprint is unchanged by the removal, so a relying party pinning the key by fingerprint still treats it as the same key, and no private key or hash collision is involved; the natural moment for the strip is the key refresh that RFC 9580 names as the reason to refetch a key at all - to learn about changes in expiration, features, preferences and revocation - which is exactly the update it defeats. This is a downgrade rather than a forgery, nothing being attributed to a key that did not authorise it, and the concerning direction is encryption, to a key meant to have been retired. OpenPGPCertificate.isBoundBy now requires a valid Direct Key self-signature on a version 6 primary key before any component of the certificate - the primary key, its subkeys or its identities - is treated as bound, so a version 6 certificate stripped of it offers no keys at all rather than an unexpiring set. Version 4 certificates are unaffected: there the key expiration legitimately lives on the user ID self-signature and the fallback is correct, so it stays. The revocation-only version 6 certificate of sec. 10.1.2, which legitimately carries no Direct Key signature, is unaffected as well - its key was already refused as revoked, and reading the revocation does not go through the binding check.\u003c/li\u003e\n\u003cli\u003eThe lightweight LMSSigner and HSSSigner refused a key wrapped in ParametersWithRandom, which is how BcContentSignerBuilder passes a key whenever setSecureRandom() has been called - so BcHssLmsContentSignerBuilder built a working signer until a random was set and then failed with \u0026quot;Incorrect Key Parameters\u0026quot;, and the two signers themselves raised ClassCastException on the same input. All three now unwrap it, as the promoted ML-DSA and SLH-DSA signers already did. The random is accepted and not used: LMS derives its message randomiser C from the key's seed and the one-time index, so it is deterministic and cannot repeat while q does not. Note SP 800-208 sec. 6.1 asks for C to come from an approved random bit generator, which this implementation does not do; that is unchanged here, and a supplied random is now ignored rather than refused.\u003c/li\u003e\n\u003cli\u003eLMS signature verification did not apply two of the checks RFC 8554 sec. 5.4.2 requires before a signature is processed. Step 2g refuses a signature whose LMS typecode is not the one from the public key, and without it the path computation took its height and tree digest from the parameter set the signature named rather than the key's, so a signature claiming a height-25 parameter set drove a 25-level computation against a height-5 key. Step 2i refuses a leaf number q outside the tree, and without it an out-of-range q flowed into the node arithmetic and was left for the candidate-root comparison to catch. Neither was a forgery - the domain separation between D_LEAF and D_INTR and the final comparison saw to that - but both are attacker-chosen work the specification says to refuse up front. Both are now checked, and a signature failing either is still reported as not verifying rather than thrown out of Signature.verify(). The catch around the signature decode in LMSSigner and HSSSigner has also been narrowed to the decode itself, as the corresponding SPI was corrected to do for github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2408\"\u003e#2408\u003c/a\u003e: past the parse the engine reports an inconsistent signature by returning false rather than by throwing, so the wider catch caught nothing while standing ready to turn a future internal error into a quiet false.\u003c/li\u003e\n\u003cli\u003eThe LMS and HSS key parameter classes now apply at construction the checks their decoders apply, so a key built directly cannot be one the decoder would refuse. LMSPrivateKeyParameters accepted an identifier of any length although the decoder reads exactly 16 bytes - such a key encoded but could not be read back - and left q, maxQ and the seed length unchecked; the seed is now required to be at least m bytes at decode as well, where a one-byte seed had been decoding silently and then deriving every one-time key from it. HSSPrivateKeyParameters checked neither its level count nor that it had been given a component key per level and a chaining signature per level below the root, and then indexed both lists, so a mismatch surfaced as IndexOutOfBoundsException - or, where a level happened to match, as a null chaining signature that only failed at signing time; the level is now checked after the reset that fills it in, since a null is legitimate on the way in. LMSPrivateKeyParameters.getInstance(byte[], byte[]) adopted the public key supplied beside the private one without comparing them, so a mismatched public key was simply reported by getPublicKey(); it now cross-checks the identifier, both parameter sets and, where the tree cache already holds it, the root, as the HSS entry point does. The decoders also now report a bad version or seed length as IOException rather than IllegalStateException, so a caller can catch one type for a malformed key, and the package-private LM-OTS public key decoder no longer declares throws Exception or dereferences an unrecognised typecode. The deprecated org.bouncycastle.pqc.crypto.lms copies carry the decoder corrections.\u003c/li\u003e\n\u003cli\u003eIn the LMS JCE layer, LMSKeyGenParameterSpec.fromNames knew all twenty LMS parameter-set names but only four of the sixteen LM-OTS ones, so none of the SP 800-208 n24 or SHAKE sets could be named; all sixteen are now present. KeyPairGenerator.initialize(int, SecureRandom) reports InvalidParameterException, which is what the JCA specifies and which extends the IllegalArgumentException it raised before, so existing catches still match. BCLMSPrivateKey.getIndex now takes the exhaustion check and the index read under the key's own monitor rather than as two separate calls, and two unused fields have gone from LMSSignatureSpi. Note that the LMS Signature claims its one-time key at the first update() rather than at sign(), so a Signature that is initialised and updated and then abandoned spends an index without producing a signature - the safe direction for a one-time scheme, and now documented on the SPI.\u003c/li\u003e\n\u003cli\u003eEvery other key pair generator that refuses a key size did the same thing the LMS one did above. KeyPairGenerator.initialize(int, SecureRandom) is documented to raise InvalidParameterException when the key size is not one the generator supports, and thirty of them raised a bare IllegalArgumentException instead, so a caller following the JCA and catching the documented type saw an exception escaping rather than a refusal. The ML-DSA, ML-KEM, SLH-DSA, Classic McEliece, FrodoKEM, NTRU and composite signature and KEM generators in the BC provider, and every generator in BCPQC, now raise InvalidParameterException - NewHope included, where the value is a key size it will not take rather than a mode of initialisation it does not offer. InvalidParameterException extends IllegalArgumentException, so callers written against the old behaviour go on catching it unchanged. The two RSA generators are corrected as well, and differently: theirs is a key size below a floor rather than a mode of initialisation they do not offer, and the refusal is raised by the lightweight RSAKeyGenerationParameters, which cannot name a java.security exception at all, so the RSA KeyPairGeneratorSpi now translates it - keeping the message verbatim and the original exception as the cause, through a new SecurityExceptions.invalidParameterException factory, since InvalidParameterException has no constructor that takes one. Of the 304 KeyPairGenerator services the two providers register, 299 now refuse a nonsense key size the way the JCA defines it and five accept it as a strength they can work with, with none left raising a bare IllegalArgumentException; that is asserted as a sweep over both providers rather than per algorithm, so a generator added later is covered without the test being touched. The jdk1.3 provider overlays of the four generators that have one carry the same change, and the jdk1.3 SecurityExceptions overlay gains the new factory along with the invalidAlgorithmParameterException one it had been missing.\u003c/li\u003e\n\u003cli\u003eKeyPairGenerator.initialize(AlgorithmParameterSpec, SecureRandom) had the same shape of problem as the int overload above, and only 44 of the 304 services the two providers register reported an unusable spec as the InvalidAlgorithmParameterException that method declares. The twenty-three PQC generators that resolve a parameter set by name - cmce, frodokem, mldsa, mlkem, slhdsa, aimer, bike, faest, falcon, haetae, hqc, mayo, mqom, ntru, ntruplus, both ntruprime variants, qruov, saber, sdith, smaugt, snova and sqisign, 230 services between them - case-folded the name they got back from the spec without checking it, so a spec with no getName() method, and a null spec, produced a NullPointerException from inside the fold; their own \u0026quot;is this name one I know\u0026quot; branch, which does report the declared exception, was unreachable. The two composite generators, whose parameter set is fixed by the algorithm name so that null is the only spec they accept, refused every other one with IllegalArgumentException. RSA answered correctly for a spec of the wrong type but not for one of the right type carrying values its lightweight parameters will not take - an even public exponent, or a key size below the floor - which is now translated the same way the int overload's is. All 304 services now report the declared exception, with the composites still taking the null spec that is right for them; note that InvalidAlgorithmParameterException is a checked exception and not an IllegalArgumentException, so a caller that was catching what these threw before has to catch the declared type instead.\u003c/li\u003e\n\u003cli\u003eAn HSS private key claimed the two records of its position under two different monitors. The top-level index and the bottom component key's one-time index q are independent records of the same position - the decoder requires them to agree, see the entry below - but generateLMSContext incremented the index under the HSS key's own monitor, released it, and only then claimed q under the component key's. A getEncoded() issued in between saw the index advanced and q not, and produced an encoding this implementation's own decoder rejects; and two threads meeting at a bottom-tree boundary could both pass the exhaustion test, take consecutive top-level indices and claim the same q, after which one of them was refused with \u0026quot;ots private key exhausted\u0026quot; by a key still reporting usages remaining, a top-level index had been spent with no signature made, and the two records stayed one apart for the rest of the key's life in that process - so it could no longer be encoded, cloned or sharded, and getIndex() and getUsagesRemaining() misreported by one. No one-time key was reused: the component key's claim is itself atomic, and the divergence runs index ahead of leaves, so the effect was on the key's usability rather than on the signatures it had made. Both records are now claimed under the one monitor, and the component key is claimed before the index is incremented so that an exhausted one leaves both untouched. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the same correction.\u003c/li\u003e\n\u003cli\u003eTimeStampToken parsed the attacker-controlled TSTInfo content of a time-stamp token (org.bouncycastle.tsp.TimeStampToken, reached from TimeStampResponse(byte[]) and (InputStream)) inside a try that caught only CMSException, so a well-formed RFC 3161 TimeStampResp whose embedded token carried a malformed TSTInfo - a SEQUENCE with fewer elements than the five mandatory fields, a non-SEQUENCE, truncated DER, or an unknown context tag - let an IllegalArgumentException or a NoSuchElementException escape the constructor's declared throws TSPException, IOException contract. A token signed by no signers or by more than one raised a bare IllegalArgumentException from the same constructor, before that try, for the same reason. Both are now reported as TSPException, matching the package-private TimeStampResponse(DLSequence) constructor and the existing getSignedAttributes guard in the same method; the signer-count refusal is a TSPValidationException, as the neighbouring check on the content type already was. Related, and the cause of the NoSuchElementException: asn1.tsp.TSTInfo read its five mandatory fields off the sequence with no bound on how many elements were actually there, so a short SEQUENCE left the enumeration to run out rather than being refused, and an oversize one was accepted with its extra elements absorbed into the optional slots. Decode now requires the five to ten elements RFC 3161 sec. 2.4.2 gives the type, which is what the sibling Accuracy and ArchiveTimeStamp decoders already did, so the failure is the IllegalArgumentException that getInstance is expected to raise (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2415\"\u003e#2415\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eNeither the HSS nor the XMSS^MT private key decoder checked its declared index against the traversal state stored beside it, although the two are independent records of the same position in the key and so can be compared. For HSS the records are the top-level index and the component keys' one-time indices q; for XMSS^MT they are the global index and the per-layer BDS states. A stored key whose index had been rolled back while its state stayed advanced - a partial write, a restore from backup, a buggy storage layer - was therefore accepted, and it then signed a second message under a one-time key the key had already used, producing a signature that verified, so nothing anywhere surfaced the reuse. RFC 8554 sec. 1 and RFC 8391 sec. 1.1 both require each one-time key to be used exactly once, and this is the failure those requirements exist to prevent; the single-tree XMSS decoder has tied its BDS state to its index since that state was first validated, and this brings the two multi-tree schemes into line. HSS decode now requires the declared index to equal the position the component q values imply - a level above the last contributes (q - 1) leaves of the levels beneath it, since its q has already advanced past the subtree it signed - and XMSS^MT decode now requires each present layer's BDS index to equal the leaf index that layer derives from the global index, allowing the one position where a layer has moved into a new subtree and its state legitimately still carries the previous subtree's final index. A layer with no state yet is unaffected, since those are built lazily at signing time. Related, and the same shape of omission: an XMSS or XMSS^MT private key encoding carries the tree root twice - the key's own root field and the root node of the BDS state stored beside it, which for XMSS^MT is the top layer's - and the two were never compared either. A corrupted root was accepted and then poisoned every signature the key made, because the root is hashed into the message digest: the signature did not verify and nothing indicated why. Decode now requires the two copies to agree. The BDS node values themselves are not checkable the way the LMS tree cache above is - a BDS authentication path, stack, retain or keep node does not have its children stored alongside it, so recomputing one means building a subtree, which is the work the state exists to avoid. Both checks are integer comparisons over the levels of the key, too small to measure against the surrounding decode, and both were verified not to reject any legitimate key by walking every index a key can reach: the full key space of the two-level HSS and the h=4/d=2, h=6/d=2, h=6/d=3, h=9/d=3 and h=8/d=4 XMSS^MT parameter sets, plus a three-level HSS key across a subtree boundary and an HSS shard. Since those node values cannot be recomputed, the encoded state now carries a checksum over itself instead, with the owning key's public seed hashed in front of it. Any corruption of the stored state is refused at decode rather than being loaded and then producing signatures that silently do not verify, and because the public seed is bound in, a state transplanted between two keys of the same parameter set is refused too, even though it is internally consistent and arrives with its own matching root. The public seed is bound rather than the secret seed or the PRF key deliberately: the state's own root and index are inside the encoding and so are already covered, hashing secret material would make the stored checksum a commitment to it for no gain in detection, and the PRF key does not influence the state at all. \u003cstrong\u003eThis is an error-detecting code and not integrity protection\u003c/strong\u003e - anyone able to rewrite the stored key recomputes it, so it establishes that the state is unchanged since it was written, never that it was correct when written, and the allocation bounds on the encoding remain the guard against a crafted one. It costs one SHA-256 over the state, measured at 5 to 8 microseconds each way for the h=10 and h=16 parameter sets, and 32 bytes of encoding. The state encoding was added earlier in this same cycle and has not been released, so the checksum is simply part of it rather than a new version: a state written by a 1.86 beta is rejected, which is recovered from by re-exporting the key. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the HSS check as well (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2414\"\u003e#2414\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe S/MIME example smoke test in the misc module (org.bouncycastle.mail.smime.examples.test.AllTests) drove SendSignedAndEncryptedMail against smtp.gmail.com, and that example finishes with Transport.send() under JavaMail's default settings, which have no connect timeout. Where outbound port 25 is refused the failure was swallowed and the test passed; where it is silently dropped, as on many home networks, the connect blocked and ./gradlew build hung in :misc:test indefinitely with \u0026quot;0 tests completed\u0026quot;. The test now delivers to an SMTP stub on a loopback port, with connect / read / write timeouts as a backstop, and asserts the message arrived (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2407\"\u003e#2407\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation took the traditional component public key bytes it feeds the KEM combiner from the recipient key's own encoding, while decapsulation recomputes the point from the private key and so always produced an uncompressed one. Section 4 of draft-ietf-lamps-pq-composite-kem requires an EC component to be carried as an uncompressed point, but a component key that encodes itself compressed - a BC EC key whose point format has been set through org.bouncycastle.jce.interfaces.ECPointEncoder, or a key from a provider that preserves a compressed encoding - was passed through as it came. Both sides then combined a different tradPK and derived different shared secrets, with no error reported on either: encapsulation and decapsulation both succeeded and the recipient simply could not decrypt. The EC component is now normalised to an uncompressed point wherever the engine serialises one, which covers the ephemeral key that forms the ciphertext as well. X25519 and X448 components have a single encoding and were unaffected, as were EC keys left in their default (uncompressed) format, whose shared secrets are unchanged. CompositePublicKey.getEncoded() took its component bytes the same way, so such a key also encoded to a composite key other implementations reject and whose bytes changed across an encode / decode / encode round trip - 1238 bytes rather than 1270 for MLKEM768-ECDH-P256, and for the composite ML-DSA keys sharing that method, 2006 rather than 2038 for MLDSA65-ECDSA-P256. It now normalises the component the same way. This is a write-side change only: a composite key carrying a compressed EC component is still decoded, since the component key factories accept either form, and continues to verify signatures as before - it simply re-encodes in the normalised form. The shared normalisation is org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil.getUncompressedSubjectPublicKeyBytes.\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation threw a NullPointerException, wrapped in an IllegalStateException out of KeyGenerator.generateKey(), when the SecureRandom it was given was null - which javax.crypto.KEM.newEncapsulator() documents as a request for the provider's default, and which KeyGenerator.init(spec, null) passes straight through. The three RSA-OAEP composites draw the traditional shared secret from that random directly, so they were the ones affected; the ECDH and X25519 / X448 composites escaped only because their component KeyPairGenerators default a random of their own. CompositeMLKEMEngine now defaults one through CryptoServicesRegistrar.getSecureRandom() on first use, as the composite KEM Cipher's wrap path already did, and as the KEM generators corrected earlier in this cycle now do. Related, the engine now also clears the ML-KEM component's shared secret alongside the traditional one on both the encapsulate and decapsulate paths - the copy handed back by getEncoded() was left in the heap - as section 3.5 of draft-ietf-lamps-pq-composite-kem requires.\u003c/li\u003e\n\u003cli\u003eCompositePublicKey.getAlgorithm() and CompositePrivateKey.getAlgorithm() returned null for all twelve Composite ML-KEM (draft-ietf-lamps-pq-composite-kem) parameter sets. Both classes resolved the name through the composite signature index only, which holds the composite ML-DSA OIDs, so a composite KEM key pair - generated, parsed from a certificate, or read from PKCS#8 - reported no algorithm at all, and the standard JCA idiom of reconstructing a key with KeyFactory.getInstance(key.getAlgorithm()) raised a NullPointerException. The lookup now falls back to the composite KEM index, so the name returned is the one the provider registers the algorithm under (e.g. MLKEM768-X25519-SHA3-256), matching the composite ML-DSA behaviour. The same single-index assumption made the CompositePublicKey(SubjectPublicKeyInfo) and CompositePrivateKey(PrivateKeyInfo) constructors reject a composite KEM key with \u0026quot;unable to create CompositePublicKey from SubjectPublicKeyInfo\u0026quot;; they now dispatch to the composite KEM key factory for those OIDs. Keys obtained through KeyFactory or through BouncyCastleProvider.getPublicKey / getPrivateKey were unaffected and are unchanged (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2404\"\u003e#2404\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe org.bouncycastle.jcajce.spec.KEMKDFSpec constructor stored a null otherInfo as given, so getOtherInfo() returned null, and three of the KDF branches KdfUtil.makeKeyBytes dispatches to - KMAC-128, KMAC-256 and SHAKE-256 - read the otherInfo length without a guard and threw NullPointerException out of the KEM operation, where the KDF2, KDF3 and HKDF branches tolerate a null through KDFParameters / HKDFParameters. The Builder of every spec in the package already mapped null to empty, so no provider path reached it, but the constructor is protected on a public class and KdfUtil is documented for callers building their own KEM integration; the deprecated KEMParameterSpec passes a null itself and escaped only because it also pins the KDF to null. The constructor now stores empty for a null, so getOtherInfo() never returns null, and a null and an explicitly empty otherInfo derive the same key.\u003c/li\u003e\n\u003cli\u003eQR-UOV signature verification accepted a signature encoding that was not canonical, so the encoding of a signature was not unique even after the trailing-byte fix of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e. Each F_q element of the signature is stored in ceil(log2 q) bits, one more bit pattern than the field has elements: q itself is representable and is arithmetically congruent to zero, so an element written as q verified exactly as the same element written as zero would, and the bits padding the last element out to the byte boundary were never read at all. Every zero element of a signature therefore carried a second encoding, and for the q = 7 parameter sets roughly one element in seven is zero - a single qruov_5_q7_L10 signature measured 256 spare bits, so on the order of 2^256 distinct byte strings verified for the one message and key. Verification now rejects any element outside [0, q) and any set padding bit; a signature produced by this or by the reference implementation is unaffected, as the KAT vectors of every parameter set confirm. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSNOVA signature verification ignored four bits inside the signature for any parameter set whose solution is an odd number of GF(16) nibbles - the SNOVA_24_5_5, SNOVA_25_8_3, SNOVA_29_6_5 and SNOVA_66_15_3 families, sixteen of the forty-four parameter sets. The last byte of the encoded solution carries a single nibble and the signer leaves the top four bits zero, but the decoder did not read them, so sixteen distinct byte strings verified for one signature. This is the same non-unique encoding github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e closed for bytes following the signature, applied inside it; the verifier now requires those bits to be zero. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSnovaPrivateKeyParameters did not validate the length of the private key encoding handed to it - the only one of the five schemes of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e that did not - and SnovaParameters.getPrivateKeyLength() reported the expanded (\u0026quot;ESK\u0026quot;) length even for a parameter set whose private key is the seed pair. A private key encoding reaches this constructor straight from a PKCS#8 blob, so a wrong length went undetected: a seed-form key with extra bytes appended was accepted and signed under a different derived key, and a short expanded-form key sized the signer's decode buffer negatively, throwing NegativeArraySizeException out of generateSignature() rather than being reported at construction. Related, the signing retry loop could not terminate: the vinegar values are derived from a single-byte counter, so only 256 distinct linear systems can be tried, and an expanded-form private key that is not a real central map is singular for all of them - generateSignature() then span forever rather than failing. The length is now checked at construction, getPrivateKeyLength() reports the length that parameter set's private key actually has, and the retry loop gives up after its 256 attempts as MAYO's does.\u003c/li\u003e\n\u003cli\u003eMayoSigner and MayoKeyPairGenerator did not clear several buffers holding secret key material that the MAYO reference implementation explicitly clears. Signing left the secret oil space O, the expanded L = (P1 + P1^t) * O + P2, and the M / VPV / Ox intermediates of the central map in place, having gone to the trouble of clearing eleven other buffers; key generation left the expanded seed, whose tail is the encoded oil space, and the P1 * O + P2 half of P; and the row-echelon step left the packed echelon form of the secret linear system and its pivot rows. Separately, if all 256 attempts at solving for the signature had given a rank-deficient system, signing emitted a signature built from the failed attempt's state instead of reporting the failure the reference returns, and AIMerSigner.generateSignature returned an empty array on failure, which a caller would hand on as though it were a signature. Both now throw.\u003c/li\u003e\n\u003cli\u003eFive PQC signature schemes - MAYO, SNOVA, QR-UOV, SQIsign and AIMer - returned the NIST crypto_sign \u0026quot;sm\u0026quot; signed-message envelope from generateSignature() rather than the signature. That envelope is an artefact of the reference KAT harness, which records the message alongside the signature so a vector file can be self-contained; it is not part of any of the five specifications, and no other BC signer emits it (Falcon's KAT test rebuilds the equivalent envelope in the test, which is where it belongs). Two consequences followed, both reaching the JCA Signature services of every parameter set of the five schemes in BouncyCastlePQCProvider. First, since the message was appended to the signature, verification had to skip whatever followed the signature proper, and it did so by checking only that the buffer was long enough - so any number of trailing bytes could be added to a valid signature, or the appended message replaced with unrelated data, and it still verified. A signature encoding was therefore not unique: anyone holding one valid signature could produce unlimited distinct byte strings that all verified for the same message and key, which breaks any use that treats the signature bytes as an identifier, deduplicates on them, or records them as evidence. Second, the envelope propagated into everything built on the operator layer: because ContentSigner hands the signature straight into the structure being signed, every X.509 certificate, CRL, CMS SignedData and TLS CertificateVerify BC produced with one of these algorithms carried a verbatim copy of the signed data inside its own signature field - a self-signed MAYO-1 certificate came to 3567 bytes where the same certificate is now 2020 - which no other implementation can parse as a signature, and which in a detached CMS signature meant the \u0026quot;detached\u0026quot; signature carried the content. generateSignature() now returns the bare signature, and verifySignature() requires exactly the parameter set's signature length, so appended or truncated data is rejected rather than ignored. \u003cstrong\u003eThis is a behavioural change for signatures produced by an earlier release\u003c/strong\u003e - MAYO and SNOVA from 1.84, QR-UOV, SQIsign and AIMer from 1.85 - which are no longer accepted in the envelope form they were emitted in; the signature bytes themselves are unchanged, so a stored value can be recovered by taking the leading signature-length bytes, or for AIMer, whose envelope was message || signature rather than signature || message, the trailing ones. The KAT tests now rebuild the envelope before comparing against the vector files, which continue to record it. Note that AIMer's verification had already been made length-exact during this cycle (see the entry below relating to github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2401\"\u003e#2401\u003c/a\u003e), so of the five only its envelope remained (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe MLS implementation did not bind an X.509 credential to the LeafNode's signature_key. LeafNode.verify() checked a leaf's signature against the signature_key declared in the leaf itself, while the X.509 credential's certificate chain was stored but never parsed or checked, so the certificate's public key was never required to match signature_key (RFC 9420 sec. 5.3). A leaf could therefore carry one party's certificate while being signed by an unrelated key and still be accepted under that party's identity through KeyPackage.verify() and the Group leaf-validation path. LeafNode.verify() now requires the end-entity certificate's subject public key, in the cipher suite's signature encoding, to equal signature_key for an X.509 credential, and rejects the leaf otherwise - including an empty chain or a certificate whose key type does not match the cipher suite; certificate-chain and identity validation to a trust anchor remain the application's responsibility per RFC 9420 sec. 5.3.1. A public org.bouncycastle.mls.codec.Certificate(byte[]) constructor and a Credential.getCertificates() accessor are added so callers can build and inspect X.509 credentials. Basic credentials are unaffected.\u003c/li\u003e\n\u003cli\u003eThe SecureRandom supplied to org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder.setSecureRandom() did not drive the content IV / nonce for any algorithm other than RC2. EnvelopedDataHelper.generateParameters passed the caller's SecureRandom to the AlgorithmParameterGenerator only in the RC2_CBC branch; every other content-encryption algorithm - AES-CBC, AES-GCM, AES-CCM, Camellia, ARIA, SEED and the rest - reached pGen.generateParameters() on an uninitialised generator, so the IV / nonce was drawn from a default SecureRandom and setSecureRandom() was silently ignored (the builder's javadoc states that random is used for IV/nonce generation). The generator is now initialised with the supplied random on the general path as well, so a caller who provides a specific randomness source - for a controlled or FIPS-approved DRBG, say - has it honoured for the content IV / nonce. The session-key generation path was unaffected and already used the supplied random. Because the content IV / nonce now comes from the supplied SecureRandom, the org.bouncycastle.crypto.util JournalingSecureRandom / JournaledAlgorithm reproducible-encryption support records it in the transcript: a resumed session reproduces the IV / nonce by regenerating it from the replayed randomness - build the resuming encryptor from the content-algorithm OID - rather than by reusing the AlgorithmIdentifier captured from the first encryption, which no longer keeps the transcript aligned.\u003c/li\u003e\n\u003cli\u003eThe NTRU LPRime, NTRU+ and SMAUG-T KEM generators threw a NullPointerException when constructed with a null SecureRandom, where every other KEM generator - including NTRU LPRime's own SNTRU Prime counterpart in the same package - defaults one through CryptoServicesRegistrar.getSecureRandom(). This is reachable from the lightweight API directly, and from javax.crypto.KEM, whose newEncapsulator() documents a null random as a request for the provider's default.\u003c/li\u003e\n\u003cli\u003eFrodoKEMEngine kept a single SHAKE instance in a field, so an engine reached concurrently produced wrong results. It is reached that way through org.bouncycastle.crypto.kems.FrodoKEMExtractor, which holds one engine for its lifetime: two threads extracting through one extractor interleaved the digest's absorb and squeeze phases, yielding shared secrets that silently did not match the sender's, or an IllegalStateException of \u0026quot;attempt to absorb while squeezing\u0026quot; from inside extractSecret. The digest is now built per call, as CMCEEngine's already was, which makes an extractor safe to share. Encapsulation was unaffected, since FrodoKEMGenerator builds an engine per call. Results for any single-threaded use are unchanged - the reference KAT vectors are byte-identical.\u003c/li\u003e\n\u003cli\u003eThe BCJSSE provider carried the TLS 1.2 coupling between the supported_groups extension and ECDSA over into TLS 1.3: an ECDSA signature scheme was treated as usable - offered in the signature_algorithms and signature_algorithms_cert extensions, and eligible when selecting the local credentials - only while the corresponding curve was among the named groups enabled for key exchange, both per context (a group unavailable for key agreement disabled the scheme outright) and per connection (the curve had to be in the supported_groups list about to be sent). RFC 8446 sec. 4.2.7 scopes supported_groups to key exchange only, with signature algorithms negotiated independently (sec. 4.2.3), so this incorrect restriction in TLS 1.3 has been removed. Ed25519, Ed448 and the RSA schemes were unaffected (as well as typical deployments using a default configuration for named groups).\u003c/li\u003e\n\u003cli\u003eThe bcmail module descriptor did not declare its javax.mail/javax.activation dependences, so a modular (module-path) consumer of the jar hit IllegalAccessError/module-resolution failures when the S/MIME classes touched the mail API. The descriptor now requires them optionally (requires static) under all four module names those libraries are known by - the automatic names mail and activation carried by the javax.mail:mail / javax.activation:activation artifacts, and the explicit names java.mail and java.activation carried by the newer com.sun.mail / com.sun.activation ones - a hard requires on any one name would break users of the others (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2389\"\u003e#2389\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFour type-coercion helpers in the OER / IEEE 1609.2 (ITS) decoder tested the wrong type in the identity fast path that lets a getInstance() factory return an argument that is already of the target type. org.bouncycastle.oer.its.ieee1609dot2.basetypes.UINT32.getInstance and org.bouncycastle.oer.its.etsi102941.basetypes.Version.getInstance guarded on UINT8 - a sibling of UINT32 under UintBase, and unrelated to Version - so passing a UINT8 threw ClassCastException, while passing an actual UINT32 or Version missed the fast path and fell through to ASN1Integer.getInstance, which rejects them: neither factory accepted its own type. org.bouncycastle.oer.its.etsi103097.EtsiTs103097DataEncryptedUnicast.getInstance guarded on its sibling EtsiTs103097DataEncrypted and then cast to the unicast type, so an EtsiTs103097DataEncrypted threw ClassCastException. org.bouncycastle.oer.OEROptional.getObject(Class) called value.getClass().isInstance(type) with the arguments transposed, which is always false because the argument is a java.lang.Class, so the cast path was dead and every optional field was resolved reflectively, failing with IllegalStateException for a target type with no static getInstance. Each guard now names the type it returns, matching the sibling UINT8 / UINT16 / UINT64 and EtsiTs103097DataEncrypted factories (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2373\"\u003e#2373\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eDefaultAlgorithmNameFinder and DefaultSignatureNameFinder had no entries at all for the ShangMi algorithms, so an SM2 signature AlgorithmIdentifier that DefaultSignatureAlgorithmIdentifierFinder itself produces came back named only by its OID string - getAlgorithmName(GMObjectIdentifiers.sm2sign_with_sm3) returned \u0026quot;1.2.156.10197.1.501\u0026quot; and hasAlgorithmName returned false. Both finders now name sm2sign_with_sm3 as SM3WITHSM2 and sm2sign_with_sha256 as SHA256WITHSM2, and DefaultAlgorithmNameFinder additionally names the sm3 digest. All three resolve through the BC provider, as Signature and MessageDigest respectively. The remaining GM arc - the SM4 cipher modes, the sm2encrypt variants, and the SM1 / SM6 / SSF33 ciphers BC does not implement - is still unnamed (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2377\"\u003e#2377\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe RFC 4998 evidence-record classes compared the digest AlgorithmIdentifier named by a time-stamp authority with the one their own DigestCalculator uses, and did so with AlgorithmIdentifier.equals(), which compares the encodings. A TSA that names SHA-256 with an explicit NULL parameters field - DigiCert among them - therefore failed against BC's own calculator, which names it with the parameters absent, and ERSArchiveTimeStampGenerator.generateArchiveTimeStamp rejected the response with \u0026quot;time stamp imprint for wrong algorithm\u0026quot;. Both spellings name the same digest and RFC 5754 sec. 2 requires a receiver to accept either, while requiring that identifiers be generated with the parameters absent, which BC already does. The three affected comparisons - the two in ERSArchiveTimeStampGenerator and the digest check in ERSEvidenceRecord.renew - now use the new AlgorithmIdentifier.areEquivalent, which matches on the algorithm and treats an absent parameters field and NULL as the same, and the consistency check across an evidence record's archive time stamp chain uses it too. An identifier carrying an actual parameter structure is never equivalent to one carrying none (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2379\"\u003e#2379\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eEDIPartyName.toASN1Primitive emitted the nameAssigner and partyName DirectoryStrings without their context tags, so an EDIPartyName built through its public constructor could not be parsed back by EDIPartyName.getInstance, which correctly requires them. RFC 5280 sec. 4.2.1.6 tags both members [0] and [1], and those tags are explicit despite the module's IMPLICIT TAGS because DirectoryString is a CHOICE, which X.680 does not allow to be tagged implicitly - the decoder already had this right. The encoder now matches it. Note the type was added during the 1.85 cycle and GeneralName validates its ediPartyName alternative through it, so a GeneralName carrying an untagged ediPartyName - including one BC itself produced - is rejected where 1.84 passed it through unexamined; the untagged form is not read leniently (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2380\"\u003e#2380\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eRSASSA-PSS could not be used with a RIPEMD digest through the JCA API. Nothing registered the RIPEMD PSS signatures, so Signature.getInstance(\u0026quot;RIPEMD160WITHRSAANDMGF1\u0026quot;) raised NoSuchAlgorithmException, and the generic RSASSA-PSS route with an explicit PSSParameterSpec failed too: org.bouncycastle.jcajce.provider.util.DigestFactory.getDigest returned null for a RIPEMD name, and isSameDigest - an allow-list of the SHA families and MD5 - reported two identical RIPEMD names as different digests, so the spec was rejected with \u0026quot;digest algorithm for MGF should be the same as for PSS parameters\u0026quot;. isSameDigest now answers true for equal names whatever the digest, which also covers Whirlpool, SM3, GOST3411 and anything else outside that allow-list; DigestFactory recognises RIPEMD128, RIPEMD160 and RIPEMD256 by name and OID; the three PSS signatures are registered with MGF1 over the same digest and a salt of the digest length; and DefaultSignatureAlgorithmIdentifierFinder gains the matching RIPEMD*WITHRSAANDMGF1 entries with their RSASSA-PSS-params, so the operator/JcaContentSignerBuilder path works as well. Note BC continues to require the PSS hash and the MGF1 hash to be the same, which RFC 8017 does not itself demand (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2381\"\u003e#2381\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe opt-in key-size validation on CMS key-transport recipients (org.bouncycastle.cms.jcajce.JceKeyTransRecipient.setKeySizeValidation(true)) never ran for a message using RFC 9709 CEK derivation (id-alg-cek-hkdf-sha256): the branch that should have selected the actual content-encryption algorithm carried in the KDF AlgorithmIdentifier's parameters compared the encrypted-key byte array against the id-alg-cek-hkdf-sha256 object identifier - a comparison that is always false - so the check fell through to a key-size lookup on the outer KDF OID, which has no registered key size, and silently checked nothing. A key-transport EnvelopedData/AuthEnvelopedData whose transported (and HKDF-derived) content-encryption key did not match the key size of the advertised content-encryption algorithm was therefore accepted even with validation enabled. The recipient now dispatches on the content-encryption AlgorithmIdentifier's algorithm OID, so key-size validation of RFC 9709 messages checks the recovered key against the inner content-encryption algorithm. Messages with a matching key size, non-HKDF messages, and recipients that do not enable validation are unaffected.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003eSee full diff in \u003ca href=\"https://github.com/bcgit/bc-java/commits\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark` from 0.29.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/blockquote\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/blockquote\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/42b4fb7adfe288ef13e9e27ab20aff7e91b0ab9d\"\u003e\u003ccode\u003e42b4fb7\u003c/code\u003e\u003c/a\u003e Prepare CHANGELOG for version 0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/b76e09d7a8362abb5f04e1d6b91dbd6da279a6fc\"\u003e\u003ccode\u003eb76e09d\u003c/code\u003e\u003c/a\u003e Limit how deep inline nodes may nest by default (100)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/49f65cb5cbec93cff713179990307145198e7061\"\u003e\u003ccode\u003e49f65cb\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing deeply nested emphasis\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/610f84b83e68c381e8f784ae4d044c80e1948b67\"\u003e\u003ccode\u003e610f84b\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological autolink email addresses\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/9f1d73897a56cbd74c39347af351a473e70297e1\"\u003e\u003ccode\u003e9f1d738\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological HTML block attributes\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/e13297e849995fdd582a85841067bff1d9c35ee5\"\u003e\u003ccode\u003ee13297e\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing pathological backticks\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/89d1bd3fa1524e8217ed61db5e8116c82434470f\"\u003e\u003ccode\u003e89d1bd3\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing with lots of \u003ccode\u003e\u0026lt;\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/commonmark/commonmark-java/compare/commonmark-parent-0.29.0...commonmark-parent-0.30.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark-ext-autolink` from 0.29.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark-ext-autolink's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing patho...\n\n_Description has been truncated_","html_url":"https://github.com/GabOnezio/Sophia/pull/13","url":"https://dependabot.ecosyste.ms/api/v1/hosts/GitHub/repositories/GabOnezio%2FSophia/issues/13","packages_url":"https://dependabot.ecosyste.ms/api/v1/issues/13/packages"}},{"old_version":"5.4.0","new_version":"5.5.0","update_type":"minor","path":null,"pr_created_at":"2026-09-09T20:37:26.000Z","version_change":"5.4.0 → 5.5.0","issue":{"uuid":"5404482044","node_id":"PR_kwDOTknthM8AAAABC5NZ1A","number":38,"state":"closed","title":"build(deps): bump the android-deps group across 1 directory with 24 updates","user":"dependabot[bot]","labels":["dependencies","java"],"assignees":[],"locked":false,"comments_count":1,"pull_request":true,"closed_at":"2026-09-11T20:36:33.000Z","author_association":null,"state_reason":null,"created_at":"2026-09-09T20:37:26.000Z","updated_at":"2026-09-11T20:36:35.000Z","time_to_close":172747,"merged_at":null,"merged_by":null,"closed_by":null,"dependency_metadata":{"prefix":"build(deps): bump","group_name":"android-deps","update_count":24,"packages":[{"name":"gradle-wrapper","old_version":"9.6.1","new_version":"9.7.1","repository_url":"https://github.com/gradle/gradle"},{"name":"androidx.appcompat:appcompat","old_version":"1.7.1","new_version":"1.8.0"},{"name":"androidx.wear.protolayout:protolayout","old_version":"1.4.1","new_version":"1.4.2"},{"name":"androidx.wear.protolayout:protolayout-material3","old_version":"1.4.1","new_version":"1.4.2"},{"name":"androidx.wear.tiles:tiles","old_version":"1.6.1","new_version":"1.6.2"},{"name":"org.bouncycastle:bcprov-jdk18on","old_version":"1.85","new_version":"1.85.2","repository_url":"https://github.com/bcgit/bc-java"},{"name":"org.commonmark:commonmark","old_version":"0.29.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-autolink","old_version":"0.29.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-strikethrough","old_version":"0.29.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-tables","old_version":"0.29.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-task-list-items","old_version":"0.29.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"io.coil-kt.coil3:coil-compose","old_version":"3.5.0","new_version":"3.6.2","repository_url":"https://github.com/coil-kt/coil"},{"name":"io.coil-kt.coil3:coil-svg","old_version":"3.5.0","new_version":"3.6.2","repository_url":"https://github.com/coil-kt/coil"},{"name":"org.junit.vintage:junit-vintage-engine","old_version":"6.1.2","new_version":"6.1.3","repository_url":"https://github.com/junit-team/junit-framework"},{"name":"io.kotest:kotest-assertions-core-jvm","old_version":"6.2.3","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"io.kotest:kotest-runner-junit5-jvm","old_version":"6.2.3","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"com.squareup.okhttp3:mockwebserver","old_version":"5.4.0","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.squareup.okhttp3:okhttp","old_version":"5.4.0","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.android.application","old_version":"9.3.1","new_version":"9.4.0"},{"name":"com.android.library","old_version":"9.3.1","new_version":"9.4.0"},{"name":"com.android.test","old_version":"9.3.1","new_version":"9.4.0"},{"name":"org.jetbrains.kotlin.plugin.compose","old_version":"2.4.10","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"},{"name":"org.jetbrains.kotlin.plugin.serialization","old_version":"2.4.10","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"},{"name":"com.google.devtools.ksp","old_version":"2.3.10","new_version":"2.3.11","repository_url":"https://github.com/google/ksp"}],"path":null,"ecosystem":"maven"},"body":"Bumps the android-deps group with 24 updates in the /apps/android directory:\n\n| Package | From | To |\n| --- | --- | --- |\n| [gradle-wrapper](https://github.com/gradle/gradle) | `9.6.1` | `9.7.1` |\n| androidx.appcompat:appcompat | `1.7.1` | `1.8.0` |\n| androidx.wear.protolayout:protolayout | `1.4.1` | `1.4.2` |\n| androidx.wear.protolayout:protolayout-material3 | `1.4.1` | `1.4.2` |\n| androidx.wear.tiles:tiles | `1.6.1` | `1.6.2` |\n| [org.bouncycastle:bcprov-jdk18on](https://github.com/bcgit/bc-java) | `1.85` | `1.85.2` |\n| [org.commonmark:commonmark](https://github.com/commonmark/commonmark-java) | `0.29.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-autolink](https://github.com/commonmark/commonmark-java) | `0.29.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-strikethrough](https://github.com/commonmark/commonmark-java) | `0.29.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-tables](https://github.com/commonmark/commonmark-java) | `0.29.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-task-list-items](https://github.com/commonmark/commonmark-java) | `0.29.0` | `0.30.0` |\n| [io.coil-kt.coil3:coil-compose](https://github.com/coil-kt/coil) | `3.5.0` | `3.6.2` |\n| [io.coil-kt.coil3:coil-svg](https://github.com/coil-kt/coil) | `3.5.0` | `3.6.2` |\n| [org.junit.vintage:junit-vintage-engine](https://github.com/junit-team/junit-framework) | `6.1.2` | `6.1.3` |\n| [io.kotest:kotest-assertions-core-jvm](https://github.com/kotest/kotest) | `6.2.3` | `6.2.4` |\n| [io.kotest:kotest-runner-junit5-jvm](https://github.com/kotest/kotest) | `6.2.3` | `6.2.4` |\n| [com.squareup.okhttp3:mockwebserver](https://github.com/lysine-dev/okhttp) | `5.4.0` | `5.5.0` |\n| [com.squareup.okhttp3:okhttp](https://github.com/lysine-dev/okhttp) | `5.4.0` | `5.5.0` |\n| com.android.application | `9.3.1` | `9.4.0` |\n| com.android.library | `9.3.1` | `9.4.0` |\n| com.android.test | `9.3.1` | `9.4.0` |\n| [org.jetbrains.kotlin.plugin.compose](https://github.com/JetBrains/kotlin) | `2.4.10` | `2.4.20` |\n| [org.jetbrains.kotlin.plugin.serialization](https://github.com/JetBrains/kotlin) | `2.4.10` | `2.4.20` |\n| [com.google.devtools.ksp](https://github.com/google/ksp) | `2.3.10` | `2.3.11` |\n\n\nUpdates `gradle-wrapper` from 9.6.1 to 9.7.1\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/gradle/gradle/releases\"\u003egradle-wrapper's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e9.7.1\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.1.\u003c/p\u003e\n\u003cp\u003eThis is a patch release for 9.7.0. We recommend using 9.7.1 instead of 9.7.0.\u003c/p\u003e\n\u003cp\u003eHere are the highlights of 9.7.0 release:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIsolated Projects graduates to incubating\u003c/li\u003e\n\u003cli\u003eBroader Configuration Cache compatibility\u003c/li\u003e\n\u003cli\u003eResilient Sync helps you fix broken builds\u003c/li\u003e\n\u003cli\u003eMore source locations in problem reports\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003ca href=\"https://docs.gradle.org/9.7.1/release-notes.html\"\u003eRead the Release Notes\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eWe would like to thank the following community members for their contributions to this release of Gradle:\n\u003ca href=\"https://github.com/aSemy\"\u003eAdam\u003c/a\u003e,\n\u003ca href=\"https://github.com/Gautam-aman\"\u003eAman Gautam\u003c/a\u003e,\n\u003ca href=\"https://github.com/YukiCodepth\"\u003eAman Kumar\u003c/a\u003e,\n\u003ca href=\"https://github.com/adubrouski\"\u003eAnton Dubrouski\u003c/a\u003e,\n\u003ca href=\"https://github.com/liutikas\"\u003eAurimas\u003c/a\u003e,\n\u003ca href=\"https://github.com/gbhavya07\"\u003egbhavya07\u003c/a\u003e,\n\u003ca href=\"https://github.com/joshfriend\"\u003eJosh Friend\u003c/a\u003e,\n\u003ca href=\"https://github.com/nicklauslittle-gov\"\u003enicklauslittle-gov\u003c/a\u003e,\n\u003ca href=\"https://github.com/psoni674\"\u003ePragati\u003c/a\u003e,\n\u003ca href=\"https://github.com/Project516\"\u003eproject516\u003c/a\u003e,\n\u003ca href=\"https://github.com/Uomocapra\"\u003eQin Mi\u003c/a\u003e,\n\u003ca href=\"https://github.com/rkdfx\"\u003eRavi\u003c/a\u003e,\n\u003ca href=\"https://github.com/sk-reddy17\"\u003esk-reddy17\u003c/a\u003e,\n\u003ca href=\"https://github.com/Suvrat1629\"\u003eSuvrat Acharya\u003c/a\u003e,\n\u003ca href=\"https://github.com/ShreckYe\"\u003eYongshun Ye\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eUpgrade instructions\u003c/h2\u003e\n\u003cp\u003eSwitch your build to use Gradle 9.7.1 by updating your wrapper:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e./gradlew :wrapper --gradle-version=9.7.1 \u0026amp;\u0026amp; ./gradlew :wrapper\r\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eSee the Gradle \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/upgrading_version_9.html\"\u003e9.x upgrade guide\u003c/a\u003e to learn about deprecations, breaking changes and other considerations when upgrading.\u003c/p\u003e\n\u003cp\u003eFor Java, Groovy, Kotlin and Android compatibility, see the \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/compatibility.html\"\u003efull compatibility notes\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eReporting problems\u003c/h2\u003e\n\u003cp\u003eIf you find a problem with this release, please file a bug on \u003ca href=\"https://github.com/gradle/gradle/issues\"\u003eGitHub Issues\u003c/a\u003e adhering to our issue guidelines.\nIf you're not sure you're encountering a bug, please use the \u003ca href=\"https://discuss.gradle.org/c/help-discuss\"\u003eforum\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eWe hope you will build happiness with Gradle, and we look forward to your feedback via \u003ca href=\"https://twitter.com/gradle\"\u003eTwitter\u003c/a\u003e or on \u003ca href=\"https://github.com/gradle\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003e9.7.0\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.0.\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/92f0512e7f06d84621afba191f75e265363890cf\"\u003e\u003ccode\u003e92f0512\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38892\"\u003e#38892\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/820ee75a99a179bbffa41bcedc6477b685fabb9f\"\u003e\u003ccode\u003e820ee75\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/82c23f9bd2a89b4cc644e1f90a28a8668feb3dee\"\u003e\u003ccode\u003e82c23f9\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering problem in KTS (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38878\"\u003e#38878\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/ef11a7268fe8cc8d6ab849ec911aa11220180553\"\u003e\u003ccode\u003eef11a72\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering issue\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/bb0d8a974a71b1003efea41e4046e98855cd5ff8\"\u003e\u003ccode\u003ebb0d8a9\u003c/code\u003e\u003c/a\u003e Make relevant tests polyglot (run for multiple DSLs)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/336e129d7f95c03486acafc97abf59734acfed48\"\u003e\u003ccode\u003e336e129\u003c/code\u003e\u003c/a\u003e Update signing configuration (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38874\"\u003e#38874\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/4bdf0da2dad9884d089a6062a45ea7183e7d735d\"\u003e\u003ccode\u003e4bdf0da\u003c/code\u003e\u003c/a\u003e Update signing configuration\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/cd9b92c1b82856248cf1dc58b50378238bec7b52\"\u003e\u003ccode\u003ecd9b92c\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38839\"\u003e#38839\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/5f4e381964897ad8d6b99e5a7c77f26dba3259fb\"\u003e\u003ccode\u003e5f4e381\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/1e08ab551367aeb5fb48b26e72807e1d2b27c939\"\u003e\u003ccode\u003e1e08ab5\u003c/code\u003e\u003c/a\u003e Keep type-use annotations in extracted ABI classes (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38810\"\u003e#38810\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/gradle/gradle/compare/v9.6.1...v9.7.1\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `androidx.appcompat:appcompat` from 1.7.1 to 1.8.0\n\nUpdates `androidx.wear.protolayout:protolayout` from 1.4.1 to 1.4.2\n\nUpdates `androidx.wear.protolayout:protolayout-material3` from 1.4.1 to 1.4.2\n\nUpdates `androidx.wear.protolayout:protolayout-material3` from 1.4.1 to 1.4.2\n\nUpdates `androidx.wear.tiles:tiles` from 1.6.1 to 1.6.2\n\nUpdates `org.bouncycastle:bcprov-jdk18on` from 1.85 to 1.85.2\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.md\"\u003eorg.bouncycastle:bcprov-jdk18on's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch1\u003eBouncy Castle Crypto Package - Release Notes\u003c/h1\u003e\n\u003ch2\u003e1.0 Introduction\u003c/h2\u003e\n\u003cp\u003eThe Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. The package is organised so that it contains a light-weight API suitable for use in any environment (including the J2ME) with the additional infrastructure to conform the algorithms to the JCE framework.\u003c/p\u003e\n\u003ch2\u003e2.0 Release History\u003c/h2\u003e\n\u003cp\u003e\u003c!-- raw HTML omitted --\u003e\u003c!-- raw HTML omitted --\u003e\u003c/p\u003e\n\u003ch3\u003e2.1.1 Version\u003c/h3\u003e\n\u003cp\u003eRelease: 1.86\u003cbr /\u003e\nDate: 2026, TBD\u003c/p\u003e\n\u003ch3\u003e2.1.2 Defects Fixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) let a subkey inherit the primary key's Key Flags when its own Subkey Binding signature carried no Key Flags subpacket, which made the two capability decisions taken for one subkey disagree. OpenPGPCertificate.OpenPGPComponentKey.isSigningKey() reads the effective flags, which fell back to the primary key's direct-key or primary user ID self-signature, so a subkey bound with no flags of its own counted as signing-capable; verifyEmbeddedPrimaryKeyBinding reads the binding signature's own flags, found no signing capability there, and so skipped the embedded Primary Key Binding (cross-certification) signature that RFC 9580 sec. 5.2.1.8 and sec. 10.1.3 require of a subkey that can issue signatures. A data signature made by such a subkey was therefore attributed to the certificate and reported valid by OpenPGPSignature.OpenPGPDocumentSignature.isValid() with the cross-certification requirement never applied, where GnuPG refuses the same certificate and message as not cross-certified. An attacker holding a third party's public signing subkey - which is public material - could bind it to their own primary key with a Subkey Binding signature they are able to make, carrying no Key Flags and no embedded Primary Key Binding signature, which they cannot make without the subkey's private key, and have that party's genuine signatures verify as valid under the attacker's own identity: misattribution of a real signature rather than a forgery of a new one, since the signature still has to be one the subkey actually made. Key Flags are a statement about the key the carrying signature refers to (RFC 9580 sec. 5.2.3.29), so a subkey no longer inherits them from the certificate-wide signatures of the primary key: a Subkey Binding signature that omits the subpacket now leaves the subkey with no capabilities rather than the primary's, which makes the flags the cross-certification check consults the same flags every other decision consults. Preferences and the other subpackets a direct-key signature carries are inherited as before, and the primary key itself - whose flags legitimately come from its direct-key or user ID self-signature - is unaffected. The low-level PGPSignature / PGPPublicKeyRing API performs no binding checks by design and is unchanged.\u003c/li\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) used a version 6 key that carried no valid Direct Key signature, falling back to the primary user ID binding as it correctly does for a version 4 key. RFC 9580 sec. 5.2.3.10 requires the opposite: \u0026quot;An implementation MUST ensure that a valid Direct Key signature is present before using a version 6 key. This prevents certain attacks where an adversary strips a self-signature specifying a Key Expiration Time or certain preferences.\u0026quot; The certificate grammar says the same structurally, the Direct Key signature being mandatory in the version 6 structure of sec. 10.1.1 and optional in the version 4 one of sec. 10.1.3. Because a version 6 certificate carries its key expiration, features and algorithm preferences on the Direct Key signature - the convention the RFC recommends and the one OpenPGPKeyGenerator follows, its user ID certification carrying no expiration at all - removing that single signature packet from a published certificate silently dropped the expiration along with the preferences and features: OpenPGPCertificate.getSignatureChainFor fell back to the user ID binding, the primary key was still reported bound, and getEncryptionKeys() and getSigningKeys() went on returning the subkeys of a key whose owner had set it to expire. The primary key fingerprint is unchanged by the removal, so a relying party pinning the key by fingerprint still treats it as the same key, and no private key or hash collision is involved; the natural moment for the strip is the key refresh that RFC 9580 names as the reason to refetch a key at all - to learn about changes in expiration, features, preferences and revocation - which is exactly the update it defeats. This is a downgrade rather than a forgery, nothing being attributed to a key that did not authorise it, and the concerning direction is encryption, to a key meant to have been retired. OpenPGPCertificate.isBoundBy now requires a valid Direct Key self-signature on a version 6 primary key before any component of the certificate - the primary key, its subkeys or its identities - is treated as bound, so a version 6 certificate stripped of it offers no keys at all rather than an unexpiring set. Version 4 certificates are unaffected: there the key expiration legitimately lives on the user ID self-signature and the fallback is correct, so it stays. The revocation-only version 6 certificate of sec. 10.1.2, which legitimately carries no Direct Key signature, is unaffected as well - its key was already refused as revoked, and reading the revocation does not go through the binding check.\u003c/li\u003e\n\u003cli\u003eThe lightweight LMSSigner and HSSSigner refused a key wrapped in ParametersWithRandom, which is how BcContentSignerBuilder passes a key whenever setSecureRandom() has been called - so BcHssLmsContentSignerBuilder built a working signer until a random was set and then failed with \u0026quot;Incorrect Key Parameters\u0026quot;, and the two signers themselves raised ClassCastException on the same input. All three now unwrap it, as the promoted ML-DSA and SLH-DSA signers already did. The random is accepted and not used: LMS derives its message randomiser C from the key's seed and the one-time index, so it is deterministic and cannot repeat while q does not. Note SP 800-208 sec. 6.1 asks for C to come from an approved random bit generator, which this implementation does not do; that is unchanged here, and a supplied random is now ignored rather than refused.\u003c/li\u003e\n\u003cli\u003eLMS signature verification did not apply two of the checks RFC 8554 sec. 5.4.2 requires before a signature is processed. Step 2g refuses a signature whose LMS typecode is not the one from the public key, and without it the path computation took its height and tree digest from the parameter set the signature named rather than the key's, so a signature claiming a height-25 parameter set drove a 25-level computation against a height-5 key. Step 2i refuses a leaf number q outside the tree, and without it an out-of-range q flowed into the node arithmetic and was left for the candidate-root comparison to catch. Neither was a forgery - the domain separation between D_LEAF and D_INTR and the final comparison saw to that - but both are attacker-chosen work the specification says to refuse up front. Both are now checked, and a signature failing either is still reported as not verifying rather than thrown out of Signature.verify(). The catch around the signature decode in LMSSigner and HSSSigner has also been narrowed to the decode itself, as the corresponding SPI was corrected to do for github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2408\"\u003e#2408\u003c/a\u003e: past the parse the engine reports an inconsistent signature by returning false rather than by throwing, so the wider catch caught nothing while standing ready to turn a future internal error into a quiet false.\u003c/li\u003e\n\u003cli\u003eThe LMS and HSS key parameter classes now apply at construction the checks their decoders apply, so a key built directly cannot be one the decoder would refuse. LMSPrivateKeyParameters accepted an identifier of any length although the decoder reads exactly 16 bytes - such a key encoded but could not be read back - and left q, maxQ and the seed length unchecked; the seed is now required to be at least m bytes at decode as well, where a one-byte seed had been decoding silently and then deriving every one-time key from it. HSSPrivateKeyParameters checked neither its level count nor that it had been given a component key per level and a chaining signature per level below the root, and then indexed both lists, so a mismatch surfaced as IndexOutOfBoundsException - or, where a level happened to match, as a null chaining signature that only failed at signing time; the level is now checked after the reset that fills it in, since a null is legitimate on the way in. LMSPrivateKeyParameters.getInstance(byte[], byte[]) adopted the public key supplied beside the private one without comparing them, so a mismatched public key was simply reported by getPublicKey(); it now cross-checks the identifier, both parameter sets and, where the tree cache already holds it, the root, as the HSS entry point does. The decoders also now report a bad version or seed length as IOException rather than IllegalStateException, so a caller can catch one type for a malformed key, and the package-private LM-OTS public key decoder no longer declares throws Exception or dereferences an unrecognised typecode. The deprecated org.bouncycastle.pqc.crypto.lms copies carry the decoder corrections.\u003c/li\u003e\n\u003cli\u003eIn the LMS JCE layer, LMSKeyGenParameterSpec.fromNames knew all twenty LMS parameter-set names but only four of the sixteen LM-OTS ones, so none of the SP 800-208 n24 or SHAKE sets could be named; all sixteen are now present. KeyPairGenerator.initialize(int, SecureRandom) reports InvalidParameterException, which is what the JCA specifies and which extends the IllegalArgumentException it raised before, so existing catches still match. BCLMSPrivateKey.getIndex now takes the exhaustion check and the index read under the key's own monitor rather than as two separate calls, and two unused fields have gone from LMSSignatureSpi. Note that the LMS Signature claims its one-time key at the first update() rather than at sign(), so a Signature that is initialised and updated and then abandoned spends an index without producing a signature - the safe direction for a one-time scheme, and now documented on the SPI.\u003c/li\u003e\n\u003cli\u003eEvery other key pair generator that refuses a key size did the same thing the LMS one did above. KeyPairGenerator.initialize(int, SecureRandom) is documented to raise InvalidParameterException when the key size is not one the generator supports, and thirty of them raised a bare IllegalArgumentException instead, so a caller following the JCA and catching the documented type saw an exception escaping rather than a refusal. The ML-DSA, ML-KEM, SLH-DSA, Classic McEliece, FrodoKEM, NTRU and composite signature and KEM generators in the BC provider, and every generator in BCPQC, now raise InvalidParameterException - NewHope included, where the value is a key size it will not take rather than a mode of initialisation it does not offer. InvalidParameterException extends IllegalArgumentException, so callers written against the old behaviour go on catching it unchanged. The two RSA generators are corrected as well, and differently: theirs is a key size below a floor rather than a mode of initialisation they do not offer, and the refusal is raised by the lightweight RSAKeyGenerationParameters, which cannot name a java.security exception at all, so the RSA KeyPairGeneratorSpi now translates it - keeping the message verbatim and the original exception as the cause, through a new SecurityExceptions.invalidParameterException factory, since InvalidParameterException has no constructor that takes one. Of the 304 KeyPairGenerator services the two providers register, 299 now refuse a nonsense key size the way the JCA defines it and five accept it as a strength they can work with, with none left raising a bare IllegalArgumentException; that is asserted as a sweep over both providers rather than per algorithm, so a generator added later is covered without the test being touched. The jdk1.3 provider overlays of the four generators that have one carry the same change, and the jdk1.3 SecurityExceptions overlay gains the new factory along with the invalidAlgorithmParameterException one it had been missing.\u003c/li\u003e\n\u003cli\u003eKeyPairGenerator.initialize(AlgorithmParameterSpec, SecureRandom) had the same shape of problem as the int overload above, and only 44 of the 304 services the two providers register reported an unusable spec as the InvalidAlgorithmParameterException that method declares. The twenty-three PQC generators that resolve a parameter set by name - cmce, frodokem, mldsa, mlkem, slhdsa, aimer, bike, faest, falcon, haetae, hqc, mayo, mqom, ntru, ntruplus, both ntruprime variants, qruov, saber, sdith, smaugt, snova and sqisign, 230 services between them - case-folded the name they got back from the spec without checking it, so a spec with no getName() method, and a null spec, produced a NullPointerException from inside the fold; their own \u0026quot;is this name one I know\u0026quot; branch, which does report the declared exception, was unreachable. The two composite generators, whose parameter set is fixed by the algorithm name so that null is the only spec they accept, refused every other one with IllegalArgumentException. RSA answered correctly for a spec of the wrong type but not for one of the right type carrying values its lightweight parameters will not take - an even public exponent, or a key size below the floor - which is now translated the same way the int overload's is. All 304 services now report the declared exception, with the composites still taking the null spec that is right for them; note that InvalidAlgorithmParameterException is a checked exception and not an IllegalArgumentException, so a caller that was catching what these threw before has to catch the declared type instead.\u003c/li\u003e\n\u003cli\u003eAn HSS private key claimed the two records of its position under two different monitors. The top-level index and the bottom component key's one-time index q are independent records of the same position - the decoder requires them to agree, see the entry below - but generateLMSContext incremented the index under the HSS key's own monitor, released it, and only then claimed q under the component key's. A getEncoded() issued in between saw the index advanced and q not, and produced an encoding this implementation's own decoder rejects; and two threads meeting at a bottom-tree boundary could both pass the exhaustion test, take consecutive top-level indices and claim the same q, after which one of them was refused with \u0026quot;ots private key exhausted\u0026quot; by a key still reporting usages remaining, a top-level index had been spent with no signature made, and the two records stayed one apart for the rest of the key's life in that process - so it could no longer be encoded, cloned or sharded, and getIndex() and getUsagesRemaining() misreported by one. No one-time key was reused: the component key's claim is itself atomic, and the divergence runs index ahead of leaves, so the effect was on the key's usability rather than on the signatures it had made. Both records are now claimed under the one monitor, and the component key is claimed before the index is incremented so that an exhausted one leaves both untouched. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the same correction.\u003c/li\u003e\n\u003cli\u003eTimeStampToken parsed the attacker-controlled TSTInfo content of a time-stamp token (org.bouncycastle.tsp.TimeStampToken, reached from TimeStampResponse(byte[]) and (InputStream)) inside a try that caught only CMSException, so a well-formed RFC 3161 TimeStampResp whose embedded token carried a malformed TSTInfo - a SEQUENCE with fewer elements than the five mandatory fields, a non-SEQUENCE, truncated DER, or an unknown context tag - let an IllegalArgumentException or a NoSuchElementException escape the constructor's declared throws TSPException, IOException contract. A token signed by no signers or by more than one raised a bare IllegalArgumentException from the same constructor, before that try, for the same reason. Both are now reported as TSPException, matching the package-private TimeStampResponse(DLSequence) constructor and the existing getSignedAttributes guard in the same method; the signer-count refusal is a TSPValidationException, as the neighbouring check on the content type already was. Related, and the cause of the NoSuchElementException: asn1.tsp.TSTInfo read its five mandatory fields off the sequence with no bound on how many elements were actually there, so a short SEQUENCE left the enumeration to run out rather than being refused, and an oversize one was accepted with its extra elements absorbed into the optional slots. Decode now requires the five to ten elements RFC 3161 sec. 2.4.2 gives the type, which is what the sibling Accuracy and ArchiveTimeStamp decoders already did, so the failure is the IllegalArgumentException that getInstance is expected to raise (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2415\"\u003e#2415\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eNeither the HSS nor the XMSS^MT private key decoder checked its declared index against the traversal state stored beside it, although the two are independent records of the same position in the key and so can be compared. For HSS the records are the top-level index and the component keys' one-time indices q; for XMSS^MT they are the global index and the per-layer BDS states. A stored key whose index had been rolled back while its state stayed advanced - a partial write, a restore from backup, a buggy storage layer - was therefore accepted, and it then signed a second message under a one-time key the key had already used, producing a signature that verified, so nothing anywhere surfaced the reuse. RFC 8554 sec. 1 and RFC 8391 sec. 1.1 both require each one-time key to be used exactly once, and this is the failure those requirements exist to prevent; the single-tree XMSS decoder has tied its BDS state to its index since that state was first validated, and this brings the two multi-tree schemes into line. HSS decode now requires the declared index to equal the position the component q values imply - a level above the last contributes (q - 1) leaves of the levels beneath it, since its q has already advanced past the subtree it signed - and XMSS^MT decode now requires each present layer's BDS index to equal the leaf index that layer derives from the global index, allowing the one position where a layer has moved into a new subtree and its state legitimately still carries the previous subtree's final index. A layer with no state yet is unaffected, since those are built lazily at signing time. Related, and the same shape of omission: an XMSS or XMSS^MT private key encoding carries the tree root twice - the key's own root field and the root node of the BDS state stored beside it, which for XMSS^MT is the top layer's - and the two were never compared either. A corrupted root was accepted and then poisoned every signature the key made, because the root is hashed into the message digest: the signature did not verify and nothing indicated why. Decode now requires the two copies to agree. The BDS node values themselves are not checkable the way the LMS tree cache above is - a BDS authentication path, stack, retain or keep node does not have its children stored alongside it, so recomputing one means building a subtree, which is the work the state exists to avoid. Both checks are integer comparisons over the levels of the key, too small to measure against the surrounding decode, and both were verified not to reject any legitimate key by walking every index a key can reach: the full key space of the two-level HSS and the h=4/d=2, h=6/d=2, h=6/d=3, h=9/d=3 and h=8/d=4 XMSS^MT parameter sets, plus a three-level HSS key across a subtree boundary and an HSS shard. Since those node values cannot be recomputed, the encoded state now carries a checksum over itself instead, with the owning key's public seed hashed in front of it. Any corruption of the stored state is refused at decode rather than being loaded and then producing signatures that silently do not verify, and because the public seed is bound in, a state transplanted between two keys of the same parameter set is refused too, even though it is internally consistent and arrives with its own matching root. The public seed is bound rather than the secret seed or the PRF key deliberately: the state's own root and index are inside the encoding and so are already covered, hashing secret material would make the stored checksum a commitment to it for no gain in detection, and the PRF key does not influence the state at all. \u003cstrong\u003eThis is an error-detecting code and not integrity protection\u003c/strong\u003e - anyone able to rewrite the stored key recomputes it, so it establishes that the state is unchanged since it was written, never that it was correct when written, and the allocation bounds on the encoding remain the guard against a crafted one. It costs one SHA-256 over the state, measured at 5 to 8 microseconds each way for the h=10 and h=16 parameter sets, and 32 bytes of encoding. The state encoding was added earlier in this same cycle and has not been released, so the checksum is simply part of it rather than a new version: a state written by a 1.86 beta is rejected, which is recovered from by re-exporting the key. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the HSS check as well (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2414\"\u003e#2414\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe S/MIME example smoke test in the misc module (org.bouncycastle.mail.smime.examples.test.AllTests) drove SendSignedAndEncryptedMail against smtp.gmail.com, and that example finishes with Transport.send() under JavaMail's default settings, which have no connect timeout. Where outbound port 25 is refused the failure was swallowed and the test passed; where it is silently dropped, as on many home networks, the connect blocked and ./gradlew build hung in :misc:test indefinitely with \u0026quot;0 tests completed\u0026quot;. The test now delivers to an SMTP stub on a loopback port, with connect / read / write timeouts as a backstop, and asserts the message arrived (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2407\"\u003e#2407\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation took the traditional component public key bytes it feeds the KEM combiner from the recipient key's own encoding, while decapsulation recomputes the point from the private key and so always produced an uncompressed one. Section 4 of draft-ietf-lamps-pq-composite-kem requires an EC component to be carried as an uncompressed point, but a component key that encodes itself compressed - a BC EC key whose point format has been set through org.bouncycastle.jce.interfaces.ECPointEncoder, or a key from a provider that preserves a compressed encoding - was passed through as it came. Both sides then combined a different tradPK and derived different shared secrets, with no error reported on either: encapsulation and decapsulation both succeeded and the recipient simply could not decrypt. The EC component is now normalised to an uncompressed point wherever the engine serialises one, which covers the ephemeral key that forms the ciphertext as well. X25519 and X448 components have a single encoding and were unaffected, as were EC keys left in their default (uncompressed) format, whose shared secrets are unchanged. CompositePublicKey.getEncoded() took its component bytes the same way, so such a key also encoded to a composite key other implementations reject and whose bytes changed across an encode / decode / encode round trip - 1238 bytes rather than 1270 for MLKEM768-ECDH-P256, and for the composite ML-DSA keys sharing that method, 2006 rather than 2038 for MLDSA65-ECDSA-P256. It now normalises the component the same way. This is a write-side change only: a composite key carrying a compressed EC component is still decoded, since the component key factories accept either form, and continues to verify signatures as before - it simply re-encodes in the normalised form. The shared normalisation is org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil.getUncompressedSubjectPublicKeyBytes.\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation threw a NullPointerException, wrapped in an IllegalStateException out of KeyGenerator.generateKey(), when the SecureRandom it was given was null - which javax.crypto.KEM.newEncapsulator() documents as a request for the provider's default, and which KeyGenerator.init(spec, null) passes straight through. The three RSA-OAEP composites draw the traditional shared secret from that random directly, so they were the ones affected; the ECDH and X25519 / X448 composites escaped only because their component KeyPairGenerators default a random of their own. CompositeMLKEMEngine now defaults one through CryptoServicesRegistrar.getSecureRandom() on first use, as the composite KEM Cipher's wrap path already did, and as the KEM generators corrected earlier in this cycle now do. Related, the engine now also clears the ML-KEM component's shared secret alongside the traditional one on both the encapsulate and decapsulate paths - the copy handed back by getEncoded() was left in the heap - as section 3.5 of draft-ietf-lamps-pq-composite-kem requires.\u003c/li\u003e\n\u003cli\u003eCompositePublicKey.getAlgorithm() and CompositePrivateKey.getAlgorithm() returned null for all twelve Composite ML-KEM (draft-ietf-lamps-pq-composite-kem) parameter sets. Both classes resolved the name through the composite signature index only, which holds the composite ML-DSA OIDs, so a composite KEM key pair - generated, parsed from a certificate, or read from PKCS#8 - reported no algorithm at all, and the standard JCA idiom of reconstructing a key with KeyFactory.getInstance(key.getAlgorithm()) raised a NullPointerException. The lookup now falls back to the composite KEM index, so the name returned is the one the provider registers the algorithm under (e.g. MLKEM768-X25519-SHA3-256), matching the composite ML-DSA behaviour. The same single-index assumption made the CompositePublicKey(SubjectPublicKeyInfo) and CompositePrivateKey(PrivateKeyInfo) constructors reject a composite KEM key with \u0026quot;unable to create CompositePublicKey from SubjectPublicKeyInfo\u0026quot;; they now dispatch to the composite KEM key factory for those OIDs. Keys obtained through KeyFactory or through BouncyCastleProvider.getPublicKey / getPrivateKey were unaffected and are unchanged (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2404\"\u003e#2404\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe org.bouncycastle.jcajce.spec.KEMKDFSpec constructor stored a null otherInfo as given, so getOtherInfo() returned null, and three of the KDF branches KdfUtil.makeKeyBytes dispatches to - KMAC-128, KMAC-256 and SHAKE-256 - read the otherInfo length without a guard and threw NullPointerException out of the KEM operation, where the KDF2, KDF3 and HKDF branches tolerate a null through KDFParameters / HKDFParameters. The Builder of every spec in the package already mapped null to empty, so no provider path reached it, but the constructor is protected on a public class and KdfUtil is documented for callers building their own KEM integration; the deprecated KEMParameterSpec passes a null itself and escaped only because it also pins the KDF to null. The constructor now stores empty for a null, so getOtherInfo() never returns null, and a null and an explicitly empty otherInfo derive the same key.\u003c/li\u003e\n\u003cli\u003eQR-UOV signature verification accepted a signature encoding that was not canonical, so the encoding of a signature was not unique even after the trailing-byte fix of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e. Each F_q element of the signature is stored in ceil(log2 q) bits, one more bit pattern than the field has elements: q itself is representable and is arithmetically congruent to zero, so an element written as q verified exactly as the same element written as zero would, and the bits padding the last element out to the byte boundary were never read at all. Every zero element of a signature therefore carried a second encoding, and for the q = 7 parameter sets roughly one element in seven is zero - a single qruov_5_q7_L10 signature measured 256 spare bits, so on the order of 2^256 distinct byte strings verified for the one message and key. Verification now rejects any element outside [0, q) and any set padding bit; a signature produced by this or by the reference implementation is unaffected, as the KAT vectors of every parameter set confirm. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSNOVA signature verification ignored four bits inside the signature for any parameter set whose solution is an odd number of GF(16) nibbles - the SNOVA_24_5_5, SNOVA_25_8_3, SNOVA_29_6_5 and SNOVA_66_15_3 families, sixteen of the forty-four parameter sets. The last byte of the encoded solution carries a single nibble and the signer leaves the top four bits zero, but the decoder did not read them, so sixteen distinct byte strings verified for one signature. This is the same non-unique encoding github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e closed for bytes following the signature, applied inside it; the verifier now requires those bits to be zero. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSnovaPrivateKeyParameters did not validate the length of the private key encoding handed to it - the only one of the five schemes of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e that did not - and SnovaParameters.getPrivateKeyLength() reported the expanded (\u0026quot;ESK\u0026quot;) length even for a parameter set whose private key is the seed pair. A private key encoding reaches this constructor straight from a PKCS#8 blob, so a wrong length went undetected: a seed-form key with extra bytes appended was accepted and signed under a different derived key, and a short expanded-form key sized the signer's decode buffer negatively, throwing NegativeArraySizeException out of generateSignature() rather than being reported at construction. Related, the signing retry loop could not terminate: the vinegar values are derived from a single-byte counter, so only 256 distinct linear systems can be tried, and an expanded-form private key that is not a real central map is singular for all of them - generateSignature() then span forever rather than failing. The length is now checked at construction, getPrivateKeyLength() reports the length that parameter set's private key actually has, and the retry loop gives up after its 256 attempts as MAYO's does.\u003c/li\u003e\n\u003cli\u003eMayoSigner and MayoKeyPairGenerator did not clear several buffers holding secret key material that the MAYO reference implementation explicitly clears. Signing left the secret oil space O, the expanded L = (P1 + P1^t) * O + P2, and the M / VPV / Ox intermediates of the central map in place, having gone to the trouble of clearing eleven other buffers; key generation left the expanded seed, whose tail is the encoded oil space, and the P1 * O + P2 half of P; and the row-echelon step left the packed echelon form of the secret linear system and its pivot rows. Separately, if all 256 attempts at solving for the signature had given a rank-deficient system, signing emitted a signature built from the failed attempt's state instead of reporting the failure the reference returns, and AIMerSigner.generateSignature returned an empty array on failure, which a caller would hand on as though it were a signature. Both now throw.\u003c/li\u003e\n\u003cli\u003eFive PQC signature schemes - MAYO, SNOVA, QR-UOV, SQIsign and AIMer - returned the NIST crypto_sign \u0026quot;sm\u0026quot; signed-message envelope from generateSignature() rather than the signature. That envelope is an artefact of the reference KAT harness, which records the message alongside the signature so a vector file can be self-contained; it is not part of any of the five specifications, and no other BC signer emits it (Falcon's KAT test rebuilds the equivalent envelope in the test, which is where it belongs). Two consequences followed, both reaching the JCA Signature services of every parameter set of the five schemes in BouncyCastlePQCProvider. First, since the message was appended to the signature, verification had to skip whatever followed the signature proper, and it did so by checking only that the buffer was long enough - so any number of trailing bytes could be added to a valid signature, or the appended message replaced with unrelated data, and it still verified. A signature encoding was therefore not unique: anyone holding one valid signature could produce unlimited distinct byte strings that all verified for the same message and key, which breaks any use that treats the signature bytes as an identifier, deduplicates on them, or records them as evidence. Second, the envelope propagated into everything built on the operator layer: because ContentSigner hands the signature straight into the structure being signed, every X.509 certificate, CRL, CMS SignedData and TLS CertificateVerify BC produced with one of these algorithms carried a verbatim copy of the signed data inside its own signature field - a self-signed MAYO-1 certificate came to 3567 bytes where the same certificate is now 2020 - which no other implementation can parse as a signature, and which in a detached CMS signature meant the \u0026quot;detached\u0026quot; signature carried the content. generateSignature() now returns the bare signature, and verifySignature() requires exactly the parameter set's signature length, so appended or truncated data is rejected rather than ignored. \u003cstrong\u003eThis is a behavioural change for signatures produced by an earlier release\u003c/strong\u003e - MAYO and SNOVA from 1.84, QR-UOV, SQIsign and AIMer from 1.85 - which are no longer accepted in the envelope form they were emitted in; the signature bytes themselves are unchanged, so a stored value can be recovered by taking the leading signature-length bytes, or for AIMer, whose envelope was message || signature rather than signature || message, the trailing ones. The KAT tests now rebuild the envelope before comparing against the vector files, which continue to record it. Note that AIMer's verification had already been made length-exact during this cycle (see the entry below relating to github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2401\"\u003e#2401\u003c/a\u003e), so of the five only its envelope remained (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe MLS implementation did not bind an X.509 credential to the LeafNode's signature_key. LeafNode.verify() checked a leaf's signature against the signature_key declared in the leaf itself, while the X.509 credential's certificate chain was stored but never parsed or checked, so the certificate's public key was never required to match signature_key (RFC 9420 sec. 5.3). A leaf could therefore carry one party's certificate while being signed by an unrelated key and still be accepted under that party's identity through KeyPackage.verify() and the Group leaf-validation path. LeafNode.verify() now requires the end-entity certificate's subject public key, in the cipher suite's signature encoding, to equal signature_key for an X.509 credential, and rejects the leaf otherwise - including an empty chain or a certificate whose key type does not match the cipher suite; certificate-chain and identity validation to a trust anchor remain the application's responsibility per RFC 9420 sec. 5.3.1. A public org.bouncycastle.mls.codec.Certificate(byte[]) constructor and a Credential.getCertificates() accessor are added so callers can build and inspect X.509 credentials. Basic credentials are unaffected.\u003c/li\u003e\n\u003cli\u003eThe SecureRandom supplied to org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder.setSecureRandom() did not drive the content IV / nonce for any algorithm other than RC2. EnvelopedDataHelper.generateParameters passed the caller's SecureRandom to the AlgorithmParameterGenerator only in the RC2_CBC branch; every other content-encryption algorithm - AES-CBC, AES-GCM, AES-CCM, Camellia, ARIA, SEED and the rest - reached pGen.generateParameters() on an uninitialised generator, so the IV / nonce was drawn from a default SecureRandom and setSecureRandom() was silently ignored (the builder's javadoc states that random is used for IV/nonce generation). The generator is now initialised with the supplied random on the general path as well, so a caller who provides a specific randomness source - for a controlled or FIPS-approved DRBG, say - has it honoured for the content IV / nonce. The session-key generation path was unaffected and already used the supplied random. Because the content IV / nonce now comes from the supplied SecureRandom, the org.bouncycastle.crypto.util JournalingSecureRandom / JournaledAlgorithm reproducible-encryption support records it in the transcript: a resumed session reproduces the IV / nonce by regenerating it from the replayed randomness - build the resuming encryptor from the content-algorithm OID - rather than by reusing the AlgorithmIdentifier captured from the first encryption, which no longer keeps the transcript aligned.\u003c/li\u003e\n\u003cli\u003eThe NTRU LPRime, NTRU+ and SMAUG-T KEM generators threw a NullPointerException when constructed with a null SecureRandom, where every other KEM generator - including NTRU LPRime's own SNTRU Prime counterpart in the same package - defaults one through CryptoServicesRegistrar.getSecureRandom(). This is reachable from the lightweight API directly, and from javax.crypto.KEM, whose newEncapsulator() documents a null random as a request for the provider's default.\u003c/li\u003e\n\u003cli\u003eFrodoKEMEngine kept a single SHAKE instance in a field, so an engine reached concurrently produced wrong results. It is reached that way through org.bouncycastle.crypto.kems.FrodoKEMExtractor, which holds one engine for its lifetime: two threads extracting through one extractor interleaved the digest's absorb and squeeze phases, yielding shared secrets that silently did not match the sender's, or an IllegalStateException of \u0026quot;attempt to absorb while squeezing\u0026quot; from inside extractSecret. The digest is now built per call, as CMCEEngine's already was, which makes an extractor safe to share. Encapsulation was unaffected, since FrodoKEMGenerator builds an engine per call. Results for any single-threaded use are unchanged - the reference KAT vectors are byte-identical.\u003c/li\u003e\n\u003cli\u003eThe BCJSSE provider carried the TLS 1.2 coupling between the supported_groups extension and ECDSA over into TLS 1.3: an ECDSA signature scheme was treated as usable - offered in the signature_algorithms and signature_algorithms_cert extensions, and eligible when selecting the local credentials - only while the corresponding curve was among the named groups enabled for key exchange, both per context (a group unavailable for key agreement disabled the scheme outright) and per connection (the curve had to be in the supported_groups list about to be sent). RFC 8446 sec. 4.2.7 scopes supported_groups to key exchange only, with signature algorithms negotiated independently (sec. 4.2.3), so this incorrect restriction in TLS 1.3 has been removed. Ed25519, Ed448 and the RSA schemes were unaffected (as well as typical deployments using a default configuration for named groups).\u003c/li\u003e\n\u003cli\u003eThe bcmail module descriptor did not declare its javax.mail/javax.activation dependences, so a modular (module-path) consumer of the jar hit IllegalAccessError/module-resolution failures when the S/MIME classes touched the mail API. The descriptor now requires them optionally (requires static) under all four module names those libraries are known by - the automatic names mail and activation carried by the javax.mail:mail / javax.activation:activation artifacts, and the explicit names java.mail and java.activation carried by the newer com.sun.mail / com.sun.activation ones - a hard requires on any one name would break users of the others (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2389\"\u003e#2389\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFour type-coercion helpers in the OER / IEEE 1609.2 (ITS) decoder tested the wrong type in the identity fast path that lets a getInstance() factory return an argument that is already of the target type. org.bouncycastle.oer.its.ieee1609dot2.basetypes.UINT32.getInstance and org.bouncycastle.oer.its.etsi102941.basetypes.Version.getInstance guarded on UINT8 - a sibling of UINT32 under UintBase, and unrelated to Version - so passing a UINT8 threw ClassCastException, while passing an actual UINT32 or Version missed the fast path and fell through to ASN1Integer.getInstance, which rejects them: neither factory accepted its own type. org.bouncycastle.oer.its.etsi103097.EtsiTs103097DataEncryptedUnicast.getInstance guarded on its sibling EtsiTs103097DataEncrypted and then cast to the unicast type, so an EtsiTs103097DataEncrypted threw ClassCastException. org.bouncycastle.oer.OEROptional.getObject(Class) called value.getClass().isInstance(type) with the arguments transposed, which is always false because the argument is a java.lang.Class, so the cast path was dead and every optional field was resolved reflectively, failing with IllegalStateException for a target type with no static getInstance. Each guard now names the type it returns, matching the sibling UINT8 / UINT16 / UINT64 and EtsiTs103097DataEncrypted factories (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2373\"\u003e#2373\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eDefaultAlgorithmNameFinder and DefaultSignatureNameFinder had no entries at all for the ShangMi algorithms, so an SM2 signature AlgorithmIdentifier that DefaultSignatureAlgorithmIdentifierFinder itself produces came back named only by its OID string - getAlgorithmName(GMObjectIdentifiers.sm2sign_with_sm3) returned \u0026quot;1.2.156.10197.1.501\u0026quot; and hasAlgorithmName returned false. Both finders now name sm2sign_with_sm3 as SM3WITHSM2 and sm2sign_with_sha256 as SHA256WITHSM2, and DefaultAlgorithmNameFinder additionally names the sm3 digest. All three resolve through the BC provider, as Signature and MessageDigest respectively. The remaining GM arc - the SM4 cipher modes, the sm2encrypt variants, and the SM1 / SM6 / SSF33 ciphers BC does not implement - is still unnamed (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2377\"\u003e#2377\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe RFC 4998 evidence-record classes compared the digest AlgorithmIdentifier named by a time-stamp authority with the one their own DigestCalculator uses, and did so with AlgorithmIdentifier.equals(), which compares the encodings. A TSA that names SHA-256 with an explicit NULL parameters field - DigiCert among them - therefore failed against BC's own calculator, which names it with the parameters absent, and ERSArchiveTimeStampGenerator.generateArchiveTimeStamp rejected the response with \u0026quot;time stamp imprint for wrong algorithm\u0026quot;. Both spellings name the same digest and RFC 5754 sec. 2 requires a receiver to accept either, while requiring that identifiers be generated with the parameters absent, which BC already does. The three affected comparisons - the two in ERSArchiveTimeStampGenerator and the digest check in ERSEvidenceRecord.renew - now use the new AlgorithmIdentifier.areEquivalent, which matches on the algorithm and treats an absent parameters field and NULL as the same, and the consistency check across an evidence record's archive time stamp chain uses it too. An identifier carrying an actual parameter structure is never equivalent to one carrying none (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2379\"\u003e#2379\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eEDIPartyName.toASN1Primitive emitted the nameAssigner and partyName DirectoryStrings without their context tags, so an EDIPartyName built through its public constructor could not be parsed back by EDIPartyName.getInstance, which correctly requires them. RFC 5280 sec. 4.2.1.6 tags both members [0] and [1], and those tags are explicit despite the module's IMPLICIT TAGS because DirectoryString is a CHOICE, which X.680 does not allow to be tagged implicitly - the decoder already had this right. The encoder now matches it. Note the type was added during the 1.85 cycle and GeneralName validates its ediPartyName alternative through it, so a GeneralName carrying an untagged ediPartyName - including one BC itself produced - is rejected where 1.84 passed it through unexamined; the untagged form is not read leniently (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2380\"\u003e#2380\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eRSASSA-PSS could not be used with a RIPEMD digest through the JCA API. Nothing registered the RIPEMD PSS signatures, so Signature.getInstance(\u0026quot;RIPEMD160WITHRSAANDMGF1\u0026quot;) raised NoSuchAlgorithmException, and the generic RSASSA-PSS route with an explicit PSSParameterSpec failed too: org.bouncycastle.jcajce.provider.util.DigestFactory.getDigest returned null for a RIPEMD name, and isSameDigest - an allow-list of the SHA families and MD5 - reported two identical RIPEMD names as different digests, so the spec was rejected with \u0026quot;digest algorithm for MGF should be the same as for PSS parameters\u0026quot;. isSameDigest now answers true for equal names whatever the digest, which also covers Whirlpool, SM3, GOST3411 and anything else outside that allow-list; DigestFactory recognises RIPEMD128, RIPEMD160 and RIPEMD256 by name and OID; the three PSS signatures are registered with MGF1 over the same digest and a salt of the digest length; and DefaultSignatureAlgorithmIdentifierFinder gains the matching RIPEMD*WITHRSAANDMGF1 entries with their RSASSA-PSS-params, so the operator/JcaContentSignerBuilder path works as well. Note BC continues to require the PSS hash and the MGF1 hash to be the same, which RFC 8017 does not itself demand (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2381\"\u003e#2381\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe opt-in key-size validation on CMS key-transport recipients (org.bouncycastle.cms.jcajce.JceKeyTransRecipient.setKeySizeValidation(true)) never ran for a message using RFC 9709 CEK derivation (id-alg-cek-hkdf-sha256): the branch that should have selected the actual content-encryption algorithm carried in the KDF AlgorithmIdentifier's parameters compared the encrypted-key byte array against the id-alg-cek-hkdf-sha256 object identifier - a comparison that is always false - so the check fell through to a key-size lookup on the outer KDF OID, which has no registered key size, and silently checked nothing. A key-transport EnvelopedData/AuthEnvelopedData whose transported (and HKDF-derived) content-encryption key did not match the key size of the advertised content-encryption algorithm was therefore accepted even with validation enabled. The recipient now dispatches on the content-encryption AlgorithmIdentifier's algorithm OID, so key-size validation of RFC 9709 messages checks the recovered key against the inner content-encryption algorithm. Messages with a matching key size, non-HKDF messages, and recipients that do not enable validation are unaffected.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003eSee full diff in \u003ca href=\"https://github.com/bcgit/bc-java/commits\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark` from 0.29.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/blockquote\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/blockquote\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/42b4fb7adfe288ef13e9e27ab20aff7e91b0ab9d\"\u003e\u003ccode\u003e42b4fb7\u003c/code\u003e\u003c/a\u003e Prepare CHANGELOG for version 0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/b76e09d7a8362abb5f04e1d6b91dbd6da279a6fc\"\u003e\u003ccode\u003eb76e09d\u003c/code\u003e\u003c/a\u003e Limit how deep inline nodes may nest by default (100)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/49f65cb5cbec93cff713179990307145198e7061\"\u003e\u003ccode\u003e49f65cb\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing deeply nested emphasis\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/610f84b83e68c381e8f784ae4d044c80e1948b67\"\u003e\u003ccode\u003e610f84b\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological autolink email addresses\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/9f1d73897a56cbd74c39347af351a473e70297e1\"\u003e\u003ccode\u003e9f1d738\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological HTML block attributes\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/e13297e849995fdd582a85841067bff1d9c35ee5\"\u003e\u003ccode\u003ee13297e\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing pathological backticks\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/89d1bd3fa1524e8217ed61db5e8116c82434470f\"\u003e\u003ccode\u003e89d1bd3\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing with lots of \u003ccode\u003e\u0026lt;\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/commonmark/commonmark-java/compare/commonmark-parent-0.29.0...commonmark-parent-0.30.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark-ext-autolink` from 0.29.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark-ext-autolink's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003cc...\n\n_Description has been truncated_","html_url":"https://github.com/Ben-Jianming/openclaw-pqc/pull/38","url":"https://dependabot.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ben-Jianming%2Fopenclaw-pqc/issues/38","packages_url":"https://dependabot.ecosyste.ms/api/v1/issues/38/packages"}},{"old_version":"5.3.2","new_version":"5.5.0","update_type":"minor","path":null,"pr_created_at":"2026-09-09T19:52:52.000Z","version_change":"5.3.2 → 5.5.0","issue":{"uuid":"5404069327","node_id":"PR_kwDOTDTeds8AAAABC44JkA","number":31,"state":"closed","title":"build(deps): bump the android-deps group across 1 directory with 17 updates","user":"dependabot[bot]","labels":["dependencies","java"],"assignees":[],"locked":false,"comments_count":3,"pull_request":true,"closed_at":"2026-09-11T19:46:19.000Z","author_association":null,"state_reason":null,"created_at":"2026-09-09T19:52:52.000Z","updated_at":"2026-09-11T19:46:19.000Z","time_to_close":172407,"merged_at":null,"merged_by":null,"closed_by":null,"dependency_metadata":{"prefix":"build(deps): bump","group_name":"android-deps","update_count":17,"packages":[{"name":"gradle-wrapper","old_version":"9.5.1","new_version":"9.7.1","repository_url":"https://github.com/gradle/gradle"},{"name":"androidx.core:core-ktx","old_version":"1.18.0","new_version":"1.19.0"},{"name":"org.bouncycastle:bcprov-jdk18on","old_version":"1.84","new_version":"1.85.2","repository_url":"https://github.com/bcgit/bc-java"},{"name":"org.commonmark:commonmark","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-autolink","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-strikethrough","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-tables","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-task-list-items","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.junit.vintage:junit-vintage-engine","old_version":"6.1.0","new_version":"6.1.3","repository_url":"https://github.com/junit-team/junit-framework"},{"name":"io.kotest:kotest-assertions-core-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"io.kotest:kotest-runner-junit5-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"com.squareup.okhttp3:mockwebserver","old_version":"5.3.2","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.squareup.okhttp3:okhttp","old_version":"5.3.2","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.android.application","old_version":"9.2.1","new_version":"9.4.0"},{"name":"com.android.test","old_version":"9.2.1","new_version":"9.4.0"},{"name":"org.jetbrains.kotlin.plugin.compose","old_version":"2.4.0","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"},{"name":"org.jetbrains.kotlin.plugin.serialization","old_version":"2.4.0","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"}],"path":null,"ecosystem":"maven"},"body":"Bumps the android-deps group with 17 updates in the /apps/android directory:\n\n| Package | From | To |\n| --- | --- | --- |\n| [gradle-wrapper](https://github.com/gradle/gradle) | `9.5.1` | `9.7.1` |\n| androidx.core:core-ktx | `1.18.0` | `1.19.0` |\n| [org.bouncycastle:bcprov-jdk18on](https://github.com/bcgit/bc-java) | `1.84` | `1.85.2` |\n| [org.commonmark:commonmark](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-autolink](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-strikethrough](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-tables](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-task-list-items](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.junit.vintage:junit-vintage-engine](https://github.com/junit-team/junit-framework) | `6.1.0` | `6.1.3` |\n| [io.kotest:kotest-assertions-core-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [io.kotest:kotest-runner-junit5-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [com.squareup.okhttp3:mockwebserver](https://github.com/lysine-dev/okhttp) | `5.3.2` | `5.5.0` |\n| [com.squareup.okhttp3:okhttp](https://github.com/lysine-dev/okhttp) | `5.3.2` | `5.5.0` |\n| com.android.application | `9.2.1` | `9.4.0` |\n| com.android.test | `9.2.1` | `9.4.0` |\n| [org.jetbrains.kotlin.plugin.compose](https://github.com/JetBrains/kotlin) | `2.4.0` | `2.4.20` |\n| [org.jetbrains.kotlin.plugin.serialization](https://github.com/JetBrains/kotlin) | `2.4.0` | `2.4.20` |\n\n\nUpdates `gradle-wrapper` from 9.5.1 to 9.7.1\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/gradle/gradle/releases\"\u003egradle-wrapper's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e9.7.1\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.1.\u003c/p\u003e\n\u003cp\u003eThis is a patch release for 9.7.0. We recommend using 9.7.1 instead of 9.7.0.\u003c/p\u003e\n\u003cp\u003eHere are the highlights of 9.7.0 release:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIsolated Projects graduates to incubating\u003c/li\u003e\n\u003cli\u003eBroader Configuration Cache compatibility\u003c/li\u003e\n\u003cli\u003eResilient Sync helps you fix broken builds\u003c/li\u003e\n\u003cli\u003eMore source locations in problem reports\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003ca href=\"https://docs.gradle.org/9.7.1/release-notes.html\"\u003eRead the Release Notes\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eWe would like to thank the following community members for their contributions to this release of Gradle:\n\u003ca href=\"https://github.com/aSemy\"\u003eAdam\u003c/a\u003e,\n\u003ca href=\"https://github.com/Gautam-aman\"\u003eAman Gautam\u003c/a\u003e,\n\u003ca href=\"https://github.com/YukiCodepth\"\u003eAman Kumar\u003c/a\u003e,\n\u003ca href=\"https://github.com/adubrouski\"\u003eAnton Dubrouski\u003c/a\u003e,\n\u003ca href=\"https://github.com/liutikas\"\u003eAurimas\u003c/a\u003e,\n\u003ca href=\"https://github.com/gbhavya07\"\u003egbhavya07\u003c/a\u003e,\n\u003ca href=\"https://github.com/joshfriend\"\u003eJosh Friend\u003c/a\u003e,\n\u003ca href=\"https://github.com/nicklauslittle-gov\"\u003enicklauslittle-gov\u003c/a\u003e,\n\u003ca href=\"https://github.com/psoni674\"\u003ePragati\u003c/a\u003e,\n\u003ca href=\"https://github.com/Project516\"\u003eproject516\u003c/a\u003e,\n\u003ca href=\"https://github.com/Uomocapra\"\u003eQin Mi\u003c/a\u003e,\n\u003ca href=\"https://github.com/rkdfx\"\u003eRavi\u003c/a\u003e,\n\u003ca href=\"https://github.com/sk-reddy17\"\u003esk-reddy17\u003c/a\u003e,\n\u003ca href=\"https://github.com/Suvrat1629\"\u003eSuvrat Acharya\u003c/a\u003e,\n\u003ca href=\"https://github.com/ShreckYe\"\u003eYongshun Ye\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eUpgrade instructions\u003c/h2\u003e\n\u003cp\u003eSwitch your build to use Gradle 9.7.1 by updating your wrapper:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e./gradlew :wrapper --gradle-version=9.7.1 \u0026amp;\u0026amp; ./gradlew :wrapper\r\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eSee the Gradle \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/upgrading_version_9.html\"\u003e9.x upgrade guide\u003c/a\u003e to learn about deprecations, breaking changes and other considerations when upgrading.\u003c/p\u003e\n\u003cp\u003eFor Java, Groovy, Kotlin and Android compatibility, see the \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/compatibility.html\"\u003efull compatibility notes\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eReporting problems\u003c/h2\u003e\n\u003cp\u003eIf you find a problem with this release, please file a bug on \u003ca href=\"https://github.com/gradle/gradle/issues\"\u003eGitHub Issues\u003c/a\u003e adhering to our issue guidelines.\nIf you're not sure you're encountering a bug, please use the \u003ca href=\"https://discuss.gradle.org/c/help-discuss\"\u003eforum\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eWe hope you will build happiness with Gradle, and we look forward to your feedback via \u003ca href=\"https://twitter.com/gradle\"\u003eTwitter\u003c/a\u003e or on \u003ca href=\"https://github.com/gradle\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003e9.7.0\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.0.\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/92f0512e7f06d84621afba191f75e265363890cf\"\u003e\u003ccode\u003e92f0512\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38892\"\u003e#38892\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/820ee75a99a179bbffa41bcedc6477b685fabb9f\"\u003e\u003ccode\u003e820ee75\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/82c23f9bd2a89b4cc644e1f90a28a8668feb3dee\"\u003e\u003ccode\u003e82c23f9\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering problem in KTS (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38878\"\u003e#38878\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/ef11a7268fe8cc8d6ab849ec911aa11220180553\"\u003e\u003ccode\u003eef11a72\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering issue\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/bb0d8a974a71b1003efea41e4046e98855cd5ff8\"\u003e\u003ccode\u003ebb0d8a9\u003c/code\u003e\u003c/a\u003e Make relevant tests polyglot (run for multiple DSLs)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/336e129d7f95c03486acafc97abf59734acfed48\"\u003e\u003ccode\u003e336e129\u003c/code\u003e\u003c/a\u003e Update signing configuration (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38874\"\u003e#38874\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/4bdf0da2dad9884d089a6062a45ea7183e7d735d\"\u003e\u003ccode\u003e4bdf0da\u003c/code\u003e\u003c/a\u003e Update signing configuration\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/cd9b92c1b82856248cf1dc58b50378238bec7b52\"\u003e\u003ccode\u003ecd9b92c\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38839\"\u003e#38839\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/5f4e381964897ad8d6b99e5a7c77f26dba3259fb\"\u003e\u003ccode\u003e5f4e381\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/1e08ab551367aeb5fb48b26e72807e1d2b27c939\"\u003e\u003ccode\u003e1e08ab5\u003c/code\u003e\u003c/a\u003e Keep type-use annotations in extracted ABI classes (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38810\"\u003e#38810\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/gradle/gradle/compare/v9.5.1...v9.7.1\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `androidx.core:core-ktx` from 1.18.0 to 1.19.0\n\nUpdates `org.bouncycastle:bcprov-jdk18on` from 1.84 to 1.85.2\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.md\"\u003eorg.bouncycastle:bcprov-jdk18on's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch1\u003eBouncy Castle Crypto Package - Release Notes\u003c/h1\u003e\n\u003ch2\u003e1.0 Introduction\u003c/h2\u003e\n\u003cp\u003eThe Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. The package is organised so that it contains a light-weight API suitable for use in any environment (including the J2ME) with the additional infrastructure to conform the algorithms to the JCE framework.\u003c/p\u003e\n\u003ch2\u003e2.0 Release History\u003c/h2\u003e\n\u003cp\u003e\u003c!-- raw HTML omitted --\u003e\u003c!-- raw HTML omitted --\u003e\u003c/p\u003e\n\u003ch3\u003e2.1.1 Version\u003c/h3\u003e\n\u003cp\u003eRelease: 1.86\u003cbr /\u003e\nDate: 2026, TBD\u003c/p\u003e\n\u003ch3\u003e2.1.2 Defects Fixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) let a subkey inherit the primary key's Key Flags when its own Subkey Binding signature carried no Key Flags subpacket, which made the two capability decisions taken for one subkey disagree. OpenPGPCertificate.OpenPGPComponentKey.isSigningKey() reads the effective flags, which fell back to the primary key's direct-key or primary user ID self-signature, so a subkey bound with no flags of its own counted as signing-capable; verifyEmbeddedPrimaryKeyBinding reads the binding signature's own flags, found no signing capability there, and so skipped the embedded Primary Key Binding (cross-certification) signature that RFC 9580 sec. 5.2.1.8 and sec. 10.1.3 require of a subkey that can issue signatures. A data signature made by such a subkey was therefore attributed to the certificate and reported valid by OpenPGPSignature.OpenPGPDocumentSignature.isValid() with the cross-certification requirement never applied, where GnuPG refuses the same certificate and message as not cross-certified. An attacker holding a third party's public signing subkey - which is public material - could bind it to their own primary key with a Subkey Binding signature they are able to make, carrying no Key Flags and no embedded Primary Key Binding signature, which they cannot make without the subkey's private key, and have that party's genuine signatures verify as valid under the attacker's own identity: misattribution of a real signature rather than a forgery of a new one, since the signature still has to be one the subkey actually made. Key Flags are a statement about the key the carrying signature refers to (RFC 9580 sec. 5.2.3.29), so a subkey no longer inherits them from the certificate-wide signatures of the primary key: a Subkey Binding signature that omits the subpacket now leaves the subkey with no capabilities rather than the primary's, which makes the flags the cross-certification check consults the same flags every other decision consults. Preferences and the other subpackets a direct-key signature carries are inherited as before, and the primary key itself - whose flags legitimately come from its direct-key or user ID self-signature - is unaffected. The low-level PGPSignature / PGPPublicKeyRing API performs no binding checks by design and is unchanged.\u003c/li\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) used a version 6 key that carried no valid Direct Key signature, falling back to the primary user ID binding as it correctly does for a version 4 key. RFC 9580 sec. 5.2.3.10 requires the opposite: \u0026quot;An implementation MUST ensure that a valid Direct Key signature is present before using a version 6 key. This prevents certain attacks where an adversary strips a self-signature specifying a Key Expiration Time or certain preferences.\u0026quot; The certificate grammar says the same structurally, the Direct Key signature being mandatory in the version 6 structure of sec. 10.1.1 and optional in the version 4 one of sec. 10.1.3. Because a version 6 certificate carries its key expiration, features and algorithm preferences on the Direct Key signature - the convention the RFC recommends and the one OpenPGPKeyGenerator follows, its user ID certification carrying no expiration at all - removing that single signature packet from a published certificate silently dropped the expiration along with the preferences and features: OpenPGPCertificate.getSignatureChainFor fell back to the user ID binding, the primary key was still reported bound, and getEncryptionKeys() and getSigningKeys() went on returning the subkeys of a key whose owner had set it to expire. The primary key fingerprint is unchanged by the removal, so a relying party pinning the key by fingerprint still treats it as the same key, and no private key or hash collision is involved; the natural moment for the strip is the key refresh that RFC 9580 names as the reason to refetch a key at all - to learn about changes in expiration, features, preferences and revocation - which is exactly the update it defeats. This is a downgrade rather than a forgery, nothing being attributed to a key that did not authorise it, and the concerning direction is encryption, to a key meant to have been retired. OpenPGPCertificate.isBoundBy now requires a valid Direct Key self-signature on a version 6 primary key before any component of the certificate - the primary key, its subkeys or its identities - is treated as bound, so a version 6 certificate stripped of it offers no keys at all rather than an unexpiring set. Version 4 certificates are unaffected: there the key expiration legitimately lives on the user ID self-signature and the fallback is correct, so it stays. The revocation-only version 6 certificate of sec. 10.1.2, which legitimately carries no Direct Key signature, is unaffected as well - its key was already refused as revoked, and reading the revocation does not go through the binding check.\u003c/li\u003e\n\u003cli\u003eThe lightweight LMSSigner and HSSSigner refused a key wrapped in ParametersWithRandom, which is how BcContentSignerBuilder passes a key whenever setSecureRandom() has been called - so BcHssLmsContentSignerBuilder built a working signer until a random was set and then failed with \u0026quot;Incorrect Key Parameters\u0026quot;, and the two signers themselves raised ClassCastException on the same input. All three now unwrap it, as the promoted ML-DSA and SLH-DSA signers already did. The random is accepted and not used: LMS derives its message randomiser C from the key's seed and the one-time index, so it is deterministic and cannot repeat while q does not. Note SP 800-208 sec. 6.1 asks for C to come from an approved random bit generator, which this implementation does not do; that is unchanged here, and a supplied random is now ignored rather than refused.\u003c/li\u003e\n\u003cli\u003eLMS signature verification did not apply two of the checks RFC 8554 sec. 5.4.2 requires before a signature is processed. Step 2g refuses a signature whose LMS typecode is not the one from the public key, and without it the path computation took its height and tree digest from the parameter set the signature named rather than the key's, so a signature claiming a height-25 parameter set drove a 25-level computation against a height-5 key. Step 2i refuses a leaf number q outside the tree, and without it an out-of-range q flowed into the node arithmetic and was left for the candidate-root comparison to catch. Neither was a forgery - the domain separation between D_LEAF and D_INTR and the final comparison saw to that - but both are attacker-chosen work the specification says to refuse up front. Both are now checked, and a signature failing either is still reported as not verifying rather than thrown out of Signature.verify(). The catch around the signature decode in LMSSigner and HSSSigner has also been narrowed to the decode itself, as the corresponding SPI was corrected to do for github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2408\"\u003e#2408\u003c/a\u003e: past the parse the engine reports an inconsistent signature by returning false rather than by throwing, so the wider catch caught nothing while standing ready to turn a future internal error into a quiet false.\u003c/li\u003e\n\u003cli\u003eThe LMS and HSS key parameter classes now apply at construction the checks their decoders apply, so a key built directly cannot be one the decoder would refuse. LMSPrivateKeyParameters accepted an identifier of any length although the decoder reads exactly 16 bytes - such a key encoded but could not be read back - and left q, maxQ and the seed length unchecked; the seed is now required to be at least m bytes at decode as well, where a one-byte seed had been decoding silently and then deriving every one-time key from it. HSSPrivateKeyParameters checked neither its level count nor that it had been given a component key per level and a chaining signature per level below the root, and then indexed both lists, so a mismatch surfaced as IndexOutOfBoundsException - or, where a level happened to match, as a null chaining signature that only failed at signing time; the level is now checked after the reset that fills it in, since a null is legitimate on the way in. LMSPrivateKeyParameters.getInstance(byte[], byte[]) adopted the public key supplied beside the private one without comparing them, so a mismatched public key was simply reported by getPublicKey(); it now cross-checks the identifier, both parameter sets and, where the tree cache already holds it, the root, as the HSS entry point does. The decoders also now report a bad version or seed length as IOException rather than IllegalStateException, so a caller can catch one type for a malformed key, and the package-private LM-OTS public key decoder no longer declares throws Exception or dereferences an unrecognised typecode. The deprecated org.bouncycastle.pqc.crypto.lms copies carry the decoder corrections.\u003c/li\u003e\n\u003cli\u003eIn the LMS JCE layer, LMSKeyGenParameterSpec.fromNames knew all twenty LMS parameter-set names but only four of the sixteen LM-OTS ones, so none of the SP 800-208 n24 or SHAKE sets could be named; all sixteen are now present. KeyPairGenerator.initialize(int, SecureRandom) reports InvalidParameterException, which is what the JCA specifies and which extends the IllegalArgumentException it raised before, so existing catches still match. BCLMSPrivateKey.getIndex now takes the exhaustion check and the index read under the key's own monitor rather than as two separate calls, and two unused fields have gone from LMSSignatureSpi. Note that the LMS Signature claims its one-time key at the first update() rather than at sign(), so a Signature that is initialised and updated and then abandoned spends an index without producing a signature - the safe direction for a one-time scheme, and now documented on the SPI.\u003c/li\u003e\n\u003cli\u003eEvery other key pair generator that refuses a key size did the same thing the LMS one did above. KeyPairGenerator.initialize(int, SecureRandom) is documented to raise InvalidParameterException when the key size is not one the generator supports, and thirty of them raised a bare IllegalArgumentException instead, so a caller following the JCA and catching the documented type saw an exception escaping rather than a refusal. The ML-DSA, ML-KEM, SLH-DSA, Classic McEliece, FrodoKEM, NTRU and composite signature and KEM generators in the BC provider, and every generator in BCPQC, now raise InvalidParameterException - NewHope included, where the value is a key size it will not take rather than a mode of initialisation it does not offer. InvalidParameterException extends IllegalArgumentException, so callers written against the old behaviour go on catching it unchanged. The two RSA generators are corrected as well, and differently: theirs is a key size below a floor rather than a mode of initialisation they do not offer, and the refusal is raised by the lightweight RSAKeyGenerationParameters, which cannot name a java.security exception at all, so the RSA KeyPairGeneratorSpi now translates it - keeping the message verbatim and the original exception as the cause, through a new SecurityExceptions.invalidParameterException factory, since InvalidParameterException has no constructor that takes one. Of the 304 KeyPairGenerator services the two providers register, 299 now refuse a nonsense key size the way the JCA defines it and five accept it as a strength they can work with, with none left raising a bare IllegalArgumentException; that is asserted as a sweep over both providers rather than per algorithm, so a generator added later is covered without the test being touched. The jdk1.3 provider overlays of the four generators that have one carry the same change, and the jdk1.3 SecurityExceptions overlay gains the new factory along with the invalidAlgorithmParameterException one it had been missing.\u003c/li\u003e\n\u003cli\u003eKeyPairGenerator.initialize(AlgorithmParameterSpec, SecureRandom) had the same shape of problem as the int overload above, and only 44 of the 304 services the two providers register reported an unusable spec as the InvalidAlgorithmParameterException that method declares. The twenty-three PQC generators that resolve a parameter set by name - cmce, frodokem, mldsa, mlkem, slhdsa, aimer, bike, faest, falcon, haetae, hqc, mayo, mqom, ntru, ntruplus, both ntruprime variants, qruov, saber, sdith, smaugt, snova and sqisign, 230 services between them - case-folded the name they got back from the spec without checking it, so a spec with no getName() method, and a null spec, produced a NullPointerException from inside the fold; their own \u0026quot;is this name one I know\u0026quot; branch, which does report the declared exception, was unreachable. The two composite generators, whose parameter set is fixed by the algorithm name so that null is the only spec they accept, refused every other one with IllegalArgumentException. RSA answered correctly for a spec of the wrong type but not for one of the right type carrying values its lightweight parameters will not take - an even public exponent, or a key size below the floor - which is now translated the same way the int overload's is. All 304 services now report the declared exception, with the composites still taking the null spec that is right for them; note that InvalidAlgorithmParameterException is a checked exception and not an IllegalArgumentException, so a caller that was catching what these threw before has to catch the declared type instead.\u003c/li\u003e\n\u003cli\u003eAn HSS private key claimed the two records of its position under two different monitors. The top-level index and the bottom component key's one-time index q are independent records of the same position - the decoder requires them to agree, see the entry below - but generateLMSContext incremented the index under the HSS key's own monitor, released it, and only then claimed q under the component key's. A getEncoded() issued in between saw the index advanced and q not, and produced an encoding this implementation's own decoder rejects; and two threads meeting at a bottom-tree boundary could both pass the exhaustion test, take consecutive top-level indices and claim the same q, after which one of them was refused with \u0026quot;ots private key exhausted\u0026quot; by a key still reporting usages remaining, a top-level index had been spent with no signature made, and the two records stayed one apart for the rest of the key's life in that process - so it could no longer be encoded, cloned or sharded, and getIndex() and getUsagesRemaining() misreported by one. No one-time key was reused: the component key's claim is itself atomic, and the divergence runs index ahead of leaves, so the effect was on the key's usability rather than on the signatures it had made. Both records are now claimed under the one monitor, and the component key is claimed before the index is incremented so that an exhausted one leaves both untouched. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the same correction.\u003c/li\u003e\n\u003cli\u003eTimeStampToken parsed the attacker-controlled TSTInfo content of a time-stamp token (org.bouncycastle.tsp.TimeStampToken, reached from TimeStampResponse(byte[]) and (InputStream)) inside a try that caught only CMSException, so a well-formed RFC 3161 TimeStampResp whose embedded token carried a malformed TSTInfo - a SEQUENCE with fewer elements than the five mandatory fields, a non-SEQUENCE, truncated DER, or an unknown context tag - let an IllegalArgumentException or a NoSuchElementException escape the constructor's declared throws TSPException, IOException contract. A token signed by no signers or by more than one raised a bare IllegalArgumentException from the same constructor, before that try, for the same reason. Both are now reported as TSPException, matching the package-private TimeStampResponse(DLSequence) constructor and the existing getSignedAttributes guard in the same method; the signer-count refusal is a TSPValidationException, as the neighbouring check on the content type already was. Related, and the cause of the NoSuchElementException: asn1.tsp.TSTInfo read its five mandatory fields off the sequence with no bound on how many elements were actually there, so a short SEQUENCE left the enumeration to run out rather than being refused, and an oversize one was accepted with its extra elements absorbed into the optional slots. Decode now requires the five to ten elements RFC 3161 sec. 2.4.2 gives the type, which is what the sibling Accuracy and ArchiveTimeStamp decoders already did, so the failure is the IllegalArgumentException that getInstance is expected to raise (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2415\"\u003e#2415\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eNeither the HSS nor the XMSS^MT private key decoder checked its declared index against the traversal state stored beside it, although the two are independent records of the same position in the key and so can be compared. For HSS the records are the top-level index and the component keys' one-time indices q; for XMSS^MT they are the global index and the per-layer BDS states. A stored key whose index had been rolled back while its state stayed advanced - a partial write, a restore from backup, a buggy storage layer - was therefore accepted, and it then signed a second message under a one-time key the key had already used, producing a signature that verified, so nothing anywhere surfaced the reuse. RFC 8554 sec. 1 and RFC 8391 sec. 1.1 both require each one-time key to be used exactly once, and this is the failure those requirements exist to prevent; the single-tree XMSS decoder has tied its BDS state to its index since that state was first validated, and this brings the two multi-tree schemes into line. HSS decode now requires the declared index to equal the position the component q values imply - a level above the last contributes (q - 1) leaves of the levels beneath it, since its q has already advanced past the subtree it signed - and XMSS^MT decode now requires each present layer's BDS index to equal the leaf index that layer derives from the global index, allowing the one position where a layer has moved into a new subtree and its state legitimately still carries the previous subtree's final index. A layer with no state yet is unaffected, since those are built lazily at signing time. Related, and the same shape of omission: an XMSS or XMSS^MT private key encoding carries the tree root twice - the key's own root field and the root node of the BDS state stored beside it, which for XMSS^MT is the top layer's - and the two were never compared either. A corrupted root was accepted and then poisoned every signature the key made, because the root is hashed into the message digest: the signature did not verify and nothing indicated why. Decode now requires the two copies to agree. The BDS node values themselves are not checkable the way the LMS tree cache above is - a BDS authentication path, stack, retain or keep node does not have its children stored alongside it, so recomputing one means building a subtree, which is the work the state exists to avoid. Both checks are integer comparisons over the levels of the key, too small to measure against the surrounding decode, and both were verified not to reject any legitimate key by walking every index a key can reach: the full key space of the two-level HSS and the h=4/d=2, h=6/d=2, h=6/d=3, h=9/d=3 and h=8/d=4 XMSS^MT parameter sets, plus a three-level HSS key across a subtree boundary and an HSS shard. Since those node values cannot be recomputed, the encoded state now carries a checksum over itself instead, with the owning key's public seed hashed in front of it. Any corruption of the stored state is refused at decode rather than being loaded and then producing signatures that silently do not verify, and because the public seed is bound in, a state transplanted between two keys of the same parameter set is refused too, even though it is internally consistent and arrives with its own matching root. The public seed is bound rather than the secret seed or the PRF key deliberately: the state's own root and index are inside the encoding and so are already covered, hashing secret material would make the stored checksum a commitment to it for no gain in detection, and the PRF key does not influence the state at all. \u003cstrong\u003eThis is an error-detecting code and not integrity protection\u003c/strong\u003e - anyone able to rewrite the stored key recomputes it, so it establishes that the state is unchanged since it was written, never that it was correct when written, and the allocation bounds on the encoding remain the guard against a crafted one. It costs one SHA-256 over the state, measured at 5 to 8 microseconds each way for the h=10 and h=16 parameter sets, and 32 bytes of encoding. The state encoding was added earlier in this same cycle and has not been released, so the checksum is simply part of it rather than a new version: a state written by a 1.86 beta is rejected, which is recovered from by re-exporting the key. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the HSS check as well (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2414\"\u003e#2414\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe S/MIME example smoke test in the misc module (org.bouncycastle.mail.smime.examples.test.AllTests) drove SendSignedAndEncryptedMail against smtp.gmail.com, and that example finishes with Transport.send() under JavaMail's default settings, which have no connect timeout. Where outbound port 25 is refused the failure was swallowed and the test passed; where it is silently dropped, as on many home networks, the connect blocked and ./gradlew build hung in :misc:test indefinitely with \u0026quot;0 tests completed\u0026quot;. The test now delivers to an SMTP stub on a loopback port, with connect / read / write timeouts as a backstop, and asserts the message arrived (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2407\"\u003e#2407\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation took the traditional component public key bytes it feeds the KEM combiner from the recipient key's own encoding, while decapsulation recomputes the point from the private key and so always produced an uncompressed one. Section 4 of draft-ietf-lamps-pq-composite-kem requires an EC component to be carried as an uncompressed point, but a component key that encodes itself compressed - a BC EC key whose point format has been set through org.bouncycastle.jce.interfaces.ECPointEncoder, or a key from a provider that preserves a compressed encoding - was passed through as it came. Both sides then combined a different tradPK and derived different shared secrets, with no error reported on either: encapsulation and decapsulation both succeeded and the recipient simply could not decrypt. The EC component is now normalised to an uncompressed point wherever the engine serialises one, which covers the ephemeral key that forms the ciphertext as well. X25519 and X448 components have a single encoding and were unaffected, as were EC keys left in their default (uncompressed) format, whose shared secrets are unchanged. CompositePublicKey.getEncoded() took its component bytes the same way, so such a key also encoded to a composite key other implementations reject and whose bytes changed across an encode / decode / encode round trip - 1238 bytes rather than 1270 for MLKEM768-ECDH-P256, and for the composite ML-DSA keys sharing that method, 2006 rather than 2038 for MLDSA65-ECDSA-P256. It now normalises the component the same way. This is a write-side change only: a composite key carrying a compressed EC component is still decoded, since the component key factories accept either form, and continues to verify signatures as before - it simply re-encodes in the normalised form. The shared normalisation is org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil.getUncompressedSubjectPublicKeyBytes.\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation threw a NullPointerException, wrapped in an IllegalStateException out of KeyGenerator.generateKey(), when the SecureRandom it was given was null - which javax.crypto.KEM.newEncapsulator() documents as a request for the provider's default, and which KeyGenerator.init(spec, null) passes straight through. The three RSA-OAEP composites draw the traditional shared secret from that random directly, so they were the ones affected; the ECDH and X25519 / X448 composites escaped only because their component KeyPairGenerators default a random of their own. CompositeMLKEMEngine now defaults one through CryptoServicesRegistrar.getSecureRandom() on first use, as the composite KEM Cipher's wrap path already did, and as the KEM generators corrected earlier in this cycle now do. Related, the engine now also clears the ML-KEM component's shared secret alongside the traditional one on both the encapsulate and decapsulate paths - the copy handed back by getEncoded() was left in the heap - as section 3.5 of draft-ietf-lamps-pq-composite-kem requires.\u003c/li\u003e\n\u003cli\u003eCompositePublicKey.getAlgorithm() and CompositePrivateKey.getAlgorithm() returned null for all twelve Composite ML-KEM (draft-ietf-lamps-pq-composite-kem) parameter sets. Both classes resolved the name through the composite signature index only, which holds the composite ML-DSA OIDs, so a composite KEM key pair - generated, parsed from a certificate, or read from PKCS#8 - reported no algorithm at all, and the standard JCA idiom of reconstructing a key with KeyFactory.getInstance(key.getAlgorithm()) raised a NullPointerException. The lookup now falls back to the composite KEM index, so the name returned is the one the provider registers the algorithm under (e.g. MLKEM768-X25519-SHA3-256), matching the composite ML-DSA behaviour. The same single-index assumption made the CompositePublicKey(SubjectPublicKeyInfo) and CompositePrivateKey(PrivateKeyInfo) constructors reject a composite KEM key with \u0026quot;unable to create CompositePublicKey from SubjectPublicKeyInfo\u0026quot;; they now dispatch to the composite KEM key factory for those OIDs. Keys obtained through KeyFactory or through BouncyCastleProvider.getPublicKey / getPrivateKey were unaffected and are unchanged (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2404\"\u003e#2404\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe org.bouncycastle.jcajce.spec.KEMKDFSpec constructor stored a null otherInfo as given, so getOtherInfo() returned null, and three of the KDF branches KdfUtil.makeKeyBytes dispatches to - KMAC-128, KMAC-256 and SHAKE-256 - read the otherInfo length without a guard and threw NullPointerException out of the KEM operation, where the KDF2, KDF3 and HKDF branches tolerate a null through KDFParameters / HKDFParameters. The Builder of every spec in the package already mapped null to empty, so no provider path reached it, but the constructor is protected on a public class and KdfUtil is documented for callers building their own KEM integration; the deprecated KEMParameterSpec passes a null itself and escaped only because it also pins the KDF to null. The constructor now stores empty for a null, so getOtherInfo() never returns null, and a null and an explicitly empty otherInfo derive the same key.\u003c/li\u003e\n\u003cli\u003eQR-UOV signature verification accepted a signature encoding that was not canonical, so the encoding of a signature was not unique even after the trailing-byte fix of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e. Each F_q element of the signature is stored in ceil(log2 q) bits, one more bit pattern than the field has elements: q itself is representable and is arithmetically congruent to zero, so an element written as q verified exactly as the same element written as zero would, and the bits padding the last element out to the byte boundary were never read at all. Every zero element of a signature therefore carried a second encoding, and for the q = 7 parameter sets roughly one element in seven is zero - a single qruov_5_q7_L10 signature measured 256 spare bits, so on the order of 2^256 distinct byte strings verified for the one message and key. Verification now rejects any element outside [0, q) and any set padding bit; a signature produced by this or by the reference implementation is unaffected, as the KAT vectors of every parameter set confirm. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSNOVA signature verification ignored four bits inside the signature for any parameter set whose solution is an odd number of GF(16) nibbles - the SNOVA_24_5_5, SNOVA_25_8_3, SNOVA_29_6_5 and SNOVA_66_15_3 families, sixteen of the forty-four parameter sets. The last byte of the encoded solution carries a single nibble and the signer leaves the top four bits zero, but the decoder did not read them, so sixteen distinct byte strings verified for one signature. This is the same non-unique encoding github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e closed for bytes following the signature, applied inside it; the verifier now requires those bits to be zero. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSnovaPrivateKeyParameters did not validate the length of the private key encoding handed to it - the only one of the five schemes of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e that did not - and SnovaParameters.getPrivateKeyLength() reported the expanded (\u0026quot;ESK\u0026quot;) length even for a parameter set whose private key is the seed pair. A private key encoding reaches this constructor straight from a PKCS#8 blob, so a wrong length went undetected: a seed-form key with extra bytes appended was accepted and signed under a different derived key, and a short expanded-form key sized the signer's decode buffer negatively, throwing NegativeArraySizeException out of generateSignature() rather than being reported at construction. Related, the signing retry loop could not terminate: the vinegar values are derived from a single-byte counter, so only 256 distinct linear systems can be tried, and an expanded-form private key that is not a real central map is singular for all of them - generateSignature() then span forever rather than failing. The length is now checked at construction, getPrivateKeyLength() reports the length that parameter set's private key actually has, and the retry loop gives up after its 256 attempts as MAYO's does.\u003c/li\u003e\n\u003cli\u003eMayoSigner and MayoKeyPairGenerator did not clear several buffers holding secret key material that the MAYO reference implementation explicitly clears. Signing left the secret oil space O, the expanded L = (P1 + P1^t) * O + P2, and the M / VPV / Ox intermediates of the central map in place, having gone to the trouble of clearing eleven other buffers; key generation left the expanded seed, whose tail is the encoded oil space, and the P1 * O + P2 half of P; and the row-echelon step left the packed echelon form of the secret linear system and its pivot rows. Separately, if all 256 attempts at solving for the signature had given a rank-deficient system, signing emitted a signature built from the failed attempt's state instead of reporting the failure the reference returns, and AIMerSigner.generateSignature returned an empty array on failure, which a caller would hand on as though it were a signature. Both now throw.\u003c/li\u003e\n\u003cli\u003eFive PQC signature schemes - MAYO, SNOVA, QR-UOV, SQIsign and AIMer - returned the NIST crypto_sign \u0026quot;sm\u0026quot; signed-message envelope from generateSignature() rather than the signature. That envelope is an artefact of the reference KAT harness, which records the message alongside the signature so a vector file can be self-contained; it is not part of any of the five specifications, and no other BC signer emits it (Falcon's KAT test rebuilds the equivalent envelope in the test, which is where it belongs). Two consequences followed, both reaching the JCA Signature services of every parameter set of the five schemes in BouncyCastlePQCProvider. First, since the message was appended to the signature, verification had to skip whatever followed the signature proper, and it did so by checking only that the buffer was long enough - so any number of trailing bytes could be added to a valid signature, or the appended message replaced with unrelated data, and it still verified. A signature encoding was therefore not unique: anyone holding one valid signature could produce unlimited distinct byte strings that all verified for the same message and key, which breaks any use that treats the signature bytes as an identifier, deduplicates on them, or records them as evidence. Second, the envelope propagated into everything built on the operator layer: because ContentSigner hands the signature straight into the structure being signed, every X.509 certificate, CRL, CMS SignedData and TLS CertificateVerify BC produced with one of these algorithms carried a verbatim copy of the signed data inside its own signature field - a self-signed MAYO-1 certificate came to 3567 bytes where the same certificate is now 2020 - which no other implementation can parse as a signature, and which in a detached CMS signature meant the \u0026quot;detached\u0026quot; signature carried the content. generateSignature() now returns the bare signature, and verifySignature() requires exactly the parameter set's signature length, so appended or truncated data is rejected rather than ignored. \u003cstrong\u003eThis is a behavioural change for signatures produced by an earlier release\u003c/strong\u003e - MAYO and SNOVA from 1.84, QR-UOV, SQIsign and AIMer from 1.85 - which are no longer accepted in the envelope form they were emitted in; the signature bytes themselves are unchanged, so a stored value can be recovered by taking the leading signature-length bytes, or for AIMer, whose envelope was message || signature rather than signature || message, the trailing ones. The KAT tests now rebuild the envelope before comparing against the vector files, which continue to record it. Note that AIMer's verification had already been made length-exact during this cycle (see the entry below relating to github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2401\"\u003e#2401\u003c/a\u003e), so of the five only its envelope remained (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe MLS implementation did not bind an X.509 credential to the LeafNode's signature_key. LeafNode.verify() checked a leaf's signature against the signature_key declared in the leaf itself, while the X.509 credential's certificate chain was stored but never parsed or checked, so the certificate's public key was never required to match signature_key (RFC 9420 sec. 5.3). A leaf could therefore carry one party's certificate while being signed by an unrelated key and still be accepted under that party's identity through KeyPackage.verify() and the Group leaf-validation path. LeafNode.verify() now requires the end-entity certificate's subject public key, in the cipher suite's signature encoding, to equal signature_key for an X.509 credential, and rejects the leaf otherwise - including an empty chain or a certificate whose key type does not match the cipher suite; certificate-chain and identity validation to a trust anchor remain the application's responsibility per RFC 9420 sec. 5.3.1. A public org.bouncycastle.mls.codec.Certificate(byte[]) constructor and a Credential.getCertificates() accessor are added so callers can build and inspect X.509 credentials. Basic credentials are unaffected.\u003c/li\u003e\n\u003cli\u003eThe SecureRandom supplied to org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder.setSecureRandom() did not drive the content IV / nonce for any algorithm other than RC2. EnvelopedDataHelper.generateParameters passed the caller's SecureRandom to the AlgorithmParameterGenerator only in the RC2_CBC branch; every other content-encryption algorithm - AES-CBC, AES-GCM, AES-CCM, Camellia, ARIA, SEED and the rest - reached pGen.generateParameters() on an uninitialised generator, so the IV / nonce was drawn from a default SecureRandom and setSecureRandom() was silently ignored (the builder's javadoc states that random is used for IV/nonce generation). The generator is now initialised with the supplied random on the general path as well, so a caller who provides a specific randomness source - for a controlled or FIPS-approved DRBG, say - has it honoured for the content IV / nonce. The session-key generation path was unaffected and already used the supplied random. Because the content IV / nonce now comes from the supplied SecureRandom, the org.bouncycastle.crypto.util JournalingSecureRandom / JournaledAlgorithm reproducible-encryption support records it in the transcript: a resumed session reproduces the IV / nonce by regenerating it from the replayed randomness - build the resuming encryptor from the content-algorithm OID - rather than by reusing the AlgorithmIdentifier captured from the first encryption, which no longer keeps the transcript aligned.\u003c/li\u003e\n\u003cli\u003eThe NTRU LPRime, NTRU+ and SMAUG-T KEM generators threw a NullPointerException when constructed with a null SecureRandom, where every other KEM generator - including NTRU LPRime's own SNTRU Prime counterpart in the same package - defaults one through CryptoServicesRegistrar.getSecureRandom(). This is reachable from the lightweight API directly, and from javax.crypto.KEM, whose newEncapsulator() documents a null random as a request for the provider's default.\u003c/li\u003e\n\u003cli\u003eFrodoKEMEngine kept a single SHAKE instance in a field, so an engine reached concurrently produced wrong results. It is reached that way through org.bouncycastle.crypto.kems.FrodoKEMExtractor, which holds one engine for its lifetime: two threads extracting through one extractor interleaved the digest's absorb and squeeze phases, yielding shared secrets that silently did not match the sender's, or an IllegalStateException of \u0026quot;attempt to absorb while squeezing\u0026quot; from inside extractSecret. The digest is now built per call, as CMCEEngine's already was, which makes an extractor safe to share. Encapsulation was unaffected, since FrodoKEMGenerator builds an engine per call. Results for any single-threaded use are unchanged - the reference KAT vectors are byte-identical.\u003c/li\u003e\n\u003cli\u003eThe BCJSSE provider carried the TLS 1.2 coupling between the supported_groups extension and ECDSA over into TLS 1.3: an ECDSA signature scheme was treated as usable - offered in the signature_algorithms and signature_algorithms_cert extensions, and eligible when selecting the local credentials - only while the corresponding curve was among the named groups enabled for key exchange, both per context (a group unavailable for key agreement disabled the scheme outright) and per connection (the curve had to be in the supported_groups list about to be sent). RFC 8446 sec. 4.2.7 scopes supported_groups to key exchange only, with signature algorithms negotiated independently (sec. 4.2.3), so this incorrect restriction in TLS 1.3 has been removed. Ed25519, Ed448 and the RSA schemes were unaffected (as well as typical deployments using a default configuration for named groups).\u003c/li\u003e\n\u003cli\u003eThe bcmail module descriptor did not declare its javax.mail/javax.activation dependences, so a modular (module-path) consumer of the jar hit IllegalAccessError/module-resolution failures when the S/MIME classes touched the mail API. The descriptor now requires them optionally (requires static) under all four module names those libraries are known by - the automatic names mail and activation carried by the javax.mail:mail / javax.activation:activation artifacts, and the explicit names java.mail and java.activation carried by the newer com.sun.mail / com.sun.activation ones - a hard requires on any one name would break users of the others (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2389\"\u003e#2389\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFour type-coercion helpers in the OER / IEEE 1609.2 (ITS) decoder tested the wrong type in the identity fast path that lets a getInstance() factory return an argument that is already of the target type. org.bouncycastle.oer.its.ieee1609dot2.basetypes.UINT32.getInstance and org.bouncycastle.oer.its.etsi102941.basetypes.Version.getInstance guarded on UINT8 - a sibling of UINT32 under UintBase, and unrelated to Version - so passing a UINT8 threw ClassCastException, while passing an actual UINT32 or Version missed the fast path and fell through to ASN1Integer.getInstance, which rejects them: neither factory accepted its own type. org.bouncycastle.oer.its.etsi103097.EtsiTs103097DataEncryptedUnicast.getInstance guarded on its sibling EtsiTs103097DataEncrypted and then cast to the unicast type, so an EtsiTs103097DataEncrypted threw ClassCastException. org.bouncycastle.oer.OEROptional.getObject(Class) called value.getClass().isInstance(type) with the arguments transposed, which is always false because the argument is a java.lang.Class, so the cast path was dead and every optional field was resolved reflectively, failing with IllegalStateException for a target type with no static getInstance. Each guard now names the type it returns, matching the sibling UINT8 / UINT16 / UINT64 and EtsiTs103097DataEncrypted factories (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2373\"\u003e#2373\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eDefaultAlgorithmNameFinder and DefaultSignatureNameFinder had no entries at all for the ShangMi algorithms, so an SM2 signature AlgorithmIdentifier that DefaultSignatureAlgorithmIdentifierFinder itself produces came back named only by its OID string - getAlgorithmName(GMObjectIdentifiers.sm2sign_with_sm3) returned \u0026quot;1.2.156.10197.1.501\u0026quot; and hasAlgorithmName returned false. Both finders now name sm2sign_with_sm3 as SM3WITHSM2 and sm2sign_with_sha256 as SHA256WITHSM2, and DefaultAlgorithmNameFinder additionally names the sm3 digest. All three resolve through the BC provider, as Signature and MessageDigest respectively. The remaining GM arc - the SM4 cipher modes, the sm2encrypt variants, and the SM1 / SM6 / SSF33 ciphers BC does not implement - is still unnamed (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2377\"\u003e#2377\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe RFC 4998 evidence-record classes compared the digest AlgorithmIdentifier named by a time-stamp authority with the one their own DigestCalculator uses, and did so with AlgorithmIdentifier.equals(), which compares the encodings. A TSA that names SHA-256 with an explicit NULL parameters field - DigiCert among them - therefore failed against BC's own calculator, which names it with the parameters absent, and ERSArchiveTimeStampGenerator.generateArchiveTimeStamp rejected the response with \u0026quot;time stamp imprint for wrong algorithm\u0026quot;. Both spellings name the same digest and RFC 5754 sec. 2 requires a receiver to accept either, while requiring that identifiers be generated with the parameters absent, which BC already does. The three affected comparisons - the two in ERSArchiveTimeStampGenerator and the digest check in ERSEvidenceRecord.renew - now use the new AlgorithmIdentifier.areEquivalent, which matches on the algorithm and treats an absent parameters field and NULL as the same, and the consistency check across an evidence record's archive time stamp chain uses it too. An identifier carrying an actual parameter structure is never equivalent to one carrying none (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2379\"\u003e#2379\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eEDIPartyName.toASN1Primitive emitted the nameAssigner and partyName DirectoryStrings without their context tags, so an EDIPartyName built through its public constructor could not be parsed back by EDIPartyName.getInstance, which correctly requires them. RFC 5280 sec. 4.2.1.6 tags both members [0] and [1], and those tags are explicit despite the module's IMPLICIT TAGS because DirectoryString is a CHOICE, which X.680 does not allow to be tagged implicitly - the decoder already had this right. The encoder now matches it. Note the type was added during the 1.85 cycle and GeneralName validates its ediPartyName alternative through it, so a GeneralName carrying an untagged ediPartyName - including one BC itself produced - is rejected where 1.84 passed it through unexamined; the untagged form is not read leniently (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2380\"\u003e#2380\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eRSASSA-PSS could not be used with a RIPEMD digest through the JCA API. Nothing registered the RIPEMD PSS signatures, so Signature.getInstance(\u0026quot;RIPEMD160WITHRSAANDMGF1\u0026quot;) raised NoSuchAlgorithmException, and the generic RSASSA-PSS route with an explicit PSSParameterSpec failed too: org.bouncycastle.jcajce.provider.util.DigestFactory.getDigest returned null for a RIPEMD name, and isSameDigest - an allow-list of the SHA families and MD5 - reported two identical RIPEMD names as different digests, so the spec was rejected with \u0026quot;digest algorithm for MGF should be the same as for PSS parameters\u0026quot;. isSameDigest now answers true for equal names whatever the digest, which also covers Whirlpool, SM3, GOST3411 and anything else outside that allow-list; DigestFactory recognises RIPEMD128, RIPEMD160 and RIPEMD256 by name and OID; the three PSS signatures are registered with MGF1 over the same digest and a salt of the digest length; and DefaultSignatureAlgorithmIdentifierFinder gains the matching RIPEMD*WITHRSAANDMGF1 entries with their RSASSA-PSS-params, so the operator/JcaContentSignerBuilder path works as well. Note BC continues to require the PSS hash and the MGF1 hash to be the same, which RFC 8017 does not itself demand (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2381\"\u003e#2381\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe opt-in key-size validation on CMS key-transport recipients (org.bouncycastle.cms.jcajce.JceKeyTransRecipient.setKeySizeValidation(true)) never ran for a message using RFC 9709 CEK derivation (id-alg-cek-hkdf-sha256): the branch that should have selected the actual content-encryption algorithm carried in the KDF AlgorithmIdentifier's parameters compared the encrypted-key byte array against the id-alg-cek-hkdf-sha256 object identifier - a comparison that is always false - so the check fell through to a key-size lookup on the outer KDF OID, which has no registered key size, and silently checked nothing. A key-transport EnvelopedData/AuthEnvelopedData whose transported (and HKDF-derived) content-encryption key did not match the key size of the advertised content-encryption algorithm was therefore accepted even with validation enabled. The recipient now dispatches on the content-encryption AlgorithmIdentifier's algorithm OID, so key-size validation of RFC 9709 messages checks the recovered key against the inner content-encryption algorithm. Messages with a matching key size, non-HKDF messages, and recipients that do not enable validation are unaffected.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003eSee full diff in \u003ca href=\"https://github.com/bcgit/bc-java/commits\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003ecommonmark-java 0.29.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e[0.29.0] - 2026-06-20\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/42b4fb7adfe288ef13e9e27ab20aff7e91b0ab9d\"\u003e\u003ccode\u003e42b4fb7\u003c/code\u003e\u003c/a\u003e Prepare CHANGELOG for version 0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/b76e09d7a8362abb5f04e1d6b91dbd6da279a6fc\"\u003e\u003ccode\u003eb76e09d\u003c/code\u003e\u003c/a\u003e Limit how deep inline nodes may nest by default (100)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/49f65cb5cbec93cff713179990307145198e7061\"\u003e\u003ccode\u003e49f65cb\u003c/code\u003e\u003c/a\u003e Fix StackOverflowEr...\n\n_Description has been truncated_","html_url":"https://github.com/ifabrish/openclaw-ifabrish-/pull/31","url":"https://dependabot.ecosyste.ms/api/v1/hosts/GitHub/repositories/ifabrish%2Fopenclaw-ifabrish-/issues/31","packages_url":"https://dependabot.ecosyste.ms/api/v1/issues/31/packages"}},{"old_version":"5.3.2","new_version":"5.5.0","update_type":"minor","path":null,"pr_created_at":"2026-09-09T19:37:22.000Z","version_change":"5.3.2 → 5.5.0","issue":{"uuid":"5403922362","node_id":"PR_kwDOTB6pPc8AAAABC4wjig","number":31,"state":"closed","title":"chore(deps): bump the android-deps group across 1 directory with 16 updates","user":"dependabot[bot]","labels":["dependencies","java"],"assignees":[],"locked":false,"comments_count":1,"pull_request":true,"closed_at":"2026-09-11T19:35:06.000Z","author_association":null,"state_reason":null,"created_at":"2026-09-09T19:37:22.000Z","updated_at":"2026-09-11T19:35:08.000Z","time_to_close":172664,"merged_at":null,"merged_by":null,"closed_by":null,"dependency_metadata":{"prefix":"chore(deps): bump","group_name":"android-deps","update_count":16,"packages":[{"name":"gradle-wrapper","old_version":"9.5.1","new_version":"9.7.1","repository_url":"https://github.com/gradle/gradle"},{"name":"org.bouncycastle:bcprov-jdk18on","old_version":"1.84","new_version":"1.85.2","repository_url":"https://github.com/bcgit/bc-java"},{"name":"org.commonmark:commonmark","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-autolink","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-strikethrough","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-tables","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-task-list-items","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.junit.vintage:junit-vintage-engine","old_version":"6.1.0","new_version":"6.1.3","repository_url":"https://github.com/junit-team/junit-framework"},{"name":"io.kotest:kotest-assertions-core-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"io.kotest:kotest-runner-junit5-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"com.squareup.okhttp3:mockwebserver","old_version":"5.3.2","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.squareup.okhttp3:okhttp","old_version":"5.3.2","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.android.application","old_version":"9.2.1","new_version":"9.4.0"},{"name":"com.android.test","old_version":"9.2.1","new_version":"9.4.0"},{"name":"org.jetbrains.kotlin.plugin.compose","old_version":"2.4.0","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"},{"name":"org.jetbrains.kotlin.plugin.serialization","old_version":"2.4.0","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"}],"path":null,"ecosystem":"maven"},"body":"Bumps the android-deps group with 16 updates in the /apps/android directory:\n\n| Package | From | To |\n| --- | --- | --- |\n| [gradle-wrapper](https://github.com/gradle/gradle) | `9.5.1` | `9.7.1` |\n| [org.bouncycastle:bcprov-jdk18on](https://github.com/bcgit/bc-java) | `1.84` | `1.85.2` |\n| [org.commonmark:commonmark](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-autolink](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-strikethrough](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-tables](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-task-list-items](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.junit.vintage:junit-vintage-engine](https://github.com/junit-team/junit-framework) | `6.1.0` | `6.1.3` |\n| [io.kotest:kotest-assertions-core-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [io.kotest:kotest-runner-junit5-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [com.squareup.okhttp3:mockwebserver](https://github.com/lysine-dev/okhttp) | `5.3.2` | `5.5.0` |\n| [com.squareup.okhttp3:okhttp](https://github.com/lysine-dev/okhttp) | `5.3.2` | `5.5.0` |\n| com.android.application | `9.2.1` | `9.4.0` |\n| com.android.test | `9.2.1` | `9.4.0` |\n| [org.jetbrains.kotlin.plugin.compose](https://github.com/JetBrains/kotlin) | `2.4.0` | `2.4.20` |\n| [org.jetbrains.kotlin.plugin.serialization](https://github.com/JetBrains/kotlin) | `2.4.0` | `2.4.20` |\n\n\nUpdates `gradle-wrapper` from 9.5.1 to 9.7.1\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/gradle/gradle/releases\"\u003egradle-wrapper's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e9.7.1\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.1.\u003c/p\u003e\n\u003cp\u003eThis is a patch release for 9.7.0. We recommend using 9.7.1 instead of 9.7.0.\u003c/p\u003e\n\u003cp\u003eHere are the highlights of 9.7.0 release:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIsolated Projects graduates to incubating\u003c/li\u003e\n\u003cli\u003eBroader Configuration Cache compatibility\u003c/li\u003e\n\u003cli\u003eResilient Sync helps you fix broken builds\u003c/li\u003e\n\u003cli\u003eMore source locations in problem reports\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003ca href=\"https://docs.gradle.org/9.7.1/release-notes.html\"\u003eRead the Release Notes\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eWe would like to thank the following community members for their contributions to this release of Gradle:\n\u003ca href=\"https://github.com/aSemy\"\u003eAdam\u003c/a\u003e,\n\u003ca href=\"https://github.com/Gautam-aman\"\u003eAman Gautam\u003c/a\u003e,\n\u003ca href=\"https://github.com/YukiCodepth\"\u003eAman Kumar\u003c/a\u003e,\n\u003ca href=\"https://github.com/adubrouski\"\u003eAnton Dubrouski\u003c/a\u003e,\n\u003ca href=\"https://github.com/liutikas\"\u003eAurimas\u003c/a\u003e,\n\u003ca href=\"https://github.com/gbhavya07\"\u003egbhavya07\u003c/a\u003e,\n\u003ca href=\"https://github.com/joshfriend\"\u003eJosh Friend\u003c/a\u003e,\n\u003ca href=\"https://github.com/nicklauslittle-gov\"\u003enicklauslittle-gov\u003c/a\u003e,\n\u003ca href=\"https://github.com/psoni674\"\u003ePragati\u003c/a\u003e,\n\u003ca href=\"https://github.com/Project516\"\u003eproject516\u003c/a\u003e,\n\u003ca href=\"https://github.com/Uomocapra\"\u003eQin Mi\u003c/a\u003e,\n\u003ca href=\"https://github.com/rkdfx\"\u003eRavi\u003c/a\u003e,\n\u003ca href=\"https://github.com/sk-reddy17\"\u003esk-reddy17\u003c/a\u003e,\n\u003ca href=\"https://github.com/Suvrat1629\"\u003eSuvrat Acharya\u003c/a\u003e,\n\u003ca href=\"https://github.com/ShreckYe\"\u003eYongshun Ye\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eUpgrade instructions\u003c/h2\u003e\n\u003cp\u003eSwitch your build to use Gradle 9.7.1 by updating your wrapper:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e./gradlew :wrapper --gradle-version=9.7.1 \u0026amp;\u0026amp; ./gradlew :wrapper\r\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eSee the Gradle \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/upgrading_version_9.html\"\u003e9.x upgrade guide\u003c/a\u003e to learn about deprecations, breaking changes and other considerations when upgrading.\u003c/p\u003e\n\u003cp\u003eFor Java, Groovy, Kotlin and Android compatibility, see the \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/compatibility.html\"\u003efull compatibility notes\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eReporting problems\u003c/h2\u003e\n\u003cp\u003eIf you find a problem with this release, please file a bug on \u003ca href=\"https://github.com/gradle/gradle/issues\"\u003eGitHub Issues\u003c/a\u003e adhering to our issue guidelines.\nIf you're not sure you're encountering a bug, please use the \u003ca href=\"https://discuss.gradle.org/c/help-discuss\"\u003eforum\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eWe hope you will build happiness with Gradle, and we look forward to your feedback via \u003ca href=\"https://twitter.com/gradle\"\u003eTwitter\u003c/a\u003e or on \u003ca href=\"https://github.com/gradle\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003e9.7.0\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.0.\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/92f0512e7f06d84621afba191f75e265363890cf\"\u003e\u003ccode\u003e92f0512\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38892\"\u003e#38892\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/820ee75a99a179bbffa41bcedc6477b685fabb9f\"\u003e\u003ccode\u003e820ee75\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/82c23f9bd2a89b4cc644e1f90a28a8668feb3dee\"\u003e\u003ccode\u003e82c23f9\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering problem in KTS (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38878\"\u003e#38878\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/ef11a7268fe8cc8d6ab849ec911aa11220180553\"\u003e\u003ccode\u003eef11a72\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering issue\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/bb0d8a974a71b1003efea41e4046e98855cd5ff8\"\u003e\u003ccode\u003ebb0d8a9\u003c/code\u003e\u003c/a\u003e Make relevant tests polyglot (run for multiple DSLs)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/336e129d7f95c03486acafc97abf59734acfed48\"\u003e\u003ccode\u003e336e129\u003c/code\u003e\u003c/a\u003e Update signing configuration (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38874\"\u003e#38874\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/4bdf0da2dad9884d089a6062a45ea7183e7d735d\"\u003e\u003ccode\u003e4bdf0da\u003c/code\u003e\u003c/a\u003e Update signing configuration\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/cd9b92c1b82856248cf1dc58b50378238bec7b52\"\u003e\u003ccode\u003ecd9b92c\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38839\"\u003e#38839\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/5f4e381964897ad8d6b99e5a7c77f26dba3259fb\"\u003e\u003ccode\u003e5f4e381\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/1e08ab551367aeb5fb48b26e72807e1d2b27c939\"\u003e\u003ccode\u003e1e08ab5\u003c/code\u003e\u003c/a\u003e Keep type-use annotations in extracted ABI classes (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38810\"\u003e#38810\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/gradle/gradle/compare/v9.5.1...v9.7.1\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.bouncycastle:bcprov-jdk18on` from 1.84 to 1.85.2\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.md\"\u003eorg.bouncycastle:bcprov-jdk18on's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch1\u003eBouncy Castle Crypto Package - Release Notes\u003c/h1\u003e\n\u003ch2\u003e1.0 Introduction\u003c/h2\u003e\n\u003cp\u003eThe Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. The package is organised so that it contains a light-weight API suitable for use in any environment (including the J2ME) with the additional infrastructure to conform the algorithms to the JCE framework.\u003c/p\u003e\n\u003ch2\u003e2.0 Release History\u003c/h2\u003e\n\u003cp\u003e\u003c!-- raw HTML omitted --\u003e\u003c!-- raw HTML omitted --\u003e\u003c/p\u003e\n\u003ch3\u003e2.1.1 Version\u003c/h3\u003e\n\u003cp\u003eRelease: 1.86\u003cbr /\u003e\nDate: 2026, TBD\u003c/p\u003e\n\u003ch3\u003e2.1.2 Defects Fixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) let a subkey inherit the primary key's Key Flags when its own Subkey Binding signature carried no Key Flags subpacket, which made the two capability decisions taken for one subkey disagree. OpenPGPCertificate.OpenPGPComponentKey.isSigningKey() reads the effective flags, which fell back to the primary key's direct-key or primary user ID self-signature, so a subkey bound with no flags of its own counted as signing-capable; verifyEmbeddedPrimaryKeyBinding reads the binding signature's own flags, found no signing capability there, and so skipped the embedded Primary Key Binding (cross-certification) signature that RFC 9580 sec. 5.2.1.8 and sec. 10.1.3 require of a subkey that can issue signatures. A data signature made by such a subkey was therefore attributed to the certificate and reported valid by OpenPGPSignature.OpenPGPDocumentSignature.isValid() with the cross-certification requirement never applied, where GnuPG refuses the same certificate and message as not cross-certified. An attacker holding a third party's public signing subkey - which is public material - could bind it to their own primary key with a Subkey Binding signature they are able to make, carrying no Key Flags and no embedded Primary Key Binding signature, which they cannot make without the subkey's private key, and have that party's genuine signatures verify as valid under the attacker's own identity: misattribution of a real signature rather than a forgery of a new one, since the signature still has to be one the subkey actually made. Key Flags are a statement about the key the carrying signature refers to (RFC 9580 sec. 5.2.3.29), so a subkey no longer inherits them from the certificate-wide signatures of the primary key: a Subkey Binding signature that omits the subpacket now leaves the subkey with no capabilities rather than the primary's, which makes the flags the cross-certification check consults the same flags every other decision consults. Preferences and the other subpackets a direct-key signature carries are inherited as before, and the primary key itself - whose flags legitimately come from its direct-key or user ID self-signature - is unaffected. The low-level PGPSignature / PGPPublicKeyRing API performs no binding checks by design and is unchanged.\u003c/li\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) used a version 6 key that carried no valid Direct Key signature, falling back to the primary user ID binding as it correctly does for a version 4 key. RFC 9580 sec. 5.2.3.10 requires the opposite: \u0026quot;An implementation MUST ensure that a valid Direct Key signature is present before using a version 6 key. This prevents certain attacks where an adversary strips a self-signature specifying a Key Expiration Time or certain preferences.\u0026quot; The certificate grammar says the same structurally, the Direct Key signature being mandatory in the version 6 structure of sec. 10.1.1 and optional in the version 4 one of sec. 10.1.3. Because a version 6 certificate carries its key expiration, features and algorithm preferences on the Direct Key signature - the convention the RFC recommends and the one OpenPGPKeyGenerator follows, its user ID certification carrying no expiration at all - removing that single signature packet from a published certificate silently dropped the expiration along with the preferences and features: OpenPGPCertificate.getSignatureChainFor fell back to the user ID binding, the primary key was still reported bound, and getEncryptionKeys() and getSigningKeys() went on returning the subkeys of a key whose owner had set it to expire. The primary key fingerprint is unchanged by the removal, so a relying party pinning the key by fingerprint still treats it as the same key, and no private key or hash collision is involved; the natural moment for the strip is the key refresh that RFC 9580 names as the reason to refetch a key at all - to learn about changes in expiration, features, preferences and revocation - which is exactly the update it defeats. This is a downgrade rather than a forgery, nothing being attributed to a key that did not authorise it, and the concerning direction is encryption, to a key meant to have been retired. OpenPGPCertificate.isBoundBy now requires a valid Direct Key self-signature on a version 6 primary key before any component of the certificate - the primary key, its subkeys or its identities - is treated as bound, so a version 6 certificate stripped of it offers no keys at all rather than an unexpiring set. Version 4 certificates are unaffected: there the key expiration legitimately lives on the user ID self-signature and the fallback is correct, so it stays. The revocation-only version 6 certificate of sec. 10.1.2, which legitimately carries no Direct Key signature, is unaffected as well - its key was already refused as revoked, and reading the revocation does not go through the binding check.\u003c/li\u003e\n\u003cli\u003eThe lightweight LMSSigner and HSSSigner refused a key wrapped in ParametersWithRandom, which is how BcContentSignerBuilder passes a key whenever setSecureRandom() has been called - so BcHssLmsContentSignerBuilder built a working signer until a random was set and then failed with \u0026quot;Incorrect Key Parameters\u0026quot;, and the two signers themselves raised ClassCastException on the same input. All three now unwrap it, as the promoted ML-DSA and SLH-DSA signers already did. The random is accepted and not used: LMS derives its message randomiser C from the key's seed and the one-time index, so it is deterministic and cannot repeat while q does not. Note SP 800-208 sec. 6.1 asks for C to come from an approved random bit generator, which this implementation does not do; that is unchanged here, and a supplied random is now ignored rather than refused.\u003c/li\u003e\n\u003cli\u003eLMS signature verification did not apply two of the checks RFC 8554 sec. 5.4.2 requires before a signature is processed. Step 2g refuses a signature whose LMS typecode is not the one from the public key, and without it the path computation took its height and tree digest from the parameter set the signature named rather than the key's, so a signature claiming a height-25 parameter set drove a 25-level computation against a height-5 key. Step 2i refuses a leaf number q outside the tree, and without it an out-of-range q flowed into the node arithmetic and was left for the candidate-root comparison to catch. Neither was a forgery - the domain separation between D_LEAF and D_INTR and the final comparison saw to that - but both are attacker-chosen work the specification says to refuse up front. Both are now checked, and a signature failing either is still reported as not verifying rather than thrown out of Signature.verify(). The catch around the signature decode in LMSSigner and HSSSigner has also been narrowed to the decode itself, as the corresponding SPI was corrected to do for github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2408\"\u003e#2408\u003c/a\u003e: past the parse the engine reports an inconsistent signature by returning false rather than by throwing, so the wider catch caught nothing while standing ready to turn a future internal error into a quiet false.\u003c/li\u003e\n\u003cli\u003eThe LMS and HSS key parameter classes now apply at construction the checks their decoders apply, so a key built directly cannot be one the decoder would refuse. LMSPrivateKeyParameters accepted an identifier of any length although the decoder reads exactly 16 bytes - such a key encoded but could not be read back - and left q, maxQ and the seed length unchecked; the seed is now required to be at least m bytes at decode as well, where a one-byte seed had been decoding silently and then deriving every one-time key from it. HSSPrivateKeyParameters checked neither its level count nor that it had been given a component key per level and a chaining signature per level below the root, and then indexed both lists, so a mismatch surfaced as IndexOutOfBoundsException - or, where a level happened to match, as a null chaining signature that only failed at signing time; the level is now checked after the reset that fills it in, since a null is legitimate on the way in. LMSPrivateKeyParameters.getInstance(byte[], byte[]) adopted the public key supplied beside the private one without comparing them, so a mismatched public key was simply reported by getPublicKey(); it now cross-checks the identifier, both parameter sets and, where the tree cache already holds it, the root, as the HSS entry point does. The decoders also now report a bad version or seed length as IOException rather than IllegalStateException, so a caller can catch one type for a malformed key, and the package-private LM-OTS public key decoder no longer declares throws Exception or dereferences an unrecognised typecode. The deprecated org.bouncycastle.pqc.crypto.lms copies carry the decoder corrections.\u003c/li\u003e\n\u003cli\u003eIn the LMS JCE layer, LMSKeyGenParameterSpec.fromNames knew all twenty LMS parameter-set names but only four of the sixteen LM-OTS ones, so none of the SP 800-208 n24 or SHAKE sets could be named; all sixteen are now present. KeyPairGenerator.initialize(int, SecureRandom) reports InvalidParameterException, which is what the JCA specifies and which extends the IllegalArgumentException it raised before, so existing catches still match. BCLMSPrivateKey.getIndex now takes the exhaustion check and the index read under the key's own monitor rather than as two separate calls, and two unused fields have gone from LMSSignatureSpi. Note that the LMS Signature claims its one-time key at the first update() rather than at sign(), so a Signature that is initialised and updated and then abandoned spends an index without producing a signature - the safe direction for a one-time scheme, and now documented on the SPI.\u003c/li\u003e\n\u003cli\u003eEvery other key pair generator that refuses a key size did the same thing the LMS one did above. KeyPairGenerator.initialize(int, SecureRandom) is documented to raise InvalidParameterException when the key size is not one the generator supports, and thirty of them raised a bare IllegalArgumentException instead, so a caller following the JCA and catching the documented type saw an exception escaping rather than a refusal. The ML-DSA, ML-KEM, SLH-DSA, Classic McEliece, FrodoKEM, NTRU and composite signature and KEM generators in the BC provider, and every generator in BCPQC, now raise InvalidParameterException - NewHope included, where the value is a key size it will not take rather than a mode of initialisation it does not offer. InvalidParameterException extends IllegalArgumentException, so callers written against the old behaviour go on catching it unchanged. The two RSA generators are corrected as well, and differently: theirs is a key size below a floor rather than a mode of initialisation they do not offer, and the refusal is raised by the lightweight RSAKeyGenerationParameters, which cannot name a java.security exception at all, so the RSA KeyPairGeneratorSpi now translates it - keeping the message verbatim and the original exception as the cause, through a new SecurityExceptions.invalidParameterException factory, since InvalidParameterException has no constructor that takes one. Of the 304 KeyPairGenerator services the two providers register, 299 now refuse a nonsense key size the way the JCA defines it and five accept it as a strength they can work with, with none left raising a bare IllegalArgumentException; that is asserted as a sweep over both providers rather than per algorithm, so a generator added later is covered without the test being touched. The jdk1.3 provider overlays of the four generators that have one carry the same change, and the jdk1.3 SecurityExceptions overlay gains the new factory along with the invalidAlgorithmParameterException one it had been missing.\u003c/li\u003e\n\u003cli\u003eKeyPairGenerator.initialize(AlgorithmParameterSpec, SecureRandom) had the same shape of problem as the int overload above, and only 44 of the 304 services the two providers register reported an unusable spec as the InvalidAlgorithmParameterException that method declares. The twenty-three PQC generators that resolve a parameter set by name - cmce, frodokem, mldsa, mlkem, slhdsa, aimer, bike, faest, falcon, haetae, hqc, mayo, mqom, ntru, ntruplus, both ntruprime variants, qruov, saber, sdith, smaugt, snova and sqisign, 230 services between them - case-folded the name they got back from the spec without checking it, so a spec with no getName() method, and a null spec, produced a NullPointerException from inside the fold; their own \u0026quot;is this name one I know\u0026quot; branch, which does report the declared exception, was unreachable. The two composite generators, whose parameter set is fixed by the algorithm name so that null is the only spec they accept, refused every other one with IllegalArgumentException. RSA answered correctly for a spec of the wrong type but not for one of the right type carrying values its lightweight parameters will not take - an even public exponent, or a key size below the floor - which is now translated the same way the int overload's is. All 304 services now report the declared exception, with the composites still taking the null spec that is right for them; note that InvalidAlgorithmParameterException is a checked exception and not an IllegalArgumentException, so a caller that was catching what these threw before has to catch the declared type instead.\u003c/li\u003e\n\u003cli\u003eAn HSS private key claimed the two records of its position under two different monitors. The top-level index and the bottom component key's one-time index q are independent records of the same position - the decoder requires them to agree, see the entry below - but generateLMSContext incremented the index under the HSS key's own monitor, released it, and only then claimed q under the component key's. A getEncoded() issued in between saw the index advanced and q not, and produced an encoding this implementation's own decoder rejects; and two threads meeting at a bottom-tree boundary could both pass the exhaustion test, take consecutive top-level indices and claim the same q, after which one of them was refused with \u0026quot;ots private key exhausted\u0026quot; by a key still reporting usages remaining, a top-level index had been spent with no signature made, and the two records stayed one apart for the rest of the key's life in that process - so it could no longer be encoded, cloned or sharded, and getIndex() and getUsagesRemaining() misreported by one. No one-time key was reused: the component key's claim is itself atomic, and the divergence runs index ahead of leaves, so the effect was on the key's usability rather than on the signatures it had made. Both records are now claimed under the one monitor, and the component key is claimed before the index is incremented so that an exhausted one leaves both untouched. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the same correction.\u003c/li\u003e\n\u003cli\u003eTimeStampToken parsed the attacker-controlled TSTInfo content of a time-stamp token (org.bouncycastle.tsp.TimeStampToken, reached from TimeStampResponse(byte[]) and (InputStream)) inside a try that caught only CMSException, so a well-formed RFC 3161 TimeStampResp whose embedded token carried a malformed TSTInfo - a SEQUENCE with fewer elements than the five mandatory fields, a non-SEQUENCE, truncated DER, or an unknown context tag - let an IllegalArgumentException or a NoSuchElementException escape the constructor's declared throws TSPException, IOException contract. A token signed by no signers or by more than one raised a bare IllegalArgumentException from the same constructor, before that try, for the same reason. Both are now reported as TSPException, matching the package-private TimeStampResponse(DLSequence) constructor and the existing getSignedAttributes guard in the same method; the signer-count refusal is a TSPValidationException, as the neighbouring check on the content type already was. Related, and the cause of the NoSuchElementException: asn1.tsp.TSTInfo read its five mandatory fields off the sequence with no bound on how many elements were actually there, so a short SEQUENCE left the enumeration to run out rather than being refused, and an oversize one was accepted with its extra elements absorbed into the optional slots. Decode now requires the five to ten elements RFC 3161 sec. 2.4.2 gives the type, which is what the sibling Accuracy and ArchiveTimeStamp decoders already did, so the failure is the IllegalArgumentException that getInstance is expected to raise (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2415\"\u003e#2415\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eNeither the HSS nor the XMSS^MT private key decoder checked its declared index against the traversal state stored beside it, although the two are independent records of the same position in the key and so can be compared. For HSS the records are the top-level index and the component keys' one-time indices q; for XMSS^MT they are the global index and the per-layer BDS states. A stored key whose index had been rolled back while its state stayed advanced - a partial write, a restore from backup, a buggy storage layer - was therefore accepted, and it then signed a second message under a one-time key the key had already used, producing a signature that verified, so nothing anywhere surfaced the reuse. RFC 8554 sec. 1 and RFC 8391 sec. 1.1 both require each one-time key to be used exactly once, and this is the failure those requirements exist to prevent; the single-tree XMSS decoder has tied its BDS state to its index since that state was first validated, and this brings the two multi-tree schemes into line. HSS decode now requires the declared index to equal the position the component q values imply - a level above the last contributes (q - 1) leaves of the levels beneath it, since its q has already advanced past the subtree it signed - and XMSS^MT decode now requires each present layer's BDS index to equal the leaf index that layer derives from the global index, allowing the one position where a layer has moved into a new subtree and its state legitimately still carries the previous subtree's final index. A layer with no state yet is unaffected, since those are built lazily at signing time. Related, and the same shape of omission: an XMSS or XMSS^MT private key encoding carries the tree root twice - the key's own root field and the root node of the BDS state stored beside it, which for XMSS^MT is the top layer's - and the two were never compared either. A corrupted root was accepted and then poisoned every signature the key made, because the root is hashed into the message digest: the signature did not verify and nothing indicated why. Decode now requires the two copies to agree. The BDS node values themselves are not checkable the way the LMS tree cache above is - a BDS authentication path, stack, retain or keep node does not have its children stored alongside it, so recomputing one means building a subtree, which is the work the state exists to avoid. Both checks are integer comparisons over the levels of the key, too small to measure against the surrounding decode, and both were verified not to reject any legitimate key by walking every index a key can reach: the full key space of the two-level HSS and the h=4/d=2, h=6/d=2, h=6/d=3, h=9/d=3 and h=8/d=4 XMSS^MT parameter sets, plus a three-level HSS key across a subtree boundary and an HSS shard. Since those node values cannot be recomputed, the encoded state now carries a checksum over itself instead, with the owning key's public seed hashed in front of it. Any corruption of the stored state is refused at decode rather than being loaded and then producing signatures that silently do not verify, and because the public seed is bound in, a state transplanted between two keys of the same parameter set is refused too, even though it is internally consistent and arrives with its own matching root. The public seed is bound rather than the secret seed or the PRF key deliberately: the state's own root and index are inside the encoding and so are already covered, hashing secret material would make the stored checksum a commitment to it for no gain in detection, and the PRF key does not influence the state at all. \u003cstrong\u003eThis is an error-detecting code and not integrity protection\u003c/strong\u003e - anyone able to rewrite the stored key recomputes it, so it establishes that the state is unchanged since it was written, never that it was correct when written, and the allocation bounds on the encoding remain the guard against a crafted one. It costs one SHA-256 over the state, measured at 5 to 8 microseconds each way for the h=10 and h=16 parameter sets, and 32 bytes of encoding. The state encoding was added earlier in this same cycle and has not been released, so the checksum is simply part of it rather than a new version: a state written by a 1.86 beta is rejected, which is recovered from by re-exporting the key. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the HSS check as well (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2414\"\u003e#2414\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe S/MIME example smoke test in the misc module (org.bouncycastle.mail.smime.examples.test.AllTests) drove SendSignedAndEncryptedMail against smtp.gmail.com, and that example finishes with Transport.send() under JavaMail's default settings, which have no connect timeout. Where outbound port 25 is refused the failure was swallowed and the test passed; where it is silently dropped, as on many home networks, the connect blocked and ./gradlew build hung in :misc:test indefinitely with \u0026quot;0 tests completed\u0026quot;. The test now delivers to an SMTP stub on a loopback port, with connect / read / write timeouts as a backstop, and asserts the message arrived (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2407\"\u003e#2407\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation took the traditional component public key bytes it feeds the KEM combiner from the recipient key's own encoding, while decapsulation recomputes the point from the private key and so always produced an uncompressed one. Section 4 of draft-ietf-lamps-pq-composite-kem requires an EC component to be carried as an uncompressed point, but a component key that encodes itself compressed - a BC EC key whose point format has been set through org.bouncycastle.jce.interfaces.ECPointEncoder, or a key from a provider that preserves a compressed encoding - was passed through as it came. Both sides then combined a different tradPK and derived different shared secrets, with no error reported on either: encapsulation and decapsulation both succeeded and the recipient simply could not decrypt. The EC component is now normalised to an uncompressed point wherever the engine serialises one, which covers the ephemeral key that forms the ciphertext as well. X25519 and X448 components have a single encoding and were unaffected, as were EC keys left in their default (uncompressed) format, whose shared secrets are unchanged. CompositePublicKey.getEncoded() took its component bytes the same way, so such a key also encoded to a composite key other implementations reject and whose bytes changed across an encode / decode / encode round trip - 1238 bytes rather than 1270 for MLKEM768-ECDH-P256, and for the composite ML-DSA keys sharing that method, 2006 rather than 2038 for MLDSA65-ECDSA-P256. It now normalises the component the same way. This is a write-side change only: a composite key carrying a compressed EC component is still decoded, since the component key factories accept either form, and continues to verify signatures as before - it simply re-encodes in the normalised form. The shared normalisation is org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil.getUncompressedSubjectPublicKeyBytes.\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation threw a NullPointerException, wrapped in an IllegalStateException out of KeyGenerator.generateKey(), when the SecureRandom it was given was null - which javax.crypto.KEM.newEncapsulator() documents as a request for the provider's default, and which KeyGenerator.init(spec, null) passes straight through. The three RSA-OAEP composites draw the traditional shared secret from that random directly, so they were the ones affected; the ECDH and X25519 / X448 composites escaped only because their component KeyPairGenerators default a random of their own. CompositeMLKEMEngine now defaults one through CryptoServicesRegistrar.getSecureRandom() on first use, as the composite KEM Cipher's wrap path already did, and as the KEM generators corrected earlier in this cycle now do. Related, the engine now also clears the ML-KEM component's shared secret alongside the traditional one on both the encapsulate and decapsulate paths - the copy handed back by getEncoded() was left in the heap - as section 3.5 of draft-ietf-lamps-pq-composite-kem requires.\u003c/li\u003e\n\u003cli\u003eCompositePublicKey.getAlgorithm() and CompositePrivateKey.getAlgorithm() returned null for all twelve Composite ML-KEM (draft-ietf-lamps-pq-composite-kem) parameter sets. Both classes resolved the name through the composite signature index only, which holds the composite ML-DSA OIDs, so a composite KEM key pair - generated, parsed from a certificate, or read from PKCS#8 - reported no algorithm at all, and the standard JCA idiom of reconstructing a key with KeyFactory.getInstance(key.getAlgorithm()) raised a NullPointerException. The lookup now falls back to the composite KEM index, so the name returned is the one the provider registers the algorithm under (e.g. MLKEM768-X25519-SHA3-256), matching the composite ML-DSA behaviour. The same single-index assumption made the CompositePublicKey(SubjectPublicKeyInfo) and CompositePrivateKey(PrivateKeyInfo) constructors reject a composite KEM key with \u0026quot;unable to create CompositePublicKey from SubjectPublicKeyInfo\u0026quot;; they now dispatch to the composite KEM key factory for those OIDs. Keys obtained through KeyFactory or through BouncyCastleProvider.getPublicKey / getPrivateKey were unaffected and are unchanged (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2404\"\u003e#2404\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe org.bouncycastle.jcajce.spec.KEMKDFSpec constructor stored a null otherInfo as given, so getOtherInfo() returned null, and three of the KDF branches KdfUtil.makeKeyBytes dispatches to - KMAC-128, KMAC-256 and SHAKE-256 - read the otherInfo length without a guard and threw NullPointerException out of the KEM operation, where the KDF2, KDF3 and HKDF branches tolerate a null through KDFParameters / HKDFParameters. The Builder of every spec in the package already mapped null to empty, so no provider path reached it, but the constructor is protected on a public class and KdfUtil is documented for callers building their own KEM integration; the deprecated KEMParameterSpec passes a null itself and escaped only because it also pins the KDF to null. The constructor now stores empty for a null, so getOtherInfo() never returns null, and a null and an explicitly empty otherInfo derive the same key.\u003c/li\u003e\n\u003cli\u003eQR-UOV signature verification accepted a signature encoding that was not canonical, so the encoding of a signature was not unique even after the trailing-byte fix of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e. Each F_q element of the signature is stored in ceil(log2 q) bits, one more bit pattern than the field has elements: q itself is representable and is arithmetically congruent to zero, so an element written as q verified exactly as the same element written as zero would, and the bits padding the last element out to the byte boundary were never read at all. Every zero element of a signature therefore carried a second encoding, and for the q = 7 parameter sets roughly one element in seven is zero - a single qruov_5_q7_L10 signature measured 256 spare bits, so on the order of 2^256 distinct byte strings verified for the one message and key. Verification now rejects any element outside [0, q) and any set padding bit; a signature produced by this or by the reference implementation is unaffected, as the KAT vectors of every parameter set confirm. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSNOVA signature verification ignored four bits inside the signature for any parameter set whose solution is an odd number of GF(16) nibbles - the SNOVA_24_5_5, SNOVA_25_8_3, SNOVA_29_6_5 and SNOVA_66_15_3 families, sixteen of the forty-four parameter sets. The last byte of the encoded solution carries a single nibble and the signer leaves the top four bits zero, but the decoder did not read them, so sixteen distinct byte strings verified for one signature. This is the same non-unique encoding github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e closed for bytes following the signature, applied inside it; the verifier now requires those bits to be zero. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSnovaPrivateKeyParameters did not validate the length of the private key encoding handed to it - the only one of the five schemes of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e that did not - and SnovaParameters.getPrivateKeyLength() reported the expanded (\u0026quot;ESK\u0026quot;) length even for a parameter set whose private key is the seed pair. A private key encoding reaches this constructor straight from a PKCS#8 blob, so a wrong length went undetected: a seed-form key with extra bytes appended was accepted and signed under a different derived key, and a short expanded-form key sized the signer's decode buffer negatively, throwing NegativeArraySizeException out of generateSignature() rather than being reported at construction. Related, the signing retry loop could not terminate: the vinegar values are derived from a single-byte counter, so only 256 distinct linear systems can be tried, and an expanded-form private key that is not a real central map is singular for all of them - generateSignature() then span forever rather than failing. The length is now checked at construction, getPrivateKeyLength() reports the length that parameter set's private key actually has, and the retry loop gives up after its 256 attempts as MAYO's does.\u003c/li\u003e\n\u003cli\u003eMayoSigner and MayoKeyPairGenerator did not clear several buffers holding secret key material that the MAYO reference implementation explicitly clears. Signing left the secret oil space O, the expanded L = (P1 + P1^t) * O + P2, and the M / VPV / Ox intermediates of the central map in place, having gone to the trouble of clearing eleven other buffers; key generation left the expanded seed, whose tail is the encoded oil space, and the P1 * O + P2 half of P; and the row-echelon step left the packed echelon form of the secret linear system and its pivot rows. Separately, if all 256 attempts at solving for the signature had given a rank-deficient system, signing emitted a signature built from the failed attempt's state instead of reporting the failure the reference returns, and AIMerSigner.generateSignature returned an empty array on failure, which a caller would hand on as though it were a signature. Both now throw.\u003c/li\u003e\n\u003cli\u003eFive PQC signature schemes - MAYO, SNOVA, QR-UOV, SQIsign and AIMer - returned the NIST crypto_sign \u0026quot;sm\u0026quot; signed-message envelope from generateSignature() rather than the signature. That envelope is an artefact of the reference KAT harness, which records the message alongside the signature so a vector file can be self-contained; it is not part of any of the five specifications, and no other BC signer emits it (Falcon's KAT test rebuilds the equivalent envelope in the test, which is where it belongs). Two consequences followed, both reaching the JCA Signature services of every parameter set of the five schemes in BouncyCastlePQCProvider. First, since the message was appended to the signature, verification had to skip whatever followed the signature proper, and it did so by checking only that the buffer was long enough - so any number of trailing bytes could be added to a valid signature, or the appended message replaced with unrelated data, and it still verified. A signature encoding was therefore not unique: anyone holding one valid signature could produce unlimited distinct byte strings that all verified for the same message and key, which breaks any use that treats the signature bytes as an identifier, deduplicates on them, or records them as evidence. Second, the envelope propagated into everything built on the operator layer: because ContentSigner hands the signature straight into the structure being signed, every X.509 certificate, CRL, CMS SignedData and TLS CertificateVerify BC produced with one of these algorithms carried a verbatim copy of the signed data inside its own signature field - a self-signed MAYO-1 certificate came to 3567 bytes where the same certificate is now 2020 - which no other implementation can parse as a signature, and which in a detached CMS signature meant the \u0026quot;detached\u0026quot; signature carried the content. generateSignature() now returns the bare signature, and verifySignature() requires exactly the parameter set's signature length, so appended or truncated data is rejected rather than ignored. \u003cstrong\u003eThis is a behavioural change for signatures produced by an earlier release\u003c/strong\u003e - MAYO and SNOVA from 1.84, QR-UOV, SQIsign and AIMer from 1.85 - which are no longer accepted in the envelope form they were emitted in; the signature bytes themselves are unchanged, so a stored value can be recovered by taking the leading signature-length bytes, or for AIMer, whose envelope was message || signature rather than signature || message, the trailing ones. The KAT tests now rebuild the envelope before comparing against the vector files, which continue to record it. Note that AIMer's verification had already been made length-exact during this cycle (see the entry below relating to github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2401\"\u003e#2401\u003c/a\u003e), so of the five only its envelope remained (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe MLS implementation did not bind an X.509 credential to the LeafNode's signature_key. LeafNode.verify() checked a leaf's signature against the signature_key declared in the leaf itself, while the X.509 credential's certificate chain was stored but never parsed or checked, so the certificate's public key was never required to match signature_key (RFC 9420 sec. 5.3). A leaf could therefore carry one party's certificate while being signed by an unrelated key and still be accepted under that party's identity through KeyPackage.verify() and the Group leaf-validation path. LeafNode.verify() now requires the end-entity certificate's subject public key, in the cipher suite's signature encoding, to equal signature_key for an X.509 credential, and rejects the leaf otherwise - including an empty chain or a certificate whose key type does not match the cipher suite; certificate-chain and identity validation to a trust anchor remain the application's responsibility per RFC 9420 sec. 5.3.1. A public org.bouncycastle.mls.codec.Certificate(byte[]) constructor and a Credential.getCertificates() accessor are added so callers can build and inspect X.509 credentials. Basic credentials are unaffected.\u003c/li\u003e\n\u003cli\u003eThe SecureRandom supplied to org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder.setSecureRandom() did not drive the content IV / nonce for any algorithm other than RC2. EnvelopedDataHelper.generateParameters passed the caller's SecureRandom to the AlgorithmParameterGenerator only in the RC2_CBC branch; every other content-encryption algorithm - AES-CBC, AES-GCM, AES-CCM, Camellia, ARIA, SEED and the rest - reached pGen.generateParameters() on an uninitialised generator, so the IV / nonce was drawn from a default SecureRandom and setSecureRandom() was silently ignored (the builder's javadoc states that random is used for IV/nonce generation). The generator is now initialised with the supplied random on the general path as well, so a caller who provides a specific randomness source - for a controlled or FIPS-approved DRBG, say - has it honoured for the content IV / nonce. The session-key generation path was unaffected and already used the supplied random. Because the content IV / nonce now comes from the supplied SecureRandom, the org.bouncycastle.crypto.util JournalingSecureRandom / JournaledAlgorithm reproducible-encryption support records it in the transcript: a resumed session reproduces the IV / nonce by regenerating it from the replayed randomness - build the resuming encryptor from the content-algorithm OID - rather than by reusing the AlgorithmIdentifier captured from the first encryption, which no longer keeps the transcript aligned.\u003c/li\u003e\n\u003cli\u003eThe NTRU LPRime, NTRU+ and SMAUG-T KEM generators threw a NullPointerException when constructed with a null SecureRandom, where every other KEM generator - including NTRU LPRime's own SNTRU Prime counterpart in the same package - defaults one through CryptoServicesRegistrar.getSecureRandom(). This is reachable from the lightweight API directly, and from javax.crypto.KEM, whose newEncapsulator() documents a null random as a request for the provider's default.\u003c/li\u003e\n\u003cli\u003eFrodoKEMEngine kept a single SHAKE instance in a field, so an engine reached concurrently produced wrong results. It is reached that way through org.bouncycastle.crypto.kems.FrodoKEMExtractor, which holds one engine for its lifetime: two threads extracting through one extractor interleaved the digest's absorb and squeeze phases, yielding shared secrets that silently did not match the sender's, or an IllegalStateException of \u0026quot;attempt to absorb while squeezing\u0026quot; from inside extractSecret. The digest is now built per call, as CMCEEngine's already was, which makes an extractor safe to share. Encapsulation was unaffected, since FrodoKEMGenerator builds an engine per call. Results for any single-threaded use are unchanged - the reference KAT vectors are byte-identical.\u003c/li\u003e\n\u003cli\u003eThe BCJSSE provider carried the TLS 1.2 coupling between the supported_groups extension and ECDSA over into TLS 1.3: an ECDSA signature scheme was treated as usable - offered in the signature_algorithms and signature_algorithms_cert extensions, and eligible when selecting the local credentials - only while the corresponding curve was among the named groups enabled for key exchange, both per context (a group unavailable for key agreement disabled the scheme outright) and per connection (the curve had to be in the supported_groups list about to be sent). RFC 8446 sec. 4.2.7 scopes supported_groups to key exchange only, with signature algorithms negotiated independently (sec. 4.2.3), so this incorrect restriction in TLS 1.3 has been removed. Ed25519, Ed448 and the RSA schemes were unaffected (as well as typical deployments using a default configuration for named groups).\u003c/li\u003e\n\u003cli\u003eThe bcmail module descriptor did not declare its javax.mail/javax.activation dependences, so a modular (module-path) consumer of the jar hit IllegalAccessError/module-resolution failures when the S/MIME classes touched the mail API. The descriptor now requires them optionally (requires static) under all four module names those libraries are known by - the automatic names mail and activation carried by the javax.mail:mail / javax.activation:activation artifacts, and the explicit names java.mail and java.activation carried by the newer com.sun.mail / com.sun.activation ones - a hard requires on any one name would break users of the others (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2389\"\u003e#2389\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFour type-coercion helpers in the OER / IEEE 1609.2 (ITS) decoder tested the wrong type in the identity fast path that lets a getInstance() factory return an argument that is already of the target type. org.bouncycastle.oer.its.ieee1609dot2.basetypes.UINT32.getInstance and org.bouncycastle.oer.its.etsi102941.basetypes.Version.getInstance guarded on UINT8 - a sibling of UINT32 under UintBase, and unrelated to Version - so passing a UINT8 threw ClassCastException, while passing an actual UINT32 or Version missed the fast path and fell through to ASN1Integer.getInstance, which rejects them: neither factory accepted its own type. org.bouncycastle.oer.its.etsi103097.EtsiTs103097DataEncryptedUnicast.getInstance guarded on its sibling EtsiTs103097DataEncrypted and then cast to the unicast type, so an EtsiTs103097DataEncrypted threw ClassCastException. org.bouncycastle.oer.OEROptional.getObject(Class) called value.getClass().isInstance(type) with the arguments transposed, which is always false because the argument is a java.lang.Class, so the cast path was dead and every optional field was resolved reflectively, failing with IllegalStateException for a target type with no static getInstance. Each guard now names the type it returns, matching the sibling UINT8 / UINT16 / UINT64 and EtsiTs103097DataEncrypted factories (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2373\"\u003e#2373\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eDefaultAlgorithmNameFinder and DefaultSignatureNameFinder had no entries at all for the ShangMi algorithms, so an SM2 signature AlgorithmIdentifier that DefaultSignatureAlgorithmIdentifierFinder itself produces came back named only by its OID string - getAlgorithmName(GMObjectIdentifiers.sm2sign_with_sm3) returned \u0026quot;1.2.156.10197.1.501\u0026quot; and hasAlgorithmName returned false. Both finders now name sm2sign_with_sm3 as SM3WITHSM2 and sm2sign_with_sha256 as SHA256WITHSM2, and DefaultAlgorithmNameFinder additionally names the sm3 digest. All three resolve through the BC provider, as Signature and MessageDigest respectively. The remaining GM arc - the SM4 cipher modes, the sm2encrypt variants, and the SM1 / SM6 / SSF33 ciphers BC does not implement - is still unnamed (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2377\"\u003e#2377\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe RFC 4998 evidence-record classes compared the digest AlgorithmIdentifier named by a time-stamp authority with the one their own DigestCalculator uses, and did so with AlgorithmIdentifier.equals(), which compares the encodings. A TSA that names SHA-256 with an explicit NULL parameters field - DigiCert among them - therefore failed against BC's own calculator, which names it with the parameters absent, and ERSArchiveTimeStampGenerator.generateArchiveTimeStamp rejected the response with \u0026quot;time stamp imprint for wrong algorithm\u0026quot;. Both spellings name the same digest and RFC 5754 sec. 2 requires a receiver to accept either, while requiring that identifiers be generated with the parameters absent, which BC already does. The three affected comparisons - the two in ERSArchiveTimeStampGenerator and the digest check in ERSEvidenceRecord.renew - now use the new AlgorithmIdentifier.areEquivalent, which matches on the algorithm and treats an absent parameters field and NULL as the same, and the consistency check across an evidence record's archive time stamp chain uses it too. An identifier carrying an actual parameter structure is never equivalent to one carrying none (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2379\"\u003e#2379\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eEDIPartyName.toASN1Primitive emitted the nameAssigner and partyName DirectoryStrings without their context tags, so an EDIPartyName built through its public constructor could not be parsed back by EDIPartyName.getInstance, which correctly requires them. RFC 5280 sec. 4.2.1.6 tags both members [0] and [1], and those tags are explicit despite the module's IMPLICIT TAGS because DirectoryString is a CHOICE, which X.680 does not allow to be tagged implicitly - the decoder already had this right. The encoder now matches it. Note the type was added during the 1.85 cycle and GeneralName validates its ediPartyName alternative through it, so a GeneralName carrying an untagged ediPartyName - including one BC itself produced - is rejected where 1.84 passed it through unexamined; the untagged form is not read leniently (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2380\"\u003e#2380\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eRSASSA-PSS could not be used with a RIPEMD digest through the JCA API. Nothing registered the RIPEMD PSS signatures, so Signature.getInstance(\u0026quot;RIPEMD160WITHRSAANDMGF1\u0026quot;) raised NoSuchAlgorithmException, and the generic RSASSA-PSS route with an explicit PSSParameterSpec failed too: org.bouncycastle.jcajce.provider.util.DigestFactory.getDigest returned null for a RIPEMD name, and isSameDigest - an allow-list of the SHA families and MD5 - reported two identical RIPEMD names as different digests, so the spec was rejected with \u0026quot;digest algorithm for MGF should be the same as for PSS parameters\u0026quot;. isSameDigest now answers true for equal names whatever the digest, which also covers Whirlpool, SM3, GOST3411 and anything else outside that allow-list; DigestFactory recognises RIPEMD128, RIPEMD160 and RIPEMD256 by name and OID; the three PSS signatures are registered with MGF1 over the same digest and a salt of the digest length; and DefaultSignatureAlgorithmIdentifierFinder gains the matching RIPEMD*WITHRSAANDMGF1 entries with their RSASSA-PSS-params, so the operator/JcaContentSignerBuilder path works as well. Note BC continues to require the PSS hash and the MGF1 hash to be the same, which RFC 8017 does not itself demand (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2381\"\u003e#2381\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe opt-in key-size validation on CMS key-transport recipients (org.bouncycastle.cms.jcajce.JceKeyTransRecipient.setKeySizeValidation(true)) never ran for a message using RFC 9709 CEK derivation (id-alg-cek-hkdf-sha256): the branch that should have selected the actual content-encryption algorithm carried in the KDF AlgorithmIdentifier's parameters compared the encrypted-key byte array against the id-alg-cek-hkdf-sha256 object identifier - a comparison that is always false - so the check fell through to a key-size lookup on the outer KDF OID, which has no registered key size, and silently checked nothing. A key-transport EnvelopedData/AuthEnvelopedData whose transported (and HKDF-derived) content-encryption key did not match the key size of the advertised content-encryption algorithm was therefore accepted even with validation enabled. The recipient now dispatches on the content-encryption AlgorithmIdentifier's algorithm OID, so key-size validation of RFC 9709 messages checks the recovered key against the inner content-encryption algorithm. Messages with a matching key size, non-HKDF messages, and recipients that do not enable validation are unaffected.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003eSee full diff in \u003ca href=\"https://github.com/bcgit/bc-java/commits\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003ecommonmark-java 0.29.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e[0.29.0] - 2026-06-20\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/42b4fb7adfe288ef13e9e27ab20aff7e91b0ab9d\"\u003e\u003ccode\u003e42b4fb7\u003c/code\u003e\u003c/a\u003e Prepare CHANGELOG for version 0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/b76e09d7a8362abb5f04e1d6b91dbd6da279a6fc\"\u003e\u003ccode\u003eb76e09d\u003c/code\u003e\u003c/a\u003e Limit how deep inline nodes may nest by default (100)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/49f65cb5cbec93cff713179990307145198e7061\"\u003e\u003ccode\u003e49f65cb\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing deeply nested emphasis\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/c...\n\n_Description has been truncated_","html_url":"https://github.com/zetavue/openclaw-talk-transcript-persistence/pull/31","url":"https://dependabot.ecosyste.ms/api/v1/hosts/GitHub/repositories/zetavue%2Fopenclaw-talk-transcript-persistence/issues/31","packages_url":"https://dependabot.ecosyste.ms/api/v1/issues/31/packages"}},{"old_version":"5.3.2","new_version":"5.5.0","update_type":"minor","path":null,"pr_created_at":"2026-09-09T19:08:50.000Z","version_change":"5.3.2 → 5.5.0","issue":{"uuid":"5403641597","node_id":"PR_kwDOTDg46M8AAAABC4h51A","number":30,"state":"closed","title":"build(deps): bump the android-deps group across 1 directory with 17 updates","user":"dependabot[bot]","labels":["dependencies","java"],"assignees":[],"locked":false,"comments_count":1,"pull_request":true,"closed_at":"2026-09-11T19:05:27.000Z","author_association":null,"state_reason":null,"created_at":"2026-09-09T19:08:50.000Z","updated_at":"2026-09-11T19:05:28.000Z","time_to_close":172597,"merged_at":null,"merged_by":null,"closed_by":null,"dependency_metadata":{"prefix":"build(deps): bump","group_name":"android-deps","update_count":17,"packages":[{"name":"gradle-wrapper","old_version":"9.5.1","new_version":"9.7.1","repository_url":"https://github.com/gradle/gradle"},{"name":"androidx.core:core-ktx","old_version":"1.18.0","new_version":"1.19.0"},{"name":"org.bouncycastle:bcprov-jdk18on","old_version":"1.84","new_version":"1.85.2","repository_url":"https://github.com/bcgit/bc-java"},{"name":"org.commonmark:commonmark","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-autolink","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-strikethrough","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-tables","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-task-list-items","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.junit.vintage:junit-vintage-engine","old_version":"6.1.0","new_version":"6.1.3","repository_url":"https://github.com/junit-team/junit-framework"},{"name":"io.kotest:kotest-assertions-core-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"io.kotest:kotest-runner-junit5-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"com.squareup.okhttp3:mockwebserver","old_version":"5.3.2","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.squareup.okhttp3:okhttp","old_version":"5.3.2","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.android.application","old_version":"9.2.1","new_version":"9.4.0"},{"name":"com.android.test","old_version":"9.2.1","new_version":"9.4.0"},{"name":"org.jetbrains.kotlin.plugin.compose","old_version":"2.4.0","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"},{"name":"org.jetbrains.kotlin.plugin.serialization","old_version":"2.4.0","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"}],"path":null,"ecosystem":"maven"},"body":"Bumps the android-deps group with 17 updates in the /apps/android directory:\n\n| Package | From | To |\n| --- | --- | --- |\n| [gradle-wrapper](https://github.com/gradle/gradle) | `9.5.1` | `9.7.1` |\n| androidx.core:core-ktx | `1.18.0` | `1.19.0` |\n| [org.bouncycastle:bcprov-jdk18on](https://github.com/bcgit/bc-java) | `1.84` | `1.85.2` |\n| [org.commonmark:commonmark](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-autolink](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-strikethrough](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-tables](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-task-list-items](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.junit.vintage:junit-vintage-engine](https://github.com/junit-team/junit-framework) | `6.1.0` | `6.1.3` |\n| [io.kotest:kotest-assertions-core-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [io.kotest:kotest-runner-junit5-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [com.squareup.okhttp3:mockwebserver](https://github.com/lysine-dev/okhttp) | `5.3.2` | `5.5.0` |\n| [com.squareup.okhttp3:okhttp](https://github.com/lysine-dev/okhttp) | `5.3.2` | `5.5.0` |\n| com.android.application | `9.2.1` | `9.4.0` |\n| com.android.test | `9.2.1` | `9.4.0` |\n| [org.jetbrains.kotlin.plugin.compose](https://github.com/JetBrains/kotlin) | `2.4.0` | `2.4.20` |\n| [org.jetbrains.kotlin.plugin.serialization](https://github.com/JetBrains/kotlin) | `2.4.0` | `2.4.20` |\n\n\nUpdates `gradle-wrapper` from 9.5.1 to 9.7.1\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/gradle/gradle/releases\"\u003egradle-wrapper's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e9.7.1\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.1.\u003c/p\u003e\n\u003cp\u003eThis is a patch release for 9.7.0. We recommend using 9.7.1 instead of 9.7.0.\u003c/p\u003e\n\u003cp\u003eHere are the highlights of 9.7.0 release:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIsolated Projects graduates to incubating\u003c/li\u003e\n\u003cli\u003eBroader Configuration Cache compatibility\u003c/li\u003e\n\u003cli\u003eResilient Sync helps you fix broken builds\u003c/li\u003e\n\u003cli\u003eMore source locations in problem reports\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003ca href=\"https://docs.gradle.org/9.7.1/release-notes.html\"\u003eRead the Release Notes\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eWe would like to thank the following community members for their contributions to this release of Gradle:\n\u003ca href=\"https://github.com/aSemy\"\u003eAdam\u003c/a\u003e,\n\u003ca href=\"https://github.com/Gautam-aman\"\u003eAman Gautam\u003c/a\u003e,\n\u003ca href=\"https://github.com/YukiCodepth\"\u003eAman Kumar\u003c/a\u003e,\n\u003ca href=\"https://github.com/adubrouski\"\u003eAnton Dubrouski\u003c/a\u003e,\n\u003ca href=\"https://github.com/liutikas\"\u003eAurimas\u003c/a\u003e,\n\u003ca href=\"https://github.com/gbhavya07\"\u003egbhavya07\u003c/a\u003e,\n\u003ca href=\"https://github.com/joshfriend\"\u003eJosh Friend\u003c/a\u003e,\n\u003ca href=\"https://github.com/nicklauslittle-gov\"\u003enicklauslittle-gov\u003c/a\u003e,\n\u003ca href=\"https://github.com/psoni674\"\u003ePragati\u003c/a\u003e,\n\u003ca href=\"https://github.com/Project516\"\u003eproject516\u003c/a\u003e,\n\u003ca href=\"https://github.com/Uomocapra\"\u003eQin Mi\u003c/a\u003e,\n\u003ca href=\"https://github.com/rkdfx\"\u003eRavi\u003c/a\u003e,\n\u003ca href=\"https://github.com/sk-reddy17\"\u003esk-reddy17\u003c/a\u003e,\n\u003ca href=\"https://github.com/Suvrat1629\"\u003eSuvrat Acharya\u003c/a\u003e,\n\u003ca href=\"https://github.com/ShreckYe\"\u003eYongshun Ye\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eUpgrade instructions\u003c/h2\u003e\n\u003cp\u003eSwitch your build to use Gradle 9.7.1 by updating your wrapper:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e./gradlew :wrapper --gradle-version=9.7.1 \u0026amp;\u0026amp; ./gradlew :wrapper\r\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eSee the Gradle \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/upgrading_version_9.html\"\u003e9.x upgrade guide\u003c/a\u003e to learn about deprecations, breaking changes and other considerations when upgrading.\u003c/p\u003e\n\u003cp\u003eFor Java, Groovy, Kotlin and Android compatibility, see the \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/compatibility.html\"\u003efull compatibility notes\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eReporting problems\u003c/h2\u003e\n\u003cp\u003eIf you find a problem with this release, please file a bug on \u003ca href=\"https://github.com/gradle/gradle/issues\"\u003eGitHub Issues\u003c/a\u003e adhering to our issue guidelines.\nIf you're not sure you're encountering a bug, please use the \u003ca href=\"https://discuss.gradle.org/c/help-discuss\"\u003eforum\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eWe hope you will build happiness with Gradle, and we look forward to your feedback via \u003ca href=\"https://twitter.com/gradle\"\u003eTwitter\u003c/a\u003e or on \u003ca href=\"https://github.com/gradle\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003e9.7.0\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.0.\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/92f0512e7f06d84621afba191f75e265363890cf\"\u003e\u003ccode\u003e92f0512\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38892\"\u003e#38892\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/820ee75a99a179bbffa41bcedc6477b685fabb9f\"\u003e\u003ccode\u003e820ee75\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/82c23f9bd2a89b4cc644e1f90a28a8668feb3dee\"\u003e\u003ccode\u003e82c23f9\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering problem in KTS (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38878\"\u003e#38878\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/ef11a7268fe8cc8d6ab849ec911aa11220180553\"\u003e\u003ccode\u003eef11a72\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering issue\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/bb0d8a974a71b1003efea41e4046e98855cd5ff8\"\u003e\u003ccode\u003ebb0d8a9\u003c/code\u003e\u003c/a\u003e Make relevant tests polyglot (run for multiple DSLs)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/336e129d7f95c03486acafc97abf59734acfed48\"\u003e\u003ccode\u003e336e129\u003c/code\u003e\u003c/a\u003e Update signing configuration (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38874\"\u003e#38874\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/4bdf0da2dad9884d089a6062a45ea7183e7d735d\"\u003e\u003ccode\u003e4bdf0da\u003c/code\u003e\u003c/a\u003e Update signing configuration\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/cd9b92c1b82856248cf1dc58b50378238bec7b52\"\u003e\u003ccode\u003ecd9b92c\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38839\"\u003e#38839\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/5f4e381964897ad8d6b99e5a7c77f26dba3259fb\"\u003e\u003ccode\u003e5f4e381\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/1e08ab551367aeb5fb48b26e72807e1d2b27c939\"\u003e\u003ccode\u003e1e08ab5\u003c/code\u003e\u003c/a\u003e Keep type-use annotations in extracted ABI classes (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38810\"\u003e#38810\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/gradle/gradle/compare/v9.5.1...v9.7.1\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `androidx.core:core-ktx` from 1.18.0 to 1.19.0\n\nUpdates `org.bouncycastle:bcprov-jdk18on` from 1.84 to 1.85.2\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.md\"\u003eorg.bouncycastle:bcprov-jdk18on's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch1\u003eBouncy Castle Crypto Package - Release Notes\u003c/h1\u003e\n\u003ch2\u003e1.0 Introduction\u003c/h2\u003e\n\u003cp\u003eThe Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. The package is organised so that it contains a light-weight API suitable for use in any environment (including the J2ME) with the additional infrastructure to conform the algorithms to the JCE framework.\u003c/p\u003e\n\u003ch2\u003e2.0 Release History\u003c/h2\u003e\n\u003cp\u003e\u003c!-- raw HTML omitted --\u003e\u003c!-- raw HTML omitted --\u003e\u003c/p\u003e\n\u003ch3\u003e2.1.1 Version\u003c/h3\u003e\n\u003cp\u003eRelease: 1.86\u003cbr /\u003e\nDate: 2026, TBD\u003c/p\u003e\n\u003ch3\u003e2.1.2 Defects Fixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) let a subkey inherit the primary key's Key Flags when its own Subkey Binding signature carried no Key Flags subpacket, which made the two capability decisions taken for one subkey disagree. OpenPGPCertificate.OpenPGPComponentKey.isSigningKey() reads the effective flags, which fell back to the primary key's direct-key or primary user ID self-signature, so a subkey bound with no flags of its own counted as signing-capable; verifyEmbeddedPrimaryKeyBinding reads the binding signature's own flags, found no signing capability there, and so skipped the embedded Primary Key Binding (cross-certification) signature that RFC 9580 sec. 5.2.1.8 and sec. 10.1.3 require of a subkey that can issue signatures. A data signature made by such a subkey was therefore attributed to the certificate and reported valid by OpenPGPSignature.OpenPGPDocumentSignature.isValid() with the cross-certification requirement never applied, where GnuPG refuses the same certificate and message as not cross-certified. An attacker holding a third party's public signing subkey - which is public material - could bind it to their own primary key with a Subkey Binding signature they are able to make, carrying no Key Flags and no embedded Primary Key Binding signature, which they cannot make without the subkey's private key, and have that party's genuine signatures verify as valid under the attacker's own identity: misattribution of a real signature rather than a forgery of a new one, since the signature still has to be one the subkey actually made. Key Flags are a statement about the key the carrying signature refers to (RFC 9580 sec. 5.2.3.29), so a subkey no longer inherits them from the certificate-wide signatures of the primary key: a Subkey Binding signature that omits the subpacket now leaves the subkey with no capabilities rather than the primary's, which makes the flags the cross-certification check consults the same flags every other decision consults. Preferences and the other subpackets a direct-key signature carries are inherited as before, and the primary key itself - whose flags legitimately come from its direct-key or user ID self-signature - is unaffected. The low-level PGPSignature / PGPPublicKeyRing API performs no binding checks by design and is unchanged.\u003c/li\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) used a version 6 key that carried no valid Direct Key signature, falling back to the primary user ID binding as it correctly does for a version 4 key. RFC 9580 sec. 5.2.3.10 requires the opposite: \u0026quot;An implementation MUST ensure that a valid Direct Key signature is present before using a version 6 key. This prevents certain attacks where an adversary strips a self-signature specifying a Key Expiration Time or certain preferences.\u0026quot; The certificate grammar says the same structurally, the Direct Key signature being mandatory in the version 6 structure of sec. 10.1.1 and optional in the version 4 one of sec. 10.1.3. Because a version 6 certificate carries its key expiration, features and algorithm preferences on the Direct Key signature - the convention the RFC recommends and the one OpenPGPKeyGenerator follows, its user ID certification carrying no expiration at all - removing that single signature packet from a published certificate silently dropped the expiration along with the preferences and features: OpenPGPCertificate.getSignatureChainFor fell back to the user ID binding, the primary key was still reported bound, and getEncryptionKeys() and getSigningKeys() went on returning the subkeys of a key whose owner had set it to expire. The primary key fingerprint is unchanged by the removal, so a relying party pinning the key by fingerprint still treats it as the same key, and no private key or hash collision is involved; the natural moment for the strip is the key refresh that RFC 9580 names as the reason to refetch a key at all - to learn about changes in expiration, features, preferences and revocation - which is exactly the update it defeats. This is a downgrade rather than a forgery, nothing being attributed to a key that did not authorise it, and the concerning direction is encryption, to a key meant to have been retired. OpenPGPCertificate.isBoundBy now requires a valid Direct Key self-signature on a version 6 primary key before any component of the certificate - the primary key, its subkeys or its identities - is treated as bound, so a version 6 certificate stripped of it offers no keys at all rather than an unexpiring set. Version 4 certificates are unaffected: there the key expiration legitimately lives on the user ID self-signature and the fallback is correct, so it stays. The revocation-only version 6 certificate of sec. 10.1.2, which legitimately carries no Direct Key signature, is unaffected as well - its key was already refused as revoked, and reading the revocation does not go through the binding check.\u003c/li\u003e\n\u003cli\u003eThe lightweight LMSSigner and HSSSigner refused a key wrapped in ParametersWithRandom, which is how BcContentSignerBuilder passes a key whenever setSecureRandom() has been called - so BcHssLmsContentSignerBuilder built a working signer until a random was set and then failed with \u0026quot;Incorrect Key Parameters\u0026quot;, and the two signers themselves raised ClassCastException on the same input. All three now unwrap it, as the promoted ML-DSA and SLH-DSA signers already did. The random is accepted and not used: LMS derives its message randomiser C from the key's seed and the one-time index, so it is deterministic and cannot repeat while q does not. Note SP 800-208 sec. 6.1 asks for C to come from an approved random bit generator, which this implementation does not do; that is unchanged here, and a supplied random is now ignored rather than refused.\u003c/li\u003e\n\u003cli\u003eLMS signature verification did not apply two of the checks RFC 8554 sec. 5.4.2 requires before a signature is processed. Step 2g refuses a signature whose LMS typecode is not the one from the public key, and without it the path computation took its height and tree digest from the parameter set the signature named rather than the key's, so a signature claiming a height-25 parameter set drove a 25-level computation against a height-5 key. Step 2i refuses a leaf number q outside the tree, and without it an out-of-range q flowed into the node arithmetic and was left for the candidate-root comparison to catch. Neither was a forgery - the domain separation between D_LEAF and D_INTR and the final comparison saw to that - but both are attacker-chosen work the specification says to refuse up front. Both are now checked, and a signature failing either is still reported as not verifying rather than thrown out of Signature.verify(). The catch around the signature decode in LMSSigner and HSSSigner has also been narrowed to the decode itself, as the corresponding SPI was corrected to do for github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2408\"\u003e#2408\u003c/a\u003e: past the parse the engine reports an inconsistent signature by returning false rather than by throwing, so the wider catch caught nothing while standing ready to turn a future internal error into a quiet false.\u003c/li\u003e\n\u003cli\u003eThe LMS and HSS key parameter classes now apply at construction the checks their decoders apply, so a key built directly cannot be one the decoder would refuse. LMSPrivateKeyParameters accepted an identifier of any length although the decoder reads exactly 16 bytes - such a key encoded but could not be read back - and left q, maxQ and the seed length unchecked; the seed is now required to be at least m bytes at decode as well, where a one-byte seed had been decoding silently and then deriving every one-time key from it. HSSPrivateKeyParameters checked neither its level count nor that it had been given a component key per level and a chaining signature per level below the root, and then indexed both lists, so a mismatch surfaced as IndexOutOfBoundsException - or, where a level happened to match, as a null chaining signature that only failed at signing time; the level is now checked after the reset that fills it in, since a null is legitimate on the way in. LMSPrivateKeyParameters.getInstance(byte[], byte[]) adopted the public key supplied beside the private one without comparing them, so a mismatched public key was simply reported by getPublicKey(); it now cross-checks the identifier, both parameter sets and, where the tree cache already holds it, the root, as the HSS entry point does. The decoders also now report a bad version or seed length as IOException rather than IllegalStateException, so a caller can catch one type for a malformed key, and the package-private LM-OTS public key decoder no longer declares throws Exception or dereferences an unrecognised typecode. The deprecated org.bouncycastle.pqc.crypto.lms copies carry the decoder corrections.\u003c/li\u003e\n\u003cli\u003eIn the LMS JCE layer, LMSKeyGenParameterSpec.fromNames knew all twenty LMS parameter-set names but only four of the sixteen LM-OTS ones, so none of the SP 800-208 n24 or SHAKE sets could be named; all sixteen are now present. KeyPairGenerator.initialize(int, SecureRandom) reports InvalidParameterException, which is what the JCA specifies and which extends the IllegalArgumentException it raised before, so existing catches still match. BCLMSPrivateKey.getIndex now takes the exhaustion check and the index read under the key's own monitor rather than as two separate calls, and two unused fields have gone from LMSSignatureSpi. Note that the LMS Signature claims its one-time key at the first update() rather than at sign(), so a Signature that is initialised and updated and then abandoned spends an index without producing a signature - the safe direction for a one-time scheme, and now documented on the SPI.\u003c/li\u003e\n\u003cli\u003eEvery other key pair generator that refuses a key size did the same thing the LMS one did above. KeyPairGenerator.initialize(int, SecureRandom) is documented to raise InvalidParameterException when the key size is not one the generator supports, and thirty of them raised a bare IllegalArgumentException instead, so a caller following the JCA and catching the documented type saw an exception escaping rather than a refusal. The ML-DSA, ML-KEM, SLH-DSA, Classic McEliece, FrodoKEM, NTRU and composite signature and KEM generators in the BC provider, and every generator in BCPQC, now raise InvalidParameterException - NewHope included, where the value is a key size it will not take rather than a mode of initialisation it does not offer. InvalidParameterException extends IllegalArgumentException, so callers written against the old behaviour go on catching it unchanged. The two RSA generators are corrected as well, and differently: theirs is a key size below a floor rather than a mode of initialisation they do not offer, and the refusal is raised by the lightweight RSAKeyGenerationParameters, which cannot name a java.security exception at all, so the RSA KeyPairGeneratorSpi now translates it - keeping the message verbatim and the original exception as the cause, through a new SecurityExceptions.invalidParameterException factory, since InvalidParameterException has no constructor that takes one. Of the 304 KeyPairGenerator services the two providers register, 299 now refuse a nonsense key size the way the JCA defines it and five accept it as a strength they can work with, with none left raising a bare IllegalArgumentException; that is asserted as a sweep over both providers rather than per algorithm, so a generator added later is covered without the test being touched. The jdk1.3 provider overlays of the four generators that have one carry the same change, and the jdk1.3 SecurityExceptions overlay gains the new factory along with the invalidAlgorithmParameterException one it had been missing.\u003c/li\u003e\n\u003cli\u003eKeyPairGenerator.initialize(AlgorithmParameterSpec, SecureRandom) had the same shape of problem as the int overload above, and only 44 of the 304 services the two providers register reported an unusable spec as the InvalidAlgorithmParameterException that method declares. The twenty-three PQC generators that resolve a parameter set by name - cmce, frodokem, mldsa, mlkem, slhdsa, aimer, bike, faest, falcon, haetae, hqc, mayo, mqom, ntru, ntruplus, both ntruprime variants, qruov, saber, sdith, smaugt, snova and sqisign, 230 services between them - case-folded the name they got back from the spec without checking it, so a spec with no getName() method, and a null spec, produced a NullPointerException from inside the fold; their own \u0026quot;is this name one I know\u0026quot; branch, which does report the declared exception, was unreachable. The two composite generators, whose parameter set is fixed by the algorithm name so that null is the only spec they accept, refused every other one with IllegalArgumentException. RSA answered correctly for a spec of the wrong type but not for one of the right type carrying values its lightweight parameters will not take - an even public exponent, or a key size below the floor - which is now translated the same way the int overload's is. All 304 services now report the declared exception, with the composites still taking the null spec that is right for them; note that InvalidAlgorithmParameterException is a checked exception and not an IllegalArgumentException, so a caller that was catching what these threw before has to catch the declared type instead.\u003c/li\u003e\n\u003cli\u003eAn HSS private key claimed the two records of its position under two different monitors. The top-level index and the bottom component key's one-time index q are independent records of the same position - the decoder requires them to agree, see the entry below - but generateLMSContext incremented the index under the HSS key's own monitor, released it, and only then claimed q under the component key's. A getEncoded() issued in between saw the index advanced and q not, and produced an encoding this implementation's own decoder rejects; and two threads meeting at a bottom-tree boundary could both pass the exhaustion test, take consecutive top-level indices and claim the same q, after which one of them was refused with \u0026quot;ots private key exhausted\u0026quot; by a key still reporting usages remaining, a top-level index had been spent with no signature made, and the two records stayed one apart for the rest of the key's life in that process - so it could no longer be encoded, cloned or sharded, and getIndex() and getUsagesRemaining() misreported by one. No one-time key was reused: the component key's claim is itself atomic, and the divergence runs index ahead of leaves, so the effect was on the key's usability rather than on the signatures it had made. Both records are now claimed under the one monitor, and the component key is claimed before the index is incremented so that an exhausted one leaves both untouched. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the same correction.\u003c/li\u003e\n\u003cli\u003eTimeStampToken parsed the attacker-controlled TSTInfo content of a time-stamp token (org.bouncycastle.tsp.TimeStampToken, reached from TimeStampResponse(byte[]) and (InputStream)) inside a try that caught only CMSException, so a well-formed RFC 3161 TimeStampResp whose embedded token carried a malformed TSTInfo - a SEQUENCE with fewer elements than the five mandatory fields, a non-SEQUENCE, truncated DER, or an unknown context tag - let an IllegalArgumentException or a NoSuchElementException escape the constructor's declared throws TSPException, IOException contract. A token signed by no signers or by more than one raised a bare IllegalArgumentException from the same constructor, before that try, for the same reason. Both are now reported as TSPException, matching the package-private TimeStampResponse(DLSequence) constructor and the existing getSignedAttributes guard in the same method; the signer-count refusal is a TSPValidationException, as the neighbouring check on the content type already was. Related, and the cause of the NoSuchElementException: asn1.tsp.TSTInfo read its five mandatory fields off the sequence with no bound on how many elements were actually there, so a short SEQUENCE left the enumeration to run out rather than being refused, and an oversize one was accepted with its extra elements absorbed into the optional slots. Decode now requires the five to ten elements RFC 3161 sec. 2.4.2 gives the type, which is what the sibling Accuracy and ArchiveTimeStamp decoders already did, so the failure is the IllegalArgumentException that getInstance is expected to raise (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2415\"\u003e#2415\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eNeither the HSS nor the XMSS^MT private key decoder checked its declared index against the traversal state stored beside it, although the two are independent records of the same position in the key and so can be compared. For HSS the records are the top-level index and the component keys' one-time indices q; for XMSS^MT they are the global index and the per-layer BDS states. A stored key whose index had been rolled back while its state stayed advanced - a partial write, a restore from backup, a buggy storage layer - was therefore accepted, and it then signed a second message under a one-time key the key had already used, producing a signature that verified, so nothing anywhere surfaced the reuse. RFC 8554 sec. 1 and RFC 8391 sec. 1.1 both require each one-time key to be used exactly once, and this is the failure those requirements exist to prevent; the single-tree XMSS decoder has tied its BDS state to its index since that state was first validated, and this brings the two multi-tree schemes into line. HSS decode now requires the declared index to equal the position the component q values imply - a level above the last contributes (q - 1) leaves of the levels beneath it, since its q has already advanced past the subtree it signed - and XMSS^MT decode now requires each present layer's BDS index to equal the leaf index that layer derives from the global index, allowing the one position where a layer has moved into a new subtree and its state legitimately still carries the previous subtree's final index. A layer with no state yet is unaffected, since those are built lazily at signing time. Related, and the same shape of omission: an XMSS or XMSS^MT private key encoding carries the tree root twice - the key's own root field and the root node of the BDS state stored beside it, which for XMSS^MT is the top layer's - and the two were never compared either. A corrupted root was accepted and then poisoned every signature the key made, because the root is hashed into the message digest: the signature did not verify and nothing indicated why. Decode now requires the two copies to agree. The BDS node values themselves are not checkable the way the LMS tree cache above is - a BDS authentication path, stack, retain or keep node does not have its children stored alongside it, so recomputing one means building a subtree, which is the work the state exists to avoid. Both checks are integer comparisons over the levels of the key, too small to measure against the surrounding decode, and both were verified not to reject any legitimate key by walking every index a key can reach: the full key space of the two-level HSS and the h=4/d=2, h=6/d=2, h=6/d=3, h=9/d=3 and h=8/d=4 XMSS^MT parameter sets, plus a three-level HSS key across a subtree boundary and an HSS shard. Since those node values cannot be recomputed, the encoded state now carries a checksum over itself instead, with the owning key's public seed hashed in front of it. Any corruption of the stored state is refused at decode rather than being loaded and then producing signatures that silently do not verify, and because the public seed is bound in, a state transplanted between two keys of the same parameter set is refused too, even though it is internally consistent and arrives with its own matching root. The public seed is bound rather than the secret seed or the PRF key deliberately: the state's own root and index are inside the encoding and so are already covered, hashing secret material would make the stored checksum a commitment to it for no gain in detection, and the PRF key does not influence the state at all. \u003cstrong\u003eThis is an error-detecting code and not integrity protection\u003c/strong\u003e - anyone able to rewrite the stored key recomputes it, so it establishes that the state is unchanged since it was written, never that it was correct when written, and the allocation bounds on the encoding remain the guard against a crafted one. It costs one SHA-256 over the state, measured at 5 to 8 microseconds each way for the h=10 and h=16 parameter sets, and 32 bytes of encoding. The state encoding was added earlier in this same cycle and has not been released, so the checksum is simply part of it rather than a new version: a state written by a 1.86 beta is rejected, which is recovered from by re-exporting the key. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the HSS check as well (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2414\"\u003e#2414\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe S/MIME example smoke test in the misc module (org.bouncycastle.mail.smime.examples.test.AllTests) drove SendSignedAndEncryptedMail against smtp.gmail.com, and that example finishes with Transport.send() under JavaMail's default settings, which have no connect timeout. Where outbound port 25 is refused the failure was swallowed and the test passed; where it is silently dropped, as on many home networks, the connect blocked and ./gradlew build hung in :misc:test indefinitely with \u0026quot;0 tests completed\u0026quot;. The test now delivers to an SMTP stub on a loopback port, with connect / read / write timeouts as a backstop, and asserts the message arrived (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2407\"\u003e#2407\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation took the traditional component public key bytes it feeds the KEM combiner from the recipient key's own encoding, while decapsulation recomputes the point from the private key and so always produced an uncompressed one. Section 4 of draft-ietf-lamps-pq-composite-kem requires an EC component to be carried as an uncompressed point, but a component key that encodes itself compressed - a BC EC key whose point format has been set through org.bouncycastle.jce.interfaces.ECPointEncoder, or a key from a provider that preserves a compressed encoding - was passed through as it came. Both sides then combined a different tradPK and derived different shared secrets, with no error reported on either: encapsulation and decapsulation both succeeded and the recipient simply could not decrypt. The EC component is now normalised to an uncompressed point wherever the engine serialises one, which covers the ephemeral key that forms the ciphertext as well. X25519 and X448 components have a single encoding and were unaffected, as were EC keys left in their default (uncompressed) format, whose shared secrets are unchanged. CompositePublicKey.getEncoded() took its component bytes the same way, so such a key also encoded to a composite key other implementations reject and whose bytes changed across an encode / decode / encode round trip - 1238 bytes rather than 1270 for MLKEM768-ECDH-P256, and for the composite ML-DSA keys sharing that method, 2006 rather than 2038 for MLDSA65-ECDSA-P256. It now normalises the component the same way. This is a write-side change only: a composite key carrying a compressed EC component is still decoded, since the component key factories accept either form, and continues to verify signatures as before - it simply re-encodes in the normalised form. The shared normalisation is org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil.getUncompressedSubjectPublicKeyBytes.\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation threw a NullPointerException, wrapped in an IllegalStateException out of KeyGenerator.generateKey(), when the SecureRandom it was given was null - which javax.crypto.KEM.newEncapsulator() documents as a request for the provider's default, and which KeyGenerator.init(spec, null) passes straight through. The three RSA-OAEP composites draw the traditional shared secret from that random directly, so they were the ones affected; the ECDH and X25519 / X448 composites escaped only because their component KeyPairGenerators default a random of their own. CompositeMLKEMEngine now defaults one through CryptoServicesRegistrar.getSecureRandom() on first use, as the composite KEM Cipher's wrap path already did, and as the KEM generators corrected earlier in this cycle now do. Related, the engine now also clears the ML-KEM component's shared secret alongside the traditional one on both the encapsulate and decapsulate paths - the copy handed back by getEncoded() was left in the heap - as section 3.5 of draft-ietf-lamps-pq-composite-kem requires.\u003c/li\u003e\n\u003cli\u003eCompositePublicKey.getAlgorithm() and CompositePrivateKey.getAlgorithm() returned null for all twelve Composite ML-KEM (draft-ietf-lamps-pq-composite-kem) parameter sets. Both classes resolved the name through the composite signature index only, which holds the composite ML-DSA OIDs, so a composite KEM key pair - generated, parsed from a certificate, or read from PKCS#8 - reported no algorithm at all, and the standard JCA idiom of reconstructing a key with KeyFactory.getInstance(key.getAlgorithm()) raised a NullPointerException. The lookup now falls back to the composite KEM index, so the name returned is the one the provider registers the algorithm under (e.g. MLKEM768-X25519-SHA3-256), matching the composite ML-DSA behaviour. The same single-index assumption made the CompositePublicKey(SubjectPublicKeyInfo) and CompositePrivateKey(PrivateKeyInfo) constructors reject a composite KEM key with \u0026quot;unable to create CompositePublicKey from SubjectPublicKeyInfo\u0026quot;; they now dispatch to the composite KEM key factory for those OIDs. Keys obtained through KeyFactory or through BouncyCastleProvider.getPublicKey / getPrivateKey were unaffected and are unchanged (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2404\"\u003e#2404\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe org.bouncycastle.jcajce.spec.KEMKDFSpec constructor stored a null otherInfo as given, so getOtherInfo() returned null, and three of the KDF branches KdfUtil.makeKeyBytes dispatches to - KMAC-128, KMAC-256 and SHAKE-256 - read the otherInfo length without a guard and threw NullPointerException out of the KEM operation, where the KDF2, KDF3 and HKDF branches tolerate a null through KDFParameters / HKDFParameters. The Builder of every spec in the package already mapped null to empty, so no provider path reached it, but the constructor is protected on a public class and KdfUtil is documented for callers building their own KEM integration; the deprecated KEMParameterSpec passes a null itself and escaped only because it also pins the KDF to null. The constructor now stores empty for a null, so getOtherInfo() never returns null, and a null and an explicitly empty otherInfo derive the same key.\u003c/li\u003e\n\u003cli\u003eQR-UOV signature verification accepted a signature encoding that was not canonical, so the encoding of a signature was not unique even after the trailing-byte fix of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e. Each F_q element of the signature is stored in ceil(log2 q) bits, one more bit pattern than the field has elements: q itself is representable and is arithmetically congruent to zero, so an element written as q verified exactly as the same element written as zero would, and the bits padding the last element out to the byte boundary were never read at all. Every zero element of a signature therefore carried a second encoding, and for the q = 7 parameter sets roughly one element in seven is zero - a single qruov_5_q7_L10 signature measured 256 spare bits, so on the order of 2^256 distinct byte strings verified for the one message and key. Verification now rejects any element outside [0, q) and any set padding bit; a signature produced by this or by the reference implementation is unaffected, as the KAT vectors of every parameter set confirm. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSNOVA signature verification ignored four bits inside the signature for any parameter set whose solution is an odd number of GF(16) nibbles - the SNOVA_24_5_5, SNOVA_25_8_3, SNOVA_29_6_5 and SNOVA_66_15_3 families, sixteen of the forty-four parameter sets. The last byte of the encoded solution carries a single nibble and the signer leaves the top four bits zero, but the decoder did not read them, so sixteen distinct byte strings verified for one signature. This is the same non-unique encoding github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e closed for bytes following the signature, applied inside it; the verifier now requires those bits to be zero. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSnovaPrivateKeyParameters did not validate the length of the private key encoding handed to it - the only one of the five schemes of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e that did not - and SnovaParameters.getPrivateKeyLength() reported the expanded (\u0026quot;ESK\u0026quot;) length even for a parameter set whose private key is the seed pair. A private key encoding reaches this constructor straight from a PKCS#8 blob, so a wrong length went undetected: a seed-form key with extra bytes appended was accepted and signed under a different derived key, and a short expanded-form key sized the signer's decode buffer negatively, throwing NegativeArraySizeException out of generateSignature() rather than being reported at construction. Related, the signing retry loop could not terminate: the vinegar values are derived from a single-byte counter, so only 256 distinct linear systems can be tried, and an expanded-form private key that is not a real central map is singular for all of them - generateSignature() then span forever rather than failing. The length is now checked at construction, getPrivateKeyLength() reports the length that parameter set's private key actually has, and the retry loop gives up after its 256 attempts as MAYO's does.\u003c/li\u003e\n\u003cli\u003eMayoSigner and MayoKeyPairGenerator did not clear several buffers holding secret key material that the MAYO reference implementation explicitly clears. Signing left the secret oil space O, the expanded L = (P1 + P1^t) * O + P2, and the M / VPV / Ox intermediates of the central map in place, having gone to the trouble of clearing eleven other buffers; key generation left the expanded seed, whose tail is the encoded oil space, and the P1 * O + P2 half of P; and the row-echelon step left the packed echelon form of the secret linear system and its pivot rows. Separately, if all 256 attempts at solving for the signature had given a rank-deficient system, signing emitted a signature built from the failed attempt's state instead of reporting the failure the reference returns, and AIMerSigner.generateSignature returned an empty array on failure, which a caller would hand on as though it were a signature. Both now throw.\u003c/li\u003e\n\u003cli\u003eFive PQC signature schemes - MAYO, SNOVA, QR-UOV, SQIsign and AIMer - returned the NIST crypto_sign \u0026quot;sm\u0026quot; signed-message envelope from generateSignature() rather than the signature. That envelope is an artefact of the reference KAT harness, which records the message alongside the signature so a vector file can be self-contained; it is not part of any of the five specifications, and no other BC signer emits it (Falcon's KAT test rebuilds the equivalent envelope in the test, which is where it belongs). Two consequences followed, both reaching the JCA Signature services of every parameter set of the five schemes in BouncyCastlePQCProvider. First, since the message was appended to the signature, verification had to skip whatever followed the signature proper, and it did so by checking only that the buffer was long enough - so any number of trailing bytes could be added to a valid signature, or the appended message replaced with unrelated data, and it still verified. A signature encoding was therefore not unique: anyone holding one valid signature could produce unlimited distinct byte strings that all verified for the same message and key, which breaks any use that treats the signature bytes as an identifier, deduplicates on them, or records them as evidence. Second, the envelope propagated into everything built on the operator layer: because ContentSigner hands the signature straight into the structure being signed, every X.509 certificate, CRL, CMS SignedData and TLS CertificateVerify BC produced with one of these algorithms carried a verbatim copy of the signed data inside its own signature field - a self-signed MAYO-1 certificate came to 3567 bytes where the same certificate is now 2020 - which no other implementation can parse as a signature, and which in a detached CMS signature meant the \u0026quot;detached\u0026quot; signature carried the content. generateSignature() now returns the bare signature, and verifySignature() requires exactly the parameter set's signature length, so appended or truncated data is rejected rather than ignored. \u003cstrong\u003eThis is a behavioural change for signatures produced by an earlier release\u003c/strong\u003e - MAYO and SNOVA from 1.84, QR-UOV, SQIsign and AIMer from 1.85 - which are no longer accepted in the envelope form they were emitted in; the signature bytes themselves are unchanged, so a stored value can be recovered by taking the leading signature-length bytes, or for AIMer, whose envelope was message || signature rather than signature || message, the trailing ones. The KAT tests now rebuild the envelope before comparing against the vector files, which continue to record it. Note that AIMer's verification had already been made length-exact during this cycle (see the entry below relating to github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2401\"\u003e#2401\u003c/a\u003e), so of the five only its envelope remained (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe MLS implementation did not bind an X.509 credential to the LeafNode's signature_key. LeafNode.verify() checked a leaf's signature against the signature_key declared in the leaf itself, while the X.509 credential's certificate chain was stored but never parsed or checked, so the certificate's public key was never required to match signature_key (RFC 9420 sec. 5.3). A leaf could therefore carry one party's certificate while being signed by an unrelated key and still be accepted under that party's identity through KeyPackage.verify() and the Group leaf-validation path. LeafNode.verify() now requires the end-entity certificate's subject public key, in the cipher suite's signature encoding, to equal signature_key for an X.509 credential, and rejects the leaf otherwise - including an empty chain or a certificate whose key type does not match the cipher suite; certificate-chain and identity validation to a trust anchor remain the application's responsibility per RFC 9420 sec. 5.3.1. A public org.bouncycastle.mls.codec.Certificate(byte[]) constructor and a Credential.getCertificates() accessor are added so callers can build and inspect X.509 credentials. Basic credentials are unaffected.\u003c/li\u003e\n\u003cli\u003eThe SecureRandom supplied to org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder.setSecureRandom() did not drive the content IV / nonce for any algorithm other than RC2. EnvelopedDataHelper.generateParameters passed the caller's SecureRandom to the AlgorithmParameterGenerator only in the RC2_CBC branch; every other content-encryption algorithm - AES-CBC, AES-GCM, AES-CCM, Camellia, ARIA, SEED and the rest - reached pGen.generateParameters() on an uninitialised generator, so the IV / nonce was drawn from a default SecureRandom and setSecureRandom() was silently ignored (the builder's javadoc states that random is used for IV/nonce generation). The generator is now initialised with the supplied random on the general path as well, so a caller who provides a specific randomness source - for a controlled or FIPS-approved DRBG, say - has it honoured for the content IV / nonce. The session-key generation path was unaffected and already used the supplied random. Because the content IV / nonce now comes from the supplied SecureRandom, the org.bouncycastle.crypto.util JournalingSecureRandom / JournaledAlgorithm reproducible-encryption support records it in the transcript: a resumed session reproduces the IV / nonce by regenerating it from the replayed randomness - build the resuming encryptor from the content-algorithm OID - rather than by reusing the AlgorithmIdentifier captured from the first encryption, which no longer keeps the transcript aligned.\u003c/li\u003e\n\u003cli\u003eThe NTRU LPRime, NTRU+ and SMAUG-T KEM generators threw a NullPointerException when constructed with a null SecureRandom, where every other KEM generator - including NTRU LPRime's own SNTRU Prime counterpart in the same package - defaults one through CryptoServicesRegistrar.getSecureRandom(). This is reachable from the lightweight API directly, and from javax.crypto.KEM, whose newEncapsulator() documents a null random as a request for the provider's default.\u003c/li\u003e\n\u003cli\u003eFrodoKEMEngine kept a single SHAKE instance in a field, so an engine reached concurrently produced wrong results. It is reached that way through org.bouncycastle.crypto.kems.FrodoKEMExtractor, which holds one engine for its lifetime: two threads extracting through one extractor interleaved the digest's absorb and squeeze phases, yielding shared secrets that silently did not match the sender's, or an IllegalStateException of \u0026quot;attempt to absorb while squeezing\u0026quot; from inside extractSecret. The digest is now built per call, as CMCEEngine's already was, which makes an extractor safe to share. Encapsulation was unaffected, since FrodoKEMGenerator builds an engine per call. Results for any single-threaded use are unchanged - the reference KAT vectors are byte-identical.\u003c/li\u003e\n\u003cli\u003eThe BCJSSE provider carried the TLS 1.2 coupling between the supported_groups extension and ECDSA over into TLS 1.3: an ECDSA signature scheme was treated as usable - offered in the signature_algorithms and signature_algorithms_cert extensions, and eligible when selecting the local credentials - only while the corresponding curve was among the named groups enabled for key exchange, both per context (a group unavailable for key agreement disabled the scheme outright) and per connection (the curve had to be in the supported_groups list about to be sent). RFC 8446 sec. 4.2.7 scopes supported_groups to key exchange only, with signature algorithms negotiated independently (sec. 4.2.3), so this incorrect restriction in TLS 1.3 has been removed. Ed25519, Ed448 and the RSA schemes were unaffected (as well as typical deployments using a default configuration for named groups).\u003c/li\u003e\n\u003cli\u003eThe bcmail module descriptor did not declare its javax.mail/javax.activation dependences, so a modular (module-path) consumer of the jar hit IllegalAccessError/module-resolution failures when the S/MIME classes touched the mail API. The descriptor now requires them optionally (requires static) under all four module names those libraries are known by - the automatic names mail and activation carried by the javax.mail:mail / javax.activation:activation artifacts, and the explicit names java.mail and java.activation carried by the newer com.sun.mail / com.sun.activation ones - a hard requires on any one name would break users of the others (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2389\"\u003e#2389\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFour type-coercion helpers in the OER / IEEE 1609.2 (ITS) decoder tested the wrong type in the identity fast path that lets a getInstance() factory return an argument that is already of the target type. org.bouncycastle.oer.its.ieee1609dot2.basetypes.UINT32.getInstance and org.bouncycastle.oer.its.etsi102941.basetypes.Version.getInstance guarded on UINT8 - a sibling of UINT32 under UintBase, and unrelated to Version - so passing a UINT8 threw ClassCastException, while passing an actual UINT32 or Version missed the fast path and fell through to ASN1Integer.getInstance, which rejects them: neither factory accepted its own type. org.bouncycastle.oer.its.etsi103097.EtsiTs103097DataEncryptedUnicast.getInstance guarded on its sibling EtsiTs103097DataEncrypted and then cast to the unicast type, so an EtsiTs103097DataEncrypted threw ClassCastException. org.bouncycastle.oer.OEROptional.getObject(Class) called value.getClass().isInstance(type) with the arguments transposed, which is always false because the argument is a java.lang.Class, so the cast path was dead and every optional field was resolved reflectively, failing with IllegalStateException for a target type with no static getInstance. Each guard now names the type it returns, matching the sibling UINT8 / UINT16 / UINT64 and EtsiTs103097DataEncrypted factories (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2373\"\u003e#2373\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eDefaultAlgorithmNameFinder and DefaultSignatureNameFinder had no entries at all for the ShangMi algorithms, so an SM2 signature AlgorithmIdentifier that DefaultSignatureAlgorithmIdentifierFinder itself produces came back named only by its OID string - getAlgorithmName(GMObjectIdentifiers.sm2sign_with_sm3) returned \u0026quot;1.2.156.10197.1.501\u0026quot; and hasAlgorithmName returned false. Both finders now name sm2sign_with_sm3 as SM3WITHSM2 and sm2sign_with_sha256 as SHA256WITHSM2, and DefaultAlgorithmNameFinder additionally names the sm3 digest. All three resolve through the BC provider, as Signature and MessageDigest respectively. The remaining GM arc - the SM4 cipher modes, the sm2encrypt variants, and the SM1 / SM6 / SSF33 ciphers BC does not implement - is still unnamed (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2377\"\u003e#2377\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe RFC 4998 evidence-record classes compared the digest AlgorithmIdentifier named by a time-stamp authority with the one their own DigestCalculator uses, and did so with AlgorithmIdentifier.equals(), which compares the encodings. A TSA that names SHA-256 with an explicit NULL parameters field - DigiCert among them - therefore failed against BC's own calculator, which names it with the parameters absent, and ERSArchiveTimeStampGenerator.generateArchiveTimeStamp rejected the response with \u0026quot;time stamp imprint for wrong algorithm\u0026quot;. Both spellings name the same digest and RFC 5754 sec. 2 requires a receiver to accept either, while requiring that identifiers be generated with the parameters absent, which BC already does. The three affected comparisons - the two in ERSArchiveTimeStampGenerator and the digest check in ERSEvidenceRecord.renew - now use the new AlgorithmIdentifier.areEquivalent, which matches on the algorithm and treats an absent parameters field and NULL as the same, and the consistency check across an evidence record's archive time stamp chain uses it too. An identifier carrying an actual parameter structure is never equivalent to one carrying none (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2379\"\u003e#2379\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eEDIPartyName.toASN1Primitive emitted the nameAssigner and partyName DirectoryStrings without their context tags, so an EDIPartyName built through its public constructor could not be parsed back by EDIPartyName.getInstance, which correctly requires them. RFC 5280 sec. 4.2.1.6 tags both members [0] and [1], and those tags are explicit despite the module's IMPLICIT TAGS because DirectoryString is a CHOICE, which X.680 does not allow to be tagged implicitly - the decoder already had this right. The encoder now matches it. Note the type was added during the 1.85 cycle and GeneralName validates its ediPartyName alternative through it, so a GeneralName carrying an untagged ediPartyName - including one BC itself produced - is rejected where 1.84 passed it through unexamined; the untagged form is not read leniently (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2380\"\u003e#2380\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eRSASSA-PSS could not be used with a RIPEMD digest through the JCA API. Nothing registered the RIPEMD PSS signatures, so Signature.getInstance(\u0026quot;RIPEMD160WITHRSAANDMGF1\u0026quot;) raised NoSuchAlgorithmException, and the generic RSASSA-PSS route with an explicit PSSParameterSpec failed too: org.bouncycastle.jcajce.provider.util.DigestFactory.getDigest returned null for a RIPEMD name, and isSameDigest - an allow-list of the SHA families and MD5 - reported two identical RIPEMD names as different digests, so the spec was rejected with \u0026quot;digest algorithm for MGF should be the same as for PSS parameters\u0026quot;. isSameDigest now answers true for equal names whatever the digest, which also covers Whirlpool, SM3, GOST3411 and anything else outside that allow-list; DigestFactory recognises RIPEMD128, RIPEMD160 and RIPEMD256 by name and OID; the three PSS signatures are registered with MGF1 over the same digest and a salt of the digest length; and DefaultSignatureAlgorithmIdentifierFinder gains the matching RIPEMD*WITHRSAANDMGF1 entries with their RSASSA-PSS-params, so the operator/JcaContentSignerBuilder path works as well. Note BC continues to require the PSS hash and the MGF1 hash to be the same, which RFC 8017 does not itself demand (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2381\"\u003e#2381\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe opt-in key-size validation on CMS key-transport recipients (org.bouncycastle.cms.jcajce.JceKeyTransRecipient.setKeySizeValidation(true)) never ran for a message using RFC 9709 CEK derivation (id-alg-cek-hkdf-sha256): the branch that should have selected the actual content-encryption algorithm carried in the KDF AlgorithmIdentifier's parameters compared the encrypted-key byte array against the id-alg-cek-hkdf-sha256 object identifier - a comparison that is always false - so the check fell through to a key-size lookup on the outer KDF OID, which has no registered key size, and silently checked nothing. A key-transport EnvelopedData/AuthEnvelopedData whose transported (and HKDF-derived) content-encryption key did not match the key size of the advertised content-encryption algorithm was therefore accepted even with validation enabled. The recipient now dispatches on the content-encryption AlgorithmIdentifier's algorithm OID, so key-size validation of RFC 9709 messages checks the recovered key against the inner content-encryption algorithm. Messages with a matching key size, non-HKDF messages, and recipients that do not enable validation are unaffected.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003eSee full diff in \u003ca href=\"https://github.com/bcgit/bc-java/commits\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003ecommonmark-java 0.29.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e[0.29.0] - 2026-06-20\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/42b4fb7adfe288ef13e9e27ab20aff7e91b0ab9d\"\u003e\u003ccode\u003e42b4fb7\u003c/code\u003e\u003c/a\u003e Prepare CHANGELOG for version 0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/b76e09d7a8362abb5f04e1d6b91dbd6da279a6fc\"\u003e\u003ccode\u003eb76e09d\u003c/code\u003e\u003c/a\u003e Limit how deep inline nodes may nest by default (100)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/49f65cb5cbec93cff713179990307145198e7061\"\u003e\u003ccode\u003e49f65cb\u003c/code\u003e\u003c/a\u003e Fix StackOverflowEr...\n\n_Description has been truncated_","html_url":"https://github.com/SpaceX-mit/openclaw-handbook/pull/30","url":"https://dependabot.ecosyste.ms/api/v1/hosts/GitHub/repositories/SpaceX-mit%2Fopenclaw-handbook/issues/30","packages_url":"https://dependabot.ecosyste.ms/api/v1/issues/30/packages"}},{"old_version":"5.3.2","new_version":"5.5.0","update_type":"minor","path":null,"pr_created_at":"2026-09-09T18:27:01.000Z","version_change":"5.3.2 → 5.5.0","issue":{"uuid":"5403242676","node_id":"PR_kwDOS-Nvx88AAAABC4NQFQ","number":42,"state":"closed","title":"chore(deps): bump the android-deps group across 1 directory with 21 updates","user":"dependabot[bot]","labels":["dependencies","java"],"assignees":[],"locked":false,"comments_count":1,"pull_request":true,"closed_at":"2026-09-11T18:25:43.000Z","author_association":null,"state_reason":null,"created_at":"2026-09-09T18:27:01.000Z","updated_at":"2026-09-11T18:25:44.000Z","time_to_close":172722,"merged_at":null,"merged_by":null,"closed_by":null,"dependency_metadata":{"prefix":"chore(deps): bump","group_name":"android-deps","update_count":21,"packages":[{"name":"gradle-wrapper","old_version":"9.4.1","new_version":"9.7.1","repository_url":"https://github.com/gradle/gradle"},{"name":"androidx.core:core-ktx","old_version":"1.18.0","new_version":"1.19.0"},{"name":"org.bouncycastle:bcprov-jdk18on","old_version":"1.84","new_version":"1.85.2","repository_url":"https://github.com/bcgit/bc-java"},{"name":"org.commonmark:commonmark","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-autolink","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-strikethrough","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-tables","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-task-list-items","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"dnsjava:dnsjava","old_version":"3.6.4","new_version":"3.6.5","repository_url":"https://github.com/dnsjava/dnsjava"},{"name":"org.junit.vintage:junit-vintage-engine","old_version":"6.0.3","new_version":"6.1.3","repository_url":"https://github.com/junit-team/junit-framework"},{"name":"io.kotest:kotest-assertions-core-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"io.kotest:kotest-runner-junit5-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"org.jetbrains.kotlinx:kotlinx-coroutines-android","old_version":"1.10.2","new_version":"1.11.0","repository_url":"https://github.com/Kotlin/kotlinx.coroutines"},{"name":"org.jetbrains.kotlinx:kotlinx-coroutines-test","old_version":"1.10.2","new_version":"1.11.0","repository_url":"https://github.com/Kotlin/kotlinx.coroutines"},{"name":"com.google.android.material:material","old_version":"1.13.0","new_version":"1.14.0","repository_url":"https://github.com/material-components/material-components-android"},{"name":"com.squareup.okhttp3:mockwebserver","old_version":"5.3.2","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.squareup.okhttp3:okhttp","old_version":"5.3.2","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.android.application","old_version":"9.2.0","new_version":"9.4.0"},{"name":"com.android.test","old_version":"9.2.0","new_version":"9.4.0"},{"name":"org.jetbrains.kotlin.plugin.compose","old_version":"2.3.21","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"},{"name":"org.jetbrains.kotlin.plugin.serialization","old_version":"2.3.21","new_version":"2.4.20","repository_url":"https://github.com/JetBrains/kotlin"}],"path":null,"ecosystem":"maven"},"body":"Bumps the android-deps group with 21 updates in the /apps/android directory:\n\n| Package | From | To |\n| --- | --- | --- |\n| [gradle-wrapper](https://github.com/gradle/gradle) | `9.4.1` | `9.7.1` |\n| androidx.core:core-ktx | `1.18.0` | `1.19.0` |\n| [org.bouncycastle:bcprov-jdk18on](https://github.com/bcgit/bc-java) | `1.84` | `1.85.2` |\n| [org.commonmark:commonmark](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-autolink](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-strikethrough](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-tables](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-task-list-items](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [dnsjava:dnsjava](https://github.com/dnsjava/dnsjava) | `3.6.4` | `3.6.5` |\n| [org.junit.vintage:junit-vintage-engine](https://github.com/junit-team/junit-framework) | `6.0.3` | `6.1.3` |\n| [io.kotest:kotest-assertions-core-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [io.kotest:kotest-runner-junit5-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [org.jetbrains.kotlinx:kotlinx-coroutines-android](https://github.com/Kotlin/kotlinx.coroutines) | `1.10.2` | `1.11.0` |\n| [org.jetbrains.kotlinx:kotlinx-coroutines-test](https://github.com/Kotlin/kotlinx.coroutines) | `1.10.2` | `1.11.0` |\n| [com.google.android.material:material](https://github.com/material-components/material-components-android) | `1.13.0` | `1.14.0` |\n| [com.squareup.okhttp3:mockwebserver](https://github.com/lysine-dev/okhttp) | `5.3.2` | `5.5.0` |\n| [com.squareup.okhttp3:okhttp](https://github.com/lysine-dev/okhttp) | `5.3.2` | `5.5.0` |\n| com.android.application | `9.2.0` | `9.4.0` |\n| com.android.test | `9.2.0` | `9.4.0` |\n| [org.jetbrains.kotlin.plugin.compose](https://github.com/JetBrains/kotlin) | `2.3.21` | `2.4.20` |\n| [org.jetbrains.kotlin.plugin.serialization](https://github.com/JetBrains/kotlin) | `2.3.21` | `2.4.20` |\n\n\nUpdates `gradle-wrapper` from 9.4.1 to 9.7.1\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/gradle/gradle/releases\"\u003egradle-wrapper's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e9.7.1\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.1.\u003c/p\u003e\n\u003cp\u003eThis is a patch release for 9.7.0. We recommend using 9.7.1 instead of 9.7.0.\u003c/p\u003e\n\u003cp\u003eHere are the highlights of 9.7.0 release:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIsolated Projects graduates to incubating\u003c/li\u003e\n\u003cli\u003eBroader Configuration Cache compatibility\u003c/li\u003e\n\u003cli\u003eResilient Sync helps you fix broken builds\u003c/li\u003e\n\u003cli\u003eMore source locations in problem reports\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003ca href=\"https://docs.gradle.org/9.7.1/release-notes.html\"\u003eRead the Release Notes\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eWe would like to thank the following community members for their contributions to this release of Gradle:\n\u003ca href=\"https://github.com/aSemy\"\u003eAdam\u003c/a\u003e,\n\u003ca href=\"https://github.com/Gautam-aman\"\u003eAman Gautam\u003c/a\u003e,\n\u003ca href=\"https://github.com/YukiCodepth\"\u003eAman Kumar\u003c/a\u003e,\n\u003ca href=\"https://github.com/adubrouski\"\u003eAnton Dubrouski\u003c/a\u003e,\n\u003ca href=\"https://github.com/liutikas\"\u003eAurimas\u003c/a\u003e,\n\u003ca href=\"https://github.com/gbhavya07\"\u003egbhavya07\u003c/a\u003e,\n\u003ca href=\"https://github.com/joshfriend\"\u003eJosh Friend\u003c/a\u003e,\n\u003ca href=\"https://github.com/nicklauslittle-gov\"\u003enicklauslittle-gov\u003c/a\u003e,\n\u003ca href=\"https://github.com/psoni674\"\u003ePragati\u003c/a\u003e,\n\u003ca href=\"https://github.com/Project516\"\u003eproject516\u003c/a\u003e,\n\u003ca href=\"https://github.com/Uomocapra\"\u003eQin Mi\u003c/a\u003e,\n\u003ca href=\"https://github.com/rkdfx\"\u003eRavi\u003c/a\u003e,\n\u003ca href=\"https://github.com/sk-reddy17\"\u003esk-reddy17\u003c/a\u003e,\n\u003ca href=\"https://github.com/Suvrat1629\"\u003eSuvrat Acharya\u003c/a\u003e,\n\u003ca href=\"https://github.com/ShreckYe\"\u003eYongshun Ye\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eUpgrade instructions\u003c/h2\u003e\n\u003cp\u003eSwitch your build to use Gradle 9.7.1 by updating your wrapper:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e./gradlew :wrapper --gradle-version=9.7.1 \u0026amp;\u0026amp; ./gradlew :wrapper\r\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eSee the Gradle \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/upgrading_version_9.html\"\u003e9.x upgrade guide\u003c/a\u003e to learn about deprecations, breaking changes and other considerations when upgrading.\u003c/p\u003e\n\u003cp\u003eFor Java, Groovy, Kotlin and Android compatibility, see the \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/compatibility.html\"\u003efull compatibility notes\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eReporting problems\u003c/h2\u003e\n\u003cp\u003eIf you find a problem with this release, please file a bug on \u003ca href=\"https://github.com/gradle/gradle/issues\"\u003eGitHub Issues\u003c/a\u003e adhering to our issue guidelines.\nIf you're not sure you're encountering a bug, please use the \u003ca href=\"https://discuss.gradle.org/c/help-discuss\"\u003eforum\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eWe hope you will build happiness with Gradle, and we look forward to your feedback via \u003ca href=\"https://twitter.com/gradle\"\u003eTwitter\u003c/a\u003e or on \u003ca href=\"https://github.com/gradle\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003e9.7.0\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.0.\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/92f0512e7f06d84621afba191f75e265363890cf\"\u003e\u003ccode\u003e92f0512\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38892\"\u003e#38892\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/820ee75a99a179bbffa41bcedc6477b685fabb9f\"\u003e\u003ccode\u003e820ee75\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/82c23f9bd2a89b4cc644e1f90a28a8668feb3dee\"\u003e\u003ccode\u003e82c23f9\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering problem in KTS (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38878\"\u003e#38878\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/ef11a7268fe8cc8d6ab849ec911aa11220180553\"\u003e\u003ccode\u003eef11a72\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering issue\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/bb0d8a974a71b1003efea41e4046e98855cd5ff8\"\u003e\u003ccode\u003ebb0d8a9\u003c/code\u003e\u003c/a\u003e Make relevant tests polyglot (run for multiple DSLs)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/336e129d7f95c03486acafc97abf59734acfed48\"\u003e\u003ccode\u003e336e129\u003c/code\u003e\u003c/a\u003e Update signing configuration (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38874\"\u003e#38874\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/4bdf0da2dad9884d089a6062a45ea7183e7d735d\"\u003e\u003ccode\u003e4bdf0da\u003c/code\u003e\u003c/a\u003e Update signing configuration\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/cd9b92c1b82856248cf1dc58b50378238bec7b52\"\u003e\u003ccode\u003ecd9b92c\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38839\"\u003e#38839\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/5f4e381964897ad8d6b99e5a7c77f26dba3259fb\"\u003e\u003ccode\u003e5f4e381\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/1e08ab551367aeb5fb48b26e72807e1d2b27c939\"\u003e\u003ccode\u003e1e08ab5\u003c/code\u003e\u003c/a\u003e Keep type-use annotations in extracted ABI classes (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38810\"\u003e#38810\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/gradle/gradle/compare/v9.4.1...v9.7.1\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `androidx.core:core-ktx` from 1.18.0 to 1.19.0\n\nUpdates `org.bouncycastle:bcprov-jdk18on` from 1.84 to 1.85.2\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.md\"\u003eorg.bouncycastle:bcprov-jdk18on's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch1\u003eBouncy Castle Crypto Package - Release Notes\u003c/h1\u003e\n\u003ch2\u003e1.0 Introduction\u003c/h2\u003e\n\u003cp\u003eThe Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. The package is organised so that it contains a light-weight API suitable for use in any environment (including the J2ME) with the additional infrastructure to conform the algorithms to the JCE framework.\u003c/p\u003e\n\u003ch2\u003e2.0 Release History\u003c/h2\u003e\n\u003cp\u003e\u003c!-- raw HTML omitted --\u003e\u003c!-- raw HTML omitted --\u003e\u003c/p\u003e\n\u003ch3\u003e2.1.1 Version\u003c/h3\u003e\n\u003cp\u003eRelease: 1.86\u003cbr /\u003e\nDate: 2026, TBD\u003c/p\u003e\n\u003ch3\u003e2.1.2 Defects Fixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) let a subkey inherit the primary key's Key Flags when its own Subkey Binding signature carried no Key Flags subpacket, which made the two capability decisions taken for one subkey disagree. OpenPGPCertificate.OpenPGPComponentKey.isSigningKey() reads the effective flags, which fell back to the primary key's direct-key or primary user ID self-signature, so a subkey bound with no flags of its own counted as signing-capable; verifyEmbeddedPrimaryKeyBinding reads the binding signature's own flags, found no signing capability there, and so skipped the embedded Primary Key Binding (cross-certification) signature that RFC 9580 sec. 5.2.1.8 and sec. 10.1.3 require of a subkey that can issue signatures. A data signature made by such a subkey was therefore attributed to the certificate and reported valid by OpenPGPSignature.OpenPGPDocumentSignature.isValid() with the cross-certification requirement never applied, where GnuPG refuses the same certificate and message as not cross-certified. An attacker holding a third party's public signing subkey - which is public material - could bind it to their own primary key with a Subkey Binding signature they are able to make, carrying no Key Flags and no embedded Primary Key Binding signature, which they cannot make without the subkey's private key, and have that party's genuine signatures verify as valid under the attacker's own identity: misattribution of a real signature rather than a forgery of a new one, since the signature still has to be one the subkey actually made. Key Flags are a statement about the key the carrying signature refers to (RFC 9580 sec. 5.2.3.29), so a subkey no longer inherits them from the certificate-wide signatures of the primary key: a Subkey Binding signature that omits the subpacket now leaves the subkey with no capabilities rather than the primary's, which makes the flags the cross-certification check consults the same flags every other decision consults. Preferences and the other subpackets a direct-key signature carries are inherited as before, and the primary key itself - whose flags legitimately come from its direct-key or user ID self-signature - is unaffected. The low-level PGPSignature / PGPPublicKeyRing API performs no binding checks by design and is unchanged.\u003c/li\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) used a version 6 key that carried no valid Direct Key signature, falling back to the primary user ID binding as it correctly does for a version 4 key. RFC 9580 sec. 5.2.3.10 requires the opposite: \u0026quot;An implementation MUST ensure that a valid Direct Key signature is present before using a version 6 key. This prevents certain attacks where an adversary strips a self-signature specifying a Key Expiration Time or certain preferences.\u0026quot; The certificate grammar says the same structurally, the Direct Key signature being mandatory in the version 6 structure of sec. 10.1.1 and optional in the version 4 one of sec. 10.1.3. Because a version 6 certificate carries its key expiration, features and algorithm preferences on the Direct Key signature - the convention the RFC recommends and the one OpenPGPKeyGenerator follows, its user ID certification carrying no expiration at all - removing that single signature packet from a published certificate silently dropped the expiration along with the preferences and features: OpenPGPCertificate.getSignatureChainFor fell back to the user ID binding, the primary key was still reported bound, and getEncryptionKeys() and getSigningKeys() went on returning the subkeys of a key whose owner had set it to expire. The primary key fingerprint is unchanged by the removal, so a relying party pinning the key by fingerprint still treats it as the same key, and no private key or hash collision is involved; the natural moment for the strip is the key refresh that RFC 9580 names as the reason to refetch a key at all - to learn about changes in expiration, features, preferences and revocation - which is exactly the update it defeats. This is a downgrade rather than a forgery, nothing being attributed to a key that did not authorise it, and the concerning direction is encryption, to a key meant to have been retired. OpenPGPCertificate.isBoundBy now requires a valid Direct Key self-signature on a version 6 primary key before any component of the certificate - the primary key, its subkeys or its identities - is treated as bound, so a version 6 certificate stripped of it offers no keys at all rather than an unexpiring set. Version 4 certificates are unaffected: there the key expiration legitimately lives on the user ID self-signature and the fallback is correct, so it stays. The revocation-only version 6 certificate of sec. 10.1.2, which legitimately carries no Direct Key signature, is unaffected as well - its key was already refused as revoked, and reading the revocation does not go through the binding check.\u003c/li\u003e\n\u003cli\u003eThe lightweight LMSSigner and HSSSigner refused a key wrapped in ParametersWithRandom, which is how BcContentSignerBuilder passes a key whenever setSecureRandom() has been called - so BcHssLmsContentSignerBuilder built a working signer until a random was set and then failed with \u0026quot;Incorrect Key Parameters\u0026quot;, and the two signers themselves raised ClassCastException on the same input. All three now unwrap it, as the promoted ML-DSA and SLH-DSA signers already did. The random is accepted and not used: LMS derives its message randomiser C from the key's seed and the one-time index, so it is deterministic and cannot repeat while q does not. Note SP 800-208 sec. 6.1 asks for C to come from an approved random bit generator, which this implementation does not do; that is unchanged here, and a supplied random is now ignored rather than refused.\u003c/li\u003e\n\u003cli\u003eLMS signature verification did not apply two of the checks RFC 8554 sec. 5.4.2 requires before a signature is processed. Step 2g refuses a signature whose LMS typecode is not the one from the public key, and without it the path computation took its height and tree digest from the parameter set the signature named rather than the key's, so a signature claiming a height-25 parameter set drove a 25-level computation against a height-5 key. Step 2i refuses a leaf number q outside the tree, and without it an out-of-range q flowed into the node arithmetic and was left for the candidate-root comparison to catch. Neither was a forgery - the domain separation between D_LEAF and D_INTR and the final comparison saw to that - but both are attacker-chosen work the specification says to refuse up front. Both are now checked, and a signature failing either is still reported as not verifying rather than thrown out of Signature.verify(). The catch around the signature decode in LMSSigner and HSSSigner has also been narrowed to the decode itself, as the corresponding SPI was corrected to do for github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2408\"\u003e#2408\u003c/a\u003e: past the parse the engine reports an inconsistent signature by returning false rather than by throwing, so the wider catch caught nothing while standing ready to turn a future internal error into a quiet false.\u003c/li\u003e\n\u003cli\u003eThe LMS and HSS key parameter classes now apply at construction the checks their decoders apply, so a key built directly cannot be one the decoder would refuse. LMSPrivateKeyParameters accepted an identifier of any length although the decoder reads exactly 16 bytes - such a key encoded but could not be read back - and left q, maxQ and the seed length unchecked; the seed is now required to be at least m bytes at decode as well, where a one-byte seed had been decoding silently and then deriving every one-time key from it. HSSPrivateKeyParameters checked neither its level count nor that it had been given a component key per level and a chaining signature per level below the root, and then indexed both lists, so a mismatch surfaced as IndexOutOfBoundsException - or, where a level happened to match, as a null chaining signature that only failed at signing time; the level is now checked after the reset that fills it in, since a null is legitimate on the way in. LMSPrivateKeyParameters.getInstance(byte[], byte[]) adopted the public key supplied beside the private one without comparing them, so a mismatched public key was simply reported by getPublicKey(); it now cross-checks the identifier, both parameter sets and, where the tree cache already holds it, the root, as the HSS entry point does. The decoders also now report a bad version or seed length as IOException rather than IllegalStateException, so a caller can catch one type for a malformed key, and the package-private LM-OTS public key decoder no longer declares throws Exception or dereferences an unrecognised typecode. The deprecated org.bouncycastle.pqc.crypto.lms copies carry the decoder corrections.\u003c/li\u003e\n\u003cli\u003eIn the LMS JCE layer, LMSKeyGenParameterSpec.fromNames knew all twenty LMS parameter-set names but only four of the sixteen LM-OTS ones, so none of the SP 800-208 n24 or SHAKE sets could be named; all sixteen are now present. KeyPairGenerator.initialize(int, SecureRandom) reports InvalidParameterException, which is what the JCA specifies and which extends the IllegalArgumentException it raised before, so existing catches still match. BCLMSPrivateKey.getIndex now takes the exhaustion check and the index read under the key's own monitor rather than as two separate calls, and two unused fields have gone from LMSSignatureSpi. Note that the LMS Signature claims its one-time key at the first update() rather than at sign(), so a Signature that is initialised and updated and then abandoned spends an index without producing a signature - the safe direction for a one-time scheme, and now documented on the SPI.\u003c/li\u003e\n\u003cli\u003eEvery other key pair generator that refuses a key size did the same thing the LMS one did above. KeyPairGenerator.initialize(int, SecureRandom) is documented to raise InvalidParameterException when the key size is not one the generator supports, and thirty of them raised a bare IllegalArgumentException instead, so a caller following the JCA and catching the documented type saw an exception escaping rather than a refusal. The ML-DSA, ML-KEM, SLH-DSA, Classic McEliece, FrodoKEM, NTRU and composite signature and KEM generators in the BC provider, and every generator in BCPQC, now raise InvalidParameterException - NewHope included, where the value is a key size it will not take rather than a mode of initialisation it does not offer. InvalidParameterException extends IllegalArgumentException, so callers written against the old behaviour go on catching it unchanged. The two RSA generators are corrected as well, and differently: theirs is a key size below a floor rather than a mode of initialisation they do not offer, and the refusal is raised by the lightweight RSAKeyGenerationParameters, which cannot name a java.security exception at all, so the RSA KeyPairGeneratorSpi now translates it - keeping the message verbatim and the original exception as the cause, through a new SecurityExceptions.invalidParameterException factory, since InvalidParameterException has no constructor that takes one. Of the 304 KeyPairGenerator services the two providers register, 299 now refuse a nonsense key size the way the JCA defines it and five accept it as a strength they can work with, with none left raising a bare IllegalArgumentException; that is asserted as a sweep over both providers rather than per algorithm, so a generator added later is covered without the test being touched. The jdk1.3 provider overlays of the four generators that have one carry the same change, and the jdk1.3 SecurityExceptions overlay gains the new factory along with the invalidAlgorithmParameterException one it had been missing.\u003c/li\u003e\n\u003cli\u003eKeyPairGenerator.initialize(AlgorithmParameterSpec, SecureRandom) had the same shape of problem as the int overload above, and only 44 of the 304 services the two providers register reported an unusable spec as the InvalidAlgorithmParameterException that method declares. The twenty-three PQC generators that resolve a parameter set by name - cmce, frodokem, mldsa, mlkem, slhdsa, aimer, bike, faest, falcon, haetae, hqc, mayo, mqom, ntru, ntruplus, both ntruprime variants, qruov, saber, sdith, smaugt, snova and sqisign, 230 services between them - case-folded the name they got back from the spec without checking it, so a spec with no getName() method, and a null spec, produced a NullPointerException from inside the fold; their own \u0026quot;is this name one I know\u0026quot; branch, which does report the declared exception, was unreachable. The two composite generators, whose parameter set is fixed by the algorithm name so that null is the only spec they accept, refused every other one with IllegalArgumentException. RSA answered correctly for a spec of the wrong type but not for one of the right type carrying values its lightweight parameters will not take - an even public exponent, or a key size below the floor - which is now translated the same way the int overload's is. All 304 services now report the declared exception, with the composites still taking the null spec that is right for them; note that InvalidAlgorithmParameterException is a checked exception and not an IllegalArgumentException, so a caller that was catching what these threw before has to catch the declared type instead.\u003c/li\u003e\n\u003cli\u003eAn HSS private key claimed the two records of its position under two different monitors. The top-level index and the bottom component key's one-time index q are independent records of the same position - the decoder requires them to agree, see the entry below - but generateLMSContext incremented the index under the HSS key's own monitor, released it, and only then claimed q under the component key's. A getEncoded() issued in between saw the index advanced and q not, and produced an encoding this implementation's own decoder rejects; and two threads meeting at a bottom-tree boundary could both pass the exhaustion test, take consecutive top-level indices and claim the same q, after which one of them was refused with \u0026quot;ots private key exhausted\u0026quot; by a key still reporting usages remaining, a top-level index had been spent with no signature made, and the two records stayed one apart for the rest of the key's life in that process - so it could no longer be encoded, cloned or sharded, and getIndex() and getUsagesRemaining() misreported by one. No one-time key was reused: the component key's claim is itself atomic, and the divergence runs index ahead of leaves, so the effect was on the key's usability rather than on the signatures it had made. Both records are now claimed under the one monitor, and the component key is claimed before the index is incremented so that an exhausted one leaves both untouched. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the same correction.\u003c/li\u003e\n\u003cli\u003eTimeStampToken parsed the attacker-controlled TSTInfo content of a time-stamp token (org.bouncycastle.tsp.TimeStampToken, reached from TimeStampResponse(byte[]) and (InputStream)) inside a try that caught only CMSException, so a well-formed RFC 3161 TimeStampResp whose embedded token carried a malformed TSTInfo - a SEQUENCE with fewer elements than the five mandatory fields, a non-SEQUENCE, truncated DER, or an unknown context tag - let an IllegalArgumentException or a NoSuchElementException escape the constructor's declared throws TSPException, IOException contract. A token signed by no signers or by more than one raised a bare IllegalArgumentException from the same constructor, before that try, for the same reason. Both are now reported as TSPException, matching the package-private TimeStampResponse(DLSequence) constructor and the existing getSignedAttributes guard in the same method; the signer-count refusal is a TSPValidationException, as the neighbouring check on the content type already was. Related, and the cause of the NoSuchElementException: asn1.tsp.TSTInfo read its five mandatory fields off the sequence with no bound on how many elements were actually there, so a short SEQUENCE left the enumeration to run out rather than being refused, and an oversize one was accepted with its extra elements absorbed into the optional slots. Decode now requires the five to ten elements RFC 3161 sec. 2.4.2 gives the type, which is what the sibling Accuracy and ArchiveTimeStamp decoders already did, so the failure is the IllegalArgumentException that getInstance is expected to raise (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2415\"\u003e#2415\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eNeither the HSS nor the XMSS^MT private key decoder checked its declared index against the traversal state stored beside it, although the two are independent records of the same position in the key and so can be compared. For HSS the records are the top-level index and the component keys' one-time indices q; for XMSS^MT they are the global index and the per-layer BDS states. A stored key whose index had been rolled back while its state stayed advanced - a partial write, a restore from backup, a buggy storage layer - was therefore accepted, and it then signed a second message under a one-time key the key had already used, producing a signature that verified, so nothing anywhere surfaced the reuse. RFC 8554 sec. 1 and RFC 8391 sec. 1.1 both require each one-time key to be used exactly once, and this is the failure those requirements exist to prevent; the single-tree XMSS decoder has tied its BDS state to its index since that state was first validated, and this brings the two multi-tree schemes into line. HSS decode now requires the declared index to equal the position the component q values imply - a level above the last contributes (q - 1) leaves of the levels beneath it, since its q has already advanced past the subtree it signed - and XMSS^MT decode now requires each present layer's BDS index to equal the leaf index that layer derives from the global index, allowing the one position where a layer has moved into a new subtree and its state legitimately still carries the previous subtree's final index. A layer with no state yet is unaffected, since those are built lazily at signing time. Related, and the same shape of omission: an XMSS or XMSS^MT private key encoding carries the tree root twice - the key's own root field and the root node of the BDS state stored beside it, which for XMSS^MT is the top layer's - and the two were never compared either. A corrupted root was accepted and then poisoned every signature the key made, because the root is hashed into the message digest: the signature did not verify and nothing indicated why. Decode now requires the two copies to agree. The BDS node values themselves are not checkable the way the LMS tree cache above is - a BDS authentication path, stack, retain or keep node does not have its children stored alongside it, so recomputing one means building a subtree, which is the work the state exists to avoid. Both checks are integer comparisons over the levels of the key, too small to measure against the surrounding decode, and both were verified not to reject any legitimate key by walking every index a key can reach: the full key space of the two-level HSS and the h=4/d=2, h=6/d=2, h=6/d=3, h=9/d=3 and h=8/d=4 XMSS^MT parameter sets, plus a three-level HSS key across a subtree boundary and an HSS shard. Since those node values cannot be recomputed, the encoded state now carries a checksum over itself instead, with the owning key's public seed hashed in front of it. Any corruption of the stored state is refused at decode rather than being loaded and then producing signatures that silently do not verify, and because the public seed is bound in, a state transplanted between two keys of the same parameter set is refused too, even though it is internally consistent and arrives with its own matching root. The public seed is bound rather than the secret seed or the PRF key deliberately: the state's own root and index are inside the encoding and so are already covered, hashing secret material would make the stored checksum a commitment to it for no gain in detection, and the PRF key does not influence the state at all. \u003cstrong\u003eThis is an error-detecting code and not integrity protection\u003c/strong\u003e - anyone able to rewrite the stored key recomputes it, so it establishes that the state is unchanged since it was written, never that it was correct when written, and the allocation bounds on the encoding remain the guard against a crafted one. It costs one SHA-256 over the state, measured at 5 to 8 microseconds each way for the h=10 and h=16 parameter sets, and 32 bytes of encoding. The state encoding was added earlier in this same cycle and has not been released, so the checksum is simply part of it rather than a new version: a state written by a 1.86 beta is rejected, which is recovered from by re-exporting the key. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the HSS check as well (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2414\"\u003e#2414\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe S/MIME example smoke test in the misc module (org.bouncycastle.mail.smime.examples.test.AllTests) drove SendSignedAndEncryptedMail against smtp.gmail.com, and that example finishes with Transport.send() under JavaMail's default settings, which have no connect timeout. Where outbound port 25 is refused the failure was swallowed and the test passed; where it is silently dropped, as on many home networks, the connect blocked and ./gradlew build hung in :misc:test indefinitely with \u0026quot;0 tests completed\u0026quot;. The test now delivers to an SMTP stub on a loopback port, with connect / read / write timeouts as a backstop, and asserts the message arrived (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2407\"\u003e#2407\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation took the traditional component public key bytes it feeds the KEM combiner from the recipient key's own encoding, while decapsulation recomputes the point from the private key and so always produced an uncompressed one. Section 4 of draft-ietf-lamps-pq-composite-kem requires an EC component to be carried as an uncompressed point, but a component key that encodes itself compressed - a BC EC key whose point format has been set through org.bouncycastle.jce.interfaces.ECPointEncoder, or a key from a provider that preserves a compressed encoding - was passed through as it came. Both sides then combined a different tradPK and derived different shared secrets, with no error reported on either: encapsulation and decapsulation both succeeded and the recipient simply could not decrypt. The EC component is now normalised to an uncompressed point wherever the engine serialises one, which covers the ephemeral key that forms the ciphertext as well. X25519 and X448 components have a single encoding and were unaffected, as were EC keys left in their default (uncompressed) format, whose shared secrets are unchanged. CompositePublicKey.getEncoded() took its component bytes the same way, so such a key also encoded to a composite key other implementations reject and whose bytes changed across an encode / decode / encode round trip - 1238 bytes rather than 1270 for MLKEM768-ECDH-P256, and for the composite ML-DSA keys sharing that method, 2006 rather than 2038 for MLDSA65-ECDSA-P256. It now normalises the component the same way. This is a write-side change only: a composite key carrying a compressed EC component is still decoded, since the component key factories accept either form, and continues to verify signatures as before - it simply re-encodes in the normalised form. The shared normalisation is org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil.getUncompressedSubjectPublicKeyBytes.\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation threw a NullPointerException, wrapped in an IllegalStateException out of KeyGenerator.generateKey(), when the SecureRandom it was given was null - which javax.crypto.KEM.newEncapsulator() documents as a request for the provider's default, and which KeyGenerator.init(spec, null) passes straight through. The three RSA-OAEP composites draw the traditional shared secret from that random directly, so they were the ones affected; the ECDH and X25519 / X448 composites escaped only because their component KeyPairGenerators default a random of their own. CompositeMLKEMEngine now defaults one through CryptoServicesRegistrar.getSecureRandom() on first use, as the composite KEM Cipher's wrap path already did, and as the KEM generators corrected earlier in this cycle now do. Related, the engine now also clears the ML-KEM component's shared secret alongside the traditional one on both the encapsulate and decapsulate paths - the copy handed back by getEncoded() was left in the heap - as section 3.5 of draft-ietf-lamps-pq-composite-kem requires.\u003c/li\u003e\n\u003cli\u003eCompositePublicKey.getAlgorithm() and CompositePrivateKey.getAlgorithm() returned null for all twelve Composite ML-KEM (draft-ietf-lamps-pq-composite-kem) parameter sets. Both classes resolved the name through the composite signature index only, which holds the composite ML-DSA OIDs, so a composite KEM key pair - generated, parsed from a certificate, or read from PKCS#8 - reported no algorithm at all, and the standard JCA idiom of reconstructing a key with KeyFactory.getInstance(key.getAlgorithm()) raised a NullPointerException. The lookup now falls back to the composite KEM index, so the name returned is the one the provider registers the algorithm under (e.g. MLKEM768-X25519-SHA3-256), matching the composite ML-DSA behaviour. The same single-index assumption made the CompositePublicKey(SubjectPublicKeyInfo) and CompositePrivateKey(PrivateKeyInfo) constructors reject a composite KEM key with \u0026quot;unable to create CompositePublicKey from SubjectPublicKeyInfo\u0026quot;; they now dispatch to the composite KEM key factory for those OIDs. Keys obtained through KeyFactory or through BouncyCastleProvider.getPublicKey / getPrivateKey were unaffected and are unchanged (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2404\"\u003e#2404\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe org.bouncycastle.jcajce.spec.KEMKDFSpec constructor stored a null otherInfo as given, so getOtherInfo() returned null, and three of the KDF branches KdfUtil.makeKeyBytes dispatches to - KMAC-128, KMAC-256 and SHAKE-256 - read the otherInfo length without a guard and threw NullPointerException out of the KEM operation, where the KDF2, KDF3 and HKDF branches tolerate a null through KDFParameters / HKDFParameters. The Builder of every spec in the package already mapped null to empty, so no provider path reached it, but the constructor is protected on a public class and KdfUtil is documented for callers building their own KEM integration; the deprecated KEMParameterSpec passes a null itself and escaped only because it also pins the KDF to null. The constructor now stores empty for a null, so getOtherInfo() never returns null, and a null and an explicitly empty otherInfo derive the same key.\u003c/li\u003e\n\u003cli\u003eQR-UOV signature verification accepted a signature encoding that was not canonical, so the encoding of a signature was not unique even after the trailing-byte fix of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e. Each F_q element of the signature is stored in ceil(log2 q) bits, one more bit pattern than the field has elements: q itself is representable and is arithmetically congruent to zero, so an element written as q verified exactly as the same element written as zero would, and the bits padding the last element out to the byte boundary were never read at all. Every zero element of a signature therefore carried a second encoding, and for the q = 7 parameter sets roughly one element in seven is zero - a single qruov_5_q7_L10 signature measured 256 spare bits, so on the order of 2^256 distinct byte strings verified for the one message and key. Verification now rejects any element outside [0, q) and any set padding bit; a signature produced by this or by the reference implementation is unaffected, as the KAT vectors of every parameter set confirm. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSNOVA signature verification ignored four bits inside the signature for any parameter set whose solution is an odd number of GF(16) nibbles - the SNOVA_24_5_5, SNOVA_25_8_3, SNOVA_29_6_5 and SNOVA_66_15_3 families, sixteen of the forty-four parameter sets. The last byte of the encoded solution carries a single nibble and the signer leaves the top four bits zero, but the decoder did not read them, so sixteen distinct byte strings verified for one signature. This is the same non-unique encoding github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e closed for bytes following the signature, applied inside it; the verifier now requires those bits to be zero. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSnovaPrivateKeyParameters did not validate the length of the private key encoding handed to it - the only one of the five schemes of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e that did not - and SnovaParameters.getPrivateKeyLength() reported the expanded (\u0026quot;ESK\u0026quot;) length even for a parameter set whose private key is the seed pair. A private key encoding reaches this constructor straight from a PKCS#8 blob, so a wrong length went undetected: a seed-form key with extra bytes appended was accepted and signed under a different derived key, and a short expanded-form key sized the signer's decode buffer negatively, throwing NegativeArraySizeException out of generateSignature() rather than being reported at construction. Related, the signing retry loop could not terminate: the vinegar values are derived from a single-byte counter, so only 256 distinct linear systems can be tried, and an expanded-form private key that is not a real central map is singular for all of them - generateSignature() then span forever rather than failing. The length is now checked at construction, getPrivateKeyLength() reports the length that parameter set's private key actually has, and the retry loop gives up after its 256 attempts as MAYO's does.\u003c/li\u003e\n\u003cli\u003eMayoSigner and MayoKeyPairGenerator did not clear several buffers holding secret key material that the MAYO reference implementation explicitly clears. Signing left the secret oil space O, the expanded L = (P1 + P1^t) * O + P2, and the M / VPV / Ox intermediates of the central map in place, having gone to the trouble of clearing eleven other buffers; key generation left the expanded seed, whose tail is the encoded oil space, and the P1 * O + P2 half of P; and the row-echelon step left the packed echelon form of the secret linear system and its pivot rows. Separately, if all 256 attempts at solving for the signature had given a rank-deficient system, signing emitted a signature built from the failed attempt's state instead of reporting the failure the reference returns, and AIMerSigner.generateSignature returned an empty array on failure, which a caller would hand on as though it were a signature. Both now throw.\u003c/li\u003e\n\u003cli\u003eFive PQC signature schemes - MAYO, SNOVA, QR-UOV, SQIsign and AIMer - returned the NIST crypto_sign \u0026quot;sm\u0026quot; signed-message envelope from generateSignature() rather than the signature. That envelope is an artefact of the reference KAT harness, which records the message alongside the signature so a vector file can be self-contained; it is not part of any of the five specifications, and no other BC signer emits it (Falcon's KAT test rebuilds the equivalent envelope in the test, which is where it belongs). Two consequences followed, both reaching the JCA Signature services of every parameter set of the five schemes in BouncyCastlePQCProvider. First, since the message was appended to the signature, verification had to skip whatever followed the signature proper, and it did so by checking only that the buffer was long enough - so any number of trailing bytes could be added to a valid signature, or the appended message replaced with unrelated data, and it still verified. A signature encoding was therefore not unique: anyone holding one valid signature could produce unlimited distinct byte strings that all verified for the same message and key, which breaks any use that treats the signature bytes as an identifier, deduplicates on them, or records them as evidence. Second, the envelope propagated into everything built on the operator layer: because ContentSigner hands the signature straight into the structure being signed, every X.509 certificate, CRL, CMS SignedData and TLS CertificateVerify BC produced with one of these algorithms carried a verbatim copy of the signed data inside its own signature field - a self-signed MAYO-1 certificate came to 3567 bytes where the same certificate is now 2020 - which no other implementation can parse as a signature, and which in a detached CMS signature meant the \u0026quot;detached\u0026quot; signature carried the content. generateSignature() now returns the bare signature, and verifySignature() requires exactly the parameter set's signature length, so appended or truncated data is rejected rather than ignored. \u003cstrong\u003eThis is a behavioural change for signatures produced by an earlier release\u003c/strong\u003e - MAYO and SNOVA from 1.84, QR-UOV, SQIsign and AIMer from 1.85 - which are no longer accepted in the envelope form they were emitted in; the signature bytes themselves are unchanged, so a stored value can be recovered by taking the leading signature-length bytes, or for AIMer, whose envelope was message || signature rather than signature || message, the trailing ones. The KAT tests now rebuild the envelope before comparing against the vector files, which continue to record it. Note that AIMer's verification had already been made length-exact during this cycle (see the entry below relating to github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2401\"\u003e#2401\u003c/a\u003e), so of the five only its envelope remained (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe MLS implementation did not bind an X.509 credential to the LeafNode's signature_key. LeafNode.verify() checked a leaf's signature against the signature_key declared in the leaf itself, while the X.509 credential's certificate chain was stored but never parsed or checked, so the certificate's public key was never required to match signature_key (RFC 9420 sec. 5.3). A leaf could therefore carry one party's certificate while being signed by an unrelated key and still be accepted under that party's identity through KeyPackage.verify() and the Group leaf-validation path. LeafNode.verify() now requires the end-entity certificate's subject public key, in the cipher suite's signature encoding, to equal signature_key for an X.509 credential, and rejects the leaf otherwise - including an empty chain or a certificate whose key type does not match the cipher suite; certificate-chain and identity validation to a trust anchor remain the application's responsibility per RFC 9420 sec. 5.3.1. A public org.bouncycastle.mls.codec.Certificate(byte[]) constructor and a Credential.getCertificates() accessor are added so callers can build and inspect X.509 credentials. Basic credentials are unaffected.\u003c/li\u003e\n\u003cli\u003eThe SecureRandom supplied to org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder.setSecureRandom() did not drive the content IV / nonce for any algorithm other than RC2. EnvelopedDataHelper.generateParameters passed the caller's SecureRandom to the AlgorithmParameterGenerator only in the RC2_CBC branch; every other content-encryption algorithm - AES-CBC, AES-GCM, AES-CCM, Camellia, ARIA, SEED and the rest - reached pGen.generateParameters() on an uninitialised generator, so the IV / nonce was drawn from a default SecureRandom and setSecureRandom() was silently ignored (the builder's javadoc states that random is used for IV/nonce generation). The generator is now initialised with the supplied random on the general path as well, so a caller who provides a specific randomness source - for a controlled or FIPS-approved DRBG, say - has it honoured for the content IV / nonce. The session-key generation path was unaffected and already used the supplied random. Because the content IV / nonce now comes from the supplied SecureRandom, the org.bouncycastle.crypto.util JournalingSecureRandom / JournaledAlgorithm reproducible-encryption support records it in the transcript: a resumed session reproduces the IV / nonce by regenerating it from the replayed randomness - build the resuming encryptor from the content-algorithm OID - rather than by reusing the AlgorithmIdentifier captured from the first encryption, which no longer keeps the transcript aligned.\u003c/li\u003e\n\u003cli\u003eThe NTRU LPRime, NTRU+ and SMAUG-T KEM generators threw a NullPointerException when constructed with a null SecureRandom, where every other KEM generator - including NTRU LPRime's own SNTRU Prime counterpart in the same package - defaults one through CryptoServicesRegistrar.getSecureRandom(). This is reachable from the lightweight API directly, and from javax.crypto.KEM, whose newEncapsulator() documents a null random as a request for the provider's default.\u003c/li\u003e\n\u003cli\u003eFrodoKEMEngine kept a single SHAKE instance in a field, so an engine reached concurrently produced wrong results. It is reached that way through org.bouncycastle.crypto.kems.FrodoKEMExtractor, which holds one engine for its lifetime: two threads extracting through one extractor interleaved the digest's absorb and squeeze phases, yielding shared secrets that silently did not match the sender's, or an IllegalStateException of \u0026quot;attempt to absorb while squeezing\u0026quot; from inside extractSecret. The digest is now built per call, as CMCEEngine's already was, which makes an extractor safe to share. Encapsulation was unaffected, since FrodoKEMGenerator builds an engine per call. Results for any single-threaded use are unchanged - the reference KAT vectors are byte-identical.\u003c/li\u003e\n\u003cli\u003eThe BCJSSE provider carried the TLS 1.2 coupling between the supported_groups extension and ECDSA over into TLS 1.3: an ECDSA signature scheme was treated as usable - offered in the signature_algorithms and signature_algorithms_cert extensions, and eligible when selecting the local credentials - only while the corresponding curve was among the named groups enabled for key exchange, both per context (a group unavailable for key agreement disabled the scheme outright) and per connection (the curve had to be in the supported_groups list about to be sent). RFC 8446 sec. 4.2.7 scopes supported_groups to key exchange only, with signature algorithms negotiated independently (sec. 4.2.3), so this incorrect restriction in TLS 1.3 has been removed. Ed25519, Ed448 and the RSA schemes were unaffected (as well as typical deployments using a default configuration for named groups).\u003c/li\u003e\n\u003cli\u003eThe bcmail module descriptor did not declare its javax.mail/javax.activation dependences, so a modular (module-path) consumer of the jar hit IllegalAccessError/module-resolution failures when the S/MIME classes touched the mail API. The descriptor now requires them optionally (requires static) under all four module names those libraries are known by - the automatic names mail and activation carried by the javax.mail:mail / javax.activation:activation artifacts, and the explicit names java.mail and java.activation carried by the newer com.sun.mail / com.sun.activation ones - a hard requires on any one name would break users of the others (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2389\"\u003e#2389\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFour type-coercion helpers in the OER / IEEE 1609.2 (ITS) decoder tested the wrong type in the identity fast path that lets a getInstance() factory return an argument that is already of the target type. org.bouncycastle.oer.its.ieee1609dot2.basetypes.UINT32.getInstance and org.bouncycastle.oer.its.etsi102941.basetypes.Version.getInstance guarded on UINT8 - a sibling of UINT32 under UintBase, and unrelated to Version - so passing a UINT8 threw ClassCastException, while passing an actual UINT32 or Version missed the fast path and fell through to ASN1Integer.getInstance, which rejects them: neither factory accepted its own type. org.bouncycastle.oer.its.etsi103097.EtsiTs103097DataEncryptedUnicast.getInstance guarded on its sibling EtsiTs103097DataEncrypted and then cast to the unicast type, so an EtsiTs103097DataEncrypted threw ClassCastException. org.bouncycastle.oer.OEROptional.getObject(Class) called value.getClass().isInstance(type) with the arguments transposed, which is always false because the argument is a java.lang.Class, so the cast path was dead and every optional field was resolved reflectively, failing with IllegalStateException for a target type with no static getInstance. Each guard now names the type it returns, matching the sibling UINT8 / UINT16 / UINT64 and EtsiTs103097DataEncrypted factories (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2373\"\u003e#2373\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eDefaultAlgorithmNameFinder and DefaultSignatureNameFinder had no entries at all for the ShangMi algorithms, so an SM2 signature AlgorithmIdentifier that DefaultSignatureAlgorithmIdentifierFinder itself produces came back named only by its OID string - getAlgorithmName(GMObjectIdentifiers.sm2sign_with_sm3) returned \u0026quot;1.2.156.10197.1.501\u0026quot; and hasAlgorithmName returned false. Both finders now name sm2sign_with_sm3 as SM3WITHSM2 and sm2sign_with_sha256 as SHA256WITHSM2, and DefaultAlgorithmNameFinder additionally names the sm3 digest. All three resolve through the BC provider, as Signature and MessageDigest respectively. The remaining GM arc - the SM4 cipher modes, the sm2encrypt variants, and the SM1 / SM6 / SSF33 ciphers BC does not implement - is still unnamed (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2377\"\u003e#2377\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe RFC 4998 evidence-record classes compared the digest AlgorithmIdentifier named by a time-stamp authority with the one their own DigestCalculator uses, and did so with AlgorithmIdentifier.equals(), which compares the encodings. A TSA that names SHA-256 with an explicit NULL parameters field - DigiCert among them - therefore failed against BC's own calculator, which names it with the parameters absent, and ERSArchiveTimeStampGenerator.generateArchiveTimeStamp rejected the response with \u0026quot;time stamp imprint for wrong algorithm\u0026quot;. Both spellings name the same digest and RFC 5754 sec. 2 requires a receiver to accept either, while requiring that identifiers be generated with the parameters absent, which BC already does. The three affected comparisons - the two in ERSArchiveTimeStampGenerator and the digest check in ERSEvidenceRecord.renew - now use the new AlgorithmIdentifier.areEquivalent, which matches on the algorithm and treats an absent parameters field and NULL as the same, and the consistency check across an evidence record's archive time stamp chain uses it too. An identifier carrying an actual parameter structure is never equivalent to one carrying none (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2379\"\u003e#2379\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eEDIPartyName.toASN1Primitive emitted the nameAssigner and partyName DirectoryStrings without their context tags, so an EDIPartyName built through its public constructor could not be parsed back by EDIPartyName.getInstance, which correctly requires them. RFC 5280 sec. 4.2.1.6 tags both members [0] and [1], and those tags are explicit despite the module's IMPLICIT TAGS because DirectoryString is a CHOICE, which X.680 does not allow to be tagged implicitly - the decoder already had this right. The encoder now matches it. Note the type was added during the 1.85 cycle and GeneralName validates its ediPartyName alternative through it, so a GeneralName carrying an untagged ediPartyName - including one BC itself produced - is rejected where 1.84 passed it through unexamined; the untagged form is not read leniently (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2380\"\u003e#2380\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eRSASSA-PSS could not be used with a RIPEMD digest through the JCA API. Nothing registered the RIPEMD PSS signatures, so Signature.getInstance(\u0026quot;RIPEMD160WITHRSAANDMGF1\u0026quot;) raised NoSuchAlgorithmException, and the generic RSASSA-PSS route with an explicit PSSParameterSpec failed too: org.bouncycastle.jcajce.provider.util.DigestFactory.getDigest returned null for a RIPEMD name, and isSameDigest - an allow-list of the SHA families and MD5 - reported two identical RIPEMD names as different digests, so the spec was rejected with \u0026quot;digest algorithm for MGF should be the same as for PSS parameters\u0026quot;. isSameDigest now answers true for equal names whatever the digest, which also covers Whirlpool, SM3, GOST3411 and anything else outside that allow-list; DigestFactory recognises RIPEMD128, RIPEMD160 and RIPEMD256 by name and OID; the three PSS signatures are registered with MGF1 over the same digest and a salt of the digest length; and DefaultSignatureAlgorithmIdentifierFinder gains the matching RIPEMD*WITHRSAANDMGF1 entries with their RSASSA-PSS-params, so the operator/JcaContentSignerBuilder path works as well. Note BC continues to require the PSS hash and the MGF1 hash to be the same, which RFC 8017 does not itself demand (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2381\"\u003e#2381\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe opt-in key-size validation on CMS key-transport recipients (org.bouncycastle.cms.jcajce.JceKeyTransRecipient.setKeySizeValidation(true)) never ran for a message using RFC 9709 CEK derivation (id-alg-cek-hkdf-sha256): the branch that should have selected the actual content-encryption algorithm carried in the KDF AlgorithmIdentifier's parameters compared the encrypted-key byte array against the id-alg-cek-hkdf-sha256 object identifier - a comparison that is always false - so the check fell through to a key-size lookup on the outer KDF OID, which has no registered key size, and silently checked nothing. A key-transport EnvelopedData/AuthEnvelopedData whose transported (and HKDF-derived) content-encryption key did not match the key size of the advertised content-encryption algorithm was therefore accepted even with validation enabled. The recipient now dispatches on the content-encryption AlgorithmIdentifier's algorithm OID, so key-size validation of RFC 9709 messages checks the recovered key against the inner content-encryption algorithm. Messages with a matching key size, non-HKDF messages, and recipients that do not enable validation are unaffected.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003eSee full diff in \u003ca href=\"https://github.com/bcgit/bc-java/commits\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003ecommonmark-java 0.29.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e[0.29.0] - 2026-06-20\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/comm...\n\n_Description has been truncated_","html_url":"https://github.com/wangqianCAI/OBI/pull/42","url":"https://dependabot.ecosyste.ms/api/v1/hosts/GitHub/repositories/wangqianCAI%2FOBI/issues/42","packages_url":"https://dependabot.ecosyste.ms/api/v1/issues/42/packages"}},{"old_version":"4.12.0","new_version":"5.5.0","update_type":"major","path":"/android","pr_created_at":"2026-09-09T13:55:10.000Z","version_change":"4.12.0 → 5.5.0","issue":{"uuid":"5400378360","node_id":"PR_kwDOUSwqdc8AAAABC150hg","number":5,"state":"closed","title":"Bump the android group in /android with 15 updates","user":"dependabot[bot]","labels":["dependencies","java"],"assignees":[],"locked":false,"comments_count":2,"pull_request":true,"closed_at":"2026-09-09T14:06:39.000Z","author_association":null,"state_reason":null,"created_at":"2026-09-09T13:55:10.000Z","updated_at":"2026-09-09T14:06:50.000Z","time_to_close":689,"merged_at":null,"merged_by":null,"closed_by":null,"dependency_metadata":{"prefix":"Bump","group_name":"android","update_count":15,"packages":[{"name":"gradle-wrapper","old_version":"8.11.1","new_version":"9.7.1","repository_url":"https://github.com/gradle/gradle"},{"name":"androidx.core:core-ktx","old_version":"1.15.0","new_version":"1.19.0"},{"name":"androidx.appcompat:appcompat","old_version":"1.7.0","new_version":"1.8.0"},{"name":"androidx.compose:compose-bom","old_version":"2024.12.01","new_version":"2026.08.00"},{"name":"androidx.navigation:navigation-compose","old_version":"2.8.5","new_version":"2.10.0"},{"name":"com.squareup.okhttp3:okhttp","old_version":"4.12.0","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.squareup.okhttp3:mockwebserver","old_version":"4.12.0","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"org.jetbrains.kotlinx:kotlinx-serialization-json","old_version":"1.7.3","new_version":"1.11.0","repository_url":"https://github.com/Kotlin/kotlinx.serialization"},{"name":"androidx.biometric:biometric","old_version":"1.2.0-alpha05","new_version":"1.4.0-alpha07"},{"name":"org.jetbrains.kotlinx:kotlinx-coroutines-android","old_version":"1.9.0","new_version":"1.11.0","repository_url":"https://github.com/Kotlin/kotlinx.coroutines"},{"name":"org.jetbrains.kotlinx:kotlinx-coroutines-test","old_version":"1.9.0","new_version":"1.11.0","repository_url":"https://github.com/Kotlin/kotlinx.coroutines"},{"name":"com.android.application","old_version":"8.7.3","new_version":"9.4.0"},{"name":"org.jetbrains.kotlin.android","old_version":"2.0.21","new_version":"2.4.10","repository_url":"https://github.com/JetBrains/kotlin"},{"name":"org.jetbrains.kotlin.plugin.compose","old_version":"2.0.21","new_version":"2.4.10","repository_url":"https://github.com/JetBrains/kotlin"},{"name":"org.jetbrains.kotlin.plugin.serialization","old_version":"2.0.21","new_version":"2.4.10","repository_url":"https://github.com/JetBrains/kotlin"}],"path":"/android","ecosystem":"maven"},"body":"Bumps the android group in /android with 15 updates:\n\n| Package | From | To |\n| --- | --- | --- |\n| [gradle-wrapper](https://github.com/gradle/gradle) | `8.11.1` | `9.7.1` |\n| androidx.core:core-ktx | `1.15.0` | `1.19.0` |\n| androidx.appcompat:appcompat | `1.7.0` | `1.8.0` |\n| androidx.compose:compose-bom | `2024.12.01` | `2026.08.00` |\n| androidx.navigation:navigation-compose | `2.8.5` | `2.10.0` |\n| [com.squareup.okhttp3:okhttp](https://github.com/lysine-dev/okhttp) | `4.12.0` | `5.5.0` |\n| [com.squareup.okhttp3:mockwebserver](https://github.com/lysine-dev/okhttp) | `4.12.0` | `5.5.0` |\n| [org.jetbrains.kotlinx:kotlinx-serialization-json](https://github.com/Kotlin/kotlinx.serialization) | `1.7.3` | `1.11.0` |\n| androidx.biometric:biometric | `1.2.0-alpha05` | `1.4.0-alpha07` |\n| [org.jetbrains.kotlinx:kotlinx-coroutines-android](https://github.com/Kotlin/kotlinx.coroutines) | `1.9.0` | `1.11.0` |\n| [org.jetbrains.kotlinx:kotlinx-coroutines-test](https://github.com/Kotlin/kotlinx.coroutines) | `1.9.0` | `1.11.0` |\n| com.android.application | `8.7.3` | `9.4.0` |\n| [org.jetbrains.kotlin.android](https://github.com/JetBrains/kotlin) | `2.0.21` | `2.4.10` |\n| [org.jetbrains.kotlin.plugin.compose](https://github.com/JetBrains/kotlin) | `2.0.21` | `2.4.10` |\n| [org.jetbrains.kotlin.plugin.serialization](https://github.com/JetBrains/kotlin) | `2.0.21` | `2.4.10` |\n\nUpdates `gradle-wrapper` from 8.11.1 to 9.7.1\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/gradle/gradle/releases\"\u003egradle-wrapper's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e9.7.1\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.1.\u003c/p\u003e\n\u003cp\u003eThis is a patch release for 9.7.0. We recommend using 9.7.1 instead of 9.7.0.\u003c/p\u003e\n\u003cp\u003eHere are the highlights of 9.7.0 release:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIsolated Projects graduates to incubating\u003c/li\u003e\n\u003cli\u003eBroader Configuration Cache compatibility\u003c/li\u003e\n\u003cli\u003eResilient Sync helps you fix broken builds\u003c/li\u003e\n\u003cli\u003eMore source locations in problem reports\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003ca href=\"https://docs.gradle.org/9.7.1/release-notes.html\"\u003eRead the Release Notes\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eWe would like to thank the following community members for their contributions to this release of Gradle:\n\u003ca href=\"https://github.com/aSemy\"\u003eAdam\u003c/a\u003e,\n\u003ca href=\"https://github.com/Gautam-aman\"\u003eAman Gautam\u003c/a\u003e,\n\u003ca href=\"https://github.com/YukiCodepth\"\u003eAman Kumar\u003c/a\u003e,\n\u003ca href=\"https://github.com/adubrouski\"\u003eAnton Dubrouski\u003c/a\u003e,\n\u003ca href=\"https://github.com/liutikas\"\u003eAurimas\u003c/a\u003e,\n\u003ca href=\"https://github.com/gbhavya07\"\u003egbhavya07\u003c/a\u003e,\n\u003ca href=\"https://github.com/joshfriend\"\u003eJosh Friend\u003c/a\u003e,\n\u003ca href=\"https://github.com/nicklauslittle-gov\"\u003enicklauslittle-gov\u003c/a\u003e,\n\u003ca href=\"https://github.com/psoni674\"\u003ePragati\u003c/a\u003e,\n\u003ca href=\"https://github.com/Project516\"\u003eproject516\u003c/a\u003e,\n\u003ca href=\"https://github.com/Uomocapra\"\u003eQin Mi\u003c/a\u003e,\n\u003ca href=\"https://github.com/rkdfx\"\u003eRavi\u003c/a\u003e,\n\u003ca href=\"https://github.com/sk-reddy17\"\u003esk-reddy17\u003c/a\u003e,\n\u003ca href=\"https://github.com/Suvrat1629\"\u003eSuvrat Acharya\u003c/a\u003e,\n\u003ca href=\"https://github.com/ShreckYe\"\u003eYongshun Ye\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eUpgrade instructions\u003c/h2\u003e\n\u003cp\u003eSwitch your build to use Gradle 9.7.1 by updating your wrapper:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e./gradlew :wrapper --gradle-version=9.7.1 \u0026amp;\u0026amp; ./gradlew :wrapper\r\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eSee the Gradle \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/upgrading_version_9.html\"\u003e9.x upgrade guide\u003c/a\u003e to learn about deprecations, breaking changes and other considerations when upgrading.\u003c/p\u003e\n\u003cp\u003eFor Java, Groovy, Kotlin and Android compatibility, see the \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/compatibility.html\"\u003efull compatibility notes\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eReporting problems\u003c/h2\u003e\n\u003cp\u003eIf you find a problem with this release, please file a bug on \u003ca href=\"https://github.com/gradle/gradle/issues\"\u003eGitHub Issues\u003c/a\u003e adhering to our issue guidelines.\nIf you're not sure you're encountering a bug, please use the \u003ca href=\"https://discuss.gradle.org/c/help-discuss\"\u003eforum\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eWe hope you will build happiness with Gradle, and we look forward to your feedback via \u003ca href=\"https://twitter.com/gradle\"\u003eTwitter\u003c/a\u003e or on \u003ca href=\"https://github.com/gradle\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003e9.7.0\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.0.\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/92f0512e7f06d84621afba191f75e265363890cf\"\u003e\u003ccode\u003e92f0512\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38892\"\u003e#38892\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/820ee75a99a179bbffa41bcedc6477b685fabb9f\"\u003e\u003ccode\u003e820ee75\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/82c23f9bd2a89b4cc644e1f90a28a8668feb3dee\"\u003e\u003ccode\u003e82c23f9\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering problem in KTS (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38878\"\u003e#38878\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/ef11a7268fe8cc8d6ab849ec911aa11220180553\"\u003e\u003ccode\u003eef11a72\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering issue\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/bb0d8a974a71b1003efea41e4046e98855cd5ff8\"\u003e\u003ccode\u003ebb0d8a9\u003c/code\u003e\u003c/a\u003e Make relevant tests polyglot (run for multiple DSLs)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/336e129d7f95c03486acafc97abf59734acfed48\"\u003e\u003ccode\u003e336e129\u003c/code\u003e\u003c/a\u003e Update signing configuration (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38874\"\u003e#38874\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/4bdf0da2dad9884d089a6062a45ea7183e7d735d\"\u003e\u003ccode\u003e4bdf0da\u003c/code\u003e\u003c/a\u003e Update signing configuration\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/cd9b92c1b82856248cf1dc58b50378238bec7b52\"\u003e\u003ccode\u003ecd9b92c\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38839\"\u003e#38839\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/5f4e381964897ad8d6b99e5a7c77f26dba3259fb\"\u003e\u003ccode\u003e5f4e381\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/1e08ab551367aeb5fb48b26e72807e1d2b27c939\"\u003e\u003ccode\u003e1e08ab5\u003c/code\u003e\u003c/a\u003e Keep type-use annotations in extracted ABI classes (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38810\"\u003e#38810\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/gradle/gradle/compare/v8.11.1...v9.7.1\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `androidx.core:core-ktx` from 1.15.0 to 1.19.0\n\nUpdates `androidx.appcompat:appcompat` from 1.7.0 to 1.8.0\n\nUpdates `androidx.compose:compose-bom` from 2024.12.01 to 2026.08.00\n\nUpdates `androidx.navigation:navigation-compose` from 2.8.5 to 2.10.0\n\nUpdates `com.squareup.okhttp3:okhttp` from 4.12.0 to 5.5.0\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/lysine-dev/okhttp/blob/main/CHANGELOG.md\"\u003ecom.squareup.okhttp3:okhttp's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003eVersion 5.5.0\u003c/h2\u003e\n\u003cp\u003e\u003cem\u003e2026-08-16\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003eThis release introduces \u003cstrong\u003eopt-in\u003c/strong\u003e support for [Encrypted Client Hello (ECH)]. This new feature\nimproves user privacy by encrypting domain names in transit. With regular TLS, your coffee shop’s\nWi-Fi router can see that you’re visiting \u003cem\u003ewikipedia.com\u003c/em\u003e, but it cannot see which page you’re\nlooking at. With ECH, the router observes only the IP address. This additional privacy is most\neffective on sites hosted by big CDNs because the IP address doesn’t imply a particular website.\u003c/p\u003e\n\u003cp\u003eThis requires ECH support in the platform’s TLS stack. Today this is only Android 17 (API 37,\nreleased June 2026). When other TLS stacks add ECH support, we'll integrate them.\u003c/p\u003e\n\u003cp\u003eECH took a lot of work to implement because the encryption keys are published over DNS in the\n[HTTPS resource record], and we needed to write new code to fetch these records. This release\nincludes a major update to OkHttp’s DNS API: it now supports multiple resource record types (not\njust IP addresses!), asynchronous streaming results, and in-memory caching.\u003c/p\u003e\n\u003cp\u003eTo opt in, you can use \u003ccode\u003eDnsOverHttps\u003c/code\u003e:\u003c/p\u003e\n\u003cpre lang=\"kotlin\"\u003e\u003ccode\u003e// DnsOverHttps itself uses OkHttpClient. Build both clients upon the\n// same bootstrap client so they share a connection pool and dispatcher.\nval bootstrapClient = OkHttpClient()\n\u003cp\u003e// This sample uses Cloudflare's 1.1.1.1 DnsOverHttps service.\nval client = bootstrapClient.newBuilder()\n.dns(DnsOverHttps.Builder()\n.client(bootstrapClient)\n.url(\u0026quot;\u003ca href=\"https://1.1.1.1/dns-query\u0026amp;quot;.toHttpUrl()\"\u003ehttps://1.1.1.1/dns-query\u0026amp;quot;.toHttpUrl()\u003c/a\u003e)\n.build())\n.build()\n\u003c/code\u003e\u003c/pre\u003e\u003c/p\u003e\n\u003cp\u003eYou could also opt in with our new \u003ccode\u003eAndroidDns\u003c/code\u003e API. Unfortunately, the privacy benefits of ECH are\nthwarted because its DNS queries are not encrypted by default.\u003c/p\u003e\n\u003cpre lang=\"kotlin\"\u003e\u003ccode\u003e// AndroidDns fetches the HTTPS DNS resource records necessary for ECH.\nval client = OkHttpClient.Builder()\n  .dns(AndroidDns())\n  .build()\n\u003c/code\u003e\u003c/pre\u003e\n\u003cul\u003e\n\u003cli\u003eNew: OkHttp artifacts are now signed with our [new signing key]. This project and three sibling\nprojects ([Retrofit], [Okio], and [SQLDelight]) recently joined [the Commonhaus Foundation].\u003c/li\u003e\n\u003cli\u003eFix: MockWebServer’s \u003ccode\u003e@StartStop\u003c/code\u003e annotation now supports \u003ccode\u003e@Nested\u003c/code\u003e JUnit 5 tests.\u003c/li\u003e\n\u003cli\u003eFix: Our default TLS hostname verifier now reject hosts that fail IP canonicalization.\u003c/li\u003e\n\u003cli\u003eFix: Closing a multipart part's sink no longer closes the entire request body.\u003c/li\u003e\n\u003cli\u003eFix: Flush HTTP/1 request bodies before detaching the timeout. We had a bug where timeouts\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/a94bdf152084d11acecd44dcd09ffef203f4f0aa\"\u003e\u003ccode\u003ea94bdf1\u003c/code\u003e\u003c/a\u003e Prepare for release 5.5.0.\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/ecc3b05adfe6b2607b8ec251562c2cccf7c1923a\"\u003e\u003ccode\u003eecc3b05\u003c/code\u003e\u003c/a\u003e Use a fixed size for DoH request body (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9687\"\u003e#9687\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/9926082660dfa6f1cc848c6f465cf5ccb998e415\"\u003e\u003ccode\u003e9926082\u003c/code\u003e\u003c/a\u003e Revert \u0026quot;Use a fixed size for DoH request body\u0026quot; (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9686\"\u003e#9686\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/0070c2e7b4c162ee03abf1c88fd94083e94697f4\"\u003e\u003ccode\u003e0070c2e\u003c/code\u003e\u003c/a\u003e Use a fixed size for DoH request body\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/15764539c69842dad607462f102a2507223dbfe7\"\u003e\u003ccode\u003e1576453\u003c/code\u003e\u003c/a\u003e Order ServiceMetadata records per the spec (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9683\"\u003e#9683\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/fb582e976a9a82d691342a4d57b3c72208ce416c\"\u003e\u003ccode\u003efb582e9\u003c/code\u003e\u003c/a\u003e Flip wiring of Dns.SYSTEM (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9682\"\u003e#9682\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/4e884abb1a207c321acffb070c476acb4b89fa3f\"\u003e\u003ccode\u003e4e884ab\u003c/code\u003e\u003c/a\u003e retryOnConnectionFailure doesn't impact ECH retries (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9681\"\u003e#9681\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/0433cee8131b63fa2c0634fa2f9b3a01f9a8b1f3\"\u003e\u003ccode\u003e0433cee\u003c/code\u003e\u003c/a\u003e Only one contributing.md doc (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9678\"\u003e#9678\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/a2cf5aa9f8711dabe514871e9dc4a9336a0e403f\"\u003e\u003ccode\u003ea2cf5aa\u003c/code\u003e\u003c/a\u003e Don't recover after an ECH public_name fails to verify (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9680\"\u003e#9680\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/5410de9760bce8719129c3d08eb19e5bace75f6e\"\u003e\u003ccode\u003e5410de9\u003c/code\u003e\u003c/a\u003e Test ECH + HTTP proxy (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9671\"\u003e#9671\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/lysine-dev/okhttp/compare/parent-4.12.0...parent-5.5.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `com.squareup.okhttp3:mockwebserver` from 4.12.0 to 5.5.0\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/lysine-dev/okhttp/blob/main/CHANGELOG.md\"\u003ecom.squareup.okhttp3:mockwebserver's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003eVersion 5.5.0\u003c/h2\u003e\n\u003cp\u003e\u003cem\u003e2026-08-16\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003eThis release introduces \u003cstrong\u003eopt-in\u003c/strong\u003e support for [Encrypted Client Hello (ECH)]. This new feature\nimproves user privacy by encrypting domain names in transit. With regular TLS, your coffee shop’s\nWi-Fi router can see that you’re visiting \u003cem\u003ewikipedia.com\u003c/em\u003e, but it cannot see which page you’re\nlooking at. With ECH, the router observes only the IP address. This additional privacy is most\neffective on sites hosted by big CDNs because the IP address doesn’t imply a particular website.\u003c/p\u003e\n\u003cp\u003eThis requires ECH support in the platform’s TLS stack. Today this is only Android 17 (API 37,\nreleased June 2026). When other TLS stacks add ECH support, we'll integrate them.\u003c/p\u003e\n\u003cp\u003eECH took a lot of work to implement because the encryption keys are published over DNS in the\n[HTTPS resource record], and we needed to write new code to fetch these records. This release\nincludes a major update to OkHttp’s DNS API: it now supports multiple resource record types (not\njust IP addresses!), asynchronous streaming results, and in-memory caching.\u003c/p\u003e\n\u003cp\u003eTo opt in, you can use \u003ccode\u003eDnsOverHttps\u003c/code\u003e:\u003c/p\u003e\n\u003cpre lang=\"kotlin\"\u003e\u003ccode\u003e// DnsOverHttps itself uses OkHttpClient. Build both clients upon the\n// same bootstrap client so they share a connection pool and dispatcher.\nval bootstrapClient = OkHttpClient()\n\u003cp\u003e// This sample uses Cloudflare's 1.1.1.1 DnsOverHttps service.\nval client = bootstrapClient.newBuilder()\n.dns(DnsOverHttps.Builder()\n.client(bootstrapClient)\n.url(\u0026quot;\u003ca href=\"https://1.1.1.1/dns-query\u0026amp;quot;.toHttpUrl()\"\u003ehttps://1.1.1.1/dns-query\u0026amp;quot;.toHttpUrl()\u003c/a\u003e)\n.build())\n.build()\n\u003c/code\u003e\u003c/pre\u003e\u003c/p\u003e\n\u003cp\u003eYou could also opt in with our new \u003ccode\u003eAndroidDns\u003c/code\u003e API. Unfortunately, the privacy benefits of ECH are\nthwarted because its DNS queries are not encrypted by default.\u003c/p\u003e\n\u003cpre lang=\"kotlin\"\u003e\u003ccode\u003e// AndroidDns fetches the HTTPS DNS resource records necessary for ECH.\nval client = OkHttpClient.Builder()\n  .dns(AndroidDns())\n  .build()\n\u003c/code\u003e\u003c/pre\u003e\n\u003cul\u003e\n\u003cli\u003eNew: OkHttp artifacts are now signed with our [new signing key]. This project and three sibling\nprojects ([Retrofit], [Okio], and [SQLDelight]) recently joined [the Commonhaus Foundation].\u003c/li\u003e\n\u003cli\u003eFix: MockWebServer’s \u003ccode\u003e@StartStop\u003c/code\u003e annotation now supports \u003ccode\u003e@Nested\u003c/code\u003e JUnit 5 tests.\u003c/li\u003e\n\u003cli\u003eFix: Our default TLS hostname verifier now reject hosts that fail IP canonicalization.\u003c/li\u003e\n\u003cli\u003eFix: Closing a multipart part's sink no longer closes the entire request body.\u003c/li\u003e\n\u003cli\u003eFix: Flush HTTP/1 request bodies before detaching the timeout. We had a bug where timeouts\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/a94bdf152084d11acecd44dcd09ffef203f4f0aa\"\u003e\u003ccode\u003ea94bdf1\u003c/code\u003e\u003c/a\u003e Prepare for release 5.5.0.\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/ecc3b05adfe6b2607b8ec251562c2cccf7c1923a\"\u003e\u003ccode\u003eecc3b05\u003c/code\u003e\u003c/a\u003e Use a fixed size for DoH request body (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9687\"\u003e#9687\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/9926082660dfa6f1cc848c6f465cf5ccb998e415\"\u003e\u003ccode\u003e9926082\u003c/code\u003e\u003c/a\u003e Revert \u0026quot;Use a fixed size for DoH request body\u0026quot; (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9686\"\u003e#9686\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/0070c2e7b4c162ee03abf1c88fd94083e94697f4\"\u003e\u003ccode\u003e0070c2e\u003c/code\u003e\u003c/a\u003e Use a fixed size for DoH request body\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/15764539c69842dad607462f102a2507223dbfe7\"\u003e\u003ccode\u003e1576453\u003c/code\u003e\u003c/a\u003e Order ServiceMetadata records per the spec (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9683\"\u003e#9683\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/fb582e976a9a82d691342a4d57b3c72208ce416c\"\u003e\u003ccode\u003efb582e9\u003c/code\u003e\u003c/a\u003e Flip wiring of Dns.SYSTEM (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9682\"\u003e#9682\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/4e884abb1a207c321acffb070c476acb4b89fa3f\"\u003e\u003ccode\u003e4e884ab\u003c/code\u003e\u003c/a\u003e retryOnConnectionFailure doesn't impact ECH retries (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9681\"\u003e#9681\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/0433cee8131b63fa2c0634fa2f9b3a01f9a8b1f3\"\u003e\u003ccode\u003e0433cee\u003c/code\u003e\u003c/a\u003e Only one contributing.md doc (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9678\"\u003e#9678\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/a2cf5aa9f8711dabe514871e9dc4a9336a0e403f\"\u003e\u003ccode\u003ea2cf5aa\u003c/code\u003e\u003c/a\u003e Don't recover after an ECH public_name fails to verify (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9680\"\u003e#9680\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/5410de9760bce8719129c3d08eb19e5bace75f6e\"\u003e\u003ccode\u003e5410de9\u003c/code\u003e\u003c/a\u003e Test ECH + HTTP proxy (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9671\"\u003e#9671\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/lysine-dev/okhttp/compare/parent-4.12.0...parent-5.5.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `com.squareup.okhttp3:mockwebserver` from 4.12.0 to 5.5.0\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/lysine-dev/okhttp/blob/main/CHANGELOG.md\"\u003ecom.squareup.okhttp3:mockwebserver's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003eVersion 5.5.0\u003c/h2\u003e\n\u003cp\u003e\u003cem\u003e2026-08-16\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003eThis release introduces \u003cstrong\u003eopt-in\u003c/strong\u003e support for [Encrypted Client Hello (ECH)]. This new feature\nimproves user privacy by encrypting domain names in transit. With regular TLS, your coffee shop’s\nWi-Fi router can see that you’re visiting \u003cem\u003ewikipedia.com\u003c/em\u003e, but it cannot see which page you’re\nlooking at. With ECH, the router observes only the IP address. This additional privacy is most\neffective on sites hosted by big CDNs because the IP address doesn’t imply a particular website.\u003c/p\u003e\n\u003cp\u003eThis requires ECH support in the platform’s TLS stack. Today this is only Android 17 (API 37,\nreleased June 2026). When other TLS stacks add ECH support, we'll integrate them.\u003c/p\u003e\n\u003cp\u003eECH took a lot of work to implement because the encryption keys are published over DNS in the\n[HTTPS resource record], and we needed to write new code to fetch these records. This release\nincludes a major update to OkHttp’s DNS API: it now supports multiple resource record types (not\njust IP addresses!), asynchronous streaming results, and in-memory caching.\u003c/p\u003e\n\u003cp\u003eTo opt in, you can use \u003ccode\u003eDnsOverHttps\u003c/code\u003e:\u003c/p\u003e\n\u003cpre lang=\"kotlin\"\u003e\u003ccode\u003e// DnsOverHttps itself uses OkHttpClient. Build both clients upon the\n// same bootstrap client so they share a connection pool and dispatcher.\nval bootstrapClient = OkHttpClient()\n\u003cp\u003e// This sample uses Cloudflare's 1.1.1.1 DnsOverHttps service.\nval client = bootstrapClient.newBuilder()\n.dns(DnsOverHttps.Builder()\n.client(bootstrapClient)\n.url(\u0026quot;\u003ca href=\"https://1.1.1.1/dns-query\u0026amp;quot;.toHttpUrl()\"\u003ehttps://1.1.1.1/dns-query\u0026amp;quot;.toHttpUrl()\u003c/a\u003e)\n.build())\n.build()\n\u003c/code\u003e\u003c/pre\u003e\u003c/p\u003e\n\u003cp\u003eYou could also opt in with our new \u003ccode\u003eAndroidDns\u003c/code\u003e API. Unfortunately, the privacy benefits of ECH are\nthwarted because its DNS queries are not encrypted by default.\u003c/p\u003e\n\u003cpre lang=\"kotlin\"\u003e\u003ccode\u003e// AndroidDns fetches the HTTPS DNS resource records necessary for ECH.\nval client = OkHttpClient.Builder()\n  .dns(AndroidDns())\n  .build()\n\u003c/code\u003e\u003c/pre\u003e\n\u003cul\u003e\n\u003cli\u003eNew: OkHttp artifacts are now signed with our [new signing key]. This project and three sibling\nprojects ([Retrofit], [Okio], and [SQLDelight]) recently joined [the Commonhaus Foundation].\u003c/li\u003e\n\u003cli\u003eFix: MockWebServer’s \u003ccode\u003e@StartStop\u003c/code\u003e annotation now supports \u003ccode\u003e@Nested\u003c/code\u003e JUnit 5 tests.\u003c/li\u003e\n\u003cli\u003eFix: Our default TLS hostname verifier now reject hosts that fail IP canonicalization.\u003c/li\u003e\n\u003cli\u003eFix: Closing a multipart part's sink no longer closes the entire request body.\u003c/li\u003e\n\u003cli\u003eFix: Flush HTTP/1 request bodies before detaching the timeout. We had a bug where timeouts\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/a94bdf152084d11acecd44dcd09ffef203f4f0aa\"\u003e\u003ccode\u003ea94bdf1\u003c/code\u003e\u003c/a\u003e Prepare for release 5.5.0.\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/ecc3b05adfe6b2607b8ec251562c2cccf7c1923a\"\u003e\u003ccode\u003eecc3b05\u003c/code\u003e\u003c/a\u003e Use a fixed size for DoH request body (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9687\"\u003e#9687\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/9926082660dfa6f1cc848c6f465cf5ccb998e415\"\u003e\u003ccode\u003e9926082\u003c/code\u003e\u003c/a\u003e Revert \u0026quot;Use a fixed size for DoH request body\u0026quot; (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9686\"\u003e#9686\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/0070c2e7b4c162ee03abf1c88fd94083e94697f4\"\u003e\u003ccode\u003e0070c2e\u003c/code\u003e\u003c/a\u003e Use a fixed size for DoH request body\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/15764539c69842dad607462f102a2507223dbfe7\"\u003e\u003ccode\u003e1576453\u003c/code\u003e\u003c/a\u003e Order ServiceMetadata records per the spec (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9683\"\u003e#9683\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/fb582e976a9a82d691342a4d57b3c72208ce416c\"\u003e\u003ccode\u003efb582e9\u003c/code\u003e\u003c/a\u003e Flip wiring of Dns.SYSTEM (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9682\"\u003e#9682\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/4e884abb1a207c321acffb070c476acb4b89fa3f\"\u003e\u003ccode\u003e4e884ab\u003c/code\u003e\u003c/a\u003e retryOnConnectionFailure doesn't impact ECH retries (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9681\"\u003e#9681\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/0433cee8131b63fa2c0634fa2f9b3a01f9a8b1f3\"\u003e\u003ccode\u003e0433cee\u003c/code\u003e\u003c/a\u003e Only one contributing.md doc (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9678\"\u003e#9678\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/a2cf5aa9f8711dabe514871e9dc4a9336a0e403f\"\u003e\u003ccode\u003ea2cf5aa\u003c/code\u003e\u003c/a\u003e Don't recover after an ECH public_name fails to verify (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9680\"\u003e#9680\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/5410de9760bce8719129c3d08eb19e5bace75f6e\"\u003e\u003ccode\u003e5410de9\u003c/code\u003e\u003c/a\u003e Test ECH + HTTP proxy (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9671\"\u003e#9671\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/lysine-dev/okhttp/compare/parent-4.12.0...parent-5.5.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.jetbrains.kotlinx:kotlinx-serialization-json` from 1.7.3 to 1.11.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/Kotlin/kotlinx.serialization/releases\"\u003eorg.jetbrains.kotlinx:kotlinx-serialization-json's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e1.11.0\u003c/h2\u003e\n\u003cp\u003eThis release is based on Kotlin 2.3.20 and provides a new Json exceptions API and some bugfixes and improvements.\u003c/p\u003e\n\u003ch2\u003eExpose Json exceptions structure\u003c/h2\u003e\n\u003cp\u003eTo make working with exceptions easier and providing proper error codes in e.g., REST APIs,\nclasses \u003ccode\u003eJsonException\u003c/code\u003e, \u003ccode\u003eJsonDecodingException\u003c/code\u003e, and \u003ccode\u003eJsonEncodingException\u003c/code\u003e are now public.\nThey have relevant public properties, such as \u003ccode\u003eshortMessage\u003c/code\u003e, \u003ccode\u003epath\u003c/code\u003e, \u003ccode\u003eoffset\u003c/code\u003e, and others.\nThis API is currently experimental, and we're going to improve it further in the subsequent releases.\nSee the linked issues for the details: \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/1930\"\u003e#1930\u003c/a\u003e, \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/1877\"\u003e#1877\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eAbility to hide user input from exception messages for security/privacy reasons.\u003c/h2\u003e\n\u003cp\u003eHistorically, exception messages in kotlinx.serialization often included the input Json itself for debuggability reason.\nSuch behavior may pose additional challenges for logging, analytics, and other systems, since\na system is not always allowed to store user data due to privacy/security reasons, which imposes additional sanitation logic.\nTo address this issue, a new property \u003ccode\u003eexceptionsWithDebugInfo\u003c/code\u003e is added to \u003ccode\u003eJsonConfiguration\u003c/code\u003e.\nDisable it to hide user input from exception messages.\nIMPORTANT: This behavior will be enabled by default when this property becomes stable.\nSee \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/2590\"\u003e#2590\u003c/a\u003e for more details.\u003c/p\u003e\n\u003ch2\u003eBugfixes and improvements\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eCBOR: Relax value range check when decoding numbers (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/3167\"\u003e#3167\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eUse a specialized writeDecimalLong method for IO stream integrations in Json (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/3152\"\u003e#3152\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e1.10.0\u003c/h2\u003e\n\u003cp\u003eThis release is based on Kotlin 2.3.0 and contains all of the changes from 1.10.0-RC.\nThe only additional change is a fix for ProtoBuf packing of Kotlin unsigned types (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/3079\"\u003e#3079\u003c/a\u003e).\nBig thanks to \u003ca href=\"https://github.com/KosmX\"\u003eKosmX\u003c/a\u003e for contributing the fix.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eFor your convenience, the changelog for 1.10.0-RC is duplicated below:\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch2\u003eStabilization of APIs\u003c/h2\u003e\n\u003cp\u003ekotlinx-serialization 1.10 and subsequent releases will be focused on stabilization of existing APIs.\nThe following APIs and configuration options are no longer experimental because they're widely used without any known major issues:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003eJson\u003c/code\u003e configuration options: \u003ccode\u003edecodeEnumsCaseInsensitive\u003c/code\u003e, \u003ccode\u003eallowTrailingComma\u003c/code\u003e, \u003ccode\u003eallowComments\u003c/code\u003e, and \u003ccode\u003eprettyPrintIndent\u003c/code\u003e. (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/3100\"\u003e#3100\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e@EncodeDefault\u003c/code\u003e annotation and its modes. (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/3106\"\u003e#3106\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eJsonUnquotedLiteral\u003c/code\u003e constructor function (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/2900\"\u003e#2900\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eJsonPrimitive\u003c/code\u003e constructor function overloads that accept unsigned types. (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/3117\"\u003e#3117\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eJSON DSL functions on \u003ccode\u003eJsonElement\u003c/code\u003e with \u003ccode\u003eNothing?\u003c/code\u003e overloads. (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/3117\"\u003e#3117\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003eReadiness for return value checker\u003c/h2\u003e\n\u003cp\u003eKotlin 2.3.0 \u003ca href=\"https://kotlinlang.org/docs/whatsnew23.html#unused-return-value-checker\"\u003eintroduces a new feature\u003c/a\u003e aimed at helping you to catch bugs related to the accidentally ignored return value of the function.\nkotlinx-serialization 1.10.0-RC code is fully marked for this feature, meaning that you can get warnings for unused function calls like \u003ccode\u003eJson.encodeToString(...)\u003c/code\u003e. To get the warnings, the feature has to be enabled in your project as \u003ca href=\"https://kotlinlang.org/docs/unused-return-value-checker.html#configure-the-unused-return-value-checker\"\u003edescribed here\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003ePolymorphism improvements\u003c/h2\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/Kotlin/kotlinx.serialization/blob/master/CHANGELOG.md\"\u003eorg.jetbrains.kotlinx:kotlinx-serialization-json's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch1\u003e1.11.0 / 2026-04-10\u003c/h1\u003e\n\u003cp\u003eThis release is based on Kotlin 2.3.20 and provides new Json exceptions API and some bugfixes and improvements.\u003c/p\u003e\n\u003ch2\u003eExpose Json exceptions structure\u003c/h2\u003e\n\u003cp\u003eTo make working with exceptions easier and providing proper error codes in e.g., REST APIs,\nclasses \u003ccode\u003eJsonException\u003c/code\u003e, \u003ccode\u003eJsonDecodingException\u003c/code\u003e, and \u003ccode\u003eJsonEncodingException\u003c/code\u003e are now public.\nThey have relevant public properties, such as \u003ccode\u003eshortMessage\u003c/code\u003e, \u003ccode\u003epath\u003c/code\u003e, \u003ccode\u003eoffset\u003c/code\u003e, and others.\nThis API is currently experimental, and we're going to improve it further in the subsequent releases.\nSee the linked issues for the details: \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/1930\"\u003e#1930\u003c/a\u003e, \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/1877\"\u003e#1877\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eAbility to hide user input from exception messages for security/privacy reasons.\u003c/h2\u003e\n\u003cp\u003eHistorically, exception messages in kotlinx.serialization often included the input Json itself for debuggability reason.\nSuch behavior may pose additional challenges for logging, analytics, and other systems, since\na system is not always allowed to store user data due to privacy/security reasons, which imposes additional sanitation logic.\nTo address this issue, a new property \u003ccode\u003eexceptionsWithDebugInfo\u003c/code\u003e is added to \u003ccode\u003eJsonConfiguration\u003c/code\u003e.\nDisable it to hide user input from exception messages.\nIMPORTANT: This behavior will be enabled by default when this property becomes stable.\nSee \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/2590\"\u003e#2590\u003c/a\u003e for more details.\u003c/p\u003e\n\u003ch2\u003eBugfixes and improvements\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eCBOR: Relax value range check when decoding numbers (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/3167\"\u003e#3167\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eUse a specialized writeDecimalLong method for IO stream integrations in Json (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/3152\"\u003e#3152\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1\u003e1.10.0 / 2026-01-21\u003c/h1\u003e\n\u003cp\u003eThis release is based on Kotlin 2.3.0 and contains all of the changes from 1.10.0-RC.\nThe only additional change is a fix for ProtoBuf packing of Kotlin unsigned types (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/3079\"\u003e#3079\u003c/a\u003e).\nBig thanks to \u003ca href=\"https://github.com/KosmX\"\u003eKosmX\u003c/a\u003e for contributing the fix.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eFor your convenience, the changelog for 1.10.0-RC is duplicated below:\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch2\u003eStabilization of APIs\u003c/h2\u003e\n\u003cp\u003ekotlinx-serialization 1.10 and subsequent releases will be focused on stabilization of existing APIs.\nThe following APIs and configuration options are no longer experimental because they're widely used without any known major issues:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003eJson\u003c/code\u003e configuration options: \u003ccode\u003edecodeEnumsCaseInsensitive\u003c/code\u003e, \u003ccode\u003eallowTrailingComma\u003c/code\u003e, \u003ccode\u003eallowComments\u003c/code\u003e, and \u003ccode\u003eprettyPrintIndent\u003c/code\u003e. (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/3100\"\u003e#3100\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e@EncodeDefault\u003c/code\u003e annotation and its modes. (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/3106\"\u003e#3106\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eJsonUnquotedLiteral\u003c/code\u003e constructor function (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/2900\"\u003e#2900\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eJsonPrimitive\u003c/code\u003e constructor function overloads that accept unsigned types. (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/3117\"\u003e#3117\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eJSON DSL functions on \u003ccode\u003eJsonElement\u003c/code\u003e with \u003ccode\u003eNothing?\u003c/code\u003e overloads. (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/3117\"\u003e#3117\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003eReadiness for return value checker\u003c/h2\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.serialization/commit/6956af2e6073347c7832c3c5b374fa3b5a345956\"\u003e\u003ccode\u003e6956af2\u003c/code\u003e\u003c/a\u003e Prepare 1.11 release\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.serialization/commit/390d84c68a19cbf7fa453dec22a333648bde49b4\"\u003e\u003ccode\u003e390d84c\u003c/code\u003e\u003c/a\u003e Merge remote-tracking branch 'origin/master' into dev\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.serialization/commit/431fe2dc0a144300b33038820d24fc30302c8abc\"\u003e\u003ccode\u003e431fe2d\u003c/code\u003e\u003c/a\u003e Use local repo for publishing (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/3171\"\u003e#3171\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.serialization/commit/05c12b60a6717b99053fb82e1f94d2f859727374\"\u003e\u003ccode\u003e05c12b6\u003c/code\u003e\u003c/a\u003e Add usage attribute to \u0026quot;testRepositories\u0026quot; configuration\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.serialization/commit/a4e1f082ef2e72caa139b474c05657de6015da20\"\u003e\u003ccode\u003ea4e1f08\u003c/code\u003e\u003c/a\u003e Bump Kover version to 0.9.8 release (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/3174\"\u003e#3174\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.serialization/commit/304e858ccc7066854637d86ab80056f5f2bcc094\"\u003e\u003ccode\u003e304e858\u003c/code\u003e\u003c/a\u003e Expose Json exceptions structure (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/3145\"\u003e#3145\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.serialization/commit/4a0338ef5093d765138151bc30282e909ca459e4\"\u003e\u003ccode\u003e4a0338e\u003c/code\u003e\u003c/a\u003e Included G Play SDK verification file for core-jvm (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/3169\"\u003e#3169\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.serialization/commit/421f64c74f0ea6d4a3cdc8dd483505366e3f6c8f\"\u003e\u003ccode\u003e421f64c\u003c/code\u003e\u003c/a\u003e CBOR: Relax value range check when decoding numbers (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.serialization/issues/3167\"\u003e#3167\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.serialization/commit/85a4f126ec491c77e2b3686cc22c1bae27a20783\"\u003e\u003ccode\u003e85a4f12\u003c/code\u003e\u003c/a\u003e KT-84955: mark apple x64 tagets as deprecated error\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.serialization/commit/bd38b0e49bce38d1a55576e89856bc63990167ed\"\u003e\u003ccode\u003ebd38b0e\u003c/code\u003e\u003c/a\u003e Remove dead code\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/Kotlin/kotlinx.serialization/compare/v1.7.3...v1.11.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `androidx.biometric:biometric` from 1.2.0-alpha05 to 1.4.0-alpha07\n\nUpdates `org.jetbrains.kotlinx:kotlinx-coroutines-android` from 1.9.0 to 1.11.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/Kotlin/kotlinx.coroutines/releases\"\u003eorg.jetbrains.kotlinx:kotlinx-coroutines-android's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e1.11.0\u003c/h2\u003e\n\u003ch3\u003eVarious\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eKotlin was updated to 2.2.20 (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4545\"\u003e#4545\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eImproved the published jar files (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/3842\"\u003e#3842\u003c/a\u003e, \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4599\"\u003e#4599\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eVarious documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4433\"\u003e#4433\u003c/a\u003e, \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4596\"\u003e#4596\u003c/a\u003e).\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eBreaking changes and deprecations\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eMoved \u003ccode\u003ePromise\u003c/code\u003e-related functions from JS and Wasm/JS to the new \u003ccode\u003eweb\u003c/code\u003e target. On Wasm/JS, this is a breaking change. Before the change, \u003ccode\u003ePromise\u003c/code\u003e on Wasm/JS could work with arbitrary Kotlin types, but now, only \u003ccode\u003eJsAny\u003c/code\u003e subtypes are accepted (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4563\"\u003e#4563\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eChanged handling of coroutine exceptions that can't be propagated on JS and Wasm/JS. B\nefore, exceptions were logged, but now, they are reported to the JS runtime (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4451\"\u003e#4451\u003c/a\u003e, \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4631\"\u003e#4631\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eDeprecated using \u003ccode\u003eCoroutineDispatcher\u003c/code\u003e as the coroutine context key; now, \u003ccode\u003eContinuationInterceptor\u003c/code\u003e has to be used instead (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4333\"\u003e#4333\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdvanced the deprecation levels on \u003ccode\u003ekotlinx-coroutines-test\u003c/code\u003e APIs (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4604\"\u003e#4604\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdded lint functions that mark passing a \u003ccode\u003eJob\u003c/code\u003e to coroutine builders as deprecated (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4435\"\u003e#4435\u003c/a\u003e).\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eBug fixes and improvements\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eAdded a \u003ccode\u003ecallsInPlace(EXACTLY_ONCE)\u003c/code\u003e contract to \u003ccode\u003erunBlocking\u003c/code\u003e in code shared between JVM and Native (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4368\"\u003e#4368\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdded a \u003ccode\u003ecallsInPlace(EXACTLY_ONCE)\u003c/code\u003e contract to \u003ccode\u003esuspendCancellableCoroutine\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4574\"\u003e#4574\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFixed \u003ccode\u003eflowOn\u003c/code\u003e incorrectly handling \u003ccode\u003eThreadContextElement\u003c/code\u003e updates (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4403\"\u003e#4403\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFixed exceptions in user-supplied \u003ccode\u003eThread.UncaughtExceptionHandler\u003c/code\u003e instances causing the internal coroutines machinery to fail (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4516\"\u003e#4516\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFixed \u003ccode\u003eCoroutineDispatcher.asScheduler\u003c/code\u003e in the RxJava integration not cancelling outstanding work when a \u003ccode\u003eWorker\u003c/code\u003e gets cancelled, which led to memory leaks in some scenarios (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4615\"\u003e#4615\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFixed \u003ccode\u003eSharedFlow\u003c/code\u003e entering an invalid state when a subscriber and an emitter are cancelled simultaneously (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4583\"\u003e#4583\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFixed an R8 optimization leading to \u003ccode\u003eshareIn\u003c/code\u003e/\u003ccode\u003estateIn\u003c/code\u003e coroutines getting garbage-collected (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4646\"\u003e#4646\u003c/a\u003e). Thanks, \u003ca href=\"https://github.com/solevic\"\u003e\u003ccode\u003e@​solevic\u003c/code\u003e\u003c/a\u003e!\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eSmall additions\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eAdded \u003ccode\u003eCompletableDeferred.asDeferred\u003c/code\u003e for obtaining a read-only \u003ccode\u003eDeferred\u003c/code\u003e view (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4408\"\u003e#4408\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdded \u003ccode\u003eSharedFlow.asFlow\u003c/code\u003e for obtaining a \u003ccode\u003eFlow\u003c/code\u003e view with hidden hot flow semantics (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4530\"\u003e#4530\u003c/a\u003e). Thanks, \u003ca href=\"https://github.com/g000sha256\"\u003e\u003ccode\u003e@​g000sha256\u003c/code\u003e\u003c/a\u003e!\u003c/li\u003e\n\u003cli\u003eAdded a \u003ccode\u003eStateFlow.collectLatest\u003c/code\u003e overload returning \u003ccode\u003eNothing\u003c/code\u003e to assist with finding unreachable code (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4454\"\u003e#4454\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdded \u003ccode\u003eReceiveChannel.consumeTo\u003c/code\u003e for consuming a \u003ccode\u003eReceiveChannel\u003c/code\u003e into a \u003ccode\u003eMutableCollection\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4520\"\u003e#4520\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdded a \u003ccode\u003eStateFlow\u0026lt;T\u0026gt;.onSubscription\u003c/code\u003e overload returning a \u003ccode\u003eStateFlow\u0026lt;T\u0026gt;\u003c/code\u003e, similar to \u003ccode\u003eSharedFlow\u0026lt;T\u0026gt;.onSubscription\u003c/code\u003e returning \u003ccode\u003eSharedFlow\u0026lt;T\u0026gt;\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4275\"\u003e#4275\u003c/a\u003e). Thanks, \u003ca href=\"https://github.com/xit0c\"\u003e\u003ccode\u003e@​xit0c\u003c/code\u003e\u003c/a\u003e!\u003c/li\u003e\n\u003cli\u003eAdded terminal \u003ccode\u003eFlow\u003c/code\u003e operators for collecting a \u003ccode\u003eFlow\u003c/code\u003e to a \u003ccode\u003eMap\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/1541\"\u003e#1541\u003c/a\u003e).\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChangelog relative to version 1.11.0\u003c/h3\u003e\n\u003cp\u003eNo changes, only the version is increased.\u003c/p\u003e\n\u003ch2\u003e1.11.0-rc02\u003c/h2\u003e\n\u003cp\u003eRestored binary compatibility with 1.10.2 and older versions on Wasm/JS for usages of \u003ccode\u003ePromise\u003c/code\u003e-related functions (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4661\"\u003e#4661\u003c/a\u003e).\u003c/p\u003e\n\u003ch2\u003e1.11.0-rc01\u003c/h2\u003e\n\u003ch3\u003eVarious\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eKotlin was updated to 2.2.20 (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4545\"\u003e#4545\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eImproved the published jar files (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/3842\"\u003e#3842\u003c/a\u003e, \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4599\"\u003e#4599\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eVarious documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4433\"\u003e#4433\u003c/a\u003e, \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4596\"\u003e#4596\u003c/a\u003e).\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eBreaking changes and deprecations\u003c/h3\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/Kotlin/kotlinx.coroutines/blob/master/CHANGES.md\"\u003eorg.jetbrains.kotlinx:kotlinx-coroutines-android's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003eVersion 1.11.0\u003c/h2\u003e\n\u003ch3\u003eVarious\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eKotlin was updated to 2.2.20 (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4545\"\u003e#4545\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eImproved the published jar files (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/3842\"\u003e#3842\u003c/a\u003e, \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4599\"\u003e#4599\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eVarious documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4433\"\u003e#4433\u003c/a\u003e, \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4596\"\u003e#4596\u003c/a\u003e).\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eBreaking changes and deprecations\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eMoved \u003ccode\u003ePromise\u003c/code\u003e-related functions from JS and Wasm/JS to the new \u003ccode\u003eweb\u003c/code\u003e target. On Wasm/JS, this is a breaking change. Before the change, \u003ccode\u003ePromise\u003c/code\u003e on Wasm/JS could work with arbitrary Kotlin types, but now, only \u003ccode\u003eJsAny\u003c/code\u003e subtypes are accepted (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4563\"\u003e#4563\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eChanged handling of coroutine exceptions that can't be propagated on JS and Wasm/JS. Before, exceptions were logged, but now, they are reported to the JS runtime (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4451\"\u003e#4451\u003c/a\u003e, \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4631\"\u003e#4631\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eDeprecated using \u003ccode\u003eCoroutineDispatcher\u003c/code\u003e as the coroutine context key; now, \u003ccode\u003eContinuationInterceptor\u003c/code\u003e has to be used instead (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4333\"\u003e#4333\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdvanced the deprecation levels on \u003ccode\u003ekotlinx-coroutines-test\u003c/code\u003e APIs (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4604\"\u003e#4604\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdded lint functions that mark passing a \u003ccode\u003eJob\u003c/code\u003e to coroutine builders as deprecated (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4435\"\u003e#4435\u003c/a\u003e).\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eBug fixes and improvements\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eAdded a \u003ccode\u003ecallsInPlace(EXACTLY_ONCE)\u003c/code\u003e contract to \u003ccode\u003erunBlocking\u003c/code\u003e in code shared between JVM and Native (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4368\"\u003e#4368\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdded a \u003ccode\u003ecallsInPlace(EXACTLY_ONCE)\u003c/code\u003e contract to \u003ccode\u003esuspendCancellableCoroutine\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4574\"\u003e#4574\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFixed \u003ccode\u003eflowOn\u003c/code\u003e incorrectly handling \u003ccode\u003eThreadContextElement\u003c/code\u003e updates (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4403\"\u003e#4403\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFixed exceptions in user-supplied \u003ccode\u003eThread.UncaughtExceptionHandler\u003c/code\u003e instances causing the internal coroutines machinery to fail (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4516\"\u003e#4516\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFixed \u003ccode\u003eCoroutineDispatcher.asScheduler\u003c/code\u003e in the RxJava integration not cancelling outstanding work when a \u003ccode\u003eWorker\u003c/code\u003e gets cancelled, which led to memory leaks in some scenarios (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4615\"\u003e#4615\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFixed \u003ccode\u003eSharedFlow\u003c/code\u003e entering an invalid state when a subscriber and an emitter are cancelled simultaneously (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4583\"\u003e#4583\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFixed an R8 optimization leading to \u003ccode\u003eshareIn\u003c/code\u003e/\u003ccode\u003estateIn\u003c/code\u003e coroutines getting garbage-collected (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4646\"\u003e#4646\u003c/a\u003e). Thanks, \u003ca href=\"https://github.com/solevic\"\u003e\u003ccode\u003e@​solevic\u003c/code\u003e\u003c/a\u003e!\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eSmall additions\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eAdded \u003ccode\u003eCompletableDeferred.asDeferred\u003c/code\u003e for obtaining a read-only \u003ccode\u003eDeferred\u003c/code\u003e view (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4408\"\u003e#4408\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdded \u003ccode\u003eSharedFlow.asFlow\u003c/code\u003e for obtaining a \u003ccode\u003eFlow\u003c/code\u003e view with hidden hot flow semantics (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4530\"\u003e#4530\u003c/a\u003e). Thanks, \u003ca href=\"https://github.com/g000sha256\"\u003e\u003ccode\u003e@​g000sha256\u003c/code\u003e\u003c/a\u003e!\u003c/li\u003e\n\u003cli\u003eAdded a \u003ccode\u003eStateFlow.collectLatest\u003c/code\u003e overload returning \u003ccode\u003eNothing\u003c/code\u003e to assist with finding unreachable code (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4454\"\u003e#4454\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdded \u003ccode\u003eReceiveChannel.consumeTo\u003c/code\u003e for consuming a \u003ccode\u003eReceiveChannel\u003c/code\u003e into a \u003ccode\u003eMutableCollection\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4520\"\u003e#4520\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdded a \u003ccode\u003eStateFlow\u0026lt;T\u0026gt;.onSubscription\u003c/code\u003e overload returning a \u003ccode\u003eStateFlow\u0026lt;T\u0026gt;\u003c/code\u003e, similar to \u003ccode\u003eSharedFlow\u0026lt;T\u0026gt;.onSubscription\u003c/code\u003e returning \u003ccode\u003eSharedFlow\u0026lt;T\u0026gt;\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4275\"\u003e#4275\u003c/a\u003e). Thanks, \u003ca href=\"https://github.com/xit0c\"\u003e\u003ccode\u003e@​xit0c\u003c/code\u003e\u003c/a\u003e!\u003c/li\u003e\n\u003cli\u003eAdded terminal \u003ccode\u003eFlow\u003c/code\u003e operators for collecting a \u003ccode\u003eFlow\u003c/code\u003e to a \u003ccode\u003eMap\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/1541\"\u003e#1541\u003c/a\u003e).\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChangelog relative to version 1.11.0\u003c/h3\u003e\n\u003cp\u003eNo changes, only the version is increased.\u003c/p\u003e\n\u003ch2\u003eVersion 1.11.0-rc02\u003c/h2\u003e\n\u003cp\u003eRestored binary compatibility with 1.10.2 and older versions on Wasm/JS for usages of \u003ccode\u003ePromise\u003c/code\u003e-related functions (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4661\"\u003e#4661\u003c/a\u003e).\u003c/p\u003e\n\u003ch2\u003eVersion 1.11.0-rc01\u003c/h2\u003e\n\u003ch3\u003eVarious\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eKotlin was updated to 2.2.20 (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4545\"\u003e#4545\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eImproved the published jar files (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/3842\"\u003e#3842\u003c/a\u003e, \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4599\"\u003e#4599\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eVarious documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4433\"\u003e#4433\u003c/a\u003e, \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4596\"\u003e#4596\u003c/a\u003e).\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.coroutines/commit/8564f65764d3d05893cec026c6e94250e2b23874\"\u003e\u003ccode\u003e8564f65\u003c/code\u003e\u003c/a\u003e Version 1.11.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.coroutines/commit/a4c6af96c15fe30f5d4e8b810ea74f8babd5805c\"\u003e\u003ccode\u003ea4c6af9\u003c/code\u003e\u003c/a\u003e Merge remote-tracking branch 'origin/master' into develop\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.coroutines/commit/ef917b460aa741691fbf991ee1b813049cae18c9\"\u003e\u003ccode\u003eef917b4\u003c/code\u003e\u003c/a\u003e KT-84955: mark apple x64 tagets as deprecated error (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4645\"\u003e#4645\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.coroutines/commit/5ebc421e341bf2ddce734d369da87df1985e80bd\"\u003e\u003ccode\u003e5ebc421\u003c/code\u003e\u003c/a\u003e Update the release procedure description (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4670\"\u003e#4670\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.coroutines/commit/95f46a073bc4a1230352108cea1835fd22219a80\"\u003e\u003ccode\u003e95f46a0\u003c/code\u003e\u003c/a\u003e Remove old maven repository settings (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4672\"\u003e#4672\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.coroutines/commit/b4f4f0aa6acb692f3fbcadd70e4958e3e9d370fc\"\u003e\u003ccode\u003eb4f4f0a\u003c/code\u003e\u003c/a\u003e Fix package name of \u003ccode\u003eToMapCollectionSamplesTest\u003c/code\u003e. (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4674\"\u003e#4674\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.coroutines/commit/86738dca7dc9ac82249abc8206263fa0065ee631\"\u003e\u003ccode\u003e86738dc\u003c/code\u003e\u003c/a\u003e Added templates to the issue creation wizard (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4654\"\u003e#4654\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.coroutines/commit/330fcc221fb583f0b119f34191f735a73b827378\"\u003e\u003ccode\u003e330fcc2\u003c/code\u003e\u003c/a\u003e Version 1.11.0-rc02\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.coroutines/commit/e31cef6e9f2d26794be7d75ecbf3033b6432d582\"\u003e\u003ccode\u003ee31cef6\u003c/code\u003e\u003c/a\u003e Merge remote-tracking branch 'origin/master' into develop\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.coroutines/commit/dc6e9f61eaf3a67f4bf474a7987aedc3f16cef37\"\u003e\u003ccode\u003edc6e9f6\u003c/code\u003e\u003c/a\u003e Restore Promise-related functions on Wasm/JS as HIDDEN (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4661\"\u003e#4661\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/Kotlin/kotlinx.coroutines/compare/1.9.0...1.11.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.jetbrains.kotlinx:kotlinx-coroutines-test` from 1.9.0 to 1.11.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/Kotlin/kotlinx.coroutines/releases\"\u003eorg.jetbrains.kotlinx:kotlinx-coroutines-test's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e1.11.0\u003c/h2\u003e\n\u003ch3\u003eVarious\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eKotlin was updated to 2.2.20 (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4545\"\u003e#4545\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eImproved the published jar files (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/3842\"\u003e#3842\u003c/a\u003e, \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4599\"\u003e#4599\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eVarious documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4433\"\u003e#4433\u003c/a\u003e, \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4596\"\u003e#4596\u003c/a\u003e).\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eBreaking changes and deprecations\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eMoved \u003ccode\u003ePromise\u003c/code\u003e-related functions from JS and Wasm/JS to the new \u003ccode\u003eweb\u003c/code\u003e target. On Wasm/JS, this is a breaking change. Before the change, \u003ccode\u003ePromise\u003c/code\u003e on Wasm/JS could work with arbitrary Kotlin types, but now, only \u003ccode\u003eJsAny\u003c/code\u003e subtypes are accepted (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4563\"\u003e#4563\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eChanged handling of coroutine exceptions that can't be propagated on JS and Wasm/JS. B\nefore, exceptions were logged, but now, they are reported to the JS runtime (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4451\"\u003e#4451\u003c/a\u003e, \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4631\"\u003e#4631\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eDeprecated using \u003ccode\u003eCoroutineDispatcher\u003c/code\u003e as the coroutine context key; now, \u003ccode\u003eContinuationInterceptor\u003c/code\u003e has to be used instead (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4333\"\u003e#4333\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdvanced the deprecation levels on \u003ccode\u003ekotlinx-coroutines-test\u003c/code\u003e APIs (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4604\"\u003e#4604\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdded lint functions that mark passing a \u003ccode\u003eJob\u003c/code\u003e to coroutine builders as deprecated (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4435\"\u003e#4435\u003c/a\u003e).\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eBug fixes and improvements\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eAdded a \u003ccode\u003ecallsInPlace(EXACTLY_ONCE)\u003c/code\u003e contract to \u003ccode\u003erunBlocking\u003c/code\u003e in code shared between JVM and Native (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4368\"\u003e#4368\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdded a \u003ccode\u003ecallsInPlace(EXACTLY_ONCE)\u003c/code\u003e contract to \u003ccode\u003esuspendCancellableCoroutine\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4574\"\u003e#4574\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFixed \u003ccode\u003eflowOn\u003c/code\u003e incorrectly handling \u003ccode\u003eThreadContextElement\u003c/code\u003e updates (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4403\"\u003e#4403\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFixed exceptions in user-supplied \u003ccode\u003eThread.UncaughtExceptionHandler\u003c/code\u003e instances causing the internal coroutines machinery to fail (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4516\"\u003e#4516\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFixed \u003ccode\u003eCoroutineDispatcher.asScheduler\u003c/code\u003e in the RxJava integration not cancelling outstanding work when a \u003ccode\u003eWorker\u003c/code\u003e gets cancelled, which led to memory leaks in some scenarios (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4615\"\u003e#4615\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFixed \u003ccode\u003eSharedFlow\u003c/code\u003e entering an invalid state when a subscriber and an emitter are cancelled simultaneously (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4583\"\u003e#4583\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFixed an R8 optimization leading to \u003ccode\u003eshareIn\u003c/code\u003e/\u003ccode\u003estateIn\u003c/code\u003e coroutines getting garbage-collected (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4646\"\u003e#4646\u003c/a\u003e). Thanks, \u003ca href=\"https://github.com/solevic\"\u003e\u003ccode\u003e@​solevic\u003c/code\u003e\u003c/a\u003e!\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eSmall additions\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eAdded \u003ccode\u003eCompletableDeferred.asDeferred\u003c/code\u003e for obtaining a read-only \u003ccode\u003eDeferred\u003c/code\u003e view (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4408\"\u003e#4408\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdded \u003ccode\u003eSharedFlow.asFlow\u003c/code\u003e for obtaining a \u003ccode\u003eFlow\u003c/code\u003e view with hidden hot flow semantics (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4530\"\u003e#4530\u003c/a\u003e). Thanks, \u003ca href=\"https://github.com/g000sha256\"\u003e\u003ccode\u003e@​g000sha256\u003c/code\u003e\u003c/a\u003e!\u003c/li\u003e\n\u003cli\u003eAdded a \u003ccode\u003eStateFlow.collectLatest\u003c/code\u003e overload returning \u003ccode\u003eNothing\u003c/code\u003e to assist with finding unreachable code (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4454\"\u003e#4454\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdded \u003ccode\u003eReceiveChannel.consumeTo\u003c/code\u003e for consuming a \u003ccode\u003eReceiveChannel\u003c/code\u003e into a \u003ccode\u003eMutableCollection\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4520\"\u003e#4520\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdded a \u003ccode\u003eStateFlow\u0026lt;T\u0026gt;.onSubscription\u003c/code\u003e overload returning a \u003ccode\u003eStateFlow\u0026lt;T\u0026gt;\u003c/code\u003e, similar to \u003ccode\u003eSharedFlow\u0026lt;T\u0026gt;.onSubscription\u003c/code\u003e returning \u003ccode\u003eSharedFlow\u0026lt;T\u0026gt;\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4275\"\u003e#4275\u003c/a\u003e). Thanks, \u003ca href=\"https://github.com/xit0c\"\u003e\u003ccode\u003e@​xit0c\u003c/code\u003e\u003c/a\u003e!\u003c/li\u003e\n\u003cli\u003eAdded terminal \u003ccode\u003eFlow\u003c/code\u003e operators for collecting a \u003ccode\u003eFlow\u003c/code\u003e to a \u003ccode\u003eMap\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/1541\"\u003e#1541\u003c/a\u003e).\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChangelog relative to version 1.11.0\u003c/h3\u003e\n\u003cp\u003eNo changes, only the version is increased.\u003c/p\u003e\n\u003ch2\u003e1.11.0-rc02\u003c/h2\u003e\n\u003cp\u003eRestored binary compatibility with 1.10.2 and older versions on Wasm/JS for usages of \u003ccode\u003ePromise\u003c/code\u003e-related functions (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4661\"\u003e#4661\u003c/a\u003e).\u003c/p\u003e\n\u003ch2\u003e1.11.0-rc01\u003c/h2\u003e\n\u003ch3\u003eVarious\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eKotlin was updated to 2.2.20 (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4545\"\u003e#4545\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eImproved the published jar files (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/3842\"\u003e#3842\u003c/a\u003e, \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4599\"\u003e#4599\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eVarious documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4433\"\u003e#4433\u003c/a\u003e, \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4596\"\u003e#4596\u003c/a\u003e).\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eBreaking changes and deprecations\u003c/h3\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/Kotlin/kotlinx.coroutines/blob/master/CHANGES.md\"\u003eorg.jetbrains.kotlinx:kotlinx-coroutines-test's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003eVersion 1.11.0\u003c/h2\u003e\n\u003ch3\u003eVarious\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eKotlin was updated to 2.2.20 (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4545\"\u003e#4545\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eImproved the published jar files (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/3842\"\u003e#3842\u003c/a\u003e, \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4599\"\u003e#4599\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eVarious documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4433\"\u003e#4433\u003c/a\u003e, \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4596\"\u003e#4596\u003c/a\u003e).\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eBreaking changes and deprecations\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eMoved \u003ccode\u003ePromise\u003c/code\u003e-related functions from JS and Wasm/JS to the new \u003ccode\u003eweb\u003c/code\u003e target. On Wasm/JS, this is a breaking change. Before the change, \u003ccode\u003ePromise\u003c/code\u003e on Wasm/JS could work with arbitrary Kotlin types, but now, only \u003ccode\u003eJsAny\u003c/code\u003e subtypes are accepted (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4563\"\u003e#4563\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eChanged handling of coroutine exceptions that can't be propagated on JS and Wasm/JS. Before, exceptions were logged, but now, they are reported to the JS runtime (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4451\"\u003e#4451\u003c/a\u003e, \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4631\"\u003e#4631\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eDeprecated using \u003ccode\u003eCoroutineDispatcher\u003c/code\u003e as the coroutine context key; now, \u003ccode\u003eContinuationInterceptor\u003c/code\u003e has to be used instead (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4333\"\u003e#4333\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdvanced the deprecation levels on \u003ccode\u003ekotlinx-coroutines-test\u003c/code\u003e APIs (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4604\"\u003e#4604\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdded lint functions that mark passing a \u003ccode\u003eJob\u003c/code\u003e to coroutine builders as deprecated (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4435\"\u003e#4435\u003c/a\u003e).\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eBug fixes and improvements\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eAdded a \u003ccode\u003ecallsInPlace(EXACTLY_ONCE)\u003c/code\u003e contract to \u003ccode\u003erunBlocking\u003c/code\u003e in code shared between JVM and Native (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4368\"\u003e#4368\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdded a \u003ccode\u003ecallsInPlace(EXACTLY_ONCE)\u003c/code\u003e contract to \u003ccode\u003esuspendCancellableCoroutine\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4574\"\u003e#4574\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFixed \u003ccode\u003eflowOn\u003c/code\u003e incorrectly handling \u003ccode\u003eThreadContextElement\u003c/code\u003e updates (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4403\"\u003e#4403\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFixed exceptions in user-supplied \u003ccode\u003eThread.UncaughtExceptionHandler\u003c/code\u003e instances causing the internal coroutines machinery to fail (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4516\"\u003e#4516\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFixed \u003ccode\u003eCoroutineDispatcher.asScheduler\u003c/code\u003e in the RxJava integration not cancelling outstanding work when a \u003ccode\u003eWorker\u003c/code\u003e gets cancelled, which led to memory leaks in some scenarios (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4615\"\u003e#4615\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFixed \u003ccode\u003eSharedFlow\u003c/code\u003e entering an invalid state when a subscriber and an emitter are cancelled simultaneously (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4583\"\u003e#4583\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFixed an R8 optimization leading to \u003ccode\u003eshareIn\u003c/code\u003e/\u003ccode\u003estateIn\u003c/code\u003e coroutines getting garbage-collected (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4646\"\u003e#4646\u003c/a\u003e). Thanks, \u003ca href=\"https://github.com/solevic\"\u003e\u003ccode\u003e@​solevic\u003c/code\u003e\u003c/a\u003e!\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eSmall additions\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eAdded \u003ccode\u003eCompletableDeferred.asDeferred\u003c/code\u003e for obtaining a read-only \u003ccode\u003eDeferred\u003c/code\u003e view (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4408\"\u003e#4408\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdded \u003ccode\u003eSharedFlow.asFlow\u003c/code\u003e for obtaining a \u003ccode\u003eFlow\u003c/code\u003e view with hidden hot flow semantics (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4530\"\u003e#4530\u003c/a\u003e). Thanks, \u003ca href=\"https://github.com/g000sha256\"\u003e\u003ccode\u003e@​g000sha256\u003c/code\u003e\u003c/a\u003e!\u003c/li\u003e\n\u003cli\u003eAdded a \u003ccode\u003eStateFlow.collectLatest\u003c/code\u003e overload returning \u003ccode\u003eNothing\u003c/code\u003e to assist with finding unreachable code (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4454\"\u003e#4454\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdded \u003ccode\u003eReceiveChannel.consumeTo\u003c/code\u003e for consuming a \u003ccode\u003eReceiveChannel\u003c/code\u003e into a \u003ccode\u003eMutableCollection\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4520\"\u003e#4520\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eAdded a \u003ccode\u003eStateFlow\u0026lt;T\u0026gt;.onSubscription\u003c/code\u003e overload returning a \u003ccode\u003eStateFlow\u0026lt;T\u0026gt;\u003c/code\u003e, similar to \u003ccode\u003eSharedFlow\u0026lt;T\u0026gt;.onSubscription\u003c/code\u003e returning \u003ccode\u003eSharedFlow\u0026lt;T\u0026gt;\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4275\"\u003e#4275\u003c/a\u003e). Thanks, \u003ca href=\"https://github.com/xit0c\"\u003e\u003ccode\u003e@​xit0c\u003c/code\u003e\u003c/a\u003e!\u003c/li\u003e\n\u003cli\u003eAdded terminal \u003ccode\u003eFlow\u003c/code\u003e operators for collecting a \u003ccode\u003eFlow\u003c/code\u003e to a \u003ccode\u003eMap\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/1541\"\u003e#1541\u003c/a\u003e).\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChangelog relative to version 1.11.0\u003c/h3\u003e\n\u003cp\u003eNo changes, only the version is increased.\u003c/p\u003e\n\u003ch2\u003eVersion 1.11.0-rc02\u003c/h2\u003e\n\u003cp\u003eRestored binary compatibility with 1.10.2 and older versions on Wasm/JS for usages of \u003ccode\u003ePromise\u003c/code\u003e-related functions (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4661\"\u003e#4661\u003c/a\u003e).\u003c/p\u003e\n\u003ch2\u003eVersion 1.11.0-rc01\u003c/h2\u003e\n\u003ch3\u003eVarious\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eKotlin was updated to 2.2.20 (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4545\"\u003e#4545\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eImproved the published jar files (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/3842\"\u003e#3842\u003c/a\u003e, \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4599\"\u003e#4599\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eVarious documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4433\"\u003e#4433\u003c/a\u003e, \u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4596\"\u003e#4596\u003c/a\u003e).\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.coroutines/commit/8564f65764d3d05893cec026c6e94250e2b23874\"\u003e\u003ccode\u003e8564f65\u003c/code\u003e\u003c/a\u003e Version 1.11.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.coroutines/commit/a4c6af96c15fe30f5d4e8b810ea74f8babd5805c\"\u003e\u003ccode\u003ea4c6af9\u003c/code\u003e\u003c/a\u003e Merge remote-tracking branch 'origin/master' into develop\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.coroutines/commit/ef917b460aa741691fbf991ee1b813049cae18c9\"\u003e\u003ccode\u003eef917b4\u003c/code\u003e\u003c/a\u003e KT-84955: mark apple x64 tagets as deprecated error (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4645\"\u003e#4645\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.coroutines/commit/5ebc421e341bf2ddce734d369da87df1985e80bd\"\u003e\u003ccode\u003e5ebc421\u003c/code\u003e\u003c/a\u003e Update the release procedure description (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4670\"\u003e#4670\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.coroutines/commit/95f46a073bc4a1230352108cea1835fd22219a80\"\u003e\u003ccode\u003e95f46a0\u003c/code\u003e\u003c/a\u003e Remove old maven repository settings (\u003ca href=\"https://redirect.github.com/Kotlin/kotlinx.coroutines/issues/4672\"\u003e#4672\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Kotlin/kotlinx.coroutine...\n\n_Description has been truncated_","html_url":"https://github.com/Classxx/walkie/pull/5","url":"https://dependabot.ecosyste.ms/api/v1/hosts/GitHub/repositories/Classxx%2Fwalkie/issues/5","packages_url":"https://dependabot.ecosyste.ms/api/v1/issues/5/packages"}},{"old_version":"4.12.0","new_version":"5.5.0","update_type":"major","path":null,"pr_created_at":"2026-09-07T01:05:42.000Z","version_change":"4.12.0 → 5.5.0","issue":{"uuid":"5368832045","node_id":"PR_kwDOJ9Dpyc8AAAABCcn4eQ","number":630,"state":"open","title":"chore(deps-dev): bump com.squareup.okhttp3:mockwebserver from 4.12.0 to 5.5.0","user":"dependabot[bot]","labels":[],"assignees":[],"locked":false,"comments_count":1,"pull_request":true,"closed_at":null,"author_association":null,"state_reason":null,"created_at":"2026-09-07T01:05:42.000Z","updated_at":"2026-09-07T01:05:43.000Z","time_to_close":null,"merged_at":null,"merged_by":null,"closed_by":null,"dependency_metadata":{"prefix":"chore(deps-dev)","packages":[{"name":"com.squareup.okhttp3:mockwebserver","old_version":"4.12.0","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"}],"path":null,"ecosystem":"maven"},"body":"Bumps [com.squareup.okhttp3:mockwebserver](https://github.com/lysine-dev/okhttp) from 4.12.0 to 5.5.0.\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/lysine-dev/okhttp/blob/main/CHANGELOG.md\"\u003ecom.squareup.okhttp3:mockwebserver's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003eVersion 5.5.0\u003c/h2\u003e\n\u003cp\u003e\u003cem\u003e2026-08-16\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003eThis release introduces \u003cstrong\u003eopt-in\u003c/strong\u003e support for [Encrypted Client Hello (ECH)]. This new feature\nimproves user privacy by encrypting domain names in transit. With regular TLS, your coffee shop’s\nWi-Fi router can see that you’re visiting \u003cem\u003ewikipedia.com\u003c/em\u003e, but it cannot see which page you’re\nlooking at. With ECH, the router observes only the IP address. This additional privacy is most\neffective on sites hosted by big CDNs because the IP address doesn’t imply a particular website.\u003c/p\u003e\n\u003cp\u003eThis requires ECH support in the platform’s TLS stack. Today this is only Android 17 (API 37,\nreleased June 2026). When other TLS stacks add ECH support, we'll integrate them.\u003c/p\u003e\n\u003cp\u003eECH took a lot of work to implement because the encryption keys are published over DNS in the\n[HTTPS resource record], and we needed to write new code to fetch these records. This release\nincludes a major update to OkHttp’s DNS API: it now supports multiple resource record types (not\njust IP addresses!), asynchronous streaming results, and in-memory caching.\u003c/p\u003e\n\u003cp\u003eTo opt in, you can use \u003ccode\u003eDnsOverHttps\u003c/code\u003e:\u003c/p\u003e\n\u003cpre lang=\"kotlin\"\u003e\u003ccode\u003e// DnsOverHttps itself uses OkHttpClient. Build both clients upon the\n// same bootstrap client so they share a connection pool and dispatcher.\nval bootstrapClient = OkHttpClient()\n\u003cp\u003e// This sample uses Cloudflare's 1.1.1.1 DnsOverHttps service.\nval client = bootstrapClient.newBuilder()\n.dns(DnsOverHttps.Builder()\n.client(bootstrapClient)\n.url(\u0026quot;\u003ca href=\"https://1.1.1.1/dns-query\u0026amp;quot;.toHttpUrl()\"\u003ehttps://1.1.1.1/dns-query\u0026amp;quot;.toHttpUrl()\u003c/a\u003e)\n.build())\n.build()\n\u003c/code\u003e\u003c/pre\u003e\u003c/p\u003e\n\u003cp\u003eYou could also opt in with our new \u003ccode\u003eAndroidDns\u003c/code\u003e API. Unfortunately, the privacy benefits of ECH are\nthwarted because its DNS queries are not encrypted by default.\u003c/p\u003e\n\u003cpre lang=\"kotlin\"\u003e\u003ccode\u003e// AndroidDns fetches the HTTPS DNS resource records necessary for ECH.\nval client = OkHttpClient.Builder()\n  .dns(AndroidDns())\n  .build()\n\u003c/code\u003e\u003c/pre\u003e\n\u003cul\u003e\n\u003cli\u003eNew: OkHttp artifacts are now signed with our [new signing key]. This project and three sibling\nprojects ([Retrofit], [Okio], and [SQLDelight]) recently joined [the Commonhaus Foundation].\u003c/li\u003e\n\u003cli\u003eFix: MockWebServer’s \u003ccode\u003e@StartStop\u003c/code\u003e annotation now supports \u003ccode\u003e@Nested\u003c/code\u003e JUnit 5 tests.\u003c/li\u003e\n\u003cli\u003eFix: Our default TLS hostname verifier now reject hosts that fail IP canonicalization.\u003c/li\u003e\n\u003cli\u003eFix: Closing a multipart part's sink no longer closes the entire request body.\u003c/li\u003e\n\u003cli\u003eFix: Flush HTTP/1 request bodies before detaching the timeout. We had a bug where timeouts\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/a94bdf152084d11acecd44dcd09ffef203f4f0aa\"\u003e\u003ccode\u003ea94bdf1\u003c/code\u003e\u003c/a\u003e Prepare for release 5.5.0.\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/ecc3b05adfe6b2607b8ec251562c2cccf7c1923a\"\u003e\u003ccode\u003eecc3b05\u003c/code\u003e\u003c/a\u003e Use a fixed size for DoH request body (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9687\"\u003e#9687\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/9926082660dfa6f1cc848c6f465cf5ccb998e415\"\u003e\u003ccode\u003e9926082\u003c/code\u003e\u003c/a\u003e Revert \u0026quot;Use a fixed size for DoH request body\u0026quot; (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9686\"\u003e#9686\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/0070c2e7b4c162ee03abf1c88fd94083e94697f4\"\u003e\u003ccode\u003e0070c2e\u003c/code\u003e\u003c/a\u003e Use a fixed size for DoH request body\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/15764539c69842dad607462f102a2507223dbfe7\"\u003e\u003ccode\u003e1576453\u003c/code\u003e\u003c/a\u003e Order ServiceMetadata records per the spec (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9683\"\u003e#9683\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/fb582e976a9a82d691342a4d57b3c72208ce416c\"\u003e\u003ccode\u003efb582e9\u003c/code\u003e\u003c/a\u003e Flip wiring of Dns.SYSTEM (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9682\"\u003e#9682\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/4e884abb1a207c321acffb070c476acb4b89fa3f\"\u003e\u003ccode\u003e4e884ab\u003c/code\u003e\u003c/a\u003e retryOnConnectionFailure doesn't impact ECH retries (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9681\"\u003e#9681\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/0433cee8131b63fa2c0634fa2f9b3a01f9a8b1f3\"\u003e\u003ccode\u003e0433cee\u003c/code\u003e\u003c/a\u003e Only one contributing.md doc (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9678\"\u003e#9678\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/a2cf5aa9f8711dabe514871e9dc4a9336a0e403f\"\u003e\u003ccode\u003ea2cf5aa\u003c/code\u003e\u003c/a\u003e Don't recover after an ECH public_name fails to verify (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9680\"\u003e#9680\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/5410de9760bce8719129c3d08eb19e5bace75f6e\"\u003e\u003ccode\u003e5410de9\u003c/code\u003e\u003c/a\u003e Test ECH + HTTP proxy (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9671\"\u003e#9671\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/lysine-dev/okhttp/compare/parent-4.12.0...parent-5.5.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\n\n[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=com.squareup.okhttp3:mockwebserver\u0026package-manager=maven\u0026previous-version=4.12.0\u0026new-version=5.5.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)\n\nDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.\n\n[//]: # (dependabot-automerge-start)\n[//]: # (dependabot-automerge-end)\n\n---\n\n\u003cdetails\u003e\n\u003csummary\u003eDependabot commands and options\u003c/summary\u003e\n\u003cbr /\u003e\n\nYou can trigger Dependabot actions by commenting on this PR:\n- `@dependabot rebase` will rebase this PR\n- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it\n- `@dependabot show \u003cdependency name\u003e ignore conditions` will show all of the ignore conditions of the specified dependency\n- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)\n\n\n\u003c/details\u003e","html_url":"https://github.com/Jason-Clark-FG/OpenMetadata-FG/pull/630","url":"https://dependabot.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jason-Clark-FG%2FOpenMetadata-FG/issues/630","packages_url":"https://dependabot.ecosyste.ms/api/v1/issues/630/packages"}},{"old_version":"4.12.0","new_version":"5.5.0","update_type":"major","path":"/android","pr_created_at":"2026-09-06T19:52:49.000Z","version_change":"4.12.0 → 5.5.0","issue":{"uuid":"5367280542","node_id":"PR_kwDOUI8uTs8AAAABCbceaw","number":9,"state":"closed","title":"build(deps): bump com.squareup.okhttp3:mockwebserver from 4.12.0 to 5.5.0 in /android","user":"dependabot[bot]","labels":["dependencies","java"],"assignees":[],"locked":false,"comments_count":2,"pull_request":true,"closed_at":"2026-09-10T20:52:27.000Z","author_association":null,"state_reason":null,"created_at":"2026-09-06T19:52:49.000Z","updated_at":"2026-09-10T20:52:29.000Z","time_to_close":349178,"merged_at":null,"merged_by":null,"closed_by":null,"dependency_metadata":{"prefix":"build(deps)","packages":[{"name":"com.squareup.okhttp3:mockwebserver","old_version":"4.12.0","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"}],"path":"/android","ecosystem":"maven"},"body":"Bumps [com.squareup.okhttp3:mockwebserver](https://github.com/lysine-dev/okhttp) from 4.12.0 to 5.5.0.\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/lysine-dev/okhttp/blob/main/CHANGELOG.md\"\u003ecom.squareup.okhttp3:mockwebserver's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003eVersion 5.5.0\u003c/h2\u003e\n\u003cp\u003e\u003cem\u003e2026-08-16\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003eThis release introduces \u003cstrong\u003eopt-in\u003c/strong\u003e support for [Encrypted Client Hello (ECH)]. This new feature\nimproves user privacy by encrypting domain names in transit. With regular TLS, your coffee shop’s\nWi-Fi router can see that you’re visiting \u003cem\u003ewikipedia.com\u003c/em\u003e, but it cannot see which page you’re\nlooking at. With ECH, the router observes only the IP address. This additional privacy is most\neffective on sites hosted by big CDNs because the IP address doesn’t imply a particular website.\u003c/p\u003e\n\u003cp\u003eThis requires ECH support in the platform’s TLS stack. Today this is only Android 17 (API 37,\nreleased June 2026). When other TLS stacks add ECH support, we'll integrate them.\u003c/p\u003e\n\u003cp\u003eECH took a lot of work to implement because the encryption keys are published over DNS in the\n[HTTPS resource record], and we needed to write new code to fetch these records. This release\nincludes a major update to OkHttp’s DNS API: it now supports multiple resource record types (not\njust IP addresses!), asynchronous streaming results, and in-memory caching.\u003c/p\u003e\n\u003cp\u003eTo opt in, you can use \u003ccode\u003eDnsOverHttps\u003c/code\u003e:\u003c/p\u003e\n\u003cpre lang=\"kotlin\"\u003e\u003ccode\u003e// DnsOverHttps itself uses OkHttpClient. Build both clients upon the\n// same bootstrap client so they share a connection pool and dispatcher.\nval bootstrapClient = OkHttpClient()\n\u003cp\u003e// This sample uses Cloudflare's 1.1.1.1 DnsOverHttps service.\nval client = bootstrapClient.newBuilder()\n.dns(DnsOverHttps.Builder()\n.client(bootstrapClient)\n.url(\u0026quot;\u003ca href=\"https://1.1.1.1/dns-query\u0026amp;quot;.toHttpUrl()\"\u003ehttps://1.1.1.1/dns-query\u0026amp;quot;.toHttpUrl()\u003c/a\u003e)\n.build())\n.build()\n\u003c/code\u003e\u003c/pre\u003e\u003c/p\u003e\n\u003cp\u003eYou could also opt in with our new \u003ccode\u003eAndroidDns\u003c/code\u003e API. Unfortunately, the privacy benefits of ECH are\nthwarted because its DNS queries are not encrypted by default.\u003c/p\u003e\n\u003cpre lang=\"kotlin\"\u003e\u003ccode\u003e// AndroidDns fetches the HTTPS DNS resource records necessary for ECH.\nval client = OkHttpClient.Builder()\n  .dns(AndroidDns())\n  .build()\n\u003c/code\u003e\u003c/pre\u003e\n\u003cul\u003e\n\u003cli\u003eNew: OkHttp artifacts are now signed with our [new signing key]. This project and three sibling\nprojects ([Retrofit], [Okio], and [SQLDelight]) recently joined [the Commonhaus Foundation].\u003c/li\u003e\n\u003cli\u003eFix: MockWebServer’s \u003ccode\u003e@StartStop\u003c/code\u003e annotation now supports \u003ccode\u003e@Nested\u003c/code\u003e JUnit 5 tests.\u003c/li\u003e\n\u003cli\u003eFix: Our default TLS hostname verifier now reject hosts that fail IP canonicalization.\u003c/li\u003e\n\u003cli\u003eFix: Closing a multipart part's sink no longer closes the entire request body.\u003c/li\u003e\n\u003cli\u003eFix: Flush HTTP/1 request bodies before detaching the timeout. We had a bug where timeouts\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/a94bdf152084d11acecd44dcd09ffef203f4f0aa\"\u003e\u003ccode\u003ea94bdf1\u003c/code\u003e\u003c/a\u003e Prepare for release 5.5.0.\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/ecc3b05adfe6b2607b8ec251562c2cccf7c1923a\"\u003e\u003ccode\u003eecc3b05\u003c/code\u003e\u003c/a\u003e Use a fixed size for DoH request body (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9687\"\u003e#9687\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/9926082660dfa6f1cc848c6f465cf5ccb998e415\"\u003e\u003ccode\u003e9926082\u003c/code\u003e\u003c/a\u003e Revert \u0026quot;Use a fixed size for DoH request body\u0026quot; (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9686\"\u003e#9686\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/0070c2e7b4c162ee03abf1c88fd94083e94697f4\"\u003e\u003ccode\u003e0070c2e\u003c/code\u003e\u003c/a\u003e Use a fixed size for DoH request body\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/15764539c69842dad607462f102a2507223dbfe7\"\u003e\u003ccode\u003e1576453\u003c/code\u003e\u003c/a\u003e Order ServiceMetadata records per the spec (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9683\"\u003e#9683\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/fb582e976a9a82d691342a4d57b3c72208ce416c\"\u003e\u003ccode\u003efb582e9\u003c/code\u003e\u003c/a\u003e Flip wiring of Dns.SYSTEM (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9682\"\u003e#9682\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/4e884abb1a207c321acffb070c476acb4b89fa3f\"\u003e\u003ccode\u003e4e884ab\u003c/code\u003e\u003c/a\u003e retryOnConnectionFailure doesn't impact ECH retries (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9681\"\u003e#9681\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/0433cee8131b63fa2c0634fa2f9b3a01f9a8b1f3\"\u003e\u003ccode\u003e0433cee\u003c/code\u003e\u003c/a\u003e Only one contributing.md doc (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9678\"\u003e#9678\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/a2cf5aa9f8711dabe514871e9dc4a9336a0e403f\"\u003e\u003ccode\u003ea2cf5aa\u003c/code\u003e\u003c/a\u003e Don't recover after an ECH public_name fails to verify (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9680\"\u003e#9680\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/lysine-dev/okhttp/commit/5410de9760bce8719129c3d08eb19e5bace75f6e\"\u003e\u003ccode\u003e5410de9\u003c/code\u003e\u003c/a\u003e Test ECH + HTTP proxy (\u003ca href=\"https://redirect.github.com/lysine-dev/okhttp/issues/9671\"\u003e#9671\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/lysine-dev/okhttp/compare/parent-4.12.0...parent-5.5.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\n\n[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=com.squareup.okhttp3:mockwebserver\u0026package-manager=gradle\u0026previous-version=4.12.0\u0026new-version=5.5.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)\n\nDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.\n\n[//]: # (dependabot-automerge-start)\n[//]: # (dependabot-automerge-end)\n\n---\n\n\u003cdetails\u003e\n\u003csummary\u003eDependabot commands and options\u003c/summary\u003e\n\u003cbr /\u003e\n\nYou can trigger Dependabot actions by commenting on this PR:\n- `@dependabot rebase` will rebase this PR\n- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it\n- `@dependabot show \u003cdependency name\u003e ignore conditions` will show all of the ignore conditions of the specified dependency\n- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)\n\n\n\u003c/details\u003e","html_url":"https://github.com/ersingundem/larenor/pull/9","url":"https://dependabot.ecosyste.ms/api/v1/hosts/GitHub/repositories/ersingundem%2Flarenor/issues/9","packages_url":"https://dependabot.ecosyste.ms/api/v1/issues/9/packages"}},{"old_version":"5.3.2","new_version":"5.5.0","update_type":"minor","path":null,"pr_created_at":"2026-09-02T19:52:55.000Z","version_change":"5.3.2 → 5.5.0","issue":{"uuid":"5328543030","node_id":"PR_kwDOTDTeds8AAAABB9DfdA","number":30,"state":"closed","title":"build(deps): bump the android-deps group across 1 directory with 19 updates","user":"dependabot[bot]","labels":["dependencies","java"],"assignees":[],"locked":false,"comments_count":3,"pull_request":true,"closed_at":"2026-09-09T19:45:28.000Z","author_association":null,"state_reason":null,"created_at":"2026-09-02T19:52:55.000Z","updated_at":"2026-09-09T19:45:28.000Z","time_to_close":604353,"merged_at":null,"merged_by":null,"closed_by":null,"dependency_metadata":{"prefix":"build(deps): bump","group_name":"android-deps","update_count":19,"packages":[{"name":"gradle-wrapper","old_version":"9.5.1","new_version":"9.7.1","repository_url":"https://github.com/gradle/gradle"},{"name":"androidx.compose:compose-bom","old_version":"2026.05.01","new_version":"2026.08.00"},{"name":"androidx.core:core-ktx","old_version":"1.18.0","new_version":"1.19.0"},{"name":"androidx.webkit:webkit","old_version":"1.15.0","new_version":"1.17.0"},{"name":"org.bouncycastle:bcprov-jdk18on","old_version":"1.84","new_version":"1.85.2","repository_url":"https://github.com/bcgit/bc-java"},{"name":"org.commonmark:commonmark","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-autolink","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-strikethrough","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-tables","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-task-list-items","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.junit.vintage:junit-vintage-engine","old_version":"6.1.0","new_version":"6.1.3","repository_url":"https://github.com/junit-team/junit-framework"},{"name":"io.kotest:kotest-assertions-core-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"io.kotest:kotest-runner-junit5-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"com.squareup.okhttp3:mockwebserver","old_version":"5.3.2","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.squareup.okhttp3:okhttp","old_version":"5.3.2","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.android.application","old_version":"9.2.1","new_version":"9.4.0"},{"name":"com.android.test","old_version":"9.2.1","new_version":"9.4.0"},{"name":"org.jetbrains.kotlin.plugin.compose","old_version":"2.4.0","new_version":"2.4.10","repository_url":"https://github.com/JetBrains/kotlin"},{"name":"org.jetbrains.kotlin.plugin.serialization","old_version":"2.4.0","new_version":"2.4.10","repository_url":"https://github.com/JetBrains/kotlin"}],"path":null,"ecosystem":"maven"},"body":"Bumps the android-deps group with 19 updates in the /apps/android directory:\n\n| Package | From | To |\n| --- | --- | --- |\n| [gradle-wrapper](https://github.com/gradle/gradle) | `9.5.1` | `9.7.1` |\n| androidx.compose:compose-bom | `2026.05.01` | `2026.08.00` |\n| androidx.core:core-ktx | `1.18.0` | `1.19.0` |\n| androidx.webkit:webkit | `1.15.0` | `1.17.0` |\n| [org.bouncycastle:bcprov-jdk18on](https://github.com/bcgit/bc-java) | `1.84` | `1.85.2` |\n| [org.commonmark:commonmark](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-autolink](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-strikethrough](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-tables](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-task-list-items](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.junit.vintage:junit-vintage-engine](https://github.com/junit-team/junit-framework) | `6.1.0` | `6.1.3` |\n| [io.kotest:kotest-assertions-core-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [io.kotest:kotest-runner-junit5-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [com.squareup.okhttp3:mockwebserver](https://github.com/lysine-dev/okhttp) | `5.3.2` | `5.5.0` |\n| [com.squareup.okhttp3:okhttp](https://github.com/lysine-dev/okhttp) | `5.3.2` | `5.5.0` |\n| com.android.application | `9.2.1` | `9.4.0` |\n| com.android.test | `9.2.1` | `9.4.0` |\n| [org.jetbrains.kotlin.plugin.compose](https://github.com/JetBrains/kotlin) | `2.4.0` | `2.4.10` |\n| [org.jetbrains.kotlin.plugin.serialization](https://github.com/JetBrains/kotlin) | `2.4.0` | `2.4.10` |\n\n\nUpdates `gradle-wrapper` from 9.5.1 to 9.7.1\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/gradle/gradle/releases\"\u003egradle-wrapper's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e9.7.1\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.1.\u003c/p\u003e\n\u003cp\u003eThis is a patch release for 9.7.0. We recommend using 9.7.1 instead of 9.7.0.\u003c/p\u003e\n\u003cp\u003eHere are the highlights of 9.7.0 release:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIsolated Projects graduates to incubating\u003c/li\u003e\n\u003cli\u003eBroader Configuration Cache compatibility\u003c/li\u003e\n\u003cli\u003eResilient Sync helps you fix broken builds\u003c/li\u003e\n\u003cli\u003eMore source locations in problem reports\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003ca href=\"https://docs.gradle.org/9.7.1/release-notes.html\"\u003eRead the Release Notes\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eWe would like to thank the following community members for their contributions to this release of Gradle:\n\u003ca href=\"https://github.com/aSemy\"\u003eAdam\u003c/a\u003e,\n\u003ca href=\"https://github.com/Gautam-aman\"\u003eAman Gautam\u003c/a\u003e,\n\u003ca href=\"https://github.com/YukiCodepth\"\u003eAman Kumar\u003c/a\u003e,\n\u003ca href=\"https://github.com/adubrouski\"\u003eAnton Dubrouski\u003c/a\u003e,\n\u003ca href=\"https://github.com/liutikas\"\u003eAurimas\u003c/a\u003e,\n\u003ca href=\"https://github.com/gbhavya07\"\u003egbhavya07\u003c/a\u003e,\n\u003ca href=\"https://github.com/joshfriend\"\u003eJosh Friend\u003c/a\u003e,\n\u003ca href=\"https://github.com/nicklauslittle-gov\"\u003enicklauslittle-gov\u003c/a\u003e,\n\u003ca href=\"https://github.com/psoni674\"\u003ePragati\u003c/a\u003e,\n\u003ca href=\"https://github.com/Project516\"\u003eproject516\u003c/a\u003e,\n\u003ca href=\"https://github.com/Uomocapra\"\u003eQin Mi\u003c/a\u003e,\n\u003ca href=\"https://github.com/rkdfx\"\u003eRavi\u003c/a\u003e,\n\u003ca href=\"https://github.com/sk-reddy17\"\u003esk-reddy17\u003c/a\u003e,\n\u003ca href=\"https://github.com/Suvrat1629\"\u003eSuvrat Acharya\u003c/a\u003e,\n\u003ca href=\"https://github.com/ShreckYe\"\u003eYongshun Ye\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eUpgrade instructions\u003c/h2\u003e\n\u003cp\u003eSwitch your build to use Gradle 9.7.1 by updating your wrapper:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e./gradlew :wrapper --gradle-version=9.7.1 \u0026amp;\u0026amp; ./gradlew :wrapper\r\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eSee the Gradle \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/upgrading_version_9.html\"\u003e9.x upgrade guide\u003c/a\u003e to learn about deprecations, breaking changes and other considerations when upgrading.\u003c/p\u003e\n\u003cp\u003eFor Java, Groovy, Kotlin and Android compatibility, see the \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/compatibility.html\"\u003efull compatibility notes\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eReporting problems\u003c/h2\u003e\n\u003cp\u003eIf you find a problem with this release, please file a bug on \u003ca href=\"https://github.com/gradle/gradle/issues\"\u003eGitHub Issues\u003c/a\u003e adhering to our issue guidelines.\nIf you're not sure you're encountering a bug, please use the \u003ca href=\"https://discuss.gradle.org/c/help-discuss\"\u003eforum\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eWe hope you will build happiness with Gradle, and we look forward to your feedback via \u003ca href=\"https://twitter.com/gradle\"\u003eTwitter\u003c/a\u003e or on \u003ca href=\"https://github.com/gradle\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003e9.7.0\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.0.\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/92f0512e7f06d84621afba191f75e265363890cf\"\u003e\u003ccode\u003e92f0512\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38892\"\u003e#38892\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/820ee75a99a179bbffa41bcedc6477b685fabb9f\"\u003e\u003ccode\u003e820ee75\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/82c23f9bd2a89b4cc644e1f90a28a8668feb3dee\"\u003e\u003ccode\u003e82c23f9\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering problem in KTS (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38878\"\u003e#38878\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/ef11a7268fe8cc8d6ab849ec911aa11220180553\"\u003e\u003ccode\u003eef11a72\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering issue\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/bb0d8a974a71b1003efea41e4046e98855cd5ff8\"\u003e\u003ccode\u003ebb0d8a9\u003c/code\u003e\u003c/a\u003e Make relevant tests polyglot (run for multiple DSLs)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/336e129d7f95c03486acafc97abf59734acfed48\"\u003e\u003ccode\u003e336e129\u003c/code\u003e\u003c/a\u003e Update signing configuration (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38874\"\u003e#38874\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/4bdf0da2dad9884d089a6062a45ea7183e7d735d\"\u003e\u003ccode\u003e4bdf0da\u003c/code\u003e\u003c/a\u003e Update signing configuration\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/cd9b92c1b82856248cf1dc58b50378238bec7b52\"\u003e\u003ccode\u003ecd9b92c\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38839\"\u003e#38839\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/5f4e381964897ad8d6b99e5a7c77f26dba3259fb\"\u003e\u003ccode\u003e5f4e381\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/1e08ab551367aeb5fb48b26e72807e1d2b27c939\"\u003e\u003ccode\u003e1e08ab5\u003c/code\u003e\u003c/a\u003e Keep type-use annotations in extracted ABI classes (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38810\"\u003e#38810\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/gradle/gradle/compare/v9.5.1...v9.7.1\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `androidx.compose:compose-bom` from 2026.05.01 to 2026.08.00\n\nUpdates `androidx.core:core-ktx` from 1.18.0 to 1.19.0\n\nUpdates `androidx.webkit:webkit` from 1.15.0 to 1.17.0\n\nUpdates `org.bouncycastle:bcprov-jdk18on` from 1.84 to 1.85.2\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.md\"\u003eorg.bouncycastle:bcprov-jdk18on's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch1\u003eBouncy Castle Crypto Package - Release Notes\u003c/h1\u003e\n\u003ch2\u003e1.0 Introduction\u003c/h2\u003e\n\u003cp\u003eThe Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. The package is organised so that it contains a light-weight API suitable for use in any environment (including the J2ME) with the additional infrastructure to conform the algorithms to the JCE framework.\u003c/p\u003e\n\u003ch2\u003e2.0 Release History\u003c/h2\u003e\n\u003cp\u003e\u003c!-- raw HTML omitted --\u003e\u003c!-- raw HTML omitted --\u003e\u003c/p\u003e\n\u003ch3\u003e2.1.1 Version\u003c/h3\u003e\n\u003cp\u003eRelease: 1.86\u003cbr /\u003e\nDate: 2026, TBD\u003c/p\u003e\n\u003ch3\u003e2.1.2 Defects Fixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) let a subkey inherit the primary key's Key Flags when its own Subkey Binding signature carried no Key Flags subpacket, which made the two capability decisions taken for one subkey disagree. OpenPGPCertificate.OpenPGPComponentKey.isSigningKey() reads the effective flags, which fell back to the primary key's direct-key or primary user ID self-signature, so a subkey bound with no flags of its own counted as signing-capable; verifyEmbeddedPrimaryKeyBinding reads the binding signature's own flags, found no signing capability there, and so skipped the embedded Primary Key Binding (cross-certification) signature that RFC 9580 sec. 5.2.1.8 and sec. 10.1.3 require of a subkey that can issue signatures. A data signature made by such a subkey was therefore attributed to the certificate and reported valid by OpenPGPSignature.OpenPGPDocumentSignature.isValid() with the cross-certification requirement never applied, where GnuPG refuses the same certificate and message as not cross-certified. An attacker holding a third party's public signing subkey - which is public material - could bind it to their own primary key with a Subkey Binding signature they are able to make, carrying no Key Flags and no embedded Primary Key Binding signature, which they cannot make without the subkey's private key, and have that party's genuine signatures verify as valid under the attacker's own identity: misattribution of a real signature rather than a forgery of a new one, since the signature still has to be one the subkey actually made. Key Flags are a statement about the key the carrying signature refers to (RFC 9580 sec. 5.2.3.29), so a subkey no longer inherits them from the certificate-wide signatures of the primary key: a Subkey Binding signature that omits the subpacket now leaves the subkey with no capabilities rather than the primary's, which makes the flags the cross-certification check consults the same flags every other decision consults. Preferences and the other subpackets a direct-key signature carries are inherited as before, and the primary key itself - whose flags legitimately come from its direct-key or user ID self-signature - is unaffected. The low-level PGPSignature / PGPPublicKeyRing API performs no binding checks by design and is unchanged.\u003c/li\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) used a version 6 key that carried no valid Direct Key signature, falling back to the primary user ID binding as it correctly does for a version 4 key. RFC 9580 sec. 5.2.3.10 requires the opposite: \u0026quot;An implementation MUST ensure that a valid Direct Key signature is present before using a version 6 key. This prevents certain attacks where an adversary strips a self-signature specifying a Key Expiration Time or certain preferences.\u0026quot; The certificate grammar says the same structurally, the Direct Key signature being mandatory in the version 6 structure of sec. 10.1.1 and optional in the version 4 one of sec. 10.1.3. Because a version 6 certificate carries its key expiration, features and algorithm preferences on the Direct Key signature - the convention the RFC recommends and the one OpenPGPKeyGenerator follows, its user ID certification carrying no expiration at all - removing that single signature packet from a published certificate silently dropped the expiration along with the preferences and features: OpenPGPCertificate.getSignatureChainFor fell back to the user ID binding, the primary key was still reported bound, and getEncryptionKeys() and getSigningKeys() went on returning the subkeys of a key whose owner had set it to expire. The primary key fingerprint is unchanged by the removal, so a relying party pinning the key by fingerprint still treats it as the same key, and no private key or hash collision is involved; the natural moment for the strip is the key refresh that RFC 9580 names as the reason to refetch a key at all - to learn about changes in expiration, features, preferences and revocation - which is exactly the update it defeats. This is a downgrade rather than a forgery, nothing being attributed to a key that did not authorise it, and the concerning direction is encryption, to a key meant to have been retired. OpenPGPCertificate.isBoundBy now requires a valid Direct Key self-signature on a version 6 primary key before any component of the certificate - the primary key, its subkeys or its identities - is treated as bound, so a version 6 certificate stripped of it offers no keys at all rather than an unexpiring set. Version 4 certificates are unaffected: there the key expiration legitimately lives on the user ID self-signature and the fallback is correct, so it stays. The revocation-only version 6 certificate of sec. 10.1.2, which legitimately carries no Direct Key signature, is unaffected as well - its key was already refused as revoked, and reading the revocation does not go through the binding check.\u003c/li\u003e\n\u003cli\u003eThe lightweight LMSSigner and HSSSigner refused a key wrapped in ParametersWithRandom, which is how BcContentSignerBuilder passes a key whenever setSecureRandom() has been called - so BcHssLmsContentSignerBuilder built a working signer until a random was set and then failed with \u0026quot;Incorrect Key Parameters\u0026quot;, and the two signers themselves raised ClassCastException on the same input. All three now unwrap it, as the promoted ML-DSA and SLH-DSA signers already did. The random is accepted and not used: LMS derives its message randomiser C from the key's seed and the one-time index, so it is deterministic and cannot repeat while q does not. Note SP 800-208 sec. 6.1 asks for C to come from an approved random bit generator, which this implementation does not do; that is unchanged here, and a supplied random is now ignored rather than refused.\u003c/li\u003e\n\u003cli\u003eLMS signature verification did not apply two of the checks RFC 8554 sec. 5.4.2 requires before a signature is processed. Step 2g refuses a signature whose LMS typecode is not the one from the public key, and without it the path computation took its height and tree digest from the parameter set the signature named rather than the key's, so a signature claiming a height-25 parameter set drove a 25-level computation against a height-5 key. Step 2i refuses a leaf number q outside the tree, and without it an out-of-range q flowed into the node arithmetic and was left for the candidate-root comparison to catch. Neither was a forgery - the domain separation between D_LEAF and D_INTR and the final comparison saw to that - but both are attacker-chosen work the specification says to refuse up front. Both are now checked, and a signature failing either is still reported as not verifying rather than thrown out of Signature.verify(). The catch around the signature decode in LMSSigner and HSSSigner has also been narrowed to the decode itself, as the corresponding SPI was corrected to do for github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2408\"\u003e#2408\u003c/a\u003e: past the parse the engine reports an inconsistent signature by returning false rather than by throwing, so the wider catch caught nothing while standing ready to turn a future internal error into a quiet false.\u003c/li\u003e\n\u003cli\u003eThe LMS and HSS key parameter classes now apply at construction the checks their decoders apply, so a key built directly cannot be one the decoder would refuse. LMSPrivateKeyParameters accepted an identifier of any length although the decoder reads exactly 16 bytes - such a key encoded but could not be read back - and left q, maxQ and the seed length unchecked; the seed is now required to be at least m bytes at decode as well, where a one-byte seed had been decoding silently and then deriving every one-time key from it. HSSPrivateKeyParameters checked neither its level count nor that it had been given a component key per level and a chaining signature per level below the root, and then indexed both lists, so a mismatch surfaced as IndexOutOfBoundsException - or, where a level happened to match, as a null chaining signature that only failed at signing time; the level is now checked after the reset that fills it in, since a null is legitimate on the way in. LMSPrivateKeyParameters.getInstance(byte[], byte[]) adopted the public key supplied beside the private one without comparing them, so a mismatched public key was simply reported by getPublicKey(); it now cross-checks the identifier, both parameter sets and, where the tree cache already holds it, the root, as the HSS entry point does. The decoders also now report a bad version or seed length as IOException rather than IllegalStateException, so a caller can catch one type for a malformed key, and the package-private LM-OTS public key decoder no longer declares throws Exception or dereferences an unrecognised typecode. The deprecated org.bouncycastle.pqc.crypto.lms copies carry the decoder corrections.\u003c/li\u003e\n\u003cli\u003eIn the LMS JCE layer, LMSKeyGenParameterSpec.fromNames knew all twenty LMS parameter-set names but only four of the sixteen LM-OTS ones, so none of the SP 800-208 n24 or SHAKE sets could be named; all sixteen are now present. KeyPairGenerator.initialize(int, SecureRandom) reports InvalidParameterException, which is what the JCA specifies and which extends the IllegalArgumentException it raised before, so existing catches still match. BCLMSPrivateKey.getIndex now takes the exhaustion check and the index read under the key's own monitor rather than as two separate calls, and two unused fields have gone from LMSSignatureSpi. Note that the LMS Signature claims its one-time key at the first update() rather than at sign(), so a Signature that is initialised and updated and then abandoned spends an index without producing a signature - the safe direction for a one-time scheme, and now documented on the SPI.\u003c/li\u003e\n\u003cli\u003eAn HSS private key claimed the two records of its position under two different monitors. The top-level index and the bottom component key's one-time index q are independent records of the same position - the decoder requires them to agree, see the entry below - but generateLMSContext incremented the index under the HSS key's own monitor, released it, and only then claimed q under the component key's. A getEncoded() issued in between saw the index advanced and q not, and produced an encoding this implementation's own decoder rejects; and two threads meeting at a bottom-tree boundary could both pass the exhaustion test, take consecutive top-level indices and claim the same q, after which one of them was refused with \u0026quot;ots private key exhausted\u0026quot; by a key still reporting usages remaining, a top-level index had been spent with no signature made, and the two records stayed one apart for the rest of the key's life in that process - so it could no longer be encoded, cloned or sharded, and getIndex() and getUsagesRemaining() misreported by one. No one-time key was reused: the component key's claim is itself atomic, and the divergence runs index ahead of leaves, so the effect was on the key's usability rather than on the signatures it had made. Both records are now claimed under the one monitor, and the component key is claimed before the index is incremented so that an exhausted one leaves both untouched. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the same correction.\u003c/li\u003e\n\u003cli\u003eNeither the HSS nor the XMSS^MT private key decoder checked its declared index against the traversal state stored beside it, although the two are independent records of the same position in the key and so can be compared. For HSS the records are the top-level index and the component keys' one-time indices q; for XMSS^MT they are the global index and the per-layer BDS states. A stored key whose index had been rolled back while its state stayed advanced - a partial write, a restore from backup, a buggy storage layer - was therefore accepted, and it then signed a second message under a one-time key the key had already used, producing a signature that verified, so nothing anywhere surfaced the reuse. RFC 8554 sec. 1 and RFC 8391 sec. 1.1 both require each one-time key to be used exactly once, and this is the failure those requirements exist to prevent; the single-tree XMSS decoder has tied its BDS state to its index since that state was first validated, and this brings the two multi-tree schemes into line. HSS decode now requires the declared index to equal the position the component q values imply - a level above the last contributes (q - 1) leaves of the levels beneath it, since its q has already advanced past the subtree it signed - and XMSS^MT decode now requires each present layer's BDS index to equal the leaf index that layer derives from the global index, allowing the one position where a layer has moved into a new subtree and its state legitimately still carries the previous subtree's final index. A layer with no state yet is unaffected, since those are built lazily at signing time. Related, and the same shape of omission: an XMSS or XMSS^MT private key encoding carries the tree root twice - the key's own root field and the root node of the BDS state stored beside it, which for XMSS^MT is the top layer's - and the two were never compared either. A corrupted root was accepted and then poisoned every signature the key made, because the root is hashed into the message digest: the signature did not verify and nothing indicated why. Decode now requires the two copies to agree. The BDS node values themselves are not checkable the way the LMS tree cache above is - a BDS authentication path, stack, retain or keep node does not have its children stored alongside it, so recomputing one means building a subtree, which is the work the state exists to avoid. Both checks are integer comparisons over the levels of the key, too small to measure against the surrounding decode, and both were verified not to reject any legitimate key by walking every index a key can reach: the full key space of the two-level HSS and the h=4/d=2, h=6/d=2, h=6/d=3, h=9/d=3 and h=8/d=4 XMSS^MT parameter sets, plus a three-level HSS key across a subtree boundary and an HSS shard. Since those node values cannot be recomputed, the encoded state now carries a checksum over itself instead, with the owning key's public seed hashed in front of it. Any corruption of the stored state is refused at decode rather than being loaded and then producing signatures that silently do not verify, and because the public seed is bound in, a state transplanted between two keys of the same parameter set is refused too, even though it is internally consistent and arrives with its own matching root. The public seed is bound rather than the secret seed or the PRF key deliberately: the state's own root and index are inside the encoding and so are already covered, hashing secret material would make the stored checksum a commitment to it for no gain in detection, and the PRF key does not influence the state at all. \u003cstrong\u003eThis is an error-detecting code and not integrity protection\u003c/strong\u003e - anyone able to rewrite the stored key recomputes it, so it establishes that the state is unchanged since it was written, never that it was correct when written, and the allocation bounds on the encoding remain the guard against a crafted one. It costs one SHA-256 over the state, measured at 5 to 8 microseconds each way for the h=10 and h=16 parameter sets, and 32 bytes of encoding. The state encoding was added earlier in this same cycle and has not been released, so the checksum is simply part of it rather than a new version: a state written by a 1.86 beta is rejected, which is recovered from by re-exporting the key. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the HSS check as well (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2414\"\u003e#2414\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe S/MIME example smoke test in the misc module (org.bouncycastle.mail.smime.examples.test.AllTests) drove SendSignedAndEncryptedMail against smtp.gmail.com, and that example finishes with Transport.send() under JavaMail's default settings, which have no connect timeout. Where outbound port 25 is refused the failure was swallowed and the test passed; where it is silently dropped, as on many home networks, the connect blocked and ./gradlew build hung in :misc:test indefinitely with \u0026quot;0 tests completed\u0026quot;. The test now delivers to an SMTP stub on a loopback port, with connect / read / write timeouts as a backstop, and asserts the message arrived (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2407\"\u003e#2407\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation took the traditional component public key bytes it feeds the KEM combiner from the recipient key's own encoding, while decapsulation recomputes the point from the private key and so always produced an uncompressed one. Section 4 of draft-ietf-lamps-pq-composite-kem requires an EC component to be carried as an uncompressed point, but a component key that encodes itself compressed - a BC EC key whose point format has been set through org.bouncycastle.jce.interfaces.ECPointEncoder, or a key from a provider that preserves a compressed encoding - was passed through as it came. Both sides then combined a different tradPK and derived different shared secrets, with no error reported on either: encapsulation and decapsulation both succeeded and the recipient simply could not decrypt. The EC component is now normalised to an uncompressed point wherever the engine serialises one, which covers the ephemeral key that forms the ciphertext as well. X25519 and X448 components have a single encoding and were unaffected, as were EC keys left in their default (uncompressed) format, whose shared secrets are unchanged. CompositePublicKey.getEncoded() took its component bytes the same way, so such a key also encoded to a composite key other implementations reject and whose bytes changed across an encode / decode / encode round trip - 1238 bytes rather than 1270 for MLKEM768-ECDH-P256, and for the composite ML-DSA keys sharing that method, 2006 rather than 2038 for MLDSA65-ECDSA-P256. It now normalises the component the same way. This is a write-side change only: a composite key carrying a compressed EC component is still decoded, since the component key factories accept either form, and continues to verify signatures as before - it simply re-encodes in the normalised form. The shared normalisation is org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil.getUncompressedSubjectPublicKeyBytes.\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation threw a NullPointerException, wrapped in an IllegalStateException out of KeyGenerator.generateKey(), when the SecureRandom it was given was null - which javax.crypto.KEM.newEncapsulator() documents as a request for the provider's default, and which KeyGenerator.init(spec, null) passes straight through. The three RSA-OAEP composites draw the traditional shared secret from that random directly, so they were the ones affected; the ECDH and X25519 / X448 composites escaped only because their component KeyPairGenerators default a random of their own. CompositeMLKEMEngine now defaults one through CryptoServicesRegistrar.getSecureRandom() on first use, as the composite KEM Cipher's wrap path already did, and as the KEM generators corrected earlier in this cycle now do. Related, the engine now also clears the ML-KEM component's shared secret alongside the traditional one on both the encapsulate and decapsulate paths - the copy handed back by getEncoded() was left in the heap - as section 3.5 of draft-ietf-lamps-pq-composite-kem requires.\u003c/li\u003e\n\u003cli\u003eCompositePublicKey.getAlgorithm() and CompositePrivateKey.getAlgorithm() returned null for all twelve Composite ML-KEM (draft-ietf-lamps-pq-composite-kem) parameter sets. Both classes resolved the name through the composite signature index only, which holds the composite ML-DSA OIDs, so a composite KEM key pair - generated, parsed from a certificate, or read from PKCS#8 - reported no algorithm at all, and the standard JCA idiom of reconstructing a key with KeyFactory.getInstance(key.getAlgorithm()) raised a NullPointerException. The lookup now falls back to the composite KEM index, so the name returned is the one the provider registers the algorithm under (e.g. MLKEM768-X25519-SHA3-256), matching the composite ML-DSA behaviour. The same single-index assumption made the CompositePublicKey(SubjectPublicKeyInfo) and CompositePrivateKey(PrivateKeyInfo) constructors reject a composite KEM key with \u0026quot;unable to create CompositePublicKey from SubjectPublicKeyInfo\u0026quot;; they now dispatch to the composite KEM key factory for those OIDs. Keys obtained through KeyFactory or through BouncyCastleProvider.getPublicKey / getPrivateKey were unaffected and are unchanged (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2404\"\u003e#2404\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe org.bouncycastle.jcajce.spec.KEMKDFSpec constructor stored a null otherInfo as given, so getOtherInfo() returned null, and three of the KDF branches KdfUtil.makeKeyBytes dispatches to - KMAC-128, KMAC-256 and SHAKE-256 - read the otherInfo length without a guard and threw NullPointerException out of the KEM operation, where the KDF2, KDF3 and HKDF branches tolerate a null through KDFParameters / HKDFParameters. The Builder of every spec in the package already mapped null to empty, so no provider path reached it, but the constructor is protected on a public class and KdfUtil is documented for callers building their own KEM integration; the deprecated KEMParameterSpec passes a null itself and escaped only because it also pins the KDF to null. The constructor now stores empty for a null, so getOtherInfo() never returns null, and a null and an explicitly empty otherInfo derive the same key.\u003c/li\u003e\n\u003cli\u003eQR-UOV signature verification accepted a signature encoding that was not canonical, so the encoding of a signature was not unique even after the trailing-byte fix of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e. Each F_q element of the signature is stored in ceil(log2 q) bits, one more bit pattern than the field has elements: q itself is representable and is arithmetically congruent to zero, so an element written as q verified exactly as the same element written as zero would, and the bits padding the last element out to the byte boundary were never read at all. Every zero element of a signature therefore carried a second encoding, and for the q = 7 parameter sets roughly one element in seven is zero - a single qruov_5_q7_L10 signature measured 256 spare bits, so on the order of 2^256 distinct byte strings verified for the one message and key. Verification now rejects any element outside [0, q) and any set padding bit; a signature produced by this or by the reference implementation is unaffected, as the KAT vectors of every parameter set confirm. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSNOVA signature verification ignored four bits inside the signature for any parameter set whose solution is an odd number of GF(16) nibbles - the SNOVA_24_5_5, SNOVA_25_8_3, SNOVA_29_6_5 and SNOVA_66_15_3 families, sixteen of the forty-four parameter sets. The last byte of the encoded solution carries a single nibble and the signer leaves the top four bits zero, but the decoder did not read them, so sixteen distinct byte strings verified for one signature. This is the same non-unique encoding github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e closed for bytes following the signature, applied inside it; the verifier now requires those bits to be zero. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSnovaPrivateKeyParameters did not validate the length of the private key encoding handed to it - the only one of the five schemes of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e that did not - and SnovaParameters.getPrivateKeyLength() reported the expanded (\u0026quot;ESK\u0026quot;) length even for a parameter set whose private key is the seed pair. A private key encoding reaches this constructor straight from a PKCS#8 blob, so a wrong length went undetected: a seed-form key with extra bytes appended was accepted and signed under a different derived key, and a short expanded-form key sized the signer's decode buffer negatively, throwing NegativeArraySizeException out of generateSignature() rather than being reported at construction. Related, the signing retry loop could not terminate: the vinegar values are derived from a single-byte counter, so only 256 distinct linear systems can be tried, and an expanded-form private key that is not a real central map is singular for all of them - generateSignature() then span forever rather than failing. The length is now checked at construction, getPrivateKeyLength() reports the length that parameter set's private key actually has, and the retry loop gives up after its 256 attempts as MAYO's does.\u003c/li\u003e\n\u003cli\u003eMayoSigner and MayoKeyPairGenerator did not clear several buffers holding secret key material that the MAYO reference implementation explicitly clears. Signing left the secret oil space O, the expanded L = (P1 + P1^t) * O + P2, and the M / VPV / Ox intermediates of the central map in place, having gone to the trouble of clearing eleven other buffers; key generation left the expanded seed, whose tail is the encoded oil space, and the P1 * O + P2 half of P; and the row-echelon step left the packed echelon form of the secret linear system and its pivot rows. Separately, if all 256 attempts at solving for the signature had given a rank-deficient system, signing emitted a signature built from the failed attempt's state instead of reporting the failure the reference returns, and AIMerSigner.generateSignature returned an empty array on failure, which a caller would hand on as though it were a signature. Both now throw.\u003c/li\u003e\n\u003cli\u003eFive PQC signature schemes - MAYO, SNOVA, QR-UOV, SQIsign and AIMer - returned the NIST crypto_sign \u0026quot;sm\u0026quot; signed-message envelope from generateSignature() rather than the signature. That envelope is an artefact of the reference KAT harness, which records the message alongside the signature so a vector file can be self-contained; it is not part of any of the five specifications, and no other BC signer emits it (Falcon's KAT test rebuilds the equivalent envelope in the test, which is where it belongs). Two consequences followed, both reaching the JCA Signature services of every parameter set of the five schemes in BouncyCastlePQCProvider. First, since the message was appended to the signature, verification had to skip whatever followed the signature proper, and it did so by checking only that the buffer was long enough - so any number of trailing bytes could be added to a valid signature, or the appended message replaced with unrelated data, and it still verified. A signature encoding was therefore not unique: anyone holding one valid signature could produce unlimited distinct byte strings that all verified for the same message and key, which breaks any use that treats the signature bytes as an identifier, deduplicates on them, or records them as evidence. Second, the envelope propagated into everything built on the operator layer: because ContentSigner hands the signature straight into the structure being signed, every X.509 certificate, CRL, CMS SignedData and TLS CertificateVerify BC produced with one of these algorithms carried a verbatim copy of the signed data inside its own signature field - a self-signed MAYO-1 certificate came to 3567 bytes where the same certificate is now 2020 - which no other implementation can parse as a signature, and which in a detached CMS signature meant the \u0026quot;detached\u0026quot; signature carried the content. generateSignature() now returns the bare signature, and verifySignature() requires exactly the parameter set's signature length, so appended or truncated data is rejected rather than ignored. \u003cstrong\u003eThis is a behavioural change for signatures produced by an earlier release\u003c/strong\u003e - MAYO and SNOVA from 1.84, QR-UOV, SQIsign and AIMer from 1.85 - which are no longer accepted in the envelope form they were emitted in; the signature bytes themselves are unchanged, so a stored value can be recovered by taking the leading signature-length bytes, or for AIMer, whose envelope was message || signature rather than signature || message, the trailing ones. The KAT tests now rebuild the envelope before comparing against the vector files, which continue to record it. Note that AIMer's verification had already been made length-exact during this cycle (see the entry below relating to github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2401\"\u003e#2401\u003c/a\u003e), so of the five only its envelope remained (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe MLS implementation did not bind an X.509 credential to the LeafNode's signature_key. LeafNode.verify() checked a leaf's signature against the signature_key declared in the leaf itself, while the X.509 credential's certificate chain was stored but never parsed or checked, so the certificate's public key was never required to match signature_key (RFC 9420 sec. 5.3). A leaf could therefore carry one party's certificate while being signed by an unrelated key and still be accepted under that party's identity through KeyPackage.verify() and the Group leaf-validation path. LeafNode.verify() now requires the end-entity certificate's subject public key, in the cipher suite's signature encoding, to equal signature_key for an X.509 credential, and rejects the leaf otherwise - including an empty chain or a certificate whose key type does not match the cipher suite; certificate-chain and identity validation to a trust anchor remain the application's responsibility per RFC 9420 sec. 5.3.1. A public org.bouncycastle.mls.codec.Certificate(byte[]) constructor and a Credential.getCertificates() accessor are added so callers can build and inspect X.509 credentials. Basic credentials are unaffected.\u003c/li\u003e\n\u003cli\u003eThe SecureRandom supplied to org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder.setSecureRandom() did not drive the content IV / nonce for any algorithm other than RC2. EnvelopedDataHelper.generateParameters passed the caller's SecureRandom to the AlgorithmParameterGenerator only in the RC2_CBC branch; every other content-encryption algorithm - AES-CBC, AES-GCM, AES-CCM, Camellia, ARIA, SEED and the rest - reached pGen.generateParameters() on an uninitialised generator, so the IV / nonce was drawn from a default SecureRandom and setSecureRandom() was silently ignored (the builder's javadoc states that random is used for IV/nonce generation). The generator is now initialised with the supplied random on the general path as well, so a caller who provides a specific randomness source - for a controlled or FIPS-approved DRBG, say - has it honoured for the content IV / nonce. The session-key generation path was unaffected and already used the supplied random. Because the content IV / nonce now comes from the supplied SecureRandom, the org.bouncycastle.crypto.util JournalingSecureRandom / JournaledAlgorithm reproducible-encryption support records it in the transcript: a resumed session reproduces the IV / nonce by regenerating it from the replayed randomness - build the resuming encryptor from the content-algorithm OID - rather than by reusing the AlgorithmIdentifier captured from the first encryption, which no longer keeps the transcript aligned.\u003c/li\u003e\n\u003cli\u003eThe NTRU LPRime, NTRU+ and SMAUG-T KEM generators threw a NullPointerException when constructed with a null SecureRandom, where every other KEM generator - including NTRU LPRime's own SNTRU Prime counterpart in the same package - defaults one through CryptoServicesRegistrar.getSecureRandom(). This is reachable from the lightweight API directly, and from javax.crypto.KEM, whose newEncapsulator() documents a null random as a request for the provider's default.\u003c/li\u003e\n\u003cli\u003eFrodoKEMEngine kept a single SHAKE instance in a field, so an engine reached concurrently produced wrong results. It is reached that way through org.bouncycastle.crypto.kems.FrodoKEMExtractor, which holds one engine for its lifetime: two threads extracting through one extractor interleaved the digest's absorb and squeeze phases, yielding shared secrets that silently did not match the sender's, or an IllegalStateException of \u0026quot;attempt to absorb while squeezing\u0026quot; from inside extractSecret. The digest is now built per call, as CMCEEngine's already was, which makes an extractor safe to share. Encapsulation was unaffected, since FrodoKEMGenerator builds an engine per call. Results for any single-threaded use are unchanged - the reference KAT vectors are byte-identical.\u003c/li\u003e\n\u003cli\u003eThe BCJSSE provider carried the TLS 1.2 coupling between the supported_groups extension and ECDSA over into TLS 1.3: an ECDSA signature scheme was treated as usable - offered in the signature_algorithms and signature_algorithms_cert extensions, and eligible when selecting the local credentials - only while the corresponding curve was among the named groups enabled for key exchange, both per context (a group unavailable for key agreement disabled the scheme outright) and per connection (the curve had to be in the supported_groups list about to be sent). RFC 8446 sec. 4.2.7 scopes supported_groups to key exchange only, with signature algorithms negotiated independently (sec. 4.2.3), so this incorrect restriction in TLS 1.3 has been removed. Ed25519, Ed448 and the RSA schemes were unaffected (as well as typical deployments using a default configuration for named groups).\u003c/li\u003e\n\u003cli\u003eThe bcmail module descriptor did not declare its javax.mail/javax.activation dependences, so a modular (module-path) consumer of the jar hit IllegalAccessError/module-resolution failures when the S/MIME classes touched the mail API. The descriptor now requires them optionally (requires static) under all four module names those libraries are known by - the automatic names mail and activation carried by the javax.mail:mail / javax.activation:activation artifacts, and the explicit names java.mail and java.activation carried by the newer com.sun.mail / com.sun.activation ones - a hard requires on any one name would break users of the others (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2389\"\u003e#2389\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFour type-coercion helpers in the OER / IEEE 1609.2 (ITS) decoder tested the wrong type in the identity fast path that lets a getInstance() factory return an argument that is already of the target type. org.bouncycastle.oer.its.ieee1609dot2.basetypes.UINT32.getInstance and org.bouncycastle.oer.its.etsi102941.basetypes.Version.getInstance guarded on UINT8 - a sibling of UINT32 under UintBase, and unrelated to Version - so passing a UINT8 threw ClassCastException, while passing an actual UINT32 or Version missed the fast path and fell through to ASN1Integer.getInstance, which rejects them: neither factory accepted its own type. org.bouncycastle.oer.its.etsi103097.EtsiTs103097DataEncryptedUnicast.getInstance guarded on its sibling EtsiTs103097DataEncrypted and then cast to the unicast type, so an EtsiTs103097DataEncrypted threw ClassCastException. org.bouncycastle.oer.OEROptional.getObject(Class) called value.getClass().isInstance(type) with the arguments transposed, which is always false because the argument is a java.lang.Class, so the cast path was dead and every optional field was resolved reflectively, failing with IllegalStateException for a target type with no static getInstance. Each guard now names the type it returns, matching the sibling UINT8 / UINT16 / UINT64 and EtsiTs103097DataEncrypted factories (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2373\"\u003e#2373\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eDefaultAlgorithmNameFinder and DefaultSignatureNameFinder had no entries at all for the ShangMi algorithms, so an SM2 signature AlgorithmIdentifier that DefaultSignatureAlgorithmIdentifierFinder itself produces came back named only by its OID string - getAlgorithmName(GMObjectIdentifiers.sm2sign_with_sm3) returned \u0026quot;1.2.156.10197.1.501\u0026quot; and hasAlgorithmName returned false. Both finders now name sm2sign_with_sm3 as SM3WITHSM2 and sm2sign_with_sha256 as SHA256WITHSM2, and DefaultAlgorithmNameFinder additionally names the sm3 digest. All three resolve through the BC provider, as Signature and MessageDigest respectively. The remaining GM arc - the SM4 cipher modes, the sm2encrypt variants, and the SM1 / SM6 / SSF33 ciphers BC does not implement - is still unnamed (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2377\"\u003e#2377\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe RFC 4998 evidence-record classes compared the digest AlgorithmIdentifier named by a time-stamp authority with the one their own DigestCalculator uses, and did so with AlgorithmIdentifier.equals(), which compares the encodings. A TSA that names SHA-256 with an explicit NULL parameters field - DigiCert among them - therefore failed against BC's own calculator, which names it with the parameters absent, and ERSArchiveTimeStampGenerator.generateArchiveTimeStamp rejected the response with \u0026quot;time stamp imprint for wrong algorithm\u0026quot;. Both spellings name the same digest and RFC 5754 sec. 2 requires a receiver to accept either, while requiring that identifiers be generated with the parameters absent, which BC already does. The three affected comparisons - the two in ERSArchiveTimeStampGenerator and the digest check in ERSEvidenceRecord.renew - now use the new AlgorithmIdentifier.areEquivalent, which matches on the algorithm and treats an absent parameters field and NULL as the same, and the consistency check across an evidence record's archive time stamp chain uses it too. An identifier carrying an actual parameter structure is never equivalent to one carrying none (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2379\"\u003e#2379\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eEDIPartyName.toASN1Primitive emitted the nameAssigner and partyName DirectoryStrings without their context tags, so an EDIPartyName built through its public constructor could not be parsed back by EDIPartyName.getInstance, which correctly requires them. RFC 5280 sec. 4.2.1.6 tags both members [0] and [1], and those tags are explicit despite the module's IMPLICIT TAGS because DirectoryString is a CHOICE, which X.680 does not allow to be tagged implicitly - the decoder already had this right. The encoder now matches it. Note the type was added during the 1.85 cycle and GeneralName validates its ediPartyName alternative through it, so a GeneralName carrying an untagged ediPartyName - including one BC itself produced - is rejected where 1.84 passed it through unexamined; the untagged form is not read leniently (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2380\"\u003e#2380\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eRSASSA-PSS could not be used with a RIPEMD digest through the JCA API. Nothing registered the RIPEMD PSS signatures, so Signature.getInstance(\u0026quot;RIPEMD160WITHRSAANDMGF1\u0026quot;) raised NoSuchAlgorithmException, and the generic RSASSA-PSS route with an explicit PSSParameterSpec failed too: org.bouncycastle.jcajce.provider.util.DigestFactory.getDigest returned null for a RIPEMD name, and isSameDigest - an allow-list of the SHA families and MD5 - reported two identical RIPEMD names as different digests, so the spec was rejected with \u0026quot;digest algorithm for MGF should be the same as for PSS parameters\u0026quot;. isSameDigest now answers true for equal names whatever the digest, which also covers Whirlpool, SM3, GOST3411 and anything else outside that allow-list; DigestFactory recognises RIPEMD128, RIPEMD160 and RIPEMD256 by name and OID; the three PSS signatures are registered with MGF1 over the same digest and a salt of the digest length; and DefaultSignatureAlgorithmIdentifierFinder gains the matching RIPEMD*WITHRSAANDMGF1 entries with their RSASSA-PSS-params, so the operator/JcaContentSignerBuilder path works as well. Note BC continues to require the PSS hash and the MGF1 hash to be the same, which RFC 8017 does not itself demand (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2381\"\u003e#2381\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe opt-in key-size validation on CMS key-transport recipients (org.bouncycastle.cms.jcajce.JceKeyTransRecipient.setKeySizeValidation(true)) never ran for a message using RFC 9709 CEK derivation (id-alg-cek-hkdf-sha256): the branch that should have selected the actual content-encryption algorithm carried in the KDF AlgorithmIdentifier's parameters compared the encrypted-key byte array against the id-alg-cek-hkdf-sha256 object identifier - a comparison that is always false - so the check fell through to a key-size lookup on the outer KDF OID, which has no registered key size, and silently checked nothing. A key-transport EnvelopedData/AuthEnvelopedData whose transported (and HKDF-derived) content-encryption key did not match the key size of the advertised content-encryption algorithm was therefore accepted even with validation enabled. The recipient now dispatches on the content-encryption AlgorithmIdentifier's algorithm OID, so key-size validation of RFC 9709 messages checks the recovered key against the inner content-encryption algorithm. Messages with a matching key size, non-HKDF messages, and recipients that do not enable validation are unaffected.\u003c/li\u003e\n\u003cli\u003eThe OpenPGP v6 SEIPD (Symmetrically Encrypted Integrity Protected Data, version 2 / RFC 9580 sec. 5.13.2) packet parser read the AEAD chunk-size octet without bounding it. The chunk length is 2^(chunkSize + 6) bytes and the AEAD decryptor allocates a buffer of that size up front, so a crafted v6 encrypted message (reachable with only the recipient's public key) declaring chunkSize 24 forced a 1 GiB allocation on decrypt, and chunkSize 25 (where the int cast of the chunk length wraps negative) threw a NegativeArraySizeException -- a pre-authentication resource-exhaustion denial of service. This is the version 6 sibling of the version 5 AEADEncDataPacket issue fixed under CVE-2026-3505, which bounded that packet's chunk size at 16 but left the v6 SymmetricEncIntegrityPacket unbounded. SymmetricEncIntegrityPacket now rejects a chunk-size octet outside 0..16 (a 4 MiB chunk, matching the v5 ceiling) with a MalformedPacketException at parse, before any allocation.\u003c/li\u003e\n\u003cli\u003eThe Ed25519 KeyFactory in the JDK 11+ and JDK 15+ multi-release overlays (META-INF/versions/11 and /15) had drifted from the base implementation on the OpenSSH key-spec path: it used the no-passphrase OpenSSHPrivateKeyUtil.parsePrivateKeyBlob overload, so a passphrase-encrypted openssh-key-v1 Ed25519 private key that KeyFactory.getInstance(\u0026quot;Ed25519\u0026quot;, \u0026quot;BC\u0026quot;).generatePrivate(new OpenSSHPrivateKeySpec(blob, passphrase)) decoded correctly on JDK 8 failed on JDK 11 and later; it also let a raw RuntimeException escape on a malformed blob and threw IllegalStateException (JDK 11) instead of InvalidKeySpecException for a non-Ed25519 key. The overlays now match the base implementation (passphrase support, parse errors wrapped as InvalidKeySpecException). Relatedly, the OpenSSH wrong-key-type and decode-failure paths across the RSA, DSA, EC and Ed25519 KeyFactorySpi implementations now consistently raise InvalidKeySpecException (previously a mix of IllegalArgumentException / IllegalStateException) and wrap a malformed OpenSSH public key, and an incorrect \u0026quot;public key is not RSA private key\u0026quot; message on the RSA private path was corrected. The multi-release test tasks now exercise the OpenSSH key specs against the multi-release jar.\u003c/li\u003e\n\u003cli\u003eThe Ant-built utility jars (bcutil-jdk15to18, bcutil-jdk14) duplicated org.bouncycastle.asn1.iana.IANAObjectIdentifiers, which since 1.85 (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2176\"\u003e#2176\u003c/a\u003e) lives only in core and is therefore already shipped in bcprov. The shared ant/bc+-build.xml build-util target still copied org/bouncycastle/asn1/iana/** into bcutil, so a project depending on both bcprov and bcutil (for example via bcpkix) failed an Android/R8 build with \u0026quot;Duplicate class org.bouncycastle.asn1.iana.IANAObjectIdentifiers found in modules bcprov-jdk15to18-1.85.jar and bcutil-jdk15to18-1.85.jar\u0026quot;. The iana package is no longer bundled into bcutil (it remains in bcprov); the Gradle jdk18on jars were already correct (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2356\"\u003e#2356\u003c/a\u003e).\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003eSee full diff in \u003ca href=\"https://github.com/bcgit/bc-java/commits\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003ecommonmark-java 0.29.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e[0.29.0] - 2026-06-20\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/42b4fb7adfe288ef13e9e27ab20aff7e91b0ab9d\"\u003e\u003ccode\u003e42b4fb7\u003c/code\u003e\u003c/a\u003e Prepare CHANGELOG for version 0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/b76e09d7a8362abb5f04e1d6b91dbd6da279a6fc\"\u003e\u003ccode\u003eb76e09d\u003c/code\u003e\u003c/a\u003e Limit how deep inline nodes may nest by default (100)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/49f65cb5cbec93cff713179990307145198e7061\"\u003e\u003ccode\u003e49f65cb\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing deeply nested emphasis\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/610f84b83e68c381e8f784ae4d044c80e1948b67\"\u003e\u003ccode\u003e610f84b\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological autolink email addresses\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/9f1d73897a56cbd74c39347af351a473e70297e1\"\u003e\u003ccode\u003e9f1d738\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological HTML block attributes\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/e13297e849995fdd582a85841067bff1d9c35ee5\"\u003e\u003ccode\u003ee13297e\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing pathological backticks\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/89d1bd3fa1524e8217ed61db5e8116c82434470f\"\u003e\u003ccode\u003e89d1bd3\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing with lots of \u003ccode\u003e\u0026lt;\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/commonmark/commonmark-java/compare/commonmark-parent-0.28.0...commonmark-parent-0.30.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark-ext-autolink` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark-ext-autolink's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of...\n\n_Description has been truncated_","html_url":"https://github.com/ifabrish/openclaw-ifabrish-/pull/30","url":"https://dependabot.ecosyste.ms/api/v1/hosts/GitHub/repositories/ifabrish%2Fopenclaw-ifabrish-/issues/30","packages_url":"https://dependabot.ecosyste.ms/api/v1/issues/30/packages"}},{"old_version":"5.4.0","new_version":"5.5.0","update_type":"minor","path":null,"pr_created_at":"2026-08-31T01:38:15.000Z","version_change":"5.4.0 → 5.5.0","issue":{"uuid":"5295533440","node_id":"PR_kwDOSB4jqM8AAAABBitosA","number":70,"state":"closed","title":"build(deps): bump the android-deps group across 1 directory with 28 updates","user":"dependabot[bot]","labels":["dependencies","java"],"assignees":[],"locked":false,"comments_count":1,"pull_request":true,"closed_at":"2026-09-04T05:38:51.000Z","author_association":null,"state_reason":null,"created_at":"2026-08-31T01:38:15.000Z","updated_at":"2026-09-04T05:38:53.000Z","time_to_close":360036,"merged_at":null,"merged_by":null,"closed_by":null,"dependency_metadata":{"prefix":"build(deps): bump","group_name":"android-deps","update_count":28,"packages":[{"name":"gradle-wrapper","old_version":"9.6.1","new_version":"9.7.1","repository_url":"https://github.com/gradle/gradle"},{"name":"androidx.appcompat:appcompat","old_version":"1.7.1","new_version":"1.8.0"},{"name":"androidx.compose:compose-bom","old_version":"2026.06.01","new_version":"2026.08.00"},{"name":"androidx.webkit:webkit","old_version":"1.16.0","new_version":"1.17.0"},{"name":"androidx.wear.protolayout:protolayout","old_version":"1.4.1","new_version":"1.4.2"},{"name":"androidx.wear.protolayout:protolayout-material3","old_version":"1.4.1","new_version":"1.4.2"},{"name":"androidx.wear.tiles:tiles","old_version":"1.6.1","new_version":"1.6.2"},{"name":"org.bouncycastle:bcprov-jdk18on","old_version":"1.85","new_version":"1.85.2","repository_url":"https://github.com/bcgit/bc-java"},{"name":"org.commonmark:commonmark","old_version":"0.29.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-autolink","old_version":"0.29.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-strikethrough","old_version":"0.29.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-tables","old_version":"0.29.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-task-list-items","old_version":"0.29.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"io.coil-kt.coil3:coil-compose","old_version":"3.5.0","new_version":"3.6.0","repository_url":"https://github.com/coil-kt/coil"},{"name":"io.coil-kt.coil3:coil-svg","old_version":"3.5.0","new_version":"3.6.0","repository_url":"https://github.com/coil-kt/coil"},{"name":"org.junit.vintage:junit-vintage-engine","old_version":"6.1.2","new_version":"6.1.3","repository_url":"https://github.com/junit-team/junit-framework"},{"name":"io.kotest:kotest-assertions-core-jvm","old_version":"6.2.3","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"io.kotest:kotest-runner-junit5-jvm","old_version":"6.2.3","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"androidx.media3:media3-datasource-okhttp","old_version":"1.10.1","new_version":"1.11.0","repository_url":"https://github.com/androidx/media"},{"name":"androidx.media3:media3-exoplayer","old_version":"1.10.1","new_version":"1.11.0","repository_url":"https://github.com/androidx/media"},{"name":"androidx.media3:media3-session","old_version":"1.10.1","new_version":"1.11.0","repository_url":"https://github.com/androidx/media"},{"name":"androidx.media3:media3-ui","old_version":"1.10.1","new_version":"1.11.0","repository_url":"https://github.com/androidx/media"},{"name":"com.squareup.okhttp3:mockwebserver","old_version":"5.4.0","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.squareup.okhttp3:okhttp","old_version":"5.4.0","new_version":"5.5.0","repository_url":"https://github.com/lysine-dev/okhttp"},{"name":"com.android.application","old_version":"9.3.1","new_version":"9.3.2"},{"name":"com.android.library","old_version":"9.3.1","new_version":"9.3.2"},{"name":"com.android.test","old_version":"9.3.1","new_version":"9.3.2"},{"name":"com.google.devtools.ksp","old_version":"2.3.10","new_version":"2.3.11","repository_url":"https://github.com/google/ksp"}],"path":null,"ecosystem":"maven"},"body":"Bumps the android-deps group with 28 updates in the /apps/android directory:\n\n| Package | From | To |\n| --- | --- | --- |\n| [gradle-wrapper](https://github.com/gradle/gradle) | `9.6.1` | `9.7.1` |\n| androidx.appcompat:appcompat | `1.7.1` | `1.8.0` |\n| androidx.compose:compose-bom | `2026.06.01` | `2026.08.00` |\n| androidx.webkit:webkit | `1.16.0` | `1.17.0` |\n| androidx.wear.protolayout:protolayout | `1.4.1` | `1.4.2` |\n| androidx.wear.protolayout:protolayout-material3 | `1.4.1` | `1.4.2` |\n| androidx.wear.tiles:tiles | `1.6.1` | `1.6.2` |\n| [org.bouncycastle:bcprov-jdk18on](https://github.com/bcgit/bc-java) | `1.85` | `1.85.2` |\n| [org.commonmark:commonmark](https://github.com/commonmark/commonmark-java) | `0.29.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-autolink](https://github.com/commonmark/commonmark-java) | `0.29.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-strikethrough](https://github.com/commonmark/commonmark-java) | `0.29.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-tables](https://github.com/commonmark/commonmark-java) | `0.29.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-task-list-items](https://github.com/commonmark/commonmark-java) | `0.29.0` | `0.30.0` |\n| [io.coil-kt.coil3:coil-compose](https://github.com/coil-kt/coil) | `3.5.0` | `3.6.0` |\n| [io.coil-kt.coil3:coil-svg](https://github.com/coil-kt/coil) | `3.5.0` | `3.6.0` |\n| [org.junit.vintage:junit-vintage-engine](https://github.com/junit-team/junit-framework) | `6.1.2` | `6.1.3` |\n| [io.kotest:kotest-assertions-core-jvm](https://github.com/kotest/kotest) | `6.2.3` | `6.2.4` |\n| [io.kotest:kotest-runner-junit5-jvm](https://github.com/kotest/kotest) | `6.2.3` | `6.2.4` |\n| [androidx.media3:media3-datasource-okhttp](https://github.com/androidx/media) | `1.10.1` | `1.11.0` |\n| [androidx.media3:media3-exoplayer](https://github.com/androidx/media) | `1.10.1` | `1.11.0` |\n| [androidx.media3:media3-session](https://github.com/androidx/media) | `1.10.1` | `1.11.0` |\n| [androidx.media3:media3-ui](https://github.com/androidx/media) | `1.10.1` | `1.11.0` |\n| [com.squareup.okhttp3:mockwebserver](https://github.com/lysine-dev/okhttp) | `5.4.0` | `5.5.0` |\n| [com.squareup.okhttp3:okhttp](https://github.com/lysine-dev/okhttp) | `5.4.0` | `5.5.0` |\n| com.android.application | `9.3.1` | `9.3.2` |\n| com.android.library | `9.3.1` | `9.3.2` |\n| com.android.test | `9.3.1` | `9.3.2` |\n| [com.google.devtools.ksp](https://github.com/google/ksp) | `2.3.10` | `2.3.11` |\n\n\nUpdates `gradle-wrapper` from 9.6.1 to 9.7.1\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/gradle/gradle/releases\"\u003egradle-wrapper's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e9.7.1\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.1.\u003c/p\u003e\n\u003cp\u003eThis is a patch release for 9.7.0. We recommend using 9.7.1 instead of 9.7.0.\u003c/p\u003e\n\u003cp\u003eHere are the highlights of 9.7.0 release:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIsolated Projects graduates to incubating\u003c/li\u003e\n\u003cli\u003eBroader Configuration Cache compatibility\u003c/li\u003e\n\u003cli\u003eResilient Sync helps you fix broken builds\u003c/li\u003e\n\u003cli\u003eMore source locations in problem reports\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003ca href=\"https://docs.gradle.org/9.7.1/release-notes.html\"\u003eRead the Release Notes\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eWe would like to thank the following community members for their contributions to this release of Gradle:\n\u003ca href=\"https://github.com/aSemy\"\u003eAdam\u003c/a\u003e,\n\u003ca href=\"https://github.com/Gautam-aman\"\u003eAman Gautam\u003c/a\u003e,\n\u003ca href=\"https://github.com/YukiCodepth\"\u003eAman Kumar\u003c/a\u003e,\n\u003ca href=\"https://github.com/adubrouski\"\u003eAnton Dubrouski\u003c/a\u003e,\n\u003ca href=\"https://github.com/liutikas\"\u003eAurimas\u003c/a\u003e,\n\u003ca href=\"https://github.com/gbhavya07\"\u003egbhavya07\u003c/a\u003e,\n\u003ca href=\"https://github.com/joshfriend\"\u003eJosh Friend\u003c/a\u003e,\n\u003ca href=\"https://github.com/nicklauslittle-gov\"\u003enicklauslittle-gov\u003c/a\u003e,\n\u003ca href=\"https://github.com/psoni674\"\u003ePragati\u003c/a\u003e,\n\u003ca href=\"https://github.com/Project516\"\u003eproject516\u003c/a\u003e,\n\u003ca href=\"https://github.com/Uomocapra\"\u003eQin Mi\u003c/a\u003e,\n\u003ca href=\"https://github.com/rkdfx\"\u003eRavi\u003c/a\u003e,\n\u003ca href=\"https://github.com/sk-reddy17\"\u003esk-reddy17\u003c/a\u003e,\n\u003ca href=\"https://github.com/Suvrat1629\"\u003eSuvrat Acharya\u003c/a\u003e,\n\u003ca href=\"https://github.com/ShreckYe\"\u003eYongshun Ye\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eUpgrade instructions\u003c/h2\u003e\n\u003cp\u003eSwitch your build to use Gradle 9.7.1 by updating your wrapper:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e./gradlew :wrapper --gradle-version=9.7.1 \u0026amp;\u0026amp; ./gradlew :wrapper\r\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eSee the Gradle \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/upgrading_version_9.html\"\u003e9.x upgrade guide\u003c/a\u003e to learn about deprecations, breaking changes and other considerations when upgrading.\u003c/p\u003e\n\u003cp\u003eFor Java, Groovy, Kotlin and Android compatibility, see the \u003ca href=\"https://docs.gradle.org/9.7.1/userguide/compatibility.html\"\u003efull compatibility notes\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eReporting problems\u003c/h2\u003e\n\u003cp\u003eIf you find a problem with this release, please file a bug on \u003ca href=\"https://github.com/gradle/gradle/issues\"\u003eGitHub Issues\u003c/a\u003e adhering to our issue guidelines.\nIf you're not sure you're encountering a bug, please use the \u003ca href=\"https://discuss.gradle.org/c/help-discuss\"\u003eforum\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eWe hope you will build happiness with Gradle, and we look forward to your feedback via \u003ca href=\"https://twitter.com/gradle\"\u003eTwitter\u003c/a\u003e or on \u003ca href=\"https://github.com/gradle\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003e9.7.0\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.0.\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/92f0512e7f06d84621afba191f75e265363890cf\"\u003e\u003ccode\u003e92f0512\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38892\"\u003e#38892\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/820ee75a99a179bbffa41bcedc6477b685fabb9f\"\u003e\u003ccode\u003e820ee75\u003c/code\u003e\u003c/a\u003e update fixed issues for 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/82c23f9bd2a89b4cc644e1f90a28a8668feb3dee\"\u003e\u003ccode\u003e82c23f9\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering problem in KTS (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38878\"\u003e#38878\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/ef11a7268fe8cc8d6ab849ec911aa11220180553\"\u003e\u003ccode\u003eef11a72\u003c/code\u003e\u003c/a\u003e Fix annotation parameter ordering issue\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/bb0d8a974a71b1003efea41e4046e98855cd5ff8\"\u003e\u003ccode\u003ebb0d8a9\u003c/code\u003e\u003c/a\u003e Make relevant tests polyglot (run for multiple DSLs)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/336e129d7f95c03486acafc97abf59734acfed48\"\u003e\u003ccode\u003e336e129\u003c/code\u003e\u003c/a\u003e Update signing configuration (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38874\"\u003e#38874\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/4bdf0da2dad9884d089a6062a45ea7183e7d735d\"\u003e\u003ccode\u003e4bdf0da\u003c/code\u003e\u003c/a\u003e Update signing configuration\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/cd9b92c1b82856248cf1dc58b50378238bec7b52\"\u003e\u003ccode\u003ecd9b92c\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38839\"\u003e#38839\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/5f4e381964897ad8d6b99e5a7c77f26dba3259fb\"\u003e\u003ccode\u003e5f4e381\u003c/code\u003e\u003c/a\u003e List issues resolved in 9.7.1\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/1e08ab551367aeb5fb48b26e72807e1d2b27c939\"\u003e\u003ccode\u003e1e08ab5\u003c/code\u003e\u003c/a\u003e Keep type-use annotations in extracted ABI classes (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38810\"\u003e#38810\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/gradle/gradle/compare/v9.6.1...v9.7.1\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `androidx.appcompat:appcompat` from 1.7.1 to 1.8.0\n\nUpdates `androidx.compose:compose-bom` from 2026.06.01 to 2026.08.00\n\nUpdates `androidx.webkit:webkit` from 1.16.0 to 1.17.0\n\nUpdates `androidx.wear.protolayout:protolayout` from 1.4.1 to 1.4.2\n\nUpdates `androidx.wear.protolayout:protolayout-material3` from 1.4.1 to 1.4.2\n\nUpdates `androidx.wear.protolayout:protolayout-material3` from 1.4.1 to 1.4.2\n\nUpdates `androidx.wear.tiles:tiles` from 1.6.1 to 1.6.2\n\nUpdates `org.bouncycastle:bcprov-jdk18on` from 1.85 to 1.85.2\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.md\"\u003eorg.bouncycastle:bcprov-jdk18on's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch1\u003eBouncy Castle Crypto Package - Release Notes\u003c/h1\u003e\n\u003ch2\u003e1.0 Introduction\u003c/h2\u003e\n\u003cp\u003eThe Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. The package is organised so that it contains a light-weight API suitable for use in any environment (including the J2ME) with the additional infrastructure to conform the algorithms to the JCE framework.\u003c/p\u003e\n\u003ch2\u003e2.0 Release History\u003c/h2\u003e\n\u003cp\u003e\u003c!-- raw HTML omitted --\u003e\u003c!-- raw HTML omitted --\u003e\u003c/p\u003e\n\u003ch3\u003e2.1.1 Version\u003c/h3\u003e\n\u003cp\u003eRelease: 1.86\u003cbr /\u003e\nDate: 2026, TBD\u003c/p\u003e\n\u003ch3\u003e2.1.2 Defects Fixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eThe high-level OpenPGP API (org.bouncycastle.openpgp.api) let a subkey inherit the primary key's Key Flags when its own Subkey Binding signature carried no Key Flags subpacket, which made the two capability decisions taken for one subkey disagree. OpenPGPCertificate.OpenPGPComponentKey.isSigningKey() reads the effective flags, which fell back to the primary key's direct-key or primary user ID self-signature, so a subkey bound with no flags of its own counted as signing-capable; verifyEmbeddedPrimaryKeyBinding reads the binding signature's own flags, found no signing capability there, and so skipped the embedded Primary Key Binding (cross-certification) signature that RFC 9580 sec. 5.2.1.8 and sec. 10.1.3 require of a subkey that can issue signatures. A data signature made by such a subkey was therefore attributed to the certificate and reported valid by OpenPGPSignature.OpenPGPDocumentSignature.isValid() with the cross-certification requirement never applied, where GnuPG refuses the same certificate and message as not cross-certified. An attacker holding a third party's public signing subkey - which is public material - could bind it to their own primary key with a Subkey Binding signature they are able to make, carrying no Key Flags and no embedded Primary Key Binding signature, which they cannot make without the subkey's private key, and have that party's genuine signatures verify as valid under the attacker's own identity: misattribution of a real signature rather than a forgery of a new one, since the signature still has to be one the subkey actually made. Key Flags are a statement about the key the carrying signature refers to (RFC 9580 sec. 5.2.3.29), so a subkey no longer inherits them from the certificate-wide signatures of the primary key: a Subkey Binding signature that omits the subpacket now leaves the subkey with no capabilities rather than the primary's, which makes the flags the cross-certification check consults the same flags every other decision consults. Preferences and the other subpackets a direct-key signature carries are inherited as before, and the primary key itself - whose flags legitimately come from its direct-key or user ID self-signature - is unaffected. The low-level PGPSignature / PGPPublicKeyRing API performs no binding checks by design and is unchanged.\u003c/li\u003e\n\u003cli\u003eNeither the HSS nor the XMSS^MT private key decoder checked its declared index against the traversal state stored beside it, although the two are independent records of the same position in the key and so can be compared. For HSS the records are the top-level index and the component keys' one-time indices q; for XMSS^MT they are the global index and the per-layer BDS states. A stored key whose index had been rolled back while its state stayed advanced - a partial write, a restore from backup, a buggy storage layer - was therefore accepted, and it then signed a second message under a one-time key the key had already used, producing a signature that verified, so nothing anywhere surfaced the reuse. RFC 8554 sec. 1 and RFC 8391 sec. 1.1 both require each one-time key to be used exactly once, and this is the failure those requirements exist to prevent; the single-tree XMSS decoder has tied its BDS state to its index since that state was first validated, and this brings the two multi-tree schemes into line. HSS decode now requires the declared index to equal the position the component q values imply - a level above the last contributes (q - 1) leaves of the levels beneath it, since its q has already advanced past the subtree it signed - and XMSS^MT decode now requires each present layer's BDS index to equal the leaf index that layer derives from the global index, allowing the one position where a layer has moved into a new subtree and its state legitimately still carries the previous subtree's final index. A layer with no state yet is unaffected, since those are built lazily at signing time. Related, and the same shape of omission: an XMSS or XMSS^MT private key encoding carries the tree root twice - the key's own root field and the root node of the BDS state stored beside it, which for XMSS^MT is the top layer's - and the two were never compared either. A corrupted root was accepted and then poisoned every signature the key made, because the root is hashed into the message digest: the signature did not verify and nothing indicated why. Decode now requires the two copies to agree. The BDS node values themselves are not checkable the way the LMS tree cache above is - a BDS authentication path, stack, retain or keep node does not have its children stored alongside it, so recomputing one means building a subtree, which is the work the state exists to avoid. Both checks are integer comparisons over the levels of the key, too small to measure against the surrounding decode, and both were verified not to reject any legitimate key by walking every index a key can reach: the full key space of the two-level HSS and the h=4/d=2, h=6/d=2, h=6/d=3, h=9/d=3 and h=8/d=4 XMSS^MT parameter sets, plus a three-level HSS key across a subtree boundary and an HSS shard. Since those node values cannot be recomputed, the encoded state now carries a checksum over itself instead, with the owning key's public seed hashed in front of it. Any corruption of the stored state is refused at decode rather than being loaded and then producing signatures that silently do not verify, and because the public seed is bound in, a state transplanted between two keys of the same parameter set is refused too, even though it is internally consistent and arrives with its own matching root. The public seed is bound rather than the secret seed or the PRF key deliberately: the state's own root and index are inside the encoding and so are already covered, hashing secret material would make the stored checksum a commitment to it for no gain in detection, and the PRF key does not influence the state at all. \u003cstrong\u003eThis is an error-detecting code and not integrity protection\u003c/strong\u003e - anyone able to rewrite the stored key recomputes it, so it establishes that the state is unchanged since it was written, never that it was correct when written, and the allocation bounds on the encoding remain the guard against a crafted one. It costs one SHA-256 over the state, measured at 5 to 8 microseconds each way for the h=10 and h=16 parameter sets, and 32 bytes of encoding. The state encoding was added earlier in this same cycle and has not been released, so the checksum is simply part of it rather than a new version: a state written by a 1.86 beta is rejected, which is recovered from by re-exporting the key. The deprecated org.bouncycastle.pqc.crypto.lms copy carries the HSS check as well (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2414\"\u003e#2414\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe S/MIME example smoke test in the misc module (org.bouncycastle.mail.smime.examples.test.AllTests) drove SendSignedAndEncryptedMail against smtp.gmail.com, and that example finishes with Transport.send() under JavaMail's default settings, which have no connect timeout. Where outbound port 25 is refused the failure was swallowed and the test passed; where it is silently dropped, as on many home networks, the connect blocked and ./gradlew build hung in :misc:test indefinitely with \u0026quot;0 tests completed\u0026quot;. The test now delivers to an SMTP stub on a loopback port, with connect / read / write timeouts as a backstop, and asserts the message arrived (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2407\"\u003e#2407\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation took the traditional component public key bytes it feeds the KEM combiner from the recipient key's own encoding, while decapsulation recomputes the point from the private key and so always produced an uncompressed one. Section 4 of draft-ietf-lamps-pq-composite-kem requires an EC component to be carried as an uncompressed point, but a component key that encodes itself compressed - a BC EC key whose point format has been set through org.bouncycastle.jce.interfaces.ECPointEncoder, or a key from a provider that preserves a compressed encoding - was passed through as it came. Both sides then combined a different tradPK and derived different shared secrets, with no error reported on either: encapsulation and decapsulation both succeeded and the recipient simply could not decrypt. The EC component is now normalised to an uncompressed point wherever the engine serialises one, which covers the ephemeral key that forms the ciphertext as well. X25519 and X448 components have a single encoding and were unaffected, as were EC keys left in their default (uncompressed) format, whose shared secrets are unchanged. CompositePublicKey.getEncoded() took its component bytes the same way, so such a key also encoded to a composite key other implementations reject and whose bytes changed across an encode / decode / encode round trip - 1238 bytes rather than 1270 for MLKEM768-ECDH-P256, and for the composite ML-DSA keys sharing that method, 2006 rather than 2038 for MLDSA65-ECDSA-P256. It now normalises the component the same way. This is a write-side change only: a composite key carrying a compressed EC component is still decoded, since the component key factories accept either form, and continues to verify signatures as before - it simply re-encodes in the normalised form. The shared normalisation is org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil.getUncompressedSubjectPublicKeyBytes.\u003c/li\u003e\n\u003cli\u003eComposite ML-KEM encapsulation threw a NullPointerException, wrapped in an IllegalStateException out of KeyGenerator.generateKey(), when the SecureRandom it was given was null - which javax.crypto.KEM.newEncapsulator() documents as a request for the provider's default, and which KeyGenerator.init(spec, null) passes straight through. The three RSA-OAEP composites draw the traditional shared secret from that random directly, so they were the ones affected; the ECDH and X25519 / X448 composites escaped only because their component KeyPairGenerators default a random of their own. CompositeMLKEMEngine now defaults one through CryptoServicesRegistrar.getSecureRandom() on first use, as the composite KEM Cipher's wrap path already did, and as the KEM generators corrected earlier in this cycle now do. Related, the engine now also clears the ML-KEM component's shared secret alongside the traditional one on both the encapsulate and decapsulate paths - the copy handed back by getEncoded() was left in the heap - as section 3.5 of draft-ietf-lamps-pq-composite-kem requires.\u003c/li\u003e\n\u003cli\u003eCompositePublicKey.getAlgorithm() and CompositePrivateKey.getAlgorithm() returned null for all twelve Composite ML-KEM (draft-ietf-lamps-pq-composite-kem) parameter sets. Both classes resolved the name through the composite signature index only, which holds the composite ML-DSA OIDs, so a composite KEM key pair - generated, parsed from a certificate, or read from PKCS#8 - reported no algorithm at all, and the standard JCA idiom of reconstructing a key with KeyFactory.getInstance(key.getAlgorithm()) raised a NullPointerException. The lookup now falls back to the composite KEM index, so the name returned is the one the provider registers the algorithm under (e.g. MLKEM768-X25519-SHA3-256), matching the composite ML-DSA behaviour. The same single-index assumption made the CompositePublicKey(SubjectPublicKeyInfo) and CompositePrivateKey(PrivateKeyInfo) constructors reject a composite KEM key with \u0026quot;unable to create CompositePublicKey from SubjectPublicKeyInfo\u0026quot;; they now dispatch to the composite KEM key factory for those OIDs. Keys obtained through KeyFactory or through BouncyCastleProvider.getPublicKey / getPrivateKey were unaffected and are unchanged (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2404\"\u003e#2404\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe org.bouncycastle.jcajce.spec.KEMKDFSpec constructor stored a null otherInfo as given, so getOtherInfo() returned null, and three of the KDF branches KdfUtil.makeKeyBytes dispatches to - KMAC-128, KMAC-256 and SHAKE-256 - read the otherInfo length without a guard and threw NullPointerException out of the KEM operation, where the KDF2, KDF3 and HKDF branches tolerate a null through KDFParameters / HKDFParameters. The Builder of every spec in the package already mapped null to empty, so no provider path reached it, but the constructor is protected on a public class and KdfUtil is documented for callers building their own KEM integration; the deprecated KEMParameterSpec passes a null itself and escaped only because it also pins the KDF to null. The constructor now stores empty for a null, so getOtherInfo() never returns null, and a null and an explicitly empty otherInfo derive the same key.\u003c/li\u003e\n\u003cli\u003eQR-UOV signature verification accepted a signature encoding that was not canonical, so the encoding of a signature was not unique even after the trailing-byte fix of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e. Each F_q element of the signature is stored in ceil(log2 q) bits, one more bit pattern than the field has elements: q itself is representable and is arithmetically congruent to zero, so an element written as q verified exactly as the same element written as zero would, and the bits padding the last element out to the byte boundary were never read at all. Every zero element of a signature therefore carried a second encoding, and for the q = 7 parameter sets roughly one element in seven is zero - a single qruov_5_q7_L10 signature measured 256 spare bits, so on the order of 2^256 distinct byte strings verified for the one message and key. Verification now rejects any element outside [0, q) and any set padding bit; a signature produced by this or by the reference implementation is unaffected, as the KAT vectors of every parameter set confirm. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSNOVA signature verification ignored four bits inside the signature for any parameter set whose solution is an odd number of GF(16) nibbles - the SNOVA_24_5_5, SNOVA_25_8_3, SNOVA_29_6_5 and SNOVA_66_15_3 families, sixteen of the forty-four parameter sets. The last byte of the encoded solution carries a single nibble and the signer leaves the top four bits zero, but the decoder did not read them, so sixteen distinct byte strings verified for one signature. This is the same non-unique encoding github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e closed for bytes following the signature, applied inside it; the verifier now requires those bits to be zero. (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSnovaPrivateKeyParameters did not validate the length of the private key encoding handed to it - the only one of the five schemes of github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e that did not - and SnovaParameters.getPrivateKeyLength() reported the expanded (\u0026quot;ESK\u0026quot;) length even for a parameter set whose private key is the seed pair. A private key encoding reaches this constructor straight from a PKCS#8 blob, so a wrong length went undetected: a seed-form key with extra bytes appended was accepted and signed under a different derived key, and a short expanded-form key sized the signer's decode buffer negatively, throwing NegativeArraySizeException out of generateSignature() rather than being reported at construction. Related, the signing retry loop could not terminate: the vinegar values are derived from a single-byte counter, so only 256 distinct linear systems can be tried, and an expanded-form private key that is not a real central map is singular for all of them - generateSignature() then span forever rather than failing. The length is now checked at construction, getPrivateKeyLength() reports the length that parameter set's private key actually has, and the retry loop gives up after its 256 attempts as MAYO's does.\u003c/li\u003e\n\u003cli\u003eMayoSigner and MayoKeyPairGenerator did not clear several buffers holding secret key material that the MAYO reference implementation explicitly clears. Signing left the secret oil space O, the expanded L = (P1 + P1^t) * O + P2, and the M / VPV / Ox intermediates of the central map in place, having gone to the trouble of clearing eleven other buffers; key generation left the expanded seed, whose tail is the encoded oil space, and the P1 * O + P2 half of P; and the row-echelon step left the packed echelon form of the secret linear system and its pivot rows. Separately, if all 256 attempts at solving for the signature had given a rank-deficient system, signing emitted a signature built from the failed attempt's state instead of reporting the failure the reference returns, and AIMerSigner.generateSignature returned an empty array on failure, which a caller would hand on as though it were a signature. Both now throw.\u003c/li\u003e\n\u003cli\u003eFive PQC signature schemes - MAYO, SNOVA, QR-UOV, SQIsign and AIMer - returned the NIST crypto_sign \u0026quot;sm\u0026quot; signed-message envelope from generateSignature() rather than the signature. That envelope is an artefact of the reference KAT harness, which records the message alongside the signature so a vector file can be self-contained; it is not part of any of the five specifications, and no other BC signer emits it (Falcon's KAT test rebuilds the equivalent envelope in the test, which is where it belongs). Two consequences followed, both reaching the JCA Signature services of every parameter set of the five schemes in BouncyCastlePQCProvider. First, since the message was appended to the signature, verification had to skip whatever followed the signature proper, and it did so by checking only that the buffer was long enough - so any number of trailing bytes could be added to a valid signature, or the appended message replaced with unrelated data, and it still verified. A signature encoding was therefore not unique: anyone holding one valid signature could produce unlimited distinct byte strings that all verified for the same message and key, which breaks any use that treats the signature bytes as an identifier, deduplicates on them, or records them as evidence. Second, the envelope propagated into everything built on the operator layer: because ContentSigner hands the signature straight into the structure being signed, every X.509 certificate, CRL, CMS SignedData and TLS CertificateVerify BC produced with one of these algorithms carried a verbatim copy of the signed data inside its own signature field - a self-signed MAYO-1 certificate came to 3567 bytes where the same certificate is now 2020 - which no other implementation can parse as a signature, and which in a detached CMS signature meant the \u0026quot;detached\u0026quot; signature carried the content. generateSignature() now returns the bare signature, and verifySignature() requires exactly the parameter set's signature length, so appended or truncated data is rejected rather than ignored. \u003cstrong\u003eThis is a behavioural change for signatures produced by an earlier release\u003c/strong\u003e - MAYO and SNOVA from 1.84, QR-UOV, SQIsign and AIMer from 1.85 - which are no longer accepted in the envelope form they were emitted in; the signature bytes themselves are unchanged, so a stored value can be recovered by taking the leading signature-length bytes, or for AIMer, whose envelope was message || signature rather than signature || message, the trailing ones. The KAT tests now rebuild the envelope before comparing against the vector files, which continue to record it. Note that AIMer's verification had already been made length-exact during this cycle (see the entry below relating to github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2401\"\u003e#2401\u003c/a\u003e), so of the five only its envelope remained (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2403\"\u003e#2403\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe MLS implementation did not bind an X.509 credential to the LeafNode's signature_key. LeafNode.verify() checked a leaf's signature against the signature_key declared in the leaf itself, while the X.509 credential's certificate chain was stored but never parsed or checked, so the certificate's public key was never required to match signature_key (RFC 9420 sec. 5.3). A leaf could therefore carry one party's certificate while being signed by an unrelated key and still be accepted under that party's identity through KeyPackage.verify() and the Group leaf-validation path. LeafNode.verify() now requires the end-entity certificate's subject public key, in the cipher suite's signature encoding, to equal signature_key for an X.509 credential, and rejects the leaf otherwise - including an empty chain or a certificate whose key type does not match the cipher suite; certificate-chain and identity validation to a trust anchor remain the application's responsibility per RFC 9420 sec. 5.3.1. A public org.bouncycastle.mls.codec.Certificate(byte[]) constructor and a Credential.getCertificates() accessor are added so callers can build and inspect X.509 credentials. Basic credentials are unaffected.\u003c/li\u003e\n\u003cli\u003eThe SecureRandom supplied to org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder.setSecureRandom() did not drive the content IV / nonce for any algorithm other than RC2. EnvelopedDataHelper.generateParameters passed the caller's SecureRandom to the AlgorithmParameterGenerator only in the RC2_CBC branch; every other content-encryption algorithm - AES-CBC, AES-GCM, AES-CCM, Camellia, ARIA, SEED and the rest - reached pGen.generateParameters() on an uninitialised generator, so the IV / nonce was drawn from a default SecureRandom and setSecureRandom() was silently ignored (the builder's javadoc states that random is used for IV/nonce generation). The generator is now initialised with the supplied random on the general path as well, so a caller who provides a specific randomness source - for a controlled or FIPS-approved DRBG, say - has it honoured for the content IV / nonce. The session-key generation path was unaffected and already used the supplied random. Because the content IV / nonce now comes from the supplied SecureRandom, the org.bouncycastle.crypto.util JournalingSecureRandom / JournaledAlgorithm reproducible-encryption support records it in the transcript: a resumed session reproduces the IV / nonce by regenerating it from the replayed randomness - build the resuming encryptor from the content-algorithm OID - rather than by reusing the AlgorithmIdentifier captured from the first encryption, which no longer keeps the transcript aligned.\u003c/li\u003e\n\u003cli\u003eThe NTRU LPRime, NTRU+ and SMAUG-T KEM generators threw a NullPointerException when constructed with a null SecureRandom, where every other KEM generator - including NTRU LPRime's own SNTRU Prime counterpart in the same package - defaults one through CryptoServicesRegistrar.getSecureRandom(). This is reachable from the lightweight API directly, and from javax.crypto.KEM, whose newEncapsulator() documents a null random as a request for the provider's default.\u003c/li\u003e\n\u003cli\u003eFrodoKEMEngine kept a single SHAKE instance in a field, so an engine reached concurrently produced wrong results. It is reached that way through org.bouncycastle.crypto.kems.FrodoKEMExtractor, which holds one engine for its lifetime: two threads extracting through one extractor interleaved the digest's absorb and squeeze phases, yielding shared secrets that silently did not match the sender's, or an IllegalStateException of \u0026quot;attempt to absorb while squeezing\u0026quot; from inside extractSecret. The digest is now built per call, as CMCEEngine's already was, which makes an extractor safe to share. Encapsulation was unaffected, since FrodoKEMGenerator builds an engine per call. Results for any single-threaded use are unchanged - the reference KAT vectors are byte-identical.\u003c/li\u003e\n\u003cli\u003eThe BCJSSE provider carried the TLS 1.2 coupling between the supported_groups extension and ECDSA over into TLS 1.3: an ECDSA signature scheme was treated as usable - offered in the signature_algorithms and signature_algorithms_cert extensions, and eligible when selecting the local credentials - only while the corresponding curve was among the named groups enabled for key exchange, both per context (a group unavailable for key agreement disabled the scheme outright) and per connection (the curve had to be in the supported_groups list about to be sent). RFC 8446 sec. 4.2.7 scopes supported_groups to key exchange only, with signature algorithms negotiated independently (sec. 4.2.3), so this incorrect restriction in TLS 1.3 has been removed. Ed25519, Ed448 and the RSA schemes were unaffected (as well as typical deployments using a default configuration for named groups).\u003c/li\u003e\n\u003cli\u003eThe bcmail module descriptor did not declare its javax.mail/javax.activation dependences, so a modular (module-path) consumer of the jar hit IllegalAccessError/module-resolution failures when the S/MIME classes touched the mail API. The descriptor now requires them optionally (requires static) under all four module names those libraries are known by - the automatic names mail and activation carried by the javax.mail:mail / javax.activation:activation artifacts, and the explicit names java.mail and java.activation carried by the newer com.sun.mail / com.sun.activation ones - a hard requires on any one name would break users of the others (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2389\"\u003e#2389\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eFour type-coercion helpers in the OER / IEEE 1609.2 (ITS) decoder tested the wrong type in the identity fast path that lets a getInstance() factory return an argument that is already of the target type. org.bouncycastle.oer.its.ieee1609dot2.basetypes.UINT32.getInstance and org.bouncycastle.oer.its.etsi102941.basetypes.Version.getInstance guarded on UINT8 - a sibling of UINT32 under UintBase, and unrelated to Version - so passing a UINT8 threw ClassCastException, while passing an actual UINT32 or Version missed the fast path and fell through to ASN1Integer.getInstance, which rejects them: neither factory accepted its own type. org.bouncycastle.oer.its.etsi103097.EtsiTs103097DataEncryptedUnicast.getInstance guarded on its sibling EtsiTs103097DataEncrypted and then cast to the unicast type, so an EtsiTs103097DataEncrypted threw ClassCastException. org.bouncycastle.oer.OEROptional.getObject(Class) called value.getClass().isInstance(type) with the arguments transposed, which is always false because the argument is a java.lang.Class, so the cast path was dead and every optional field was resolved reflectively, failing with IllegalStateException for a target type with no static getInstance. Each guard now names the type it returns, matching the sibling UINT8 / UINT16 / UINT64 and EtsiTs103097DataEncrypted factories (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2373\"\u003e#2373\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eDefaultAlgorithmNameFinder and DefaultSignatureNameFinder had no entries at all for the ShangMi algorithms, so an SM2 signature AlgorithmIdentifier that DefaultSignatureAlgorithmIdentifierFinder itself produces came back named only by its OID string - getAlgorithmName(GMObjectIdentifiers.sm2sign_with_sm3) returned \u0026quot;1.2.156.10197.1.501\u0026quot; and hasAlgorithmName returned false. Both finders now name sm2sign_with_sm3 as SM3WITHSM2 and sm2sign_with_sha256 as SHA256WITHSM2, and DefaultAlgorithmNameFinder additionally names the sm3 digest. All three resolve through the BC provider, as Signature and MessageDigest respectively. The remaining GM arc - the SM4 cipher modes, the sm2encrypt variants, and the SM1 / SM6 / SSF33 ciphers BC does not implement - is still unnamed (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2377\"\u003e#2377\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe RFC 4998 evidence-record classes compared the digest AlgorithmIdentifier named by a time-stamp authority with the one their own DigestCalculator uses, and did so with AlgorithmIdentifier.equals(), which compares the encodings. A TSA that names SHA-256 with an explicit NULL parameters field - DigiCert among them - therefore failed against BC's own calculator, which names it with the parameters absent, and ERSArchiveTimeStampGenerator.generateArchiveTimeStamp rejected the response with \u0026quot;time stamp imprint for wrong algorithm\u0026quot;. Both spellings name the same digest and RFC 5754 sec. 2 requires a receiver to accept either, while requiring that identifiers be generated with the parameters absent, which BC already does. The three affected comparisons - the two in ERSArchiveTimeStampGenerator and the digest check in ERSEvidenceRecord.renew - now use the new AlgorithmIdentifier.areEquivalent, which matches on the algorithm and treats an absent parameters field and NULL as the same, and the consistency check across an evidence record's archive time stamp chain uses it too. An identifier carrying an actual parameter structure is never equivalent to one carrying none (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2379\"\u003e#2379\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eEDIPartyName.toASN1Primitive emitted the nameAssigner and partyName DirectoryStrings without their context tags, so an EDIPartyName built through its public constructor could not be parsed back by EDIPartyName.getInstance, which correctly requires them. RFC 5280 sec. 4.2.1.6 tags both members [0] and [1], and those tags are explicit despite the module's IMPLICIT TAGS because DirectoryString is a CHOICE, which X.680 does not allow to be tagged implicitly - the decoder already had this right. The encoder now matches it. Note the type was added during the 1.85 cycle and GeneralName validates its ediPartyName alternative through it, so a GeneralName carrying an untagged ediPartyName - including one BC itself produced - is rejected where 1.84 passed it through unexamined; the untagged form is not read leniently (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2380\"\u003e#2380\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eRSASSA-PSS could not be used with a RIPEMD digest through the JCA API. Nothing registered the RIPEMD PSS signatures, so Signature.getInstance(\u0026quot;RIPEMD160WITHRSAANDMGF1\u0026quot;) raised NoSuchAlgorithmException, and the generic RSASSA-PSS route with an explicit PSSParameterSpec failed too: org.bouncycastle.jcajce.provider.util.DigestFactory.getDigest returned null for a RIPEMD name, and isSameDigest - an allow-list of the SHA families and MD5 - reported two identical RIPEMD names as different digests, so the spec was rejected with \u0026quot;digest algorithm for MGF should be the same as for PSS parameters\u0026quot;. isSameDigest now answers true for equal names whatever the digest, which also covers Whirlpool, SM3, GOST3411 and anything else outside that allow-list; DigestFactory recognises RIPEMD128, RIPEMD160 and RIPEMD256 by name and OID; the three PSS signatures are registered with MGF1 over the same digest and a salt of the digest length; and DefaultSignatureAlgorithmIdentifierFinder gains the matching RIPEMD*WITHRSAANDMGF1 entries with their RSASSA-PSS-params, so the operator/JcaContentSignerBuilder path works as well. Note BC continues to require the PSS hash and the MGF1 hash to be the same, which RFC 8017 does not itself demand (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2381\"\u003e#2381\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eThe opt-in key-size validation on CMS key-transport recipients (org.bouncycastle.cms.jcajce.JceKeyTransRecipient.setKeySizeValidation(true)) never ran for a message using RFC 9709 CEK derivation (id-alg-cek-hkdf-sha256): the branch that should have selected the actual content-encryption algorithm carried in the KDF AlgorithmIdentifier's parameters compared the encrypted-key byte array against the id-alg-cek-hkdf-sha256 object identifier - a comparison that is always false - so the check fell through to a key-size lookup on the outer KDF OID, which has no registered key size, and silently checked nothing. A key-transport EnvelopedData/AuthEnvelopedData whose transported (and HKDF-derived) content-encryption key did not match the key size of the advertised content-encryption algorithm was therefore accepted even with validation enabled. The recipient now dispatches on the content-encryption AlgorithmIdentifier's algorithm OID, so key-size validation of RFC 9709 messages checks the recovered key against the inner content-encryption algorithm. Messages with a matching key size, non-HKDF messages, and recipients that do not enable validation are unaffected.\u003c/li\u003e\n\u003cli\u003eThe OpenPGP v6 SEIPD (Symmetrically Encrypted Integrity Protected Data, version 2 / RFC 9580 sec. 5.13.2) packet parser read the AEAD chunk-size octet without bounding it. The chunk length is 2^(chunkSize + 6) bytes and the AEAD decryptor allocates a buffer of that size up front, so a crafted v6 encrypted message (reachable with only the recipient's public key) declaring chunkSize 24 forced a 1 GiB allocation on decrypt, and chunkSize 25 (where the int cast of the chunk length wraps negative) threw a NegativeArraySizeException -- a pre-authentication resource-exhaustion denial of service. This is the version 6 sibling of the version 5 AEADEncDataPacket issue fixed under CVE-2026-3505, which bounded that packet's chunk size at 16 but left the v6 SymmetricEncIntegrityPacket unbounded. SymmetricEncIntegrityPacket now rejects a chunk-size octet outside 0..16 (a 4 MiB chunk, matching the v5 ceiling) with a MalformedPacketException at parse, before any allocation.\u003c/li\u003e\n\u003cli\u003eThe Ed25519 KeyFactory in the JDK 11+ and JDK 15+ multi-release overlays (META-INF/versions/11 and /15) had drifted from the base implementation on the OpenSSH key-spec path: it used the no-passphrase OpenSSHPrivateKeyUtil.parsePrivateKeyBlob overload, so a passphrase-encrypted openssh-key-v1 Ed25519 private key that KeyFactory.getInstance(\u0026quot;Ed25519\u0026quot;, \u0026quot;BC\u0026quot;).generatePrivate(new OpenSSHPrivateKeySpec(blob, passphrase)) decoded correctly on JDK 8 failed on JDK 11 and later; it also let a raw RuntimeException escape on a malformed blob and threw IllegalStateException (JDK 11) instead of InvalidKeySpecException for a non-Ed25519 key. The overlays now match the base implementation (passphrase support, parse errors wrapped as InvalidKeySpecException). Relatedly, the OpenSSH wrong-key-type and decode-failure paths across the RSA, DSA, EC and Ed25519 KeyFactorySpi implementations now consistently raise InvalidKeySpecException (previously a mix of IllegalArgumentException / IllegalStateException) and wrap a malformed OpenSSH public key, and an incorrect \u0026quot;public key is not RSA private key\u0026quot; message on the RSA private path was corrected. The multi-release test tasks now exercise the OpenSSH key specs against the multi-release jar.\u003c/li\u003e\n\u003cli\u003eThe Ant-built utility jars (bcutil-jdk15to18, bcutil-jdk14) duplicated org.bouncycastle.asn1.iana.IANAObjectIdentifiers, which since 1.85 (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2176\"\u003e#2176\u003c/a\u003e) lives only in core and is therefore already shipped in bcprov. The shared ant/bc+-build.xml build-util target still copied org/bouncycastle/asn1/iana/** into bcutil, so a project depending on both bcprov and bcutil (for example via bcpkix) failed an Android/R8 build with \u0026quot;Duplicate class org.bouncycastle.asn1.iana.IANAObjectIdentifiers found in modules bcprov-jdk15to18-1.85.jar and bcutil-jdk15to18-1.85.jar\u0026quot;. The iana package is no longer bundled into bcutil (it remains in bcprov); the Gradle jdk18on jars were already correct (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2356\"\u003e#2356\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eorg.bouncycastle.util.BigIntegers.intValueExact (and the byte/short/long variants) delegated to BigInteger.intValueExact from 1.85, a Java 8 method Android only provides from API level 33, so on earlier Android versions any code path using them - most visibly loading a PKCS12 keystore, whose iteration-count validation calls intValueExact - crashed with NoSuchMethodError. The range checks are open-coded again, as they were in 1.84 (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2369\"\u003e#2369\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eGOST R 34.10-94 signing (org.bouncycastle.crypto.signers.GOST3410Signer) raised the domain generator to the per-signature nonce k with a bare BigInteger.modPow, whose running time varies with the exponent. Recovering k from that timing yields the private key straight out of the signature equation s = k*m + x*r, so k is now randomised with a random multiple of q before it is raised, exactly as DSASigner already does with its own k. Since the domain parameter a has order q, raising it to a multiple of q gives 1 and the signature is unchanged - the RFC-style known-answer vectors in GOST3410Test still produce the same r and s. Those vectors drive signing from a FixedSecureRandom, so they now carry one further byte for the randomiser to consume, in the same way the DSA signing vectors already do.\u003c/li\u003e\n\u003cli\u003eKCCMBlockCipher (DSTU7624-128/256/512 CCM mode) returned the input length rather than 0 from getUpdateOutputSize(int), but like CCMBlockCipher/KGCMBlockCipher it buffers all input until doFinal and produces no output on an update. Through the JCA layer this made the caller-supplied-buffer Cipher.update(input, inOff, inLen, output, outOff) reject a correctly sized output buffer with \u0026quot;javax.crypto.ShortBufferException: output buffer too short for input.\u0026quot; when decrypting. getUpdateOutputSize now returns 0, matching the sibling CCM/KGCM modes (github \u003ca href=\"https://redirect.github.com/bcgit/bc-java/issues/2354\"\u003e#2354\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eJ-PAKE raised values to exponents carrying private material with bare BigInteger.modPow calls, whose running time varies with the exponent: the private ephemerals x1 and x2 in round 1, x2*s and the negated form of it in round 2 and in the keying material - both of which carry the password - and the v behind each Schnorr zero-knowledge proof, which together with the published r would give up x. JPAKEParticipant itself notes that leaking x1 or x2 lets an attacker brute-force the password. All of these exponents are now randomised with a random multiple of q before they are raised. A multiple of q rather than of p-1 is sound here, and much cheaper since the exponents are the size of q: the generator is checked with g^q = 1 when the JPAKEPrimeOrderGroup is built, and each value received from the other participant is checked the same way by validateZeroKnowledgeProof before it is used as a base. JPAKEUtil.calculateA and JPAKEUtil.calculateKeyingMaterial gained overloads taking a SecureRandom, and there is a new JPAKEUtil.calculateGx taking q and a SecureRandom; the existing overloads still work, taking the default from CryptoServicesRegistrar. The three-argument calculateGx has no q to work with, so it blinds with a multiple of p-1 and is deprecated in favour of the new one. The three modPow calls in validateZeroKnowledgeProof are unchanged, since their exponents are all public. The elliptic-curve variant was already routing its private scalars through ECAlgorithms.multiplySecret and needed no change.\u003c/li\u003e\n\u003cli\u003eThe PKIX CertPathBuilder (\u0026quot;PKIX\u0026quot;/\u0026quot;RFC5280\u0026quot;/\u0026quot;RFC3280\u0026quot;) matched candidate issuers by subject name only during its depth-first search, so a CertStore containing many self-issued certificates that share a single subject name and never chain to a trust anchor could be explored as a large number of partial paths before the build concluded no chain exists. The builder now bounds the total number of nodes visited per build; the limit is configurable via the org.bouncycastle.x509.max_cert_path_build_nodes system property (default 262144, far above any legitimate build) and, when exceeded, the build fails with a CertPathBuilderException naming the property. This is the builder-side companion to the existing org.bouncycastle.x509.max_policy_nodes bound.\u003c/li\u003e\n\u003cli\u003eA group of parse and revocation-handling entry points let an unchecked runtime exception (NullPointerException, ArrayIndexOutOfBoundsException, IllegalStateException or ArithmeticException) escape on empty, content-less or out-of-range input instead of the checked exception each entry point declares - the malformed input was rejected either way, but the leaked type could escape a documented throws contract. Each now fails with its declared type, and well-formed input is unaffected: org.bouncycastle.tsp.cms.CMSTimeStampedData (an empty or truncated stream; the fix also covers its org.bouncycastle.asn1.cms.MetaData and TimeStampDataUtil helpers) and org.bouncycastle.cms.CMSEnvelopedData (an EnvelopedData carrying no encryptedContent) now throw IOException / CMSException rather than NullPointerException; org.bouncycastle.tsp.TimeStampToken rejects a token whose SignerInfo carries no signed attributes with TSPValidationException rather than NullPointerException; org.bouncycastle.cert.cmp.GeneralPKIMessage, org.bouncycastle.est.CSRAttributesResponse, org.bouncycastle.cmc.SimplePKIResponse, org.bouncycastle.openssl.X509TrustedCertificateBlock, org.bouncycastle.tsp.TimeStampRequest, org.bouncycastle.tsp.TimeStampResponse, org.bouncycastle.pkcs.PKCS12PfxPdu and org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo reject empty / no-content / truncated input with their declared CertIOException / IOException / PKCSIOException rather than a leaked NullPointerException, and org.bouncycastle.cert.crmf.CertificateRequestMessage.hasSigningKeyProofOfPossessionWithPKMAC answers false for an absent or non-signing-key proof-of-possession rather than throwing NullPointerException; org.bouncycastle.crypto.util.OpenSSHPrivateKeyUtil.parsePrivateKeyBlob and org.bouncycastle.math.ec.ECCurve.decodePoint reject an empty (or null) blob / point encoding with IllegalArgumentException rather than ArrayIndexOutOfBoundsException, closing the point-decode path reached by every untrusted-point consumer (EC key parsing, ECDH/ECIES, TLS); and the PKIX revocation code no longer leaks a runtime exception on attacker-controlled CRL/OCSP fields - PKIXCertPathReviewer and X509RevocationChecker bound an out-of-range CRLReason code against their fixed reason table (reporting \u0026quot;unknown\u0026quot; instead of ArrayIndexOutOfBoundsException / ArithmeticException), RFC3280CertPathUtilities tolerates an absent reasons mask on a CRL distribution point, and ProvOcspRevocationChecker tolerates an OCSP response with no nonce extension.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003eSee full diff in \u003ca href=\"https://github.com/bcgit/bc-java/commits\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark` from 0.29.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/blockquote\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/blockquote\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/42b4fb7adfe288ef13e9e27ab20aff7e91b0ab9d\"\u003e\u003ccode\u003e42b4fb7\u003c/code\u003e\u003c/a\u003e Prepare CHANGELOG for version 0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/b76e09d7a8362abb5f04e1d6b91dbd6da279a6fc\"\u003e\u003ccode\u003eb76e09d\u003c/code\u003e\u003c/a\u003e Limit how deep inline nodes may nest by default (100)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/49f65cb5cbec93cff713179990307145198e7061\"\u003e\u003ccode\u003e49f65cb\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing deeply nested emphasis\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/610f84b83e68c381e8f784ae4d044c80e1948b67\"\u003e\u003ccode\u003e610f84b\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological autolink email addresses\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/9f1d73897a56cbd74c39347af351a473e70297e1\"\u003e\u003ccode\u003e9f1d738\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological HTML block attributes\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/e13297e849995fdd582a85841067bff1d9c35ee5\"\u003e\u003ccode\u003ee13297e\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing pathological backticks\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/89d1bd3fa1524e8217ed61db5e8116c82434470f\"\u003e\u003ccode\u003e89d1bd3\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing with lots of \u003ccode\u003e\u0026lt;\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/commonmark/commonmark-java/compare/commonmark-parent-0.29.0...commonmark-parent-0.30.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark-ext-autolink` from 0.29.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark-ext-autolink's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/blockquote\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark-ext-autolink's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply ...\n\n_Description has been truncated_","html_url":"https://github.com/jckm14/openclaw/pull/70","url":"https://dependabot.ecosyste.ms/api/v1/hosts/GitHub/repositories/jckm14%2Fopenclaw/issues/70","packages_url":"https://dependabot.ecosyste.ms/api/v1/issues/70/packages"}},{"old_version":"5.3.2","new_version":"5.4.0","update_type":"minor","path":null,"pr_created_at":"2026-08-17T18:23:33.000Z","version_change":"5.3.2 → 5.4.0","issue":{"uuid":"5174169869","node_id":"PR_kwDOTHJXZM8AAAABADENkQ","number":29,"state":"closed","title":"chore(deps): bump the android-deps group across 1 directory with 19 updates","user":"dependabot[bot]","labels":["dependencies","java"],"assignees":[],"locked":false,"comments_count":2,"pull_request":true,"closed_at":"2026-09-10T15:45:32.000Z","author_association":null,"state_reason":null,"created_at":"2026-08-17T18:23:33.000Z","updated_at":"2026-09-10T15:45:34.000Z","time_to_close":2064119,"merged_at":null,"merged_by":null,"closed_by":null,"dependency_metadata":{"prefix":"chore(deps): bump","group_name":"android-deps","update_count":19,"packages":[{"name":"gradle-wrapper","old_version":"9.5.1","new_version":"9.7.0","repository_url":"https://github.com/gradle/gradle"},{"name":"androidx.compose:compose-bom","old_version":"2026.05.01","new_version":"2026.08.00"},{"name":"androidx.core:core-ktx","old_version":"1.18.0","new_version":"1.19.0"},{"name":"androidx.webkit:webkit","old_version":"1.15.0","new_version":"1.17.0"},{"name":"org.bouncycastle:bcprov-jdk18on","old_version":"1.84","new_version":"1.85.2","repository_url":"https://github.com/bcgit/bc-java"},{"name":"org.commonmark:commonmark","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-autolink","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-strikethrough","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-tables","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-task-list-items","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.junit.vintage:junit-vintage-engine","old_version":"6.1.0","new_version":"6.1.3","repository_url":"https://github.com/junit-team/junit-framework"},{"name":"io.kotest:kotest-assertions-core-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"io.kotest:kotest-runner-junit5-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"com.squareup.okhttp3:mockwebserver","old_version":"5.3.2","new_version":"5.4.0","repository_url":"https://github.com/square/okhttp"},{"name":"com.squareup.okhttp3:okhttp","old_version":"5.3.2","new_version":"5.4.0","repository_url":"https://github.com/square/okhttp"},{"name":"com.android.application","old_version":"9.2.1","new_version":"9.3.1"},{"name":"com.android.test","old_version":"9.2.1","new_version":"9.3.1"},{"name":"org.jetbrains.kotlin.plugin.compose","old_version":"2.4.0","new_version":"2.4.10","repository_url":"https://github.com/JetBrains/kotlin"},{"name":"org.jetbrains.kotlin.plugin.serialization","old_version":"2.4.0","new_version":"2.4.10","repository_url":"https://github.com/JetBrains/kotlin"}],"path":null,"ecosystem":"maven"},"body":"Bumps the android-deps group with 19 updates in the /apps/android directory:\n\n| Package | From | To |\n| --- | --- | --- |\n| [gradle-wrapper](https://github.com/gradle/gradle) | `9.5.1` | `9.7.0` |\n| androidx.compose:compose-bom | `2026.05.01` | `2026.08.00` |\n| androidx.core:core-ktx | `1.18.0` | `1.19.0` |\n| androidx.webkit:webkit | `1.15.0` | `1.17.0` |\n| [org.bouncycastle:bcprov-jdk18on](https://github.com/bcgit/bc-java) | `1.84` | `1.85.2` |\n| [org.commonmark:commonmark](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-autolink](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-strikethrough](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-tables](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-task-list-items](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.junit.vintage:junit-vintage-engine](https://github.com/junit-team/junit-framework) | `6.1.0` | `6.1.3` |\n| [io.kotest:kotest-assertions-core-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [io.kotest:kotest-runner-junit5-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [com.squareup.okhttp3:mockwebserver](https://github.com/square/okhttp) | `5.3.2` | `5.4.0` |\n| [com.squareup.okhttp3:okhttp](https://github.com/square/okhttp) | `5.3.2` | `5.4.0` |\n| com.android.application | `9.2.1` | `9.3.1` |\n| com.android.test | `9.2.1` | `9.3.1` |\n| [org.jetbrains.kotlin.plugin.compose](https://github.com/JetBrains/kotlin) | `2.4.0` | `2.4.10` |\n| [org.jetbrains.kotlin.plugin.serialization](https://github.com/JetBrains/kotlin) | `2.4.0` | `2.4.10` |\n\n\nUpdates `gradle-wrapper` from 9.5.1 to 9.7.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/gradle/gradle/releases\"\u003egradle-wrapper's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e9.7.0\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.0.\u003c/p\u003e\n\u003cp\u003eHere are the highlights of this release:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIsolated Projects graduates to incubating\u003c/li\u003e\n\u003cli\u003eBroader Configuration Cache compatibility\u003c/li\u003e\n\u003cli\u003eMore source locations in problem reports\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003ca href=\"https://docs.gradle.org/9.7.0/release-notes.html\"\u003eRead the Release Notes\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eWe would like to thank the following community members for their contributions to this release of Gradle:\n\u003ca href=\"https://github.com/aSemy\"\u003eAdam\u003c/a\u003e,\n\u003ca href=\"https://github.com/Gautam-aman\"\u003eAman Gautam\u003c/a\u003e,\n\u003ca href=\"https://github.com/YukiCodepth\"\u003eAman Kumar\u003c/a\u003e,\n\u003ca href=\"https://github.com/adubrouski\"\u003eAnton Dubrouski\u003c/a\u003e,\n\u003ca href=\"https://github.com/liutikas\"\u003eAurimas\u003c/a\u003e,\n\u003ca href=\"https://github.com/gbhavya07\"\u003egbhavya07\u003c/a\u003e,\n\u003ca href=\"https://github.com/joshfriend\"\u003eJosh Friend\u003c/a\u003e,\n\u003ca href=\"https://github.com/nicklauslittle-gov\"\u003enicklauslittle-gov\u003c/a\u003e,\n\u003ca href=\"https://github.com/psoni674\"\u003ePragati\u003c/a\u003e,\n\u003ca href=\"https://github.com/Project516\"\u003eproject516\u003c/a\u003e,\n\u003ca href=\"https://github.com/Uomocapra\"\u003eQin Mi\u003c/a\u003e,\n\u003ca href=\"https://github.com/rkdfx\"\u003eRavi\u003c/a\u003e,\n\u003ca href=\"https://github.com/sk-reddy17\"\u003esk-reddy17\u003c/a\u003e,\n\u003ca href=\"https://github.com/Suvrat1629\"\u003eSuvrat Acharya\u003c/a\u003e,\n\u003ca href=\"https://github.com/ShreckYe\"\u003eYongshun Ye\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eUpgrade instructions\u003c/h2\u003e\n\u003cp\u003eSwitch your build to use Gradle 9.7.0 by updating your wrapper:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e./gradlew :wrapper --gradle-version=9.7.0 \u0026amp;\u0026amp; ./gradlew :wrapper\r\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eSee the Gradle \u003ca href=\"https://docs.gradle.org/9.7.0/userguide/upgrading_version_9.html\"\u003e9.x upgrade guide\u003c/a\u003e to learn about deprecations, breaking changes and other considerations when upgrading.\u003c/p\u003e\n\u003cp\u003eFor Java, Groovy, Kotlin and Android compatibility, see the \u003ca href=\"https://docs.gradle.org/9.7.0/userguide/compatibility.html\"\u003efull compatibility notes\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eReporting problems\u003c/h2\u003e\n\u003cp\u003eIf you find a problem with this release, please file a bug on \u003ca href=\"https://github.com/gradle/gradle/issues\"\u003eGitHub Issues\u003c/a\u003e adhering to our issue guidelines.\nIf you're not sure you're encountering a bug, please use the \u003ca href=\"https://discuss.gradle.org/c/help-discuss\"\u003eforum\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eWe hope you will build happiness with Gradle, and we look forward to your feedback via \u003ca href=\"https://twitter.com/gradle\"\u003eTwitter\u003c/a\u003e or on \u003ca href=\"https://github.com/gradle\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003e9.7.0 RC3\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.0 RC3.\u003c/p\u003e\n\u003cp\u003eHere are the highlights of this release:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIsolated Projects graduates to incubating\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/3defbfc59d757b873d787b2261de5c7f8a00970a\"\u003e\u003ccode\u003e3defbfc\u003c/code\u003e\u003c/a\u003e make DistributionIntegrationSpec more permissive for releases (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38766\"\u003e#38766\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/f176043d6416ca85dab736b6e7581d1f0018ee8e\"\u003e\u003ccode\u003ef176043\u003c/code\u003e\u003c/a\u003e make DistributionIntegrationSpec more permissive for releases\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/b0828dad52cf99112e2071fb10547c0d2293a51b\"\u003e\u003ccode\u003eb0828da\u003c/code\u003e\u003c/a\u003e Prepare release notes for Gradle 9.7.0GA (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38756\"\u003e#38756\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/064b6d6161b55f531be7710d68efe4404b48558a\"\u003e\u003ccode\u003e064b6d6\u003c/code\u003e\u003c/a\u003e cleanup\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/dfe7bdcc464152313992f49b6ea3846d7c0119ed\"\u003e\u003ccode\u003edfe7bdc\u003c/code\u003e\u003c/a\u003e add new training to release notes\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/756196837a985dd030d596411852b99c43d6880e\"\u003e\u003ccode\u003e7561968\u003c/code\u003e\u003c/a\u003e add release notes for 37801\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/68a1f351d3ba32e09523e5d67949cea326c0d781\"\u003e\u003ccode\u003e68a1f35\u003c/code\u003e\u003c/a\u003e cherrypick 38367 to release\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/a462c95ca92b7a5cc55172a42608fcab5fd43b4c\"\u003e\u003ccode\u003ea462c95\u003c/code\u003e\u003c/a\u003e Rebalance AllVersionsCrossVersion buckets for agents without TestDistribution...\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/820e2b14ad6b0f64a1a042dcfb43ea7e3e8f7ada\"\u003e\u003ccode\u003e820e2b1\u003c/code\u003e\u003c/a\u003e Update Gradle wrapper to version 9.7.0-rc-3 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38743\"\u003e#38743\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/75ea3d7671b4c52daf3fd26d0824b8fa7c752181\"\u003e\u003ccode\u003e75ea3d7\u003c/code\u003e\u003c/a\u003e Update Gradle wrapper to version 9.7.0-rc-3\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/gradle/gradle/compare/v9.5.1...v9.7.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `androidx.compose:compose-bom` from 2026.05.01 to 2026.08.00\n\nUpdates `androidx.core:core-ktx` from 1.18.0 to 1.19.0\n\nUpdates `androidx.webkit:webkit` from 1.15.0 to 1.17.0\n\nUpdates `org.bouncycastle:bcprov-jdk18on` from 1.84 to 1.85.2\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.html\"\u003eorg.bouncycastle:bcprov-jdk18on's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003eSee full diff in \u003ca href=\"https://github.com/bcgit/bc-java/commits\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003ecommonmark-java 0.29.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e[0.29.0] - 2026-06-20\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/42b4fb7adfe288ef13e9e27ab20aff7e91b0ab9d\"\u003e\u003ccode\u003e42b4fb7\u003c/code\u003e\u003c/a\u003e Prepare CHANGELOG for version 0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/b76e09d7a8362abb5f04e1d6b91dbd6da279a6fc\"\u003e\u003ccode\u003eb76e09d\u003c/code\u003e\u003c/a\u003e Limit how deep inline nodes may nest by default (100)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/49f65cb5cbec93cff713179990307145198e7061\"\u003e\u003ccode\u003e49f65cb\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing deeply nested emphasis\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/610f84b83e68c381e8f784ae4d044c80e1948b67\"\u003e\u003ccode\u003e610f84b\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological autolink email addresses\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/9f1d73897a56cbd74c39347af351a473e70297e1\"\u003e\u003ccode\u003e9f1d738\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological HTML block attributes\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/e13297e849995fdd582a85841067bff1d9c35ee5\"\u003e\u003ccode\u003ee13297e\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing pathological backticks\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/89d1bd3fa1524e8217ed61db5e8116c82434470f\"\u003e\u003ccode\u003e89d1bd3\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing with lots of \u003ccode\u003e\u0026lt;\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/commonmark/commonmark-java/compare/commonmark-parent-0.28.0...commonmark-parent-0.30.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark-ext-autolink` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark-ext-autolink's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003ecommonmark-java 0.29.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark-ext-autolink's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e[0.29.0] - 2026-06-20\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/42b4fb7adfe288ef13e9e27ab20aff7e91b0ab9d\"\u003e\u003ccode\u003e42b4fb7\u003c/code\u003e\u003c/a\u003e Prepare CHANGELOG for version 0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/b76e09d7a8362abb5f04e1d6b91dbd6da279a6fc\"\u003e\u003ccode\u003eb76e09d\u003c/code\u003e\u003c/a\u003e Limit how deep inline nodes may nest by default (100)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/49f65cb5cbec93cff713179990307145198e7061\"\u003e\u003ccode\u003e49f65cb\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing deeply nested emphasis\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/610f84b83e68c381e8f784ae4d044c80e1948b67\"\u003e\u003ccode\u003e610f84b\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological autolink email addresses\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/9f1d73897a56cbd74c39347af351a473e70297e1\"\u003e\u003ccode\u003e9f1d738\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological HTML block attributes\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/e13297e849995fdd582a85841067bff1d9c35ee5\"\u003e\u003ccode\u003ee13297e\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing pathological backticks\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/89d1bd3fa1524e8217ed61db5e8116c82434470f\"\u003e\u003ccode\u003e89d1bd3\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing with lots of \u003ccode\u003e\u0026lt;\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/commonmark/commonmark-java/compare/commonmark-parent-0.28.0...commonmark-parent-0.30.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark-ext-gfm-strikethrough` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark-ext-gfm-strikethrough's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003ecommonmark-java 0.29.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark-ext-gfm-strikethrough's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e[0.29.0] - 2026-06-20\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/42b4fb7adfe288ef13e9e27ab20aff7e91b0ab9d\"\u003e\u003ccode\u003e42b4fb7\u003c/code\u003e\u003c/a\u003e Prepare CHANGELOG for version 0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/b76e09d7a8362abb5f04e1d6b91dbd6da279a6fc\"\u003e\u003ccode\u003eb76e09d\u003c/code\u003e\u003c/a\u003e Limit how deep inline nodes may nest by default (100)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/49f65cb5cbec93cff713179990307145198e7061\"\u003e\u003ccode\u003e49f65cb\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing deeply nested emphasis\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/610f84b83e68c381e8f784ae4d044c80e1948b67\"\u003e\u003ccode\u003e610f84b\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological autolink email addresses\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/9f1d73897a56cbd74c39347af351a473e70297e1\"\u003e\u003ccode\u003e9f1d738\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological HTML block attributes\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/e13297e849995fdd582a85841067bff1d9c35ee5\"\u003e\u003ccode\u003ee13297e\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing pathological backticks\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/89d1bd3fa1524e8217ed61db5e8116c82434470f\"\u003e\u003ccode\u003e89d1bd3\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing with lots of \u003ccode\u003e\u0026lt;\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/commonmark/commonmark-java/compare/commonmark-parent-0.28.0...commonmark-parent-0.30.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark-ext-gfm-tables` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark-ext-gfm-tables's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003ecommonmark-java 0.29.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark-ext-gfm-tables's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e[0.29.0] - 2026-06-20\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/42b4fb7adfe288ef13e9e27ab20aff7e91b0ab9d\"\u003e\u003ccode\u003e42b4fb7\u003c/code\u003e\u003c/a\u003e Prepare CHANGELOG for version 0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/b76e09d7a8362abb5f04e1d6b91dbd6da279a6fc\"\u003e\u003ccode\u003eb76e09d\u003c/code\u003e\u003c/a\u003e Limit how deep inline nodes may nest by default (100)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/49f65cb5cbec93cff713179990307145198e7061\"\u003e\u003ccode\u003e49f65cb\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing deeply nested emphasis\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/610f84b83e68c381e8f784ae4d044c80e1948b67\"\u003e\u003ccode\u003e610f84b\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological autolink email addresses\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/9f1d73897a56cbd74c39347af351a473e70297e1\"\u003e\u003ccode\u003e9f1d738\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological HTML block attributes\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/e13297e849995fdd582a85841067bff1d9c35ee5\"\u003e\u003ccode\u003ee13297e\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing pathological backticks\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/89d1bd3fa1524e8217ed61db5e8116c82434470f\"\u003e\u003ccode\u003e89d1bd3\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing with lots of \u003ccode\u003e\u0026lt;\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/commonmark/commonmark-java/compare/commonmark-parent-0.28.0...commonmark-parent-0.30.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark-ext-task-list-items` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark-ext-task-list-items's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003ecommonmark-java 0.29.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark-ext-task-list-items's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e[0.29.0] - 2026-06-20\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/42b4fb7adfe288ef13e9e27ab20aff7e91b0ab9d\"\u003e\u003ccode\u003e42b4fb7\u003c/code\u003e\u003c/a\u003e Prepare CHANGELOG for version 0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/b76e09d7a8362abb5f04e1d6b91dbd6da279a6fc\"\u003e\u003ccode\u003eb76e09d\u003c/code\u003e\u003c/a\u003e Limit how deep inline nodes may nest by default (100)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/49f65cb5cbec93cff713179990307145198e7061\"\u003e\u003ccode\u003e49f65cb\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing deeply nested emphasis\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/610f84b83e68c381e8f784ae4d044c80e1948b67\"\u003e\u003ccode\u003e610f84b\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological autolink email addresses\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/9f1d73897a56cbd74c39347af351a473e70297e1\"\u003e\u003ccode\u003e9f1d738\u003c/code\u003e\u003c/a\u003e Fix StackOverflowEr...\n\n_Description has been truncated_","html_url":"https://github.com/amstaff666/openclaw/pull/29","url":"https://dependabot.ecosyste.ms/api/v1/hosts/GitHub/repositories/amstaff666%2Fopenclaw/issues/29","packages_url":"https://dependabot.ecosyste.ms/api/v1/issues/29/packages"}},{"old_version":"5.3.2","new_version":"5.4.0","update_type":"minor","path":null,"pr_created_at":"2026-08-17T00:20:48.000Z","version_change":"5.3.2 → 5.4.0","issue":{"uuid":"5167091043","node_id":"PR_kwDOS5U1Kc7_1rvw","number":38,"state":"closed","title":"chore(deps): bump the android-deps group across 1 directory with 23 updates","user":"dependabot[bot]","labels":["dependencies","java"],"assignees":[],"locked":false,"comments_count":1,"pull_request":true,"closed_at":"2026-09-10T00:08:35.000Z","author_association":null,"state_reason":null,"created_at":"2026-08-17T00:20:48.000Z","updated_at":"2026-09-10T00:08:37.000Z","time_to_close":2072867,"merged_at":null,"merged_by":null,"closed_by":null,"dependency_metadata":{"prefix":"chore(deps): bump","group_name":"android-deps","update_count":23,"packages":[{"name":"gradle-wrapper","old_version":"9.4.1","new_version":"9.7.0","repository_url":"https://github.com/gradle/gradle"},{"name":"androidx.compose:compose-bom","old_version":"2026.04.01","new_version":"2026.08.00"},{"name":"androidx.core:core-ktx","old_version":"1.18.0","new_version":"1.19.0"},{"name":"androidx.webkit:webkit","old_version":"1.15.0","new_version":"1.17.0"},{"name":"org.bouncycastle:bcprov-jdk18on","old_version":"1.84","new_version":"1.85.2","repository_url":"https://github.com/bcgit/bc-java"},{"name":"org.commonmark:commonmark","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-autolink","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-strikethrough","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-gfm-tables","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"org.commonmark:commonmark-ext-task-list-items","old_version":"0.28.0","new_version":"0.30.0","repository_url":"https://github.com/commonmark/commonmark-java"},{"name":"dnsjava:dnsjava","old_version":"3.6.4","new_version":"3.6.5","repository_url":"https://github.com/dnsjava/dnsjava"},{"name":"org.junit.vintage:junit-vintage-engine","old_version":"6.0.3","new_version":"6.1.3","repository_url":"https://github.com/junit-team/junit-framework"},{"name":"io.kotest:kotest-assertions-core-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"io.kotest:kotest-runner-junit5-jvm","old_version":"6.1.11","new_version":"6.2.4","repository_url":"https://github.com/kotest/kotest"},{"name":"org.jetbrains.kotlinx:kotlinx-coroutines-android","old_version":"1.10.2","new_version":"1.11.0","repository_url":"https://github.com/Kotlin/kotlinx.coroutines"},{"name":"org.jetbrains.kotlinx:kotlinx-coroutines-test","old_version":"1.10.2","new_version":"1.11.0","repository_url":"https://github.com/Kotlin/kotlinx.coroutines"},{"name":"com.google.android.material:material","old_version":"1.13.0","new_version":"1.14.0","repository_url":"https://github.com/material-components/material-components-android"},{"name":"com.squareup.okhttp3:mockwebserver","old_version":"5.3.2","new_version":"5.4.0","repository_url":"https://github.com/square/okhttp"},{"name":"com.squareup.okhttp3:okhttp","old_version":"5.3.2","new_version":"5.4.0","repository_url":"https://github.com/square/okhttp"},{"name":"com.android.application","old_version":"9.2.0","new_version":"9.3.1"},{"name":"com.android.test","old_version":"9.2.0","new_version":"9.3.1"},{"name":"org.jetbrains.kotlin.plugin.compose","old_version":"2.3.21","new_version":"2.4.10","repository_url":"https://github.com/JetBrains/kotlin"},{"name":"org.jetbrains.kotlin.plugin.serialization","old_version":"2.3.21","new_version":"2.4.10","repository_url":"https://github.com/JetBrains/kotlin"}],"path":null,"ecosystem":"maven"},"body":"Bumps the android-deps group with 23 updates in the /apps/android directory:\n\n| Package | From | To |\n| --- | --- | --- |\n| [gradle-wrapper](https://github.com/gradle/gradle) | `9.4.1` | `9.7.0` |\n| androidx.compose:compose-bom | `2026.04.01` | `2026.08.00` |\n| androidx.core:core-ktx | `1.18.0` | `1.19.0` |\n| androidx.webkit:webkit | `1.15.0` | `1.17.0` |\n| [org.bouncycastle:bcprov-jdk18on](https://github.com/bcgit/bc-java) | `1.84` | `1.85.2` |\n| [org.commonmark:commonmark](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-autolink](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-strikethrough](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-gfm-tables](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [org.commonmark:commonmark-ext-task-list-items](https://github.com/commonmark/commonmark-java) | `0.28.0` | `0.30.0` |\n| [dnsjava:dnsjava](https://github.com/dnsjava/dnsjava) | `3.6.4` | `3.6.5` |\n| [org.junit.vintage:junit-vintage-engine](https://github.com/junit-team/junit-framework) | `6.0.3` | `6.1.3` |\n| [io.kotest:kotest-assertions-core-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [io.kotest:kotest-runner-junit5-jvm](https://github.com/kotest/kotest) | `6.1.11` | `6.2.4` |\n| [org.jetbrains.kotlinx:kotlinx-coroutines-android](https://github.com/Kotlin/kotlinx.coroutines) | `1.10.2` | `1.11.0` |\n| [org.jetbrains.kotlinx:kotlinx-coroutines-test](https://github.com/Kotlin/kotlinx.coroutines) | `1.10.2` | `1.11.0` |\n| [com.google.android.material:material](https://github.com/material-components/material-components-android) | `1.13.0` | `1.14.0` |\n| [com.squareup.okhttp3:mockwebserver](https://github.com/square/okhttp) | `5.3.2` | `5.4.0` |\n| [com.squareup.okhttp3:okhttp](https://github.com/square/okhttp) | `5.3.2` | `5.4.0` |\n| com.android.application | `9.2.0` | `9.3.1` |\n| com.android.test | `9.2.0` | `9.3.1` |\n| [org.jetbrains.kotlin.plugin.compose](https://github.com/JetBrains/kotlin) | `2.3.21` | `2.4.10` |\n| [org.jetbrains.kotlin.plugin.serialization](https://github.com/JetBrains/kotlin) | `2.3.21` | `2.4.10` |\n\n\nUpdates `gradle-wrapper` from 9.4.1 to 9.7.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/gradle/gradle/releases\"\u003egradle-wrapper's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e9.7.0\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.0.\u003c/p\u003e\n\u003cp\u003eHere are the highlights of this release:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIsolated Projects graduates to incubating\u003c/li\u003e\n\u003cli\u003eBroader Configuration Cache compatibility\u003c/li\u003e\n\u003cli\u003eMore source locations in problem reports\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003ca href=\"https://docs.gradle.org/9.7.0/release-notes.html\"\u003eRead the Release Notes\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eWe would like to thank the following community members for their contributions to this release of Gradle:\n\u003ca href=\"https://github.com/aSemy\"\u003eAdam\u003c/a\u003e,\n\u003ca href=\"https://github.com/Gautam-aman\"\u003eAman Gautam\u003c/a\u003e,\n\u003ca href=\"https://github.com/YukiCodepth\"\u003eAman Kumar\u003c/a\u003e,\n\u003ca href=\"https://github.com/adubrouski\"\u003eAnton Dubrouski\u003c/a\u003e,\n\u003ca href=\"https://github.com/liutikas\"\u003eAurimas\u003c/a\u003e,\n\u003ca href=\"https://github.com/gbhavya07\"\u003egbhavya07\u003c/a\u003e,\n\u003ca href=\"https://github.com/joshfriend\"\u003eJosh Friend\u003c/a\u003e,\n\u003ca href=\"https://github.com/nicklauslittle-gov\"\u003enicklauslittle-gov\u003c/a\u003e,\n\u003ca href=\"https://github.com/psoni674\"\u003ePragati\u003c/a\u003e,\n\u003ca href=\"https://github.com/Project516\"\u003eproject516\u003c/a\u003e,\n\u003ca href=\"https://github.com/Uomocapra\"\u003eQin Mi\u003c/a\u003e,\n\u003ca href=\"https://github.com/rkdfx\"\u003eRavi\u003c/a\u003e,\n\u003ca href=\"https://github.com/sk-reddy17\"\u003esk-reddy17\u003c/a\u003e,\n\u003ca href=\"https://github.com/Suvrat1629\"\u003eSuvrat Acharya\u003c/a\u003e,\n\u003ca href=\"https://github.com/ShreckYe\"\u003eYongshun Ye\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eUpgrade instructions\u003c/h2\u003e\n\u003cp\u003eSwitch your build to use Gradle 9.7.0 by updating your wrapper:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e./gradlew :wrapper --gradle-version=9.7.0 \u0026amp;\u0026amp; ./gradlew :wrapper\r\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eSee the Gradle \u003ca href=\"https://docs.gradle.org/9.7.0/userguide/upgrading_version_9.html\"\u003e9.x upgrade guide\u003c/a\u003e to learn about deprecations, breaking changes and other considerations when upgrading.\u003c/p\u003e\n\u003cp\u003eFor Java, Groovy, Kotlin and Android compatibility, see the \u003ca href=\"https://docs.gradle.org/9.7.0/userguide/compatibility.html\"\u003efull compatibility notes\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eReporting problems\u003c/h2\u003e\n\u003cp\u003eIf you find a problem with this release, please file a bug on \u003ca href=\"https://github.com/gradle/gradle/issues\"\u003eGitHub Issues\u003c/a\u003e adhering to our issue guidelines.\nIf you're not sure you're encountering a bug, please use the \u003ca href=\"https://discuss.gradle.org/c/help-discuss\"\u003eforum\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eWe hope you will build happiness with Gradle, and we look forward to your feedback via \u003ca href=\"https://twitter.com/gradle\"\u003eTwitter\u003c/a\u003e or on \u003ca href=\"https://github.com/gradle\"\u003eGitHub\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003e9.7.0 RC3\u003c/h2\u003e\n\u003cp\u003eThe Gradle team is excited to announce Gradle 9.7.0 RC3.\u003c/p\u003e\n\u003cp\u003eHere are the highlights of this release:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIsolated Projects graduates to incubating\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/3defbfc59d757b873d787b2261de5c7f8a00970a\"\u003e\u003ccode\u003e3defbfc\u003c/code\u003e\u003c/a\u003e make DistributionIntegrationSpec more permissive for releases (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38766\"\u003e#38766\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/f176043d6416ca85dab736b6e7581d1f0018ee8e\"\u003e\u003ccode\u003ef176043\u003c/code\u003e\u003c/a\u003e make DistributionIntegrationSpec more permissive for releases\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/b0828dad52cf99112e2071fb10547c0d2293a51b\"\u003e\u003ccode\u003eb0828da\u003c/code\u003e\u003c/a\u003e Prepare release notes for Gradle 9.7.0GA (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38756\"\u003e#38756\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/064b6d6161b55f531be7710d68efe4404b48558a\"\u003e\u003ccode\u003e064b6d6\u003c/code\u003e\u003c/a\u003e cleanup\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/dfe7bdcc464152313992f49b6ea3846d7c0119ed\"\u003e\u003ccode\u003edfe7bdc\u003c/code\u003e\u003c/a\u003e add new training to release notes\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/756196837a985dd030d596411852b99c43d6880e\"\u003e\u003ccode\u003e7561968\u003c/code\u003e\u003c/a\u003e add release notes for 37801\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/68a1f351d3ba32e09523e5d67949cea326c0d781\"\u003e\u003ccode\u003e68a1f35\u003c/code\u003e\u003c/a\u003e cherrypick 38367 to release\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/a462c95ca92b7a5cc55172a42608fcab5fd43b4c\"\u003e\u003ccode\u003ea462c95\u003c/code\u003e\u003c/a\u003e Rebalance AllVersionsCrossVersion buckets for agents without TestDistribution...\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/820e2b14ad6b0f64a1a042dcfb43ea7e3e8f7ada\"\u003e\u003ccode\u003e820e2b1\u003c/code\u003e\u003c/a\u003e Update Gradle wrapper to version 9.7.0-rc-3 (\u003ca href=\"https://redirect.github.com/gradle/gradle/issues/38743\"\u003e#38743\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/gradle/gradle/commit/75ea3d7671b4c52daf3fd26d0824b8fa7c752181\"\u003e\u003ccode\u003e75ea3d7\u003c/code\u003e\u003c/a\u003e Update Gradle wrapper to version 9.7.0-rc-3\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/gradle/gradle/compare/v9.4.1...v9.7.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `androidx.compose:compose-bom` from 2026.04.01 to 2026.08.00\n\nUpdates `androidx.core:core-ktx` from 1.18.0 to 1.19.0\n\nUpdates `androidx.webkit:webkit` from 1.15.0 to 1.17.0\n\nUpdates `org.bouncycastle:bcprov-jdk18on` from 1.84 to 1.85.2\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.html\"\u003eorg.bouncycastle:bcprov-jdk18on's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003eSee full diff in \u003ca href=\"https://github.com/bcgit/bc-java/commits\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003ecommonmark-java 0.29.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e[0.29.0] - 2026-06-20\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/42b4fb7adfe288ef13e9e27ab20aff7e91b0ab9d\"\u003e\u003ccode\u003e42b4fb7\u003c/code\u003e\u003c/a\u003e Prepare CHANGELOG for version 0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/b76e09d7a8362abb5f04e1d6b91dbd6da279a6fc\"\u003e\u003ccode\u003eb76e09d\u003c/code\u003e\u003c/a\u003e Limit how deep inline nodes may nest by default (100)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/49f65cb5cbec93cff713179990307145198e7061\"\u003e\u003ccode\u003e49f65cb\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing deeply nested emphasis\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/610f84b83e68c381e8f784ae4d044c80e1948b67\"\u003e\u003ccode\u003e610f84b\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological autolink email addresses\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/9f1d73897a56cbd74c39347af351a473e70297e1\"\u003e\u003ccode\u003e9f1d738\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological HTML block attributes\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/e13297e849995fdd582a85841067bff1d9c35ee5\"\u003e\u003ccode\u003ee13297e\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing pathological backticks\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/89d1bd3fa1524e8217ed61db5e8116c82434470f\"\u003e\u003ccode\u003e89d1bd3\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing with lots of \u003ccode\u003e\u0026lt;\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/commonmark/commonmark-java/compare/commonmark-parent-0.28.0...commonmark-parent-0.30.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark-ext-autolink` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark-ext-autolink's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003ecommonmark-java 0.29.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark-ext-autolink's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e[0.29.0] - 2026-06-20\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/42b4fb7adfe288ef13e9e27ab20aff7e91b0ab9d\"\u003e\u003ccode\u003e42b4fb7\u003c/code\u003e\u003c/a\u003e Prepare CHANGELOG for version 0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/b76e09d7a8362abb5f04e1d6b91dbd6da279a6fc\"\u003e\u003ccode\u003eb76e09d\u003c/code\u003e\u003c/a\u003e Limit how deep inline nodes may nest by default (100)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/49f65cb5cbec93cff713179990307145198e7061\"\u003e\u003ccode\u003e49f65cb\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing deeply nested emphasis\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/610f84b83e68c381e8f784ae4d044c80e1948b67\"\u003e\u003ccode\u003e610f84b\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological autolink email addresses\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/9f1d73897a56cbd74c39347af351a473e70297e1\"\u003e\u003ccode\u003e9f1d738\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological HTML block attributes\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/e13297e849995fdd582a85841067bff1d9c35ee5\"\u003e\u003ccode\u003ee13297e\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing pathological backticks\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/89d1bd3fa1524e8217ed61db5e8116c82434470f\"\u003e\u003ccode\u003e89d1bd3\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing with lots of \u003ccode\u003e\u0026lt;\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/commonmark/commonmark-java/compare/commonmark-parent-0.28.0...commonmark-parent-0.30.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark-ext-gfm-strikethrough` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark-ext-gfm-strikethrough's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003ecommonmark-java 0.29.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark-ext-gfm-strikethrough's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e[0.29.0] - 2026-06-20\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/42b4fb7adfe288ef13e9e27ab20aff7e91b0ab9d\"\u003e\u003ccode\u003e42b4fb7\u003c/code\u003e\u003c/a\u003e Prepare CHANGELOG for version 0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/b76e09d7a8362abb5f04e1d6b91dbd6da279a6fc\"\u003e\u003ccode\u003eb76e09d\u003c/code\u003e\u003c/a\u003e Limit how deep inline nodes may nest by default (100)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/49f65cb5cbec93cff713179990307145198e7061\"\u003e\u003ccode\u003e49f65cb\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing deeply nested emphasis\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/610f84b83e68c381e8f784ae4d044c80e1948b67\"\u003e\u003ccode\u003e610f84b\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological autolink email addresses\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/9f1d73897a56cbd74c39347af351a473e70297e1\"\u003e\u003ccode\u003e9f1d738\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological HTML block attributes\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/e13297e849995fdd582a85841067bff1d9c35ee5\"\u003e\u003ccode\u003ee13297e\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing pathological backticks\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/89d1bd3fa1524e8217ed61db5e8116c82434470f\"\u003e\u003ccode\u003e89d1bd3\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing with lots of \u003ccode\u003e\u0026lt;\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/commonmark/commonmark-java/compare/commonmark-parent-0.28.0...commonmark-parent-0.30.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark-ext-gfm-tables` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark-ext-gfm-tables's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003ecommonmark-java 0.29.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark-ext-gfm-tables's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e[0.29.0] - 2026-06-20\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/42b4fb7adfe288ef13e9e27ab20aff7e91b0ab9d\"\u003e\u003ccode\u003e42b4fb7\u003c/code\u003e\u003c/a\u003e Prepare CHANGELOG for version 0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/b76e09d7a8362abb5f04e1d6b91dbd6da279a6fc\"\u003e\u003ccode\u003eb76e09d\u003c/code\u003e\u003c/a\u003e Limit how deep inline nodes may nest by default (100)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/49f65cb5cbec93cff713179990307145198e7061\"\u003e\u003ccode\u003e49f65cb\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing deeply nested emphasis\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/610f84b83e68c381e8f784ae4d044c80e1948b67\"\u003e\u003ccode\u003e610f84b\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological autolink email addresses\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/9f1d73897a56cbd74c39347af351a473e70297e1\"\u003e\u003ccode\u003e9f1d738\u003c/code\u003e\u003c/a\u003e Fix StackOverflowError when parsing pathological HTML block attributes\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/e13297e849995fdd582a85841067bff1d9c35ee5\"\u003e\u003ccode\u003ee13297e\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing pathological backticks\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/89d1bd3fa1524e8217ed61db5e8116c82434470f\"\u003e\u003ccode\u003e89d1bd3\u003c/code\u003e\u003c/a\u003e Fix quadratic runtime when parsing with lots of \u003ccode\u003e\u0026lt;\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca href=\"https://github.com/commonmark/commonmark-java/compare/commonmark-parent-0.28.0...commonmark-parent-0.30.0\"\u003ecompare view\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\nUpdates `org.commonmark:commonmark-ext-task-list-items` from 0.28.0 to 0.30.0\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/releases\"\u003eorg.commonmark:commonmark-ext-task-list-items's releases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ecommonmark-java 0.30.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/HEAD/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003ecommonmark-java 0.29.0\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/HEAD/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/CHANGELOG.md\"\u003eorg.commonmark:commonmark-ext-task-list-items's changelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e[0.30.0] - 2026-08-06\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNew option \u003ccode\u003elineSeparator\u003c/code\u003e for \u003ccode\u003eMarkdownRenderer.Builder\u003c/code\u003e to change the default line\nseparator from \u003ccode\u003e\\n\u003c/code\u003e (e.g. to \u003ccode\u003e\\r\\n\u003c/code\u003e) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/442\"\u003e#442\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Support extracting the raw YAML content so that you can\ndo the YAML parsing using a library (instead of the limited built-in parsing) (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/391\"\u003e#391\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTables extension: Limit max number of parsed table cells by default (1 million cells),\nsee option \u003ccode\u003emaxCells\u003c/code\u003e in \u003ccode\u003eTablesExtension.Builder\u003c/code\u003e. Parsing will throw an error if the\nlimit would be exceeded, to protect against malicious input.\u003c/li\u003e\n\u003cli\u003eThe default for \u003ccode\u003emaxOpenBlockParsers\u003c/code\u003e for \u003ccode\u003eParser.Builder\u003c/code\u003e is now 100; configure the\noption to remove the limit.\u003c/li\u003e\n\u003cli\u003eLimit how deeply inline nodes may nest by default (100), see option \u003ccode\u003emaxInlineNesting\u003c/code\u003e in\n\u003ccode\u003eParser.Builder\u003c/code\u003e; configure the option to remove the limit. This covers emphasis-like\ndelimiters (e.g. \u003ccode\u003e*\u003c/code\u003e or the ins extension's \u003ccode\u003e+\u003c/code\u003e) as well as images, which can otherwise\nnest arbitrarily deep for a small amount of input. Anything over the limit is treated as\nplain text instead.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix quadratic runtime on various pathological inputs (where inline syntax to start a\nnode is used repeatedly but never finished):\n\u003cul\u003e\n\u003cli\u003eInline HTML like \u003ccode\u003e\u0026quot;x \u0026lt;!--\u0026quot;.repeat(100_000)\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/447\"\u003e#447\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutolink starts like \u003ccode\u003e\u0026quot;\u0026lt;\u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEmphasis like \u003ccode\u003e\u0026quot;a**b\u0026quot; + \u0026quot;c* \u0026quot;.repeat(100_000)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackticks runs of different lengths\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow errors when parsing pathological inputs with repeated syntax:\n\u003cul\u003e\n\u003cli\u003eHTML block attributes\u003c/li\u003e\n\u003cli\u003eAutolink email addresses\u003c/li\u003e\n\u003cli\u003eDeeply nested emphasis\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eFix stack overflow error when rendering/visiting deeply nested inline nodes, by capping nesting\ndepth during parsing (see \u003ccode\u003emaxInlineNesting\u003c/code\u003e above). This can happen with emphasis, e.g.\n\u003ccode\u003e\u0026quot;*\u0026quot;.repeat(n) + \u0026quot;x\u0026quot; + \u0026quot;*\u0026quot;.repeat(n)\u003c/code\u003e or \u003ccode\u003e\u0026quot;*a \u0026quot;.repeat(n) + \u0026quot; b*\u0026quot;.repeat(n)\u003c/code\u003e, as well as with\nimages, e.g. \u003ccode\u003e\u0026quot;![\u0026quot;.repeat(https://github.com/commonmark/commonmark-java/blob/main/n) + \u0026quot;x\u0026quot; + \u0026quot;](u)\u0026quot;.repeat(n)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eYAML front matter extension: Fix inefficient string concatenation for literal-block values (\u003ccode\u003e|\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2\u003e[0.29.0] - 2026-06-20\u003c/h2\u003e\n\u003ch3\u003eAdded\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSupport rendering GFM task list items to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/433\"\u003e#433\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eSupport rendering YAML front matter to Markdown (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/434\"\u003e#434\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAlerts\n\u003cul\u003e\n\u003cli\u003eAllow customizing HTML attributes for alert title \u003ccode\u003e\u0026lt;p\u0026gt;\u003c/code\u003e tag via \u003ccode\u003eAttributeProvider\u003c/code\u003e (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/427\"\u003e#427\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow authors to provide custom\ntitles per alert. See the\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#custom-alert-titles\"\u003ecustom titles section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow alerts to be nested within\nother blocks (including other alerts). See\n\u003ca href=\"https://github.com/commonmark/commonmark-java/blob/main/commonmark-ext-gfm-alerts/README.md#nesting-alerts\"\u003ethis section of the alerts README\u003c/a\u003e\nfor more information. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/430\"\u003e#430\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eNew configuration for \u003ccode\u003eAlertsExtension\u003c/code\u003e to allow the set of alert types\n(including standard GFM types) to be completely overwritten. (\u003ca href=\"https://redirect.github.com/commonmark/commonmark-java/issues/435\"\u003e#435\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/64037cf982f2b12a4a2fa1c5a75c6d3f4ab979bf\"\u003e\u003ccode\u003e64037cf\u003c/code\u003e\u003c/a\u003e [maven-release-plugin] prepare release commonmark-parent-0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/bd3e06669fd168874721267e7e5f5bd1d3433466\"\u003e\u003ccode\u003ebd3e066\u003c/code\u003e\u003c/a\u003e Fix Javadoc\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/4aaf754cc90b4a5a62647a8fc621185c934f8bbf\"\u003e\u003ccode\u003e4aaf754\u003c/code\u003e\u003c/a\u003e mvn versions:set -DnewVersion=0.30.0-SNAPSHOT\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/42b4fb7adfe288ef13e9e27ab20aff7e91b0ab9d\"\u003e\u003ccode\u003e42b4fb7\u003c/code\u003e\u003c/a\u003e Prepare CHANGELOG for version 0.30.0\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/b76e09d7a8362abb5f04e1d6b91dbd6da279a6fc\"\u003e\u003ccode\u003eb76e09d\u003c/code\u003e\u003c/a\u003e Limit how deep inline nodes may nest by default (100)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/commonmark/commonmark-java/commit/49f65cb5cbec93cff713179990307145198e706...\n\n_Description has been truncated_","html_url":"https://github.com/wang1314-coder/openclaw/pull/38","url":"https://dependabot.ecosyste.ms/api/v1/hosts/GitHub/repositories/wang1314-coder%2Fopenclaw/issues/38","packages_url":"https://dependabot.ecosyste.ms/api/v1/issues/38/packages"}}]}