Skip to content

Fix php2shell in all the v5 images (CVE-2026-109618, CVE-2026-109619) - #424

Merged
mistraloz merged 10 commits into
thecodingmachine:v5from
mistraloz:security/php2shell-rebuild
Oct 22, 2026
Merged

mistraloz merged 10 commits into
thecodingmachine:v5from
mistraloz:security/php2shell-rebuild

Conversation

@mistraloz

@mistraloz mistraloz commented Oct 22, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

php2shell (CVE-2026-109618 and CVE-2026-109619, CVSS v4 9.2): unauthenticated remote code execution in the PHP core, public exploits.

  • PHP 8.2 to 8.5: fixed in 8.2.35, 8.3.36, 8.4.27 and 8.5.12.
  • PHP 7.4, 8.0 and 8.1 (EOL): no release, but a minimal source backport from the PHP security team that keeps the version number (7.4.33, 8.0.30, 8.1.34). The packages of packages.sury.org carry it: a rebuild without cache is enough, no compilation from source.
  • NodeJS 18 and 20 variants (-node18, and -node20 on PHP 8.2+) were no longer built: they are built again, so every v5 image gets the fix.

⚠️ arm64: packages.sury.org has published the fixed packages for amd64 only (21/10). Its arm64 builds run under QEMU and are expected within a couple of days (deb.sury.org#145). Until then, test_php2shellPatched only emits a GitHub warning for a vulnerable arm64 image (it fails for amd64): the CI passes, the multi-arch images are published as usual, amd64 fixed and arm64 not yet, which the README and the php2shell page say. Once the warning is gone, a follow-up PR will turn it into an error and update the docs.

This PR fixes/implements :

  • Bug
  • Feature
  • Breaking changes (swoole removed from PHP 8.0 and 8.1)

Changes:

  • tests-suite/php-security-patches.sh (temporary): PHP 8.2+ must be at least the fixed release; on 7.4/8.0/8.1 every PHP SAPI of the image (CLI, PHP-FPM, mod_php) must contain the zend_mm_safe_error_ex symbol added by the backport. Error on amd64, warning on arm64.
  • legacy-v5.yml (manual) now covers the 7 PHP versions: all the images of 7.4 to 8.1, and only the NodeJS 18/20 images of 8.2 to 8.5 (new phpXY-<variant>-legacy-node bake groups). It runs the test suite before publishing, with the same build, test and publish steps as workflow.yml.
  • Docs: short security note at the top of the README (the fpm built-in Apache note is removed) and docs/security-php2shell.md: what to do, arm64 status and how to check an image, NodeJS 16 and older via the NODE_VERSION ARG, v4 images not fixed → migration, and Watchtower to apply the next fixes automatically. CHANGELOG and docs/contributing.md updated.
  • Fallout of the move to packages.sury.org (Install PHP from packages.sury.org instead of the Launchpad PPA #422), which broke the 7.4, 8.0 and 8.1 builds (the legacy-v5.yml run of 21/10 failed on all of them):
    • sury has no php8.0-swoole / php8.1-swoole: swoole is removed from PHP 8.0 and 8.1 (legacy versions). The install fell back to php-swoole, which installs PHP 8.5 and switches the php alternative to it: docker-install.sh now fails when php<version>-<extension> does not exist instead (no maintained extension relied on this fallback);
    • php-pear now comes from Ubuntu (1.10.13 instead of 1.10.16 from the PPA), whose pecl cannot read the metadata of event on PHP 7.4: it is installed from its archive (3.1.6, same version as the published images).

Notes for the review:

  • 7.4.33-v5-*, 8.0.30-v5-* and 8.1.34-v5-* tags will be overwritten by the fixed images (same PHP version).
  • The README says the amd64 images are fixed and the arm64 ones are not yet: to update once sury publishes arm64.

Release plan

  1. Merge, then run legacy-v5.yml manually (workflow.yml runs on the push) → amd64 fixed.
  2. Once sury has the arm64 packages: run both again → arm64 fixed, then a PR turns the arm64 warning into an error and updates the docs.

Test plan (required)

  • CI of this PR: all amd64 jobs and the arm64 jobs whose sury package is already fixed pass; the other arm64 jobs fail only on test_php2shellPatched, with the vulnerable version in the message.
  • Local (amd64): 7.4, 8.0 and 8.1 slim images (cli, fpm, apache): every PHP binary contains the fix, php-security-patches.sh passes (and fails on the currently published 8.1-v5-slim-cli). Fat cli images: build OK, php-security-patches.sh, php-extensions.sh and php-ini.sh pass (16/16 each). Fat apache/fpm and arm64 are left to legacy-v5.yml.
  • Local (amd64): php84-cli-legacy-node builds, NodeJS 18.20.8 and 20.20.2 with PHP 8.4.27.
  • Local (amd64): full test suite on the 7.4, 8.0 and 8.1 fat cli images: 46/46 each.
  • php-security-patches.sh: passes on fixed amd64 images, fails on the published (vulnerable) 8.1 and 8.4 amd64 images, warns and passes on a vulnerable arm64 image (simulated: no arm64 emulation locally). actionlint: no error on legacy-v5.yml.

Checklist

  • I followed the guidelines in CONTRIBUTING guide
  • I have squashed any insignificant commits
  • This change has comments for package types, values, functions, and non-obvious lines of code

PHP 7.4, 8.0 and 8.1 are end-of-life: CVE-2026-109618 and
CVE-2026-109619 (php2shell, CVSS 9.2) were only fixed with a source
backport (PHP-x.y-CVE-2026-109618-109619 branches of php-src) that
keeps the version number. The packages of packages.sury.org carry it,
so a rebuild without cache is enough, no compilation from source.

- Add a test checking that the images are not vulnerable: the version
  for PHP 8.2+, the zend_mm_safe_error_ex symbol added by the backport
  in every PHP SAPI (CLI, FPM, mod_php) for older versions
- legacy-v5.yml: build without cache by default, run the vital tests
  (configurable input) before publishing, the other tests being
  informative, and publish every version/variant validated on all
  architectures even if others failed
Add a security note to the README and a Security updates page
explaining how the maintained (8.2 to 8.5) and non-maintained (7.4,
8.0, 8.1) v5 images are fixed, how to check and update them, and that
the v4 images are not fixed, with a link to the migration notes.
The page is specific to php2shell: rename it security-php2shell.md.
Document the NodeJS variants that are no longer built (-node18, and
-node20 on PHP 8.2+) and remain vulnerable, recommend a maintained
NodeJS version and explain how to install another one on the fixed
slim image with the NODE_VERSION ARG.
The -node18 and -node20 variants of the maintained PHP versions were no
longer built, so they kept a PHP vulnerable to php2shell. Build them
with the legacy workflow (new -legacy-node bake groups, only their
NodeJS images are published), and add NodeJS 18 to the non-maintained
PHP versions.

Make the php2shell page and the README note go straight to what to do,
add Watchtower as a way to apply the next fixes automatically, and
remove the fpm built-in Apache note from the top of the README.
@mistraloz
mistraloz marked this pull request as draft October 22, 2026 09:16
packages.sury.org publishes the fixed PHP packages for amd64 first, the
arm64 ones can come days later. Until then, the arm64 builds fail the
php2shell test and nothing is published, amd64 included.

Add an allow_arm64_failure input to workflow.yml and legacy-v5.yml: the
amd64 images are published, the X.Y tags keep their current arm64 image
so that arm64 users are not broken, and the tags of the new PHP patch
version only have amd64. amd64 failures still block the publication.
The fixed PHP packages are not yet published for arm64 by
packages.sury.org. Say so in the README note, the php2shell page and
the changelog, explain how to check an image and how to run the amd64
image on an arm64 host in the meantime.
@mistraloz mistraloz changed the title Rebuild PHP 7.4, 8.0 and 8.1 with the php2shell fix (CVE-2026-109618, CVE-2026-109619) Fix php2shell in all the v5 images (CVE-2026-109618, CVE-2026-109619) Oct 22, 2026
packages.sury.org does not provide php8.0-swoole and php8.1-swoole. The
install then fell back to php-swoole, which installs PHP 8.5 and switches
the php alternative to it: every following extension failed its check
and the 8.0 and 8.1 images could no longer be built.

Remove swoole from these versions, and fail the build of an extension
whose package does not exist for the PHP version instead of installing
the unversioned package.
When php<version>-<extension> did not exist, the install fell back to
the unversioned php-<extension> package, which installs another PHP
version (e.g. php-swoole installs PHP 8.5). Fail instead, and add the
swoole removal to the changelog.
Since PHP comes from packages.sury.org, php-pear comes from Ubuntu
(1.10.13 instead of 1.10.16 from the PPA). On PHP 7.4, its pecl cannot
read the release metadata of event ("does not have REST xml
available"), so the 7.4 images could no longer be built.

Install event 3.1.6, the version of the published images, from its
archive URL. Only PHP 7.4 uses this extension: replace the symlink to
core with a real directory.
@mistraloz
mistraloz marked this pull request as ready for review October 22, 2026 12:07
packages.sury.org has not published the fixed PHP packages for arm64
yet. Instead of publishing amd64 alone, the php2shell test only emits a
GitHub warning for a vulnerable arm64 image, and still fails for amd64:
the CI passes, the multi-arch images are published as usual and the
arm64 status is documented.

Simplify the legacy workflow accordingly: drop the vital_tests, no_cache
and allow_arm64_failure inputs and use the build, test and publish
steps of the main workflow (the CI runners start without build cache,
so no_cache changed nothing there). Restore workflow.yml.
@mistraloz
mistraloz merged commit 4d4aa95 into thecodingmachine:v5 Oct 22, 2026
25 checks passed
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.

1 participant