[Bug 4004] New: `authorized_keys` `expiry-time=` keys keep authenticating one hour past expiry under DST

bugzilla-daemon at mindrot.org bugzilla-daemon at mindrot.org
Sat Sep 12 08:31:34 AEST 2026


https://bugzilla.mindrot.org/show_bug.cgi?id=4004

            Bug ID: 4004
           Summary: `authorized_keys` `expiry-time=` keys keep
                    authenticating one hour past expiry under DST
           Product: Portable OpenSSH
           Version: 10.5p1
          Hardware: Other
                OS: Other
            Status: NEW
          Severity: critical
          Priority: P5
         Component: sshd
          Assignee: unassigned-bugs at mindrot.org
          Reporter: khush2792001 at gmail.com

Expected behavior

An `authorized_keys` entry with `expiry-time="YYYYMMDDHHMMSS"` stops
authenticating once that moment has passed. A key whose expiry was 30
minutes
ago must be refused.

## Actual behavior

When the expiry timestamp falls inside the local timezone's DST period,
the key
keeps authenticating for **one hour past the configured expiry**. A key
that
expired 30 minutes ago still logs in successfully.

Same binary, same procedure, same "expired 30 minutes ago" input; only
`TZ`
varies (run 2026-08-25, northern-hemisphere summer):

Root cause

`auth-options.c` parses the option with the same helper as certificate
validity:

```c
} else if (opt_match(&opts, "expiry-time")) {
        ...
        if (parse_absolute_time(opt, &valid_before) != 0 ||
valid_before == 0) {
```

and `misc.c :: parse_absolute_time()` does `memset(&tm, 0, sizeof(tm))`
—
setting `tm_isdst = 0`, i.e. "DST not in effect" — then calls
`mktime()` without
ever setting `tm.tm_isdst = -1`. Every local timestamp is therefore
interpreted
as standard time, so a DST-period expiry resolves one hour late.

## Suggested fix

Identical to BUG-001 — one line in the non-UTC branch of
`parse_absolute_time()`:

```diff
+               tm.tm_isdst = -1;       /* let mktime() consult tzdata
for this date */
                tm.tm_wday = -1;
                if ((tt = mktime(&tm)) == -1 && tm.tm_wday == -1)
```


Impact

- Any deployment expiring access via `expiry-time=` grants an extra
hour beyond
  the stated deadline, for roughly half the year on DST-observing
hosts.
- **Fails open**: the error direction always favours continued access.
- **Silent**: no warning, and `sshd -T` does not surface per-key
options, so
  operators have nothing to compare against their intent.
- Automated offboarding that sets `expiry-time` to "now" leaves a
one-hour
  window in which the revoked key still works.

## Workaround

Run `sshd` with `TZ=UTC`, or remove the key outright rather than
relying on
`expiry-time` for time-critical revocation.

-- 
You are receiving this mail because:
You are watching the assignee of the bug.


More information about the openssh-bugs mailing list