Enforce a TLS 1.3 floor in Java sources

Proprietary

Rewrites JSSE and BouncyCastle protocol configuration to a TLS 1.3 floor, so that JEP 527 hybrid key exchange — which exists for TLS 1.3 only — can negotiate. Covers SSLContext.getInstance algorithm literals, the setEnabledProtocols/setProtocols sinks including BCSSLParameters, same-file protocol array constants whose only readers are those sinks, the jdk.tls.client.protocols, jdk.tls.server.protocols and https.protocols system properties, and getSupportedVersions overrides on BouncyCastle TlsPeer subclasses. Surfaces that cannot be rewritten safely — an array constant shared with non-TLS code, or a Security.setProperty("jdk.tls.disabledAlgorithms", ...) call that replaces rather than extends the JDK default list — are marked and recorded as Report only rows instead of being changed. Protocol values that are not statically resolvable are left alone without a row: finding those is the discovery recipes' job, and reporting them here would duplicate their findings. Test sources are skipped by default, because a protocol test usually enables a legacy version on purpose in order to assert that it is refused. One shape deserves review before the diff is merged: a protocol list that was deliberately widened to work around a handshake failure against a legacy peer looks exactly like an unmaintained legacy floor, and narrowing it will re-break that peer. Every rewrite is recorded in the enforcement data table with its before and after protocols, and retainTls12In scopes the exception once such a site is identified.

io.moderne.cryptography.pqc.EnforceTls13Java

Optional

The protocol floor to enforce globally: TLSv1.3 (the default) strips TLSv1.2 from every enabled-protocols list, TLSv1.2 retains it everywhere. Use retainTls12In instead when only some modules need the exception. SSLContext.getInstance algorithm names are rewritten to TLSv1.3 under either setting, because the algorithm name is a ceiling: a TLSv1.2 context can never negotiate TLS 1.3, so a TLSv1.2 floor would otherwise be capped below the version it is meant to allow.

Globs naming the sources that keep TLSv1.2 in their rewritten protocol lists, matched against both the source path and the enclosing fully qualified class name. SSLv2Hello, SSLv3, TLSv1 and TLSv1.1 are still stripped inside a matched source, and TLSv1.3 is still ensured present — the exception is for partners stuck on TLS 1.2, not for keeping a legacy floor. Separate values with commas.

rewriteContextAlgorithmBoolean

Rewrite legacy SSLContext.getInstance algorithm literals — SSL, SSLv3, TLSv1, TLSv1.1, TLSv1.2, matched case-insensitively as JCA does — to TLSv1.3. On its own this is hygiene rather than enforcement, since the algorithm name only raises the ceiling; it is enforcement because this recipe rewrites the enabled-protocols lists in the same pass. Default true.

skipTestSourcesBoolean

Leave test sources alone. A protocol test very often enables a legacy version on purpose so it can assert that the version is refused, so rewriting it hardens nothing and deletes the coverage that proves the hardening works. Set to false to rewrite tests as well, which is only useful once the production code is already enforced. Default true.

strictAlgorithmNameBoolean

Also rewrite the version-flexible algorithm names TLS and Default to TLSv1.3. Off by default: those names already permit TLS 1.3, so changing them narrows what the JVM may negotiate without making anything post-quantum ready.

mod run . --recipe=io.moderne.cryptography.pqc.EnforceTls13Java

Install it once from Recipe actions, then run it on every repository under the current directory. New to the Moderne CLI? Set it up.