On the Mineshaft Gap
Coordinating the end of never.
VulnOptiCON (FIRST Technical Colloquium) ∷ Luxembourg ∷ ∷ Solo talk
For more than twenty years, Windows has written “never”
into Kerberos as a specific date: 13 September 2037, 02:48:05 UTC,
chosen to fit inside 32-bit Unix time.
Newer Windows moves it: Windows 11 22H2 clients stopped asking for tickets that end in 2037,
and Server 2025 domain controllers now tell clients that a password which never expires
expires in the year 2100.
That fits in an unsigned 32-bit counter, but it overflows a signed 32-bit time_t,
and downstream implementations have been discovering this one at a time, in production.
This talk follows that seam. It asks why a vendor running well-structured, well-publicised migrations for NTLM and RC4 has no equivalent machinery for this one, and it proposes a cheap, non-destructive way to look for post-2038 dependencies in your own estate today, without moving a single clock.
A correction first #
For about a year, I used Kerberos as my cleanest example of a protocol-level 2038 problem. Nobody corrected me. I was wrong about the layer.
KerberosTime is ASN.1 GeneralizedTime
(YYYYMMDDHHMMSSZ), not a 32-bit epoch counter
(RFC 4120).
The protocol is fine. The problems live where implementations translate that timestamp
into their own native representation of time. The coordination argument survived;
the mechanism I had been describing did not.
“Never” is a date #
Active Directory needed a finite way to say “never”. The value chosen was 13 September 2037, 02:48:05 UTC: safely inside 32-bit Unix time, for interoperability. Windows clients before Windows 11 22H2 still ask the KDC for tickets valid until that moment, as packet captures going back to 2004 show.
Native Windows time does not have a 2038 problem; its internal clock is 64-bit. But “never” in Windows Kerberos has had a 2037 boundary all along. A 2022 public report showed Server 2019 domain logon and Group Policy failing when a lab clock was set to that date, and Server 2022 reproduced it.
Moving “never” past 2038 #
“Never” travels in two different Kerberos fields, and Microsoft has moved both.
The first is the end time a client asks for in its ticket request:
Windows 11 22H2 changed it from 2037 to the year 9999.
The second is the key expiration a domain controller returns for accounts whose passwords never expire:
Server 2025 changed it from 2037 to 2100.
Two independent attempts to move “never” past 2038, with different values,
producing the same class of problem. Both land beyond what a signed 32-bit time_t can hold;
2100 at least sits below the unsigned 32-bit horizon of 2106.
- 2034Windows Server 2025 extended support ends
- Sep 2037The old “never” (pre-Server 2025, pre-Windows 11 22H2)
- Jan 2038Signed 32-bit
time_tends - 2100The new “never” (Server 2025 key expiration)
- 2106Unsigned 32-bit Unix seconds end
- 9999Windows 11 22H2 ticket requests
“For accounts with no password expiry, we moved the Kerberos expiry out to 2100, so that our products will continue working past 2037. But some devices do not handle dates properly past 2037.”
Michael Bernstein, Microsoft, Tech Community, 21 February 2025
The breakage arrived piecemeal #
- 2022–23 Heimdal #1011. Windows 11 22H2 clients trip Heimdal’s KDC. The maintainer warns that a year of 2100 “will still cause a failure”.
- Feb 2025 Cisco ISE. Integration with Server 2025 domain controllers fails decoding the 2100 value. The workaround in the support case: revert the DCs to Server 2022.
- Jul 2025 MIT krb5 list. 32-bit GSSAPI clients cannot authenticate to Server 2025.
- Mar 2026 MIT krb5 commit 7e0e602. “Cap decoding GeneralTime when time_t is 32-bit.” As of 22 September 2026: fixed upstream, not yet in the stable 1.22.2 release.
Everyone did the reasonable thing. Microsoft would not go back to 2037. Heimdal said 2100 would still break. Both were right, and the seam sat in public for two years until customers found it in production.
MIT’s fix clamps any date it cannot store on a 32-bit platform to the largest one it can: January 2038. Usually that is harmless, because 2038 is still far enough away to mean “never”. But MIT’s own code comment notes that clamping is not safe if the value is ever re-encoded, and the commit message reasons that 32-bit platforms are “increasingly rare”. That may be a sound engineering call. “Rare” depends on which part of the ecosystem you can see.
So where’s the mechanism? #
“…we all have to work together to handle the 32-bit date limit.”
Microsoft, Tech Community, 21 February 2025
Same week, same authentication ecosystem: one vendor’s support case blamed Microsoft and suggested rolling back the upgrade; Microsoft recommended that other vendors update their software. Both positions are locally defensible. Deferral is locally rational. The first mover’s cost lands downstream; the benefit is spread across everyone. So everyone downstream has a reason to wait, and nobody owns the handover.
The contrast is instructive. The same vendor is running at least three structured ecosystem migrations right now, each with roadmaps, tooling, dates and public messaging: NTLM, NTLMv1, and RC4 in Kerberos. For 2037 → 2100, at the time of the talk, I could find no dedicated roadmap, tooling, inventory guidance or staged migration.
Forum replies, yes. Machinery, no. A bug tracker isn’t a migration plan. #
The seam #
Exposure models tell us what is reachable. What this case made me realise is that exposure is not the whole operational problem. Once remediation begins, risk can migrate to the boundary between populations. The dangerous population may be neither the remediated set nor the unremediated set, but the gap between them.
Should coordinability be a term in an exposure model, or is it a property of the transition graph between populations? I don’t know yet. I think it is the right question.
2038 is a migration interval, not an instant
- 7 Feb 2036NTP era rollover
- 13 Sep 2037Windows’ historical “never”
- 19 Jan 2038Signed 32-bit
time_t - 20 Nov 2038GPS week-number rollover
…and those are merely some of the dates we can already name. The broader coordination case is developed in XSTP.epoch.
The mineshaft canary #
Don’t move the clock. Move “never”. #
The traditional Y2038 test is to roll clocks forward and see what breaks. That can break things badly. But Server 2025 already puts a post-2038 value into the authentication path, today, for principals whose passwords never expire. That is not a corner case. It covers the service accounts that middleware runs as and, on the evidence of the field reports, the computer accounts that every domain-joined appliance uses: the Cisco ISE failure was an AD-joined appliance meeting a Server 2025 DC. So use Windows as the signal generator, and treat everything else that consumes those timestamps as the test subject.
Screen widely: computer accounts
Take the non-Windows things that are joined to your domain and authenticate with their own machine accounts: NAC and VPN appliances, NAS and storage, Linux and Unix hosts joined with SSSD or Samba, middleware. Point each one at a Server 2022 DC, then at a Server 2025 DC, with the clock left at today. Works against 2022 and fails against 2025: you have a candidate. Add the service accounts in your estate that are set to “password never expires”; there are usually a lot of them.
Computer accounts are special. Windows domain members normally rotate their machine-account password
every 30 days by default (other domain members may behave differently),
but that is the member changing its own secret over Netlogon, not password expiry.
For expiry computation, Active Directory treats workstation and server trust accounts as non-expiring
by virtue of their account type, whether or not DONT_EXPIRE_PASSWD is set
(MS-ADTS, msDS-UserPasswordExpiryTimeComputed).
In practice, Server 2025 puts machine accounts into the 2100 case: a decrypted field report from January 2025
shows a 2025 DC returning a 2100 key expiration for a computer account where Server 2022 returned 2037
(R. Baldry, Tech Community).
Their account type also means there is no expiring control to compare against.
A machine-account screen can only say “something about Server 2025 broke this”,
and Server 2025 also changed NTLM and Kerberos crypto behaviour.
A candidate is not yet a finding.
Then confirm with user principals: the 2×2
To pin a candidate on the timestamp rather than on the rest of Server 2025’s hardening, you need an independent expiry axis. Ordinary user accounts give you one; machine trust accounts do not. Where the same client stack can authenticate ordinary user principals, vary exactly two things: the DC version and password expiry. Same client, same Kerberos path, same encryption type in every cell. Only one cell crosses 2038.
- Isolate it. One Server 2025 DC, plus a Server 2022 baseline, in a lab domain or a dedicated AD site. Pin the test clients to the KDC you mean to exercise, and prove which KDC answered. The risk is not the clock; it is ordinary clients landing on a 2025 DC by accident, which is how this was first found in production.
- Make sure the difference exists. Twin test users, identical except for
password expiry, including their encryption settings. Confirm that
msDS-UserPasswordExpiryTimeComputedis finite, and comfortably before January 2038, for the expiring one. It is pinned to “never” byDONT_EXPIRE_PASSWD, bySMARTCARD_REQUIRED, or by an unlimited effective maximum password age. - Prove it on the wire. Decrypt one AS-REP per cell, using a keytab for the test account loaded into Wireshark. Confirm that 2100 appears only in the probe cell, and that every run used Kerberos (not NTLM fallback) with the same encryption type.
Read the pattern, not the single result. Failing everywhere means you have no baseline yet. Failing in both Server 2025 cells points first at a generic Server 2025 change such as RC4 or NTLM. Succeeding everywhere except the probe cell, with the replies confirmed on the wire, strongly implicates the post-2038 timestamp.
If an appliance can only authenticate with its own machine account, the 2×2 cannot be run on that path, and the screen is as far as you can go: a strong candidate, not an isolated finding.
- FAIL in the probe cell only → a post-2038 dependency, reproducible today, against a supported platform, more than a decade early. Even a “wrong” failure, from RC4 or NTLM, is an authentication dependency you needed to know about.
- PASS → only that this path survived. The client may simply never read the expiry field. It says nothing about logs, schedulers, certificates, NTP or OT firmware. This is a tracer, not a survey, and not a Y2038-safe certification.
One dead canary is evidence. A pattern of them is a business case for a Y2038 programme.
This is a thought experiment: as of the talk, it has not yet been run. If you run it, I would like to hear what you find, pass or fail, via Proper Tools or the FIRST Time Security SIG.
Three questions to take back #
- What in your estate still uses 32-bit
time_t? - Where does your fix depend on code you can’t see?
- Who owns the seam between the old population and the new one?
The problem isn’t only the old systems or the new systems. It’s whether we can cross the distance between them before “never” arrives. That’s the mineshaft gap. #
Related work #
- XSTP.epoch — ITU-T SG17 Technical Paper on global coordination requirements for 2038-class rollover events.
- FIRST Time Security SIG — where much of this work is carried.
- IEEE P4150.
- Leverett & van der Ham-de Vos, Vulnerability Abundance — why vulnerabilities are effectively unbounded and exploits are not. This talk is about a part of the problem their model does not cover.
- CVSS v5 — the Consensus-Validated Suffering System. Contributions welcome.
Selected sources #
The full source list is on the final slide of the deck.
- RFC 4120, The Kerberos Network Authentication Service (V5).
- MIT Kerberos, “Year 2038 considerations for uses of krb5_timestamp”.
- MIT krb5 commit 7e0e602, “Cap decoding GeneralTime when time_t is 32-bit”, 23 March 2026.
- Heimdal issue #1011, “KDC: TGS-REQ problem with Windows 11 22H2 client”, 2022–23.
- M. Bernstein, Microsoft Tech Community, “Server 2025 Domain Join Error ASN.1”, 21 February 2025.
- R. Baldry, Microsoft Tech Community, replies of 15 January 2025 (fails only for accounts whose password never expires) and 16 January 2025 (decrypted AS-REP: 2100 from Server 2025, 2037 from Server 2022).
- [MS-ADTS],
msDS-UserPasswordExpiryTimeComputed. - A. Bouchez, “Impossible to log into a MS AD 2025 from a 32-bit GSSAPI system”, kerberos@mit.edu, July 2025.
- O. Hartong, FalconForce, “Detection engineering rabbit holes – parsing ASN.1 packets in KQL”.
- Microsoft, “Advancing Windows security: Disabling NTLM by default”, Windows IT Pro Blog, January 2026.
- Microsoft, “Beyond RC4 for Windows authentication”, Windows Server Blog, December 2025.
- Microsoft, “Detect and remediate RC4 usage in Kerberos”, Microsoft Learn.
- Microsoft Q&A, “Windows Server 2019 Date Issue: After setting the time to 13 Sep 2037…”, March 2022.
- Microsoft Q&A, “Server 2025 Domain Controllers – Trust relationship issues…” (Cisco case as posted by a customer), February 2025.
- EventHelix Kerberos packet decodes: 20 December 2004 (Windows Server 2003 domain) and 16 August 2005 (XP client).
- Microsoft Lifecycle, Windows Server 2025.
Important, not urgent, and slipping? #
This research is self-funded and independent. Alongside it, I take on a small number of client projects, usually the kind that matter but keep sliding down the backlog:
- Reviewing exposure across legacy, embedded, or time-dependent systems
- Designing or reviewing product-security dependency management processes
- Interpreting and preparing for standards, policy, or regulatory change, including the CRA
Fixed-scope projects or retainers, from Brussels, working internationally. For a private briefing on this material, or to run the canary with someone who has thought about it, get in touch →