diff --git a/bom/application/pom.xml b/bom/application/pom.xml
index 95a9a01bddd8a..0c1e097ac73ec 100644
--- a/bom/application/pom.xml
+++ b/bom/application/pom.xml
@@ -19,7 +19,7 @@
1.0.14
3.0.2
3.0.5
- 4.7.7.Final
+ 4.7.9.Final
0.33.0
0.2.4
0.1.15
@@ -138,14 +138,14 @@
14.0.6.Final
4.5.1.Final
3.1.1
- 4.1.94.Final
+ 4.1.100.Final
1.12.0
1.0.3
3.5.0.Final
1.9.0
3.3.2
1.8.0
- 1.1.10.1
+ 1.1.10.5
0.100.0
2.13.10
@@ -197,7 +197,7 @@
1.1.1.Final
2.19.0
1.3.0.Final
- 1.11.1
+ 1.11.3
2.3.1.Final
0.1.13.Final
0.8.8
diff --git a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcJsonWebTokenProducer.java b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcJsonWebTokenProducer.java
index 2bff1c56b660a..c55faa1012630 100644
--- a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcJsonWebTokenProducer.java
+++ b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcJsonWebTokenProducer.java
@@ -79,7 +79,9 @@ private JsonWebToken getTokenCredential(Class extends TokenCredential> type) {
return new OidcJwtCallerPrincipal(jwtClaims, credential);
}
String tokenType = type == AccessTokenCredential.class ? "access" : "ID";
- LOG.tracef("Current identity is not associated with an %s token", tokenType);
+ LOG.warnf(
+ "Identity is not associated with an %s token. Access 'JsonWebToken' with '@IdToken' qualifier if ID token is required and 'JsonWebToken' without this qualifier when JWT access token is required. Inject either 'io.quarkus.security.identity.SecurityIdentity' or 'io.quarkus.oidc.UserInfo' if you need to have the same endpoint code working for both authorization code and bearer token authentication flows.",
+ tokenType);
return new NullJsonWebToken();
}
}
diff --git a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/http2/Http2RSTFloodProtectionTest.java b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/http2/Http2RSTFloodProtectionTest.java
new file mode 100644
index 0000000000000..5d99d5cd6132b
--- /dev/null
+++ b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/http2/Http2RSTFloodProtectionTest.java
@@ -0,0 +1,109 @@
+package io.quarkus.vertx.http.http2;
+
+import static io.vertx.core.http.HttpMethod.GET;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import java.io.File;
+import java.net.URL;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.event.Observes;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Assumptions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+import io.quarkus.test.QuarkusUnitTest;
+import io.quarkus.test.common.http.TestHTTPResource;
+import io.quarkus.vertx.core.runtime.VertxCoreRecorder;
+import io.vertx.core.http.HttpClient;
+import io.vertx.core.http.HttpClientOptions;
+import io.vertx.core.http.HttpClientRequest;
+import io.vertx.core.http.HttpVersion;
+import io.vertx.core.net.JdkSSLEngineOptions;
+import io.vertx.ext.web.Router;
+
+/**
+ * Reproduce CVE-2023-44487.
+ */
+public class Http2RSTFloodProtectionTest {
+
+ @TestHTTPResource(value = "/ping", ssl = true)
+ URL sslUrl;
+
+ @TestHTTPResource(value = "/ping")
+ URL url;
+
+ @RegisterExtension
+ static final QuarkusUnitTest config = new QuarkusUnitTest()
+ .withApplicationRoot((jar) -> jar
+ .addClasses(MyBean.class)
+ .addAsResource(new File("src/test/resources/conf/ssl-jks.conf"), "application.properties")
+ .addAsResource(new File("src/test/resources/conf/server-keystore.jks"), "server-keystore.jks"));
+
+ @Test
+ void testRstFloodProtectionWithTlsEnabled() throws Exception {
+ Assumptions.assumeTrue(JdkSSLEngineOptions.isAlpnAvailable()); //don't run on JDK8
+ HttpClientOptions options = new HttpClientOptions()
+ .setUseAlpn(true)
+ .setProtocolVersion(HttpVersion.HTTP_2)
+ .setSsl(true)
+ .setTrustAll(true);
+
+ var client = VertxCoreRecorder.getVertx().get().createHttpClient(options);
+ int port = sslUrl.getPort();
+ run(client, port, false);
+ }
+
+ @Test
+ public void testRstFloodProtection() throws InterruptedException {
+ HttpClientOptions options = new HttpClientOptions()
+ .setProtocolVersion(HttpVersion.HTTP_2)
+ .setHttp2ClearTextUpgrade(true);
+ var client = VertxCoreRecorder.getVertx().get().createHttpClient(options);
+ run(client, url.getPort(), true);
+ }
+
+ void run(HttpClient client, int port, boolean plain) throws InterruptedException {
+ CountDownLatch latch = new CountDownLatch(1);
+ client.connectionHandler(conn -> {
+ conn.closeHandler(v -> {
+ latch.countDown();
+ });
+ conn.goAwayHandler(ga -> {
+ Assertions.assertEquals(11, ga.getErrorCode());
+ latch.countDown();
+ });
+ });
+
+ if (plain) {
+ // Emit a first request to establish a connection.
+ // It's HTTP/1 so, does not count in the number of requests.
+ client.request(GET, port, "localhost", "/ping")
+ .compose(HttpClientRequest::send);
+ }
+
+ for (int i = 0; i < 250; i++) { // must be higher thant the NEtty limit (200 / 30s)
+ client.request(GET, port, "localhost", "/ping")
+ .onSuccess(req -> req.end().onComplete(v -> req.reset()));
+ }
+
+ if (!latch.await(10, TimeUnit.SECONDS)) {
+ fail("RST flood protection failed");
+ }
+ }
+
+ @ApplicationScoped
+ public static class MyBean {
+
+ public void register(@Observes Router router) {
+ router.get("/ping").handler(rc -> {
+ // Do nothing.
+ });
+ }
+
+ }
+}