Repository navigation
Patch PHP 7.4 for CVE-2026-109618 and CVE-2026-109619 on Alpine 3.15 - #47
Merged
Merged
Conversation
Verbatim copy of community/php7 from aports 3.15-stable (php 7.4.33-r1), fetched from git.alpinelinux.org. Every file matches the sha512sums in the APKBUILD. The next commit adds the CVE fix on top, so its diff shows only our changes. Refs #46 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Uugex1w8qZoTbBRbcFwkcp
Adds the upstream EOL fix (php-src 712e60f, "Avoid state corruption via bailout") to the Alpine 3.15 php7 recipe and bumps pkgrel to r2 so apk prefers our build over Alpine's r1. The upstream branch is based on plain 7.4.33, so its fix also introduces max_multipart_body_parts (CVE-2023-0662). Alpine already carries that in CVE-2023-0662-2.patch, so those four hunks are dropped and every Alpine patch is kept. The result applies cleanly on top of all 15 Alpine patches and its added lines are identical to ppa:ondrej/php 7.4.33-31, which ships the same fix. Refs #46 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Uugex1w8qZoTbBRbcFwkcp
A full test run with and without the fix (same recipe, non-root, arm64) differs by exactly nine tests, all caused by the fix on purpose: - tests/lang/bug45392.phpt: out-of-memory errors are now written straight to stderr before _exit(1), which adds a blank line before "Fatal error". The expected output now allows it, so the test still checks that buffered output is not leaked when memory runs out. - ext/session/tests/rfc1867*.phpt (8 tests): the fix turns session upload progress off entirely, so these tests check a feature that is gone. Disabled. Four more fail with and without the fix when built in Docker (curl_basic_009, date bug73837, streams opendir-003 and opendir-004), so they are disabled too. Refs #46 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Uugex1w8qZoTbBRbcFwkcp
A builder stage builds the patched php7 recipe as a non-root user (running abuild as root makes the opcache preloading tests fail) with Alpine's test suite enabled. The image then moves to alpine:3.15 and keeps the signed packages as a local repo in /opt/php7-apk, listed first, so images built on top get the patched 7.4.33-r2 too, for example php7-apache2 in graze/new-php. /opt rather than /srv because new-php declares /srv as a volume. gnu-libiconv 1.16 on Alpine 3.15 no longer ships preloadable_libiconv.so, so the LD_PRELOAD fix stopped working and iconv //TRANSLIT returned false (Utils::slugify would produce empty slugs). It is pinned to 1.15-r3 from the v3.13 repo, the same package the current image uses. Two new tests check that php7 is the r2 build and that php7-apache2 added later resolves to r2. Both fail against the current graze/php-alpine:7.4 and pass here, as do all 19 bats tests. Refs #46 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Uugex1w8qZoTbBRbcFwkcp
A tagged repository (@alpine313) put "gnu-libiconv@alpine313" in the apk world file. Images keep no package indexes, so any later apk call without --no-cache could not see the tag and refused to commit. The dispatch image hit this at "apk del .imagick-build-deps". Installing gnu-libiconv=1.15-r3 with a one-off --repository leaves a plain version pin that apk satisfies from the installed package. Checked by building graze/new-php:7.4 (cli and apache) and the dispatch php74 image on top: imagick 3.8.0 compiles and renders, iconv //TRANSLIT works, mod_php loads, and the dispatch health check returns 200. All 19 bats tests pass. Refs #46 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Uugex1w8qZoTbBRbcFwkcp
There was a problem hiding this comment.
🔵 Needs a closer look
The signing-key exposure needs correction, and the end-of-life runtime security backport requires human sign-off on architecture-specific validation.
1 open issue
What changed in this PR
Updates the PHP 7.4 base image to address CVE-2026-109618 and CVE-2026-109619 while preserving compatibility with downstream CLI and Apache images.
Changes:
- Builds patched PHP 7.4.33-r2 on Alpine 3.15 using Alpine’s existing recipe and patches.
- Retains signed packages in a local repository for downstream installs and pins libiconv to preserve transliteration.
- Adds package-selection checks and adjusts PHP tests for the mitigation’s intentional behavior changes.
| File | Description |
|---|---|
7.4/php.bats |
Checks installed and downstream package revisions. |
7.4/Dockerfile |
Builds patched packages and configures the runtime image. |
7.4/aports/community/php7/xfail-openssl-1.1-test.patch |
Retains Alpine’s OpenSSL test adjustment. |
7.4/aports/community/php7/sharedir.patch |
Sets the packaged PHP include path. |
7.4/aports/community/php7/php7-module.conf |
Supplies Apache PHP module configuration. |
7.4/aports/community/php7/php7-fpm.logrotate |
Supplies FPM log rotation configuration. |
7.4/aports/community/php7/php7-fpm.initd |
Supplies the FPM OpenRC service script. |
7.4/aports/community/php7/php7-fpm-version-suffix.patch |
Uses PHP 7-specific FPM paths. |
7.4/aports/community/php7/install-pear.patch |
Enables XML during PEAR installation. |
7.4/aports/community/php7/includedir.patch |
Uses versioned development-header paths. |
7.4/aports/community/php7/fix-tests-devserver.patch |
Filters development-server test output. |
7.4/aports/community/php7/fix-fpm-tests.patch |
Adjusts FPM regression-test logging. |
7.4/aports/community/php7/fix-fpm-syntax.patch |
Makes backported tests PHP 7-compatible. |
7.4/aports/community/php7/fix-curl-7.83-test.patch |
Accommodates changed curl error text. |
7.4/aports/community/php7/enchant-2.patch |
Retains Enchant 2 compatibility. |
7.4/aports/community/php7/disabled-tests.list |
Records inherited and mitigation-related test exclusions. |
7.4/aports/community/php7/CVE-2026-109618-109619.patch |
Adds the runtime security mitigation. |
7.4/aports/community/php7/CVE-2026-109618-109619-tests.patch |
Updates the memory-exhaustion output expectation. |
7.4/aports/community/php7/CVE-2023-0662-2.patch |
Retains multipart limits and regression tests. |
7.4/aports/community/php7/CVE-2023-0662-1.patch |
Retains upload-limit warning protection. |
7.4/aports/community/php7/CVE-2023-0568.patch |
Retains path-buffer bounds fixes. |
7.4/aports/community/php7/CVE-2023-0567-2.patch |
Retains short bcrypt hash validation. |
7.4/aports/community/php7/CVE-2023-0567-1.patch |
Retains malformed bcrypt salt rejection. |
7.4/aports/community/php7/APKBUILD |
Defines the patched build, tests, subpackages, and checksums. |
Review effort: Balanced
Copilot stopped work on behalf of
rick-lam due to an error
October 22, 2026 03:37
This was referenced Oct 22, 2026
rick-lam
added a commit
that referenced
this pull request
Oct 22, 2026
The build and manifest jobs needed every test in the matrix to pass, so one failing version stopped every version from publishing. Since 22 Oct 2026 pecl.php.net returns bad REST data for the 5.6, 7.0, 7.1, 7.2, 8.3 and 8.4 builds, which blocks the PHP 7.4 security fix in #47 even though its own test passes. With !cancelled() each version builds and publishes on its own. A version whose build breaks fails only its own build and manifest jobs. Every PR still runs all the tests. Fixes #48 Claude-Session: https://claude.ai/code/session_01Uugex1w8qZoTbBRbcFwkcp Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
The master build exports every layer to the registry build cache (mode=max), so the builder layer would have carried the private key used to sign the php7 packages. Anyone pulling the cache could then sign packages and indexes that the images trust. The key is now removed in the same RUN that generates and uses it, so no layer contains it. The public key stays for the runtime image. Checked locally: none of the five builder-stage layers contains a private .rsa (a control tar with one is detected), and all 19 bats tests pass. Refs #46 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Uugex1w8qZoTbBRbcFwkcp
This was referenced Oct 22, 2026
rick-lam
added a commit
that referenced
this pull request
Oct 22, 2026
Every PR built and tested all versions in versions.json, so a change to one version's folder (such as #47, only 7.4/) also showed unrelated failures from other versions. On pull requests the matrix job now diffs the PR against its base. If every changed file is inside a version folder listed in versions.json, only those versions are tested. Any other change (common/, the workflow, the Makefile, versions.json, the README), an unknown folder, or a failed diff tests every version as before. Pushes to master are unchanged. Fixes #51 Claude-Session: https://claude.ai/code/session_01Uugex1w8qZoTbBRbcFwkcp Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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
Fixes #46
graze/php-alpine:7.4runs PHP 7.4.26 on Alpine 3.13, which is affected by the critical remote code execution vulnerabilities CVE-2026-109618 and CVE-2026-109619 (https://www.php.net/archive/2026.php#2026-10-21-5). No Alpine release ships a fixed PHP 7.4 (3.15 was the last with php7, at 7.4.33-r1, and it is EOL), so this builds Alpine 3.15's own php7 recipe with the upstream fix and moves the image to Alpine 3.15. dispatch and stats web run mod_php on images built from this one.Notable Changes
7.4/aports/community/php7: Alpine 3.15's php7 recipe, first added unchanged (every file matches its sha512sums) so the following commits show only our changes.712e60ffrom the PHP security team'sPHP-7.4-CVE-2026-109618-109619branch, minus four hunks that re-addmax_multipart_body_parts(CVE-2023-0662), which Alpine already carries. All 15 Alpine patches are kept, and the added lines are identical toppa:ondrej/php7.4.33-31, which our EC2 boxes have run since 22 Oct.pkgrelgoes to r2 so apk prefers our build._exit(1)(no shutdown functions, exit code 1 not 255), and session upload progress is switched off. Nothing in web, stats or planning-api uses session upload progress.tests/lang/bug45392.phptnow expects a blank line before "Fatal error", and the 8ext/session/tests/rfc1867*.phpttests are disabled because the feature is off. 4 tests that fail with and without the fix in Docker (curl_basic_009,date/bug73837,streams/opendir-003and004) are also disabled. Everything else runs.7.4/Dockerfile: a builder stage runsabuildas a non-root user (as root, about 40 opcache preloading tests fail). The image moves toalpine:3.15and keeps the signed packages as a local repo at/opt/php7-apk, listed first, so images built on top (for examplephp7-apache2ingraze/new-php) also get r2./opt, not/srv, because new-php declares/srvas a volume.gnu-libiconv1.16 on Alpine 3.15 no longer shipspreloadable_libiconv.so, soiconv(... '//TRANSLIT')returnedfalse(Utils::slugifyin graze/web would produce empty slugs). It is pinned to 1.15-r3 from the v3.13 repo, the package the current image uses. The pin uses a one-off--repositoryrather than a tagged repo, because a tag breaks laterapk delcalls without--no-cache(dispatch's Dockerfile does that).7.4/php.batscheck that php7 is the r2 build and thatphp7-apache2installed later resolves to r2. Both fail against the currentgraze/php-alpine:7.4.QA
Done locally on arm64 (CI builds amd64 natively):
docker build 7.4/: abuild's full PHP test suite passes. Every core php7 package is7.4.33-r2, PECL extensions come from Alpine 3.15.common/php-arm64.bats,common/php.bats,7.4/php.bats19 of 19 pass, includingiconv //TRANSLIT. Debug image:php7-phpdbgis r2 and7.4/php_debug.batspasses.php7-common-7.4.26-r0).graze/new-php:7.4cli and apache on top (graze-dockernew-php/7.x, unchanged): 13 + 13 graze-docker bats tests pass,php7-apache2is r2,php7_moduleloads, Apache 2.4.58.php7-devand renders, gd and iconv work,/healthCheck.phpreturns 200 through Apache./healthCheck.phpreturns200 OK 7.4.33through mod_php.For the reviewer: check the CI build for both architectures and that
apk info -v | grep ^php7-common-in the pushed image shows7.4.33-r2.Deployment
graze/php-alpine:7.4and7.4-test.graze/new-php:7.4(cli and apache) from graze-docker.🤖 Generated with Claude Code
https://claude.ai/code/session_01Uugex1w8qZoTbBRbcFwkcp