Talk ∷ VulnOptiCON 2026

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 #

20370913024805Z

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_t ends
  • 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.

Server 2022 DC
Server 2025 DC
Password expires
Normal date — control
Normal date — control
Never expires
2037 “never” — control
2100 — the probe
  1. 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.
  2. Make sure the difference exists. Twin test users, identical except for password expiry, including their encryption settings. Confirm that msDS-UserPasswordExpiryTimeComputed is finite, and comfortably before January 2038, for the expiring one. It is pinned to “never” by DONT_EXPIRE_PASSWD, by SMARTCARD_REQUIRED, or by an unlimited effective maximum password age.
  3. 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 #

  1. What in your estate still uses 32-bit time_t?
  2. Where does your fix depend on code you can’t see?
  3. 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. #

  • 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.

Working together

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 →

Delivered: 2026-09-25 ∷ Published: 2026-10-01 ∷ TLP:CLEAR