Skip to content

Checksum formatting changes can trigger full JCEF redownloads #143

Description

@jinyiwei2012

Summary

MCEF decides whether to download the JCEF runtime by comparing the complete bytes of the local and remote .sha256 files with FileUtils.contentEquals(...).

The checksum file currently served by the MCEF mirror is not a canonical checksum line. It is a 314-byte PowerShell Get-FileHash table containing headers, column padding, CRLF line endings, and the CI runner path:


Algorithm       Hash                                                                   Path
---------       ----                                                                   ----
SHA256          E98C385542620F31A594D6FC3C38ED6BCA8A547E24CED982A1339BB3333668BE       D:\a\java-cef\java-cef\jcef_buil…

Only the 64-character hexadecimal value represents the archive checksum. Any change to the table formatting, runner path, padding, or line endings causes the complete-file comparison to fail and triggers a full JCEF download even when the semantic SHA-256 value has not changed.

This behavior is present in every maintained branch from 1.20.1 through 1.21.5, including the current default branch 1.21.4.

Impact

For mcef-forge-2.1.6-1.20.1, a checksum mismatch downloads windows_amd64.tar.gz again and extracts it. The archive currently served for the pinned java-cef commit is:

  • Size: 124309275 bytes (118.6 MiB)
  • SHA-256: E98C385542620F31A594D6FC3C38ED6BCA8A547E24CED982A1339BB3333668BE

I downloaded the archive independently and calculated the same SHA-256, so the current archive and the semantic value in the checksum file are consistent. The problem is that non-semantic formatting bytes participate in the update decision.

The impact is amplified because CefDownloadMixin calls extractJavaCefBuild(true), which deletes the downloaded archive after extraction. A false mismatch therefore causes another complete 118.6 MiB transfer rather than reusing a local archive.

Potentially related reports include #79, #95, #109, #117, #137, and #141.

Relevant code

In MCEFDownloader.downloadJavaCefChecksum():

boolean sameContent = FileUtils.contentEquals(jcefBuildHashFile, jcefBuildHashFileTemp);

On mismatch, the downloaded temporary file is used as the new marker:

jcefBuildHashFileTemp.renameTo(jcefBuildHashFile);
return false;

The current implementation also does not validate that the remote response contains a SHA-256 value before replacing the marker, and does not check the result of renameTo(...).

Expected behavior

  • Parse and compare the semantic 64-character SHA-256 value instead of comparing the complete checksum-file representation.
  • Reject malformed or truncated remote checksum content.
  • Do not replace a valid local marker when the newly downloaded checksum cannot be parsed.
  • Continue requesting a JCEF download when the actual semantic SHA-256 value changes.

Proposed scope

A small first fix can be limited to MCEFDownloader:

  1. Extract exactly one SHA-256 token from each checksum file.
  2. Compare the normalized hexadecimal values.
  3. Throw an IOException for malformed remote checksum content before replacing the existing marker.
  4. Replace the marker only after a valid semantic checksum has been obtained.

Archive caching, resumable downloads, locking, and library-path changes can be handled separately.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions