Skip to content

Security: Patch Brotli for CVE-2026-111497 and upgrade FrankenPHP to 1.13.4 - #737

Merged
jaydrogers merged 2 commits into
mainfrom
security-brotli-frankenphp-1.13.4
Oct 26, 2026
Merged

jaydrogers merged 2 commits into
mainfrom
security-brotli-frankenphp-1.13.4

Conversation

@jaydrogers

Copy link
Copy Markdown
Member

This PR patches Brotli for CVE-2026-111497 in every variation and upgrades FrankenPHP to 1.13.4.

Change Why
Every variation upgrades libbrotli1 (Debian) and brotli-libs (Alpine) at build time The official PHP images still ship vulnerable Brotli builds, and PHP's curl extension links against them
FrankenPHP 1.13.2 → 1.13.4 Security release with 7 FrankenPHP fixes, including a crash that 1.13.2 introduced

Brotli CVE-2026-111497

CVE-2026-111497 (Node2Shell) is an out-of-bounds write in the Brotli decoder. PHP reaches it through curl when a response is Brotli encoded, for example with CURLOPT_ENCODING.

The official PHP images ship vulnerable versions:

Base OS Shipped Patched
Bookworm 1.0.9-2+b6 1.0.9-2+deb12u1
Trixie 1.1.0-2+b7 1.1.0-2+deb13u1
Alpine 1.2.0-r1 1.2.1-r0

