File Formats and Protocols
In brief: Archive files, images, executables, certificates and network messages often contain a date written into a fixed-size slot. If that slot holds a 32-bit count of seconds since 1970, it runs out in 2038 (if the number is "signed") or 2106 (if "unsigned"). Some formats were designed with room to spare; others were patched with extension fields. Even where the format is fine, a program that copies the date into a 32-bit variable will still break, so both the format and the code that reads it matter.
| Risk level | Medium |
| Status | Most formats have a 2038-safe variant (pax tar, ZIP NTFS extra field, GeneralizedTime); several widely used fields are 32-bit unsigned and expire in 2106; reader/writer code on 32-bit time_t remains the main 2038 risk |
| Last reviewed | 2026-10-21 |
2038 status at a glance
- At risk ConfirmedIEC 61850 Edition 1 (substation automation)SecondSinceEpoch is a signed 32-bit INT32 in Edition 1.Do: Move to Edition 2, which uses unsigned INT32U and reaches 2106.
- At risk Confirmedcpio old binary formatThis format uses a 32-bit mtime, ending in 2038 or 2106 depending on signedness.Do: Use newc, odc or pax formats.
- At risk ConfirmedZIP extended-timestamp field (0x5455)This field uses 4-byte signed Unix times.Do: Write the NTFS extra field (0x000a), which has 64-bit times.
- Dependscpio newc (initramfs), MIT krb5 API timestampsThese are 32-bit fields. They are fine to 2106 when read as unsigned, but break in 2038 if code treats them as signed.Do: Check readers treat the field as unsigned. For krb5, cast with (time_t)(uint32_t) as MIT documents.
- DependsDNSSEC signatures and JWT tokensDNSSEC uses uint32 with serial arithmetic (a ±68-year window), and JWT numbers are bounded only by the parser.Do: Use RFC 1982 comparisons and 64-bit parsing.
Not affected or different deadline (3), and why
- Different deadlinegzip MTIME, PE/COFF TimeDateStamp, TLS 1.2 gmt_unix_timeThese are unsigned 32-bit seconds. They are informational, and they wrap in 2106.Do: Treat them as opaque or unsigned.
- Different deadlineSNMP sysUpTimeA 32-bit count of hundredths of a second, which wraps about every 497 days. This is a recurring uptime wrap, not a calendar limit.Do: Handle the wrap in monitoring tools.
- Not affectedtar (pax and ustar), Kerberos wire format, X.509 encoding, DNP3, PNGThese use text or wide fields. pax is unbounded, ustar lasts to 2242, X.509 and Kerberos use GeneralizedTime to 9999, and DNP3 counts milliseconds since 1970 far into the future.
Overview
Formats and protocols outlive the systems that create them. A tar archive written today may be restored in 2050; a certificate issued today may be valid until 2045; a protocol frozen in the 1990s is still on the wire. Three questions decide the risk for each format:
- Width and signedness of the field: signed 32-bit → 2038-01-19 03:14:07 UTC; unsigned 32-bit → 2106-02-07 06:28:15 UTC; 33-bit (11 octal digits) → 2242.
- Whether the specification defines a wider alternative (pax headers,
GeneralizedTime, the ZIP NTFS extra field). - How implementations convert the field. A 2106-safe unsigned field read into a signed 32-bit
time_tfails in 2038, and a 64-bit format field written by software that clamps to 32 bits is effectively 2038-limited.
The ITU-T 2038-class technical paper notes that protocol failures range from "fixed-width timestamp fields in networking protocol definitions, to variable-length encoding systems that have maximum-length constraints", and that resilient systems "must expect that external systems may transmit non-conformant temporal values" [1].
Technical details
Archive and compression formats
- tar (ustar). Times are stored as octal text in a 12-byte field. GNU tar documents that in ustar "File timestamps must nonnegative integers less than 2^33 seconds since the Epoch", i.e. about 1970–2242 [2]. No dates before 1970 can be stored.
- tar (GNU and pax). The GNU format lists no date limit [2]. The POSIX pax format "does not impose arbitrary restrictions on file sizes, file timestamp range or resolution", using extended-header records such as
mtime=[2]. Use--format=posix(pax) for long-term archives. - cpio. The old binary format stores times as 32-bit integers; the portable ASCII (odc) format uses 11-character octal fields; the "new ASCII" (newc/SVR4) format "uses 8-byte hexadecimal fields for all numbers" [3]. An 8-hex-digit
c_mtimeholds 32 bits: 2106 if read as unsigned, 2038 if read as signed. newc is used for Linux initramfs images. - ZIP. The core header stores the modification time in MS-DOS date/time format: 7-bit year from 1980, 2-second resolution, local time, valid to 2107 (the same encoding as FAT; see File-Systems) [4]. Extra fields add Unix or Windows time:
- gzip.
MTIMEis a 4-byte field: "seconds since 00:00:00 GMT, Jan. 1, 1970", withMTIME = 0meaning no timestamp [6]. As an unsigned value it lasts to 2106. Many tools write 0 for reproducibility.
Images and executables
- PNG
tIME. "Year: 2 bytes (complete; for example, 1995, not 95)", then one byte each for month, day, hour, minute, second [7]. Year range to 65535. Safe. - ELF. The ELF header (
e_ident,e_type, …e_shstrndx) has no timestamp field [8]. Safe at the format level. - PE/COFF. The COFF header
TimeDateStamp(4 bytes) is "the low 32 bits of the number of seconds since 00:00 January 1, 1970 (a C run-time time_t value)" [9]. Values 0 and 0xFFFFFFFF are not meaningful, and reproducible builds (IMAGE_DEBUG_TYPE_REPRO) store a non-time value [9]. Being "low 32 bits", the field wraps (2106 if read unsigned); tools that display or compare it as a signed date are the risk.
Security protocols
- X.509 (RFC 5280). Validity dates through 2049 are
UTCTime(two-digit year: YY ≥ 50 → 19YY, YY < 50 → 20YY); dates in 2050 or later "MUST be encoded as GeneralizedTime"; "no expiration" is99991231235959Z[10]. The format is safe; conversion to 32-bittime_tis not. See Devices-Networking-and-IoT for real failures in OpenSSL, GnuTLS and Tor. - Kerberos. On the wire,
KerberosTime ::= GeneralizedTime -- with no fractional seconds, in UTC ("Z") [11]. In the MIT krb5 API,krb5_timestampis a signed 32-bit integer; MIT recommends converting with(time_t)(uint32_t)timestamp, which works until February 2106 on platforms with 64-bittime_t. GSSAPI callers need no changes from MIT krb5 1.16 onward [12]. - TLS. TLS 1.2's
Randombegins withuint32 gmt_unix_time("standard UNIX 32-bit format"), but "Clocks are not required to be set correctly by the basic TLS protocol" [13]. TLS 1.3 uses 32 random bytes [14]. The real TLS 2038 risk is certificate validation (above). - DNSSEC RRSIG. Signature Expiration and Inception are 32-bit unsigned seconds since 1970. Comparisons "MUST use 'Serial number arithmetic', as defined in [RFC1982]", so values can refer to dates no more than 68 years in the past or future, and the field wraps every ~136 years [15]. Correct implementations do not fail in 2038 or 2106; implementations that compare as plain integers or convert to signed 32-bit
time_tdo. - JWT.
exp,nbfandiatareNumericDate: "A JSON numeric value representing the number of seconds from 1970-01-01T00:00:00Z UTC", and "non-integer values can be represented" [16]. The format has no width limit; the risk is libraries or databases that parse claims into 32-bit integers (general guidance, no specific CVE identified).
Time and management protocols
- NTP. 32-bit unsigned seconds since 1900, era rollover on 2036-02-07. See NTP-Era-2036.
- SNMP.
TimeTicks-basedsysUpTimereaches 2^32−1 after about 497 days and wraps, which "can lead to ambiguities in the value of TimeStamp objects"; theDateAndTimeconvention stores the year in 2 octets (0..65536) [17]. - Industrial protocols. IEC 61850 Edition 1 used a signed
INT32seconds field (2038), Edition 2 an unsignedINT32U(2106) [18]; DNP3 uses UTC milliseconds since 1970 [19]; Modbus has no standard time type. See Devices-Industrial-and-Infrastructure.
Affected versions / products
| Format / protocol | Field | Width / encoding | Overflow | Fix / safe variant |
|---|---|---|---|---|
| tar ustar | mtime |
12-byte octal (< 2^33) | 2242 [2] | pax (--format=posix) [2] |
| tar pax | mtime= record |
Decimal text, unbounded | None [2] | — |
| cpio old binary | c_mtime |
32-bit integer | 2038 or 2106 (signedness) [3] | newc/odc or pax |
| cpio odc | c_mtime |
11-char octal | 2242 [3] | — |
| cpio newc (initramfs) | c_mtime |
8-char hex = 32-bit | 2106 unsigned / 2038 signed [3] | Ensure readers treat as unsigned |
| ZIP core header | DOS date/time | 7-bit year from 1980 | 2107-12-31 [4] | Add NTFS extra field |
ZIP 0x5455 extended timestamp |
mtime/atime/ctime | 32-bit signed | 2038-01-19 [5] | 0x000a NTFS field |
ZIP 0x000a NTFS |
mtime/atime/ctime | 64-bit, 100 ns since 1601 | ~30828 [5] | — |
| gzip | MTIME |
4 bytes, Unix seconds | 2106 (unsigned) [6] | — (0 = none) |
| PNG | tIME |
2-byte year | 65535 [7] | — |
| ELF | — | no timestamp | n/a [8] | — |
| PE/COFF | TimeDateStamp |
low 32 bits of time_t |
2106 wrap [9] | Treat as opaque / unsigned |
| X.509 | notBefore/notAfter |
UTCTime ≤ 2049; GeneralizedTime ≥ 2050 | 9999 [10] | 64-bit time_t in validators |
| Kerberos (wire) | KerberosTime |
GeneralizedTime | 9999 [11] | — |
| MIT krb5 API | krb5_timestamp |
signed 32-bit | 2038; 2106 via uint32_t cast [12] |
Cast as documented |
| TLS 1.2 | gmt_unix_time |
uint32 | 2106 (no correctness requirement) [13] | TLS 1.3 random [14] |
| DNSSEC | RRSIG inception/expiration | uint32 + serial arithmetic | Wraps every ~136 years; ±68-year window [15] | Correct RFC 1982 comparison |
| JWT | exp/nbf/iat |
JSON number | None (implementation-bound) [16] | 64-bit parsing |
| NTP | timestamp seconds | uint32 since 1900 | 2036-02-07 | NTP-Era-2036 |
| SNMP | sysUpTime / DateAndTime |
32-bit ticks / 2-octet year | ~497-day wrap / 65536 [17] | Handle wrap |
| IEC 61850 | SecondSinceEpoch |
INT32 (Ed. 1) / INT32U (Ed. 2) | 2038 / 2106 [18] | Edition 2 |
| DNP3 | absolute time | UTC ms since 1970 | Far future [19] | — |
Risk & compliance notes
- Archives and backups: long-term archives and initramfs images should use formats with ≥ 2106 range; verify that restore tools on 32-bit systems handle post-2038 times.
- PKI: inventory certificates and CA roots expiring after 2038 that are validated by 32-bit clients.
- Protocol gateways: middleware that translates between protocols (for example DNP3 ↔ IEC 61850, or JSON ↔ binary) is a common place for 64→32-bit truncation [1].
- Owners: build/release engineering (archives, executables), PKI teams, network and OT protocol owners.
Detection & mitigation
-
Create test artefacts dated after 2038 and after 2106 and round-trip them through each tool:
sh touch -d '2040-01-01 UTC' f && tar --format=posix -cf t.tar f && tar -tvf t.tar touch -d '2040-01-01 UTC' f && zip t.zip f && unzip -l t.zip openssl req -x509 -newkey rsa:2048 -nodes -days 9000 -subj /CN=t -keyout k -out c && openssl x509 -in c -noout -enddate -
Fuzz parsers with boundary values: 0x7FFFFFFF, 0x80000000, 0xFFFFFFFF, and
UTCTime"491231235959Z" /GeneralizedTime"20500101000000Z". - Prefer pax tar, the ZIP NTFS extra field, and 64-bit
time_tbuilds of every parser. - See Testing-and-Detection and Remediation-Guide.
See also
- File-Systems · Databases
- Devices-Networking-and-IoT · Devices-Industrial-and-Infrastructure
- NTP-Era-2036 · GPS-Week-Rollover · Year-2106-and-Beyond
- Lang-C-and-CPP
References
- ITU-T Technical Paper XSTP.EPOCH, "Global coordination requirements for 2038-class rollover events" (liaison to IETF), 2026-07-21 — protocol-layer failure patterns.
- GNU tar manual: Controlling the Archive Format — GNU — ustar 2^33 limit; GNU and pax formats.
- cpio(5) — FreeBSD Manual Pages (libarchive) — old binary, odc and newc field widths.
- fs/fat/misc.c — Android common kernel (Linux FAT driver) — DOS date format: 7-bit year from 1980, max 2107.
- Info-ZIP extra field specification — libzip —
0x5455,0x5855,0x000afield definitions. - RFC 1952, GZIP file format specification 4.3 — IETF, 1996 —
MTIMEdefinition. - PNG Specification 1.2, Chunk Specifications — libpng.org —
tIME2-byte year. - elf(5) — Linux manual page, man7.org — ELF header fields (no timestamp).
- PE Format — Microsoft Learn — COFF
TimeDateStamp, 0/0xFFFFFFFF,IMAGE_DEBUG_TYPE_REPRO. - RFC 5280 §4.1.2.5 Validity — IETF, 2008 — UTCTime/GeneralizedTime and 2050 rule.
- RFC 4120 §5.2.3 KerberosTime — IETF, 2005 —
KerberosTime ::= GeneralizedTime. - Year 2038 considerations for uses of krb5_timestamp — MIT Kerberos 1.21 docs — signed 32-bit
krb5_timestamp;uint32_tcast to 2106; GSSAPI 1.16+. - RFC 5246 §7.4.1.2 — IETF, 2008 — TLS 1.2
gmt_unix_time. - RFC 8446 §4.1.2 — IETF, 2018 — TLS 1.3 random.
- RFC 4034 §3.1.5 — IETF, 2005 — RRSIG times, serial number arithmetic, 68/136 years.
- RFC 7519 §2 Terminology (NumericDate) — IETF, 2015 — JWT time claims.
- RFC 2579, Textual Conventions for SMIv2 — IETF, 1999 —
DateAndTimeandTimeStampwrap. - Karlheinz Schwarz, "IEC 61850 timestamp to overflow in 2038" — NettedAutomation blog, 2010-11-21 — Ed. 1 INT32 vs Ed. 2 INT32U.
- DNP3 driver documentation — Inductive Automation Ignition 8.3 — DNP3TIME, UTC ms since 1970.