Volume XXII, number 279Tuesday, October 6, 2026Latest message 1 hour ago

The Git List

News and archive of git@vger.kernel.org, since April 2005

[BUG] ZIP timestamp conversion and strict fast-import date validation

4 messages between Oct 5, 2026 and Oct 6, 2026, from Matthew E. Luallen, René Scharfe, m@sph3r3.com.

Plain Markdown or JSON for tools and agents.

Matthew E. LuallenOct 5, 2026, 13:48 UTC on lore
Hello Git community,

I'm reporting three date-handling bugs reproduced on Apple Git 2.50.1 and upstream Git 2.56.0:

1. Exporting a 1972-dated commit with git archive --format=zip produces
   a legacy DOS date interpreted as 2100, while the extended Unix
   timestamp retains 1972.
2. Exporting a commit at epoch 4294967296 (2106-02-07 06:28:16 UTC)
   wraps ZIP's four-byte extended timestamp to zero (1970). Exporting
   the same commit as TAR preserves the original value.
3. git fast-import --date-format=raw accepts -32184000 +0000, but
   git fsck --strict then reports badDate and ISO rendering returns
   literal placeholders. This occurs in strict raw mode, not just
   the deliberately permissive import mode.
For the archive cases, export the dated commit with:
    git archive --format=zip <commit> > test.zip
    git archive --format=tar <commit> > test.tar

Compare the ZIP DOS and extended timestamp fields with the TAR mtime. The overflow affects consumer behavior: in macOS tests, UnZip update mode retained different existing 2025 content because the 2106 ZIP appeared older. An in-range 2038 ZIP replaced that content.

What range-handling policy should ZIP use, and should strict raw import reject timestamps that fsck considers invalid?

Thank you, Matthew E. Luallen (@meluallen) With research, reproduction, and drafting assistance from OpenAI Codex.

René ScharfeOct 5, 2026, 19:49 UTC in reply to Matthew E. Luallen on lore

Re: [BUG] ZIP timestamp conversion and strict fast-import date validation

On 10/5/26 3:48 PM, Matthew E. Luallen wrote:
Show 8 quoted lines
> Hello Git community,
> 
> I'm reporting three date-handling bugs reproduced on Apple Git 2.50.1
> and upstream Git 2.56.0:
> 
> 1. Exporting a 1972-dated commit with git archive --format=zip produces
>    a legacy DOS date interpreted as 2100, while the extended Unix
>    timestamp retains 1972.

DOS timestamps can express years starting from 1980. Unix timestamps start at 1970. We can't provide a DOS timestamp for 1972, but can we do better? zip(1) clamps DOS timestamps to zero = the DOS epoch = 1980-01-01 00:00:00.

Is anything using the DOS timestamp even though a Unix timestamp is present?

> 2. Exporting a commit at epoch 4294967296 (2106-02-07 06:28:16 UTC)
>    wraps ZIP's four-byte extended timestamp to zero (1970). Exporting
>    the same commit as TAR preserves the original value.

tar's timestamp can range from 1970 to 2242 with standard headers and beyond indefinitely with extended headers.

We cannot put a higher value than 4294967295 into the four-byte field provided by the Unix time extension for ZIP, but we could clamp to that value. zip(1) wraps around as well, though..

(I'm using "Zip 3.0 (July 5th 2008), by Info-ZIP, with modifications by Apple Inc.")

> 3. git fast-import --date-format=raw accepts -32184000 +0000, but
>    git fsck --strict then reports badDate and ISO rendering returns
>    literal placeholders. This occurs in strict raw mode, not just
>    the deliberately permissive import mode.

Well, raw mode passes on the timestamp value with only little checks. strtoul(3) used in builtin/fast-import.c::validate_raw_date() happily accepts negative numbers. The latter function contains two NEEDSWORK comments about perhaps adding more checks, though.

René
Matthew E. LuallenOct 5, 2026, 20:32 UTC in reply to René Scharfe on lore

Re: [BUG] ZIP timestamp conversion and strict fast-import date validation

Hi René,
Thank you for the thoughtful response. I appreciate your help.
- Reader example: Python 3.14.7's ZipInfo.date_time reports 2100 for
  the 1972 ZIP despite its correct Unix timestamp. Our tested UnZip
  and bsdtar restored 1972 correctly; this is a metadata-reading example.
- Separate consequence: the 2106-to-1970 wrap caused UnZip update mode
  to retain different existing 2025 content. The 2038 control updated
  correctly. No deployed security bypass has been demonstrated.
- Fix direction: would you prefer clamping or rejecting ZIP timestamps
  beyond the Unix field's range? Our candidate rejects them. Would
  rejecting negative dates in strict raw import be a useful first step?

Attached is brief guidance on misinterpretation risks, clearer date labels, and safer downstream decisions. These suggestions complement the ordinary bug fixes without asserting a security classification.

Best, Matt

GIT TIMESTAMP GUIDANCE: INTERPRETATION, INTEGRITY AND REMEDIATION 5 October 2026 | Companion to the public Git date-handling discussion

WHY IT MATTERS
- Interpretation: dates can be mistaken for creation, publication or
  approval times. Conversion errors can mislead without malicious intent.
- Scale: repeated reliance on dates across update, review and audit
  pipelines could multiply errors. Prevalence has not been measured.
- Security impact requires attacker-influenced metadata to affect a
  security decision without independent checks. A local update decision
  changed; a production security bypass has not been demonstrated.
OBSERVED, WITH CONTROLS
- Python 3.14.7 reads the 1972 ZIP's DOS date as 2100 despite the correct
  Unix extra field. UnZip 6.00 and bsdtar 3.5.3 restored 1972; Python's
  ordinary extraction used a current local modification time.
- A 2106 commit's ZIP Unix timestamp wrapped to 1970; UnZip update mode
  kept different existing 2025 bytes. A 2038 control replaced them;
  TAR preserved 2106. Strict raw import also accepted a negative date
  subsequently rejected by strict fsck. Reader behavior varies by platform.
PRACTICAL OPTIONS
- Exporters: validate ranges before encoding. Clamp pre-1980 DOS dates
  while preserving representable Unix dates. For Unix-field overflow,
  choose rejection or documented clamping; clamping loses the original
  value. Our candidate rejects overflow. These are proposed policies.
- Importers: align strict parsing with validation; check negative values,
  complete numeric input and overflow. Keep permissive modes explicit.
  Test boundaries across timezones and archive readers.
- Consumers: decide updates using expected content/version information
  from a trusted source, not modification time alone. For change review,
  retain a trusted baseline commit and compare reachable changes; handle
  missing or rewritten history explicitly. Date windows do not establish
  complete coverage of newly received content.
- Displays: distinguish 'committer-supplied date', 'archive modification
  time' and 'server observed at'. Explain clamping and missing evidence.
  Server receipt is not original creation or first publication elsewhere.
- Evidence: preserve original bytes and independent receipt records.
  Commit signatures bind signed content to a key under a trust policy;
  they do not independently prove its claimed creation time. A validated
  trusted timestamp can support existence by a time, not exact creation.
RISK TAXONOMY, NOT A VULNERABILITY ASSIGNMENT
- Numeric representation/truncation: CWE-197; wraparound: CWE-190.
- Validation: CWE-20 (broad category). Downstream trust: CWE-807 only
  where a security decision relies on untrusted input. Display confusion
  alone does not establish it. These labels do not establish severity.
REFERENCES AND EVIDENCE
Git date controls: https://git-scm.com/docs/git-commit#_commit_information
Archive behavior: https://git-scm.com/docs/git-archive#_description
CWE taxonomy: https://cwe.mitre.org/data/definitions/197.html
https://cwe.mitre.org/data/definitions/190.html
https://cwe.mitre.org/data/definitions/20.html
https://cwe.mitre.org/data/definitions/807.html
Trusted timestamp semantics: https://www.rfc-editor.org/rfc/rfc3161
Evidence: recorded 2026-10-01 consumer-date-impact results and Git matrix;
no new experiment is claimed by this guidance.

Matthew E. Luallen (@meluallen), with research, reproduction and drafting assistance from OpenAI Codex.

m@sph3r3.comOct 6, 2026, 03:22 UTC in reply to René Scharfe on lore

Re: [BUG] ZIP timestamp conversion and strict fast-import date validation

Hi René,

Thanks for the explanation. Python 3.14.7’s ZipInfo.date_time is one example: it reads the DOS date as 2100 for the 1972 archive, even though the correct Unix timestamp is present. This affects metadata reading; the tested UnZip and bsdtar restored 1972 correctly.

The 2106 case is separate: the Unix timestamp wraps to 1970, causing UnZip update mode to retain different existing 2025 content. The 2038 control replaced that content as expected.

Best, Matthew

On Mon, 05 Oct 2026 21:49:33 +0200, René Scharfe <l.s.r@web.de> wrote:
Show 43 quoted lines
> On 10/5/26 3:48 PM, Matthew E. Luallen wrote:
> > Hello Git community,
> >
> > I'm reporting three date-handling bugs reproduced on Apple Git 2.50.1
> > and upstream Git 2.56.0:
> >
> > 1. Exporting a 1972-dated commit with git archive --format=zip produces
> >    a legacy DOS date interpreted as 2100, while the extended Unix
> >    timestamp retains 1972.
>
> DOS timestamps can express years starting from 1980.  Unix timestamps
> start at 1970.  We can't provide a DOS timestamp for 1972, but can we do
> better?  zip(1) clamps DOS timestamps to zero = the DOS epoch =
> 1980-01-01 00:00:00.
>
> Is anything using the DOS timestamp even though a Unix timestamp is
> present?
>
> > 2. Exporting a commit at epoch 4294967296 (2106-02-07 06:28:16 UTC)
> >    wraps ZIP's four-byte extended timestamp to zero (1970). Exporting
> >    the same commit as TAR preserves the original value.
>
> tar's timestamp can range from 1970 to 2242 with standard headers and
> beyond indefinitely with extended headers.
>
> We cannot put a higher value than 4294967295 into the four-byte field
> provided by the Unix time extension for ZIP, but we could clamp to that
> value.  zip(1) wraps around as well, though..
>
> (I'm using "Zip 3.0 (July 5th 2008), by Info-ZIP, with modifications by
> Apple Inc.")
>
> > 3. git fast-import --date-format=raw accepts -32184000 +0000, but
> >    git fsck --strict then reports badDate and ISO rendering returns
> >    literal placeholders. This occurs in strict raw mode, not just
> >    the deliberately permissive import mode.
>
> Well, raw mode passes on the timestamp value with only little checks.
> strtoul(3) used in builtin/fast-import.c::validate_raw_date() happily
> accepts negative numbers.  The latter function contains two NEEDSWORK
> comments about perhaps adding more checks, though.
>
> René

Back to recent threads

[BUG] ZIP timestamp conversion and strict fast-import date validation | The Git List