Each Dockerfile now lists the Brotli package so the build upgrades it. Remove them once the official images ship the fix. This is the same workaround FrankenPHP uses in its own images (#2767).

docker-php-serversideup-dep-install-alpine now runs apk add --upgrade. Without it, apk add leaves an installed package at its current version, while apt-get install on Debian upgrades it. Both helpers now behave the same way.

FrankenPHP 1.13.4

Advisory Issue
GHSA-5f4m-ff4w-g458 High. In worker mode, one unauthenticated request could crash the whole process. Introduced in 1.13.2, which we ship today
GHSA-rgpj-f2qx-xwhf putenv() from a shutdown function, destructor, or session handler left a dangling pointer
GHSA-cm3q-jw2q-9rh5 Worker mode freed an SplTempFileObject stream kept across requests
GHSA-8386-64gm-3m8q Worker mode leaked per-request environment variables into later requests
GHSA-pmvg-8483-mw84 Worker mode returned a previous request's http_get_last_response_headers()
GHSA-h764-4wh7-m7j2 Double free when a worker ended its loop after a non-form POST
GHSA-x6j6-qv7w-fq3c A fatal error during worker request startup left the request waiting forever

The Windows, macOS, and static binary fixes in that release don't apply to us.

Bookworm builds Brotli from source

1.13.4 moves cbrotli from 1.1.0 to 1.2.1, which needs libbrotli 1.1 or newer. Bookworm only has 1.0.9, so the FrankenPHP build would fail there. When pkg-config finds a libbrotli older than 1.1, the build stage compiles Brotli 1.2.1 from source (checksum verified), and the final image ships those libraries next to libwatcher. Trixie and Alpine skip this step. This matches upstream (#2777).

/etc/ld.so.conf.d/000-brotli.conf puts /usr/local/lib first. On arm64 the multiarch config sorts before libc.conf, and without this file the system 1.0.9 would still load. PHP's curl in the FrankenPHP Bookworm image uses 1.2.1 as well.

Tested locally

All amd64, PHP 8.4.27.

Image Brotli loaded FrankenPHP test-image.sh
8.4-frankenphp-bookworm 1.2.1 from /usr/local/lib, for FrankenPHP and curl 1.13.4 Passes, including Octane
8.4-frankenphp-alpine3.24 1.2.1-r0 1.13.4 Passes, including Octane
8.4-cli-bookworm 1.0.9-2+deb12u1 n/a Passes
8.4-cli-alpine3.24 1.2.1-r0 n/a Passes

CI is the first build of fpm, fpm-apache, fpm-nginx, Trixie, Alpine 3.23, and arm64. The arm64 Bookworm loader order is only covered by CI's arm64 tests.

How to test

scripts/dev.sh --variation frankenphp --version 8.4 --os bookworm
docker run --rm --entrypoint sh serversideup/php:8.4-frankenphp-bookworm -c \
  'frankenphp version; ldd /usr/local/bin/frankenphp /usr/lib/*/libcurl.so.4 | grep brotli'
scripts/test-image.sh serversideup/php:8.4-frankenphp-bookworm 8.4.27

Every Brotli library should resolve to /usr/local/lib. Repeat with --os alpine3.24 and --variation cli, and check the package version with apk list -I | grep brotli or dpkg-query -W libbrotli1.

The official PHP images still ship vulnerable libbrotli builds, which PHP's curl extension links against. List libbrotli1 (Debian) and brotli-libs (Alpine) in every variation so the build upgrades them to the patched distribution packages. Remove them once the official images ship the fix.

The Alpine install helper now runs `apk add --upgrade`, so an
already-installed package is upgraded the same way `apt-get install` does on Debian.
FrankenPHP 1.13.4 fixes seven vulnerabilities, including a crash in
worker mode that 1.13.2 introduced. Its cbrotli dependency needs libbrotli 1.1 or newer, which Bookworm doesn't ship, so Bookworm images now build Brotli 1.2.1 from source and load it ahead of the distribution library.
@github-actions

Copy link
Copy Markdown
Contributor

Images for PR #737

Build Test Publish
✅ 79 of 79 images built ✅ Every image passed on amd64 and arm64 ✅ Published to serversideup/php-dev

Try it:

docker run --rm -v "$PWD:/var/www/html" -p 8080:8080 serversideup/php-dev:737-8.5-fpm-nginx

Every image is on Docker Hub as serversideup/php-dev:737-<php>-<variation>-<os>. Browse all tags or view the run.

All images with sizes

Sizes are compressed, per architecture.

Variation PHP Base OS amd64 arm64 Image
cli 8.5.12 alpine3.23 48.1 MB 47.7 MB serversideup/php-dev:737-8.5.12-cli-alpine3.23
cli 8.5.12 alpine3.24 48.1 MB 47.7 MB serversideup/php-dev:737-8.5.12-cli-alpine3.24
cli 8.5.12 bookworm 196.2 MB 188.9 MB serversideup/php-dev:737-8.5.12-cli-bookworm
cli 8.5.12 trixie 192.8 MB 184.7 MB serversideup/php-dev:737-8.5.12-cli-trixie
cli 8.4.27 alpine3.23 45.0 MB 44.8 MB serversideup/php-dev:737-8.4.27-cli-alpine3.23
cli 8.4.27 alpine3.24 45.1 MB 44.9 MB serversideup/php-dev:737-8.4.27-cli-alpine3.24
cli 8.4.27 bookworm 192.3 MB 185.2 MB serversideup/php-dev:737-8.4.27-cli-bookworm
cli 8.4.27 trixie 188.8 MB 181.0 MB serversideup/php-dev:737-8.4.27-cli-trixie
cli 8.3.36 alpine3.23 41.0 MB 41.2 MB serversideup/php-dev:737-8.3.36-cli-alpine3.23
cli 8.3.36 alpine3.24 41.0 MB 41.2 MB serversideup/php-dev:737-8.3.36-cli-alpine3.24
cli 8.3.36 bookworm 187.4 MB 180.8 MB serversideup/php-dev:737-8.3.36-cli-bookworm
cli 8.3.36 trixie 184.0 MB 176.6 MB serversideup/php-dev:737-8.3.36-cli-trixie
cli 8.2.35 alpine3.23 40.2 MB 40.4 MB serversideup/php-dev:737-8.2.35-cli-alpine3.23
cli 8.2.35 alpine3.24 40.2 MB 40.4 MB serversideup/php-dev:737-8.2.35-cli-alpine3.24
cli 8.2.35 bookworm 186.5 MB 179.9 MB serversideup/php-dev:737-8.2.35-cli-bookworm
cli 8.2.35 trixie 183.1 MB 175.6 MB serversideup/php-dev:737-8.2.35-cli-trixie
cli 8.1.34 alpine3.22 43.4 MB 44.0 MB serversideup/php-dev:737-8.1.34-cli-alpine3.22
cli 8.1.34 bookworm 185.7 MB 179.0 MB serversideup/php-dev:737-8.1.34-cli-bookworm
cli 8.1.34 trixie 185.6 MB 178.5 MB serversideup/php-dev:737-8.1.34-cli-trixie
fpm 8.5.12 alpine3.23 42.1 MB 42.0 MB serversideup/php-dev:737-8.5.12-fpm-alpine3.23
fpm 8.5.12 alpine3.24 42.2 MB 42.0 MB serversideup/php-dev:737-8.5.12-fpm-alpine3.24
fpm 8.5.12 bookworm 184.4 MB 177.5 MB serversideup/php-dev:737-8.5.12-fpm-bookworm
fpm 8.5.12 trixie 181.0 MB 173.3 MB serversideup/php-dev:737-8.5.12-fpm-trixie
fpm 8.4.27 alpine3.23 40.0 MB 39.9 MB serversideup/php-dev:737-8.4.27-fpm-alpine3.23
fpm 8.4.27 alpine3.24 40.0 MB 40.0 MB serversideup/php-dev:737-8.4.27-fpm-alpine3.24
fpm 8.4.27 bookworm 182.3 MB 175.4 MB serversideup/php-dev:737-8.4.27-fpm-bookworm
fpm 8.4.27 trixie 178.8 MB 171.2 MB serversideup/php-dev:737-8.4.27-fpm-trixie
fpm 8.3.36 alpine3.23 36.8 MB 37.1 MB serversideup/php-dev:737-8.3.36-fpm-alpine3.23
fpm 8.3.36 alpine3.24 36.9 MB 37.2 MB serversideup/php-dev:737-8.3.36-fpm-alpine3.24
fpm 8.3.36 bookworm 179.1 MB 172.6 MB serversideup/php-dev:737-8.3.36-fpm-bookworm
fpm 8.3.36 trixie 175.7 MB 168.4 MB serversideup/php-dev:737-8.3.36-fpm-trixie
fpm 8.2.35 alpine3.23 36.1 MB 36.4 MB serversideup/php-dev:737-8.2.35-fpm-alpine3.23
fpm 8.2.35 alpine3.24 36.2 MB 36.5 MB serversideup/php-dev:737-8.2.35-fpm-alpine3.24
fpm 8.2.35 bookworm 178.4 MB 171.9 MB serversideup/php-dev:737-8.2.35-fpm-bookworm
fpm 8.2.35 trixie 175.0 MB 167.7 MB serversideup/php-dev:737-8.2.35-fpm-trixie
fpm 8.1.34 alpine3.22 39.5 MB 40.2 MB serversideup/php-dev:737-8.1.34-fpm-alpine3.22
fpm 8.1.34 bookworm 177.9 MB 171.4 MB serversideup/php-dev:737-8.1.34-fpm-bookworm
fpm 8.1.34 trixie 177.8 MB 170.8 MB serversideup/php-dev:737-8.1.34-fpm-trixie
fpm-apache 8.5.12 bookworm 190.7 MB 184.2 MB serversideup/php-dev:737-8.5.12-fpm-apache-bookworm
fpm-apache 8.5.12 trixie 187.4 MB 180.1 MB serversideup/php-dev:737-8.5.12-fpm-apache-trixie
fpm-apache 8.4.27 bookworm 188.6 MB 182.2 MB serversideup/php-dev:737-8.4.27-fpm-apache-bookworm
fpm-apache 8.4.27 trixie 185.2 MB 178.1 MB serversideup/php-dev:737-8.4.27-fpm-apache-trixie
fpm-apache 8.3.36 bookworm 185.4 MB 179.4 MB serversideup/php-dev:737-8.3.36-fpm-apache-bookworm
fpm-apache 8.3.36 trixie 182.1 MB 175.3 MB serversideup/php-dev:737-8.3.36-fpm-apache-trixie
fpm-apache 8.2.35 bookworm 184.7 MB 178.7 MB serversideup/php-dev:737-8.2.35-fpm-apache-bookworm
fpm-apache 8.2.35 trixie 181.4 MB 174.6 MB serversideup/php-dev:737-8.2.35-fpm-apache-trixie
fpm-apache 8.1.34 bookworm 184.3 MB 178.2 MB serversideup/php-dev:737-8.1.34-fpm-apache-bookworm
fpm-apache 8.1.34 trixie 184.2 MB 177.7 MB serversideup/php-dev:737-8.1.34-fpm-apache-trixie
fpm-nginx 8.5.12 alpine3.23 48.2 MB 48.5 MB serversideup/php-dev:737-8.5.12-fpm-nginx-alpine3.23
fpm-nginx 8.5.12 alpine3.24 49.6 MB 50.0 MB serversideup/php-dev:737-8.5.12-fpm-nginx-alpine3.24
fpm-nginx 8.5.12 bookworm 192.2 MB 185.6 MB serversideup/php-dev:737-8.5.12-fpm-nginx-bookworm
fpm-nginx 8.5.12 trixie 195.8 MB 188.2 MB serversideup/php-dev:737-8.5.12-fpm-nginx-trixie
fpm-nginx 8.4.27 alpine3.23 46.1 MB 46.5 MB serversideup/php-dev:737-8.4.27-fpm-nginx-alpine3.23
fpm-nginx 8.4.27 alpine3.24 47.5 MB 47.9 MB serversideup/php-dev:737-8.4.27-fpm-nginx-alpine3.24
fpm-nginx 8.4.27 bookworm 190.0 MB 183.6 MB serversideup/php-dev:737-8.4.27-fpm-nginx-bookworm
fpm-nginx 8.4.27 trixie 193.6 MB 186.2 MB serversideup/php-dev:737-8.4.27-fpm-nginx-trixie
fpm-nginx 8.3.36 alpine3.23 42.9 MB 43.7 MB serversideup/php-dev:737-8.3.36-fpm-nginx-alpine3.23
fpm-nginx 8.3.36 alpine3.24 44.3 MB 45.1 MB serversideup/php-dev:737-8.3.36-fpm-nginx-alpine3.24
fpm-nginx 8.3.36 bookworm 186.9 MB 180.8 MB serversideup/php-dev:737-8.3.36-fpm-nginx-bookworm
fpm-nginx 8.3.36 trixie 190.5 MB 183.4 MB serversideup/php-dev:737-8.3.36-fpm-nginx-trixie
fpm-nginx 8.2.35 alpine3.23 42.2 MB 43.0 MB serversideup/php-dev:737-8.2.35-fpm-nginx-alpine3.23
fpm-nginx 8.2.35 alpine3.24 43.6 MB 44.4 MB serversideup/php-dev:737-8.2.35-fpm-nginx-alpine3.24
fpm-nginx 8.2.35 bookworm 186.2 MB 180.1 MB serversideup/php-dev:737-8.2.35-fpm-nginx-bookworm
fpm-nginx 8.2.35 trixie 189.8 MB 182.7 MB serversideup/php-dev:737-8.2.35-fpm-nginx-trixie
fpm-nginx 8.1.34 alpine3.22 46.1 MB 47.3 MB serversideup/php-dev:737-8.1.34-fpm-nginx-alpine3.22
fpm-nginx 8.1.34 bookworm 186.8 MB 180.6 MB serversideup/php-dev:737-8.1.34-fpm-nginx-bookworm
fpm-nginx 8.1.34 trixie 194.4 MB 187.5 MB serversideup/php-dev:737-8.1.34-fpm-nginx-trixie
frankenphp 8.5.12 alpine3.23 77.1 MB 74.3 MB serversideup/php-dev:737-8.5.12-frankenphp-alpine3.23
frankenphp 8.5.12 alpine3.24 77.1 MB 74.4 MB serversideup/php-dev:737-8.5.12-frankenphp-alpine3.24
frankenphp 8.5.12 bookworm 219.4 MB 210.2 MB serversideup/php-dev:737-8.5.12-frankenphp-bookworm
frankenphp 8.5.12 trixie 214.6 MB 204.6 MB serversideup/php-dev:737-8.5.12-frankenphp-trixie
frankenphp 8.4.27 alpine3.23 73.0 MB 70.6 MB serversideup/php-dev:737-8.4.27-frankenphp-alpine3.23
frankenphp 8.4.27 alpine3.24 73.0 MB 70.7 MB serversideup/php-dev:737-8.4.27-frankenphp-alpine3.24
frankenphp 8.4.27 bookworm 215.5 MB 206.5 MB serversideup/php-dev:737-8.4.27-frankenphp-bookworm
frankenphp 8.4.27 trixie 210.7 MB 200.9 MB serversideup/php-dev:737-8.4.27-frankenphp-trixie
frankenphp 8.3.36 alpine3.23 68.1 MB 66.1 MB serversideup/php-dev:737-8.3.36-frankenphp-alpine3.23
frankenphp 8.3.36 alpine3.24 68.1 MB 66.2 MB serversideup/php-dev:737-8.3.36-frankenphp-alpine3.24
frankenphp 8.3.36 bookworm 210.6 MB 202.0 MB serversideup/php-dev:737-8.3.36-frankenphp-bookworm
frankenphp 8.3.36 trixie 205.8 MB 196.4 MB serversideup/php-dev:737-8.3.36-frankenphp-trixie

Updated on every push to this PR.

@jaydrogers
jaydrogers marked this pull request as ready for review October 26, 2026 23:03
@jaydrogers
jaydrogers merged commit 399b38b into main Oct 26, 2026
131 checks passed
@jaydrogers
jaydrogers deleted the security-brotli-frankenphp-1.13.4 branch October 26, 2026 23:03
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