picotls, as a TLS 1.3-only stack, determines the Hello version by `supported_versions`. `legacy_version` is checked after determining the TLS version
diff --git a/lib/picotls.c b/lib/picotls.c
index 1355ed7..519ef77 100644
--- a/lib/picotls.c
+++ b/lib/picotls.c
@@ -3620,8 +3620,8 @@
         0)
         goto Exit;
 
-    /* check if ClientHello makes sense */
-    if (!(ch.legacy_version == 0x0303 && is_supported_version(ch.selected_version))) {
+    /* bail out if CH cannot be handled as TLS 1.3, providing the application the raw CH and SNI, to help them fallback */
+    if (!is_supported_version(ch.selected_version)) {
         if (!is_second_flight && tls->ctx->on_client_hello != NULL) {
             ptls_on_client_hello_parameters_t params = {
                 .server_name = ch.server_name,
@@ -3635,6 +3635,15 @@
         ret = PTLS_ALERT_PROTOCOL_VERSION;
         goto Exit;
     }
+
+    /* Check TLS 1.3-specific constraints. Hereafter, we might exit without calling on_client_hello. That's fine because this CH is
+     * ought to be rejected. */
+    if (ch.legacy_version <= 0x0300) {
+        /* RFC 8446 Appendix D.5: any endpoint receiving a Hello message with legacy_version set to 0x0300 MUST abort the handshake
+         * with a "protocol_version" alert. */
+        ret = PTLS_ALERT_PROTOCOL_VERSION;
+        goto Exit;
+    }
     if (!(ch.compression_methods.count == 1 && ch.compression_methods.ids[0] == 0)) {
         ret = PTLS_ALERT_ILLEGAL_PARAMETER;
         goto Exit;