Skip to content

Improve updates integrity checks - #924

Open
giuscris wants to merge 3 commits into
2.xfrom
feature/check-updates-integrity
Open

Improve updates integrity checks#924
giuscris wants to merge 3 commits into
2.xfrom
feature/check-updates-integrity

Conversation

@giuscris

Copy link
Copy Markdown
Member

This pull request significantly improves the reliability and security of the update process. The most important changes are the addition of checksum verification for downloaded update archives, better handling of temporary files during downloads, and the introduction of a locking mechanism to prevent concurrent updates. These changes help ensure that updates are applied safely and only once, and that downloaded files are not corrupted or tampered with.

Update Process Security and Integrity:

  • Added SHA256 checksum verification for downloaded release archives to ensure file integrity before extraction. The checksum is parsed from GitHub asset metadata if available, and the update will abort if the checksum does not match. [1] [2] [3]
  • Modified the update process to always use a temporary file for downloads and only move it to the target location after a successful and complete download, reducing the risk of partial or corrupted files being used.

Concurrency and Reliability Improvements:

  • Introduced an exclusive lock file mechanism to prevent concurrent update runs, with a configurable timeout for handling stale locks. This prevents multiple updates from running at the same time, which could corrupt the installation. [1] [2] [3]

Data Structure and Metadata Enhancements:

  • Extended the release metadata structures to include an optional checksum field, updating all relevant type annotations and logic to handle this new field. [1] [2]
  • Added a utility import for better error messaging when handling ZIP archive extraction failures.

@giuscris giuscris added this to the 2.4.0 milestone Aug 12, 2026
@giuscris
giuscris requested a lite review from Copilot August 12, 2026 19:02
@giuscris giuscris self-assigned this Aug 12, 2026
@giuscris giuscris added the enhancement New feature or request label Aug 12, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR hardens the Formwork self-update flow by adding integrity checks for downloaded update archives, improving download atomicity via temporary files, and introducing a lock file to reduce the risk of concurrent update runs.

Changes:

  • Add optional SHA256 checksum handling for release assets and verify downloaded archives before extraction.
  • Download to a temporary file and move into place only after a complete transfer.
  • Add an update lock file and new updates.lockTimeout configuration.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
formwork/src/Updater/Updater.php Adds checksum parsing/verification, refactors extraction into helpers, and introduces an update lock mechanism.
formwork/src/Http/Client.php Makes downloads write to a temp file first, validates byte counts, then renames into place.
formwork/config/system.yaml Adds updates.lockTimeout configuration for stale-lock handling.

馃挕 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +248 to +251
$root = ROOT_PATH;
$destination = FileSystem::joinPaths($root, $filename);
$destinationDirectory = dirname($destination);

Comment thread formwork/src/Updater/Updater.php
Comment thread formwork/src/Updater/Updater.php
Comment on lines +126 to 130
$temporaryFile = FileSystem::createTemporaryFile(dirname($file));

if (($destination = @fopen($temporaryFile, 'w')) === false) {
throw new RuntimeException(sprintf('Cannot open temporary file "%s" for writing', $temporaryFile));
}

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.

Suppressed comments (2)

formwork/src/Updater/Updater.php:292

  • The lock acquisition is not actually exclusive: the existence check and subsequent write are not atomic, so two concurrent processes can both pass the check and both write the lock file, resulting in concurrent updates despite the lock. Consider creating the lock file atomically (e.g., FileSystem::createFile() using x+) and only reusing it when it is stale, to guarantee single-writer behavior.
        if (FileSystem::exists($lockFile) && (time() - FileSystem::lastModifiedTime($lockFile)) < $this->options['lockTimeout']) {
            throw new RuntimeException('An update is already in progress');
        }

        FileSystem::write($lockFile, (string) time());

formwork/src/Http/Client.php:143

  • rename($temporaryFile, $file) is executed while $destination is still open. On some platforms (notably Windows) renaming an open file can fail, causing downloads to error even though the copy succeeded. Close the stream (and ideally flush it) before attempting the rename; also delete the created temp file if fopen() fails after createTemporaryFile() succeeded.
                if (!@rename($temporaryFile, $file)) {
                    throw new RuntimeException(sprintf('Cannot move temporary file "%s" to destination "%s"', $temporaryFile, $file));
                }

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

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants