Skip to content

fix(restore): restore WordPress core without truncated files - #504

Merged
mrrobot47 merged 3 commits into
EasyEngine:developfrom
mrrobot47:fix/restore-core-download-truncation
Sep 29, 2026
Merged

mrrobot47 merged 3 commits into
EasyEngine:developfrom
mrrobot47:fix/restore-core-download-truncation

Conversation

@mrrobot47

@mrrobot47 mrrobot47 commented Sep 29, 2026 •

Copy link
Copy Markdown
Member

Problem

WordPress 7.x .tar.gz packages store paths longer than 100 bytes in PAX headers. WP-CLI 2.12 and older extracts them with PHP's PharData, which ignores those headers and truncates the names (wp-cli/wp-cli#6320, php/php-src#19311). The files under wp-includes/php-ai-client/ end up with broken names, some are lost, and WordPress fatals as soon as the AI client is used. wp core verify-checksums fails on such a tree.

ee site restore runs wp core download --force, so a restored WordPress 7.x site gets this broken core.

Fix

  • Add get_wp_core_download_command() and its shell helpers in site-utils.php. They let WP-CLI resolve the version and locale and check the md5 with wp core download --no-extract, extract the package with tar (or unzip, with a ZipArchive fallback), and then run wp core verify-checksums. The download fails unless core verifies; it only warns when the checksums can't be fetched from WordPress.org.
  • The .zip that WP-CLI 3.0 saves is handled too. --skip-content and nightly keep WP-CLI's own extraction, since those already use the unaffected .zip path.
  • The package is extracted into a temp dir before the old core is replaced, and a failed extraction fetches a fresh, md5-checked copy once. So a failed extraction (a corrupt cached package, a full disk) keeps the old core.
  • With force, wp-admin and wp-includes are replaced only after a successful extraction, so restoring onto a newer or already broken core leaves no stale files. Without force, the helper refuses to extract over an existing install, as WP-CLI does.
  • The restore now uses this helper, with force. An empty WordPress version in the backup metadata now means latest.

Testing

  • Restoring a site onto a deliberately damaged core, and restoring a site that was created with a truncated core, both end with wp core verify-checksums passing and the site's content intact.
  • The helpers were tested with WP-CLI 2.11, 2.12 and 3.0 nightly on PHP 7.4 to 8.5 images.

Dependencies

A follow-up site-type-wp PR switches site creation to the same helper and repairs existing sites, so this PR needs to be merged and released first.

WP-CLI <= 2.12 extracts core .tar.gz packages with PharData, which ignores PAX long-name headers and truncates paths over 100 bytes (wp-cli/wp-cli#6320, php/php-src#19311). WordPress >= 6.7.2 en_US packages use PAX headers, so 7.x installs lose wp-includes/php-ai-client classes and fatal when the AI client is used.

get_wp_core_download_command() lets WP-CLI resolve the version and locale and verify the md5 with `core download --no-extract`, extracts the package with tar (or unzip, falling back to ZipArchive) and gates on `core verify-checksums`: missing or modified files fail, an unreachable checksums API only warns. WP-CLI >= 3.0 saves a .zip (wp-cli/core-command#333), which is handled too. --skip-content and nightly keep WP-CLI's own extraction, as they already use the unaffected .zip path. Arguments are shell-escaped for the bash -c wrapper.
The restore ran `wp core download --force`, which truncates WordPress 7.x core files like site creation did. Use get_wp_core_download_command() instead. With force, wp-admin and wp-includes are replaced after a successful download, so a restore onto a newer or already corrupted core leaves no stale files behind.

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.

Copilot review overview

🟡 Changes recommended

Verification failures can be incorrectly ignored, and non-force downloads can overwrite existing installations.

Review effort: Balanced
Findings: 1 High severity · 1 Medium severity

Open (2)
What changed in this PR

Updates WordPress restores to avoid truncated core files by delegating extraction to native archive tools and verifying checksums.

Changes:

  • Adds WordPress package download, extraction, and verification helpers.
  • Uses the new helper during site restoration.
File Description
src/​helper/​site-utils.php Adds safe WordPress core download and extraction utilities.
src/​helper/​Site_Backup_Restore.php Integrates the helper into WordPress restoration.

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

Comment thread src/helper/site-utils.php Outdated
Comment thread src/helper/site-utils.php Outdated
…k fails

Extract the package into the temp dir and only then replace wp-admin and wp-includes, so a failed extraction (a corrupt cached package, a full disk) no longer leaves a site without core. A package from WP-CLI's cache isn't md5-checked again, so a failed extraction fetches a fresh copy once.

ee_wp_verify now fails unless core verifies, and only warns when the checksums can't be fetched from WordPress.org. Before, any other failure, such as "This does not seem to be a WordPress install", passed as a warning.

Without force, refuse to extract over an existing install, as WP-CLI does.
@mrrobot47
mrrobot47 merged commit ce7c784 into EasyEngine:develop Sep 29, 2026
1 of 5 checks passed
@mrrobot47
mrrobot47 deleted the fix/restore-core-download-truncation branch September 29, 2026 03:46
iamimmanuelraj added a commit to iamimmanuelraj/action-deploy-wordpress that referenced this pull request Oct 5, 2026
Any other verify-checksums failure (PHP/WP-CLI runtime errors etc.) now
fails the deploy instead of continuing unverified. Matches the fetch-error
handling in EasyEngine/site-command#504.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants