Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .github/workflows/legacy-v5.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ jobs:
docker pull --quiet ghcr.io/${{ github.repository_owner }}/php:rc${GITHUB_RUN_ID}-${{ matrix.php_version }}-v5-slim-${{ matrix.variant }}-amd64
# Retrieve minor
PHP_PATCH_MINOR=`docker run --rm ghcr.io/${{ github.repository_owner }}/php:rc${GITHUB_RUN_ID}-${{ matrix.php_version }}-v5-slim-${{ matrix.variant }}-amd64 php -v | head -n1 | grep -P '\d+\.\d+\.\d+' -o | head -n1`
# The php2shell backport keeps the version number of 7.4, 8.0 and 8.1: tag it apart from the existing X.Y.Z tags
if [[ " 7.4 8.0 8.1 " == *" ${{ matrix.php_version }} "* ]]; then
PHP_PATCH_MINOR="${PHP_PATCH_MINOR}-php2shell"
fi
echo "PHP_PATCH_MINOR=${PHP_PATCH_MINOR}"
echo "PHP_PATCH_MINOR=${PHP_PATCH_MINOR}" >> $GITHUB_ENV
- name: Get list of images for this variant
Expand All @@ -121,7 +125,7 @@ jobs:

for TARGET in $TARGETS; do
TAG_ORI=$(REPO="ghcr.io/${{ github.repository_owner }}/php" TAG_PREFIX="rc${GITHUB_RUN_ID}-" docker buildx bake ${TARGET} --progress=quiet --print | jq -r ".target | to_entries[] | select(.key == \"${TARGET}\") | .value.tags[0]")
TAG_PATH=$(REPO="php" PHP_PATCH_MINOR="${{ env.PHP_PATCH_MINOR }}" docker buildx bake ${TARGET} --progress=quiet --print | jq -r ".target | to_entries[] | select(.key == \"${TARGET}\") | .value.tags[0]")
TAG_PATH=$(REPO="php" IS_RELEASE="1" PHP_PATCH_MINOR="${{ env.PHP_PATCH_MINOR }}" docker buildx bake ${TARGET} --progress=quiet --print | jq -r ".target | to_entries[] | select(.key == \"${TARGET}\") | .value.tags[1]")
TAG_MINOR=$(REPO="php" docker buildx bake ${TARGET} --progress=quiet --print | jq -r ".target | to_entries[] | select(.key == \"${TARGET}\") | .value.tags[0]")

# Create manifest for rc tag (always)
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ jobs:

for TARGET in $TARGETS; do
TAG_ORI=$(REPO="ghcr.io/${{ github.repository_owner }}/php" TAG_PREFIX="rc${GITHUB_RUN_ID}-" docker buildx bake ${TARGET} --progress=quiet --print | jq -r ".target | to_entries[] | select(.key == \"${TARGET}\") | .value.tags[0]")
TAG_PATH=$(REPO="php" PHP_PATCH_MINOR="${{ env.PHP_PATCH_MINOR }}" docker buildx bake ${TARGET} --progress=quiet --print | jq -r ".target | to_entries[] | select(.key == \"${TARGET}\") | .value.tags[0]")
TAG_PATH=$(REPO="php" IS_RELEASE="1" PHP_PATCH_MINOR="${{ env.PHP_PATCH_MINOR }}" docker buildx bake ${TARGET} --progress=quiet --print | jq -r ".target | to_entries[] | select(.key == \"${TARGET}\") | .value.tags[1]")
TAG_MINOR=$(REPO="php" docker buildx bake ${TARGET} --progress=quiet --print | jq -r ".target | to_entries[] | select(.key == \"${TARGET}\") | .value.tags[0]")

# Create manifest for rc tag (always)
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@

### Minor changes

* **2026-10-23**
* Security: php2shell is fixed in the arm64 images too, now that the fixed PHP packages are published for arm64. The php2shell test fails again for a vulnerable image on every architecture
* The tags of the PHP patch versions (e.g. `8.5.12-v5-cli`) are published again: they were no longer published since 2025-12-10. The `X.Y-v5-*` tags are not affected
* PHP 7.4, 8.0 and 8.1: the images fixed against php2shell are tagged `7.4.33-php2shell-v5-*`, `8.0.30-php2shell-v5-*` and `8.1.34-php2shell-v5-*`, the existing `7.4.33-v5-*`, `8.0.30-v5-*` tags being kept unchanged

* **2026-10-21**
* Security: fix of php2shell (CVE-2026-109618 and CVE-2026-109619, CVSS 9.2) in all the v5 amd64 images. PHP 7.4, 8.0 and 8.1 images are rebuilt with the backport of the fix (same PHP version: 7.4.33, 8.0.30, 8.1.34). The arm64 images will be fixed when the fixed PHP packages are published for arm64. See [php2shell](docs/security-php2shell.md)
* NodeJS 18 and 20 variants are built again for all the PHP versions, by the legacy workflow
Expand Down
7 changes: 3 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@

# General purpose PHP images for Docker

> **Security: php2shell (CVE-2026-109618 and CVE-2026-109619, CVSS 9.2) is fixed in all the v5 amd64 images**
> **Security: php2shell (CVE-2026-109618 and CVE-2026-109619, CVSS 9.2) is fixed in all the v5 images**
>
> Pull the images again, recreate your containers and rebuild the images built from ours. The **arm64** images
> (Apple Silicon, AWS Graviton...) are **not fixed yet**: the fixed PHP packages for arm64 are still being built
> upstream, and the images will be updated as soon as they are published. The v4 images are **not** fixed: migrate to
> Pull the images again, recreate your containers and rebuild the images built from ours. **Update:** the arm64 images,
> first published without the fix, are now fixed too: pull them again. The v4 images are **not** fixed: migrate to
> v5. See [what to do](docs/security-php2shell.md).

This repository contains a set of developer-friendly, general purpose PHP images for Docker.
Expand Down
23 changes: 10 additions & 13 deletions docs/security-php2shell.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
Two critical vulnerabilities of PHP (CVSS 9.2), disclosed on 2026-10-21, allow remote code execution without
authentication. Exploits are public: update now.

All the v5 images are fixed on amd64, from PHP 7.4 to 8.5, with or without NodeJS (`-node18` to `-node26`). The
arm64 images are not fixed yet: see [arm64 images](#arm64-images).
All the v5 images are fixed, from PHP 7.4 to 8.5, on amd64 and arm64, with or without NodeJS (`-node18` to `-node26`).

> **Update: the arm64 images are now fixed too.** They were first published without the fix, the fixed PHP packages
> being published later for arm64. On arm64 (Apple Silicon, AWS Graviton...), pull the images again and recreate your
> containers, even if you already did it after 2026-10-21.

## What to do

Expand All @@ -22,17 +25,14 @@ arm64 images are not fixed yet: see [arm64 images](#arm64-images).

In your CI, check that the base image is pulled again and not taken from a cache.

3. Use the `X.Y-v5-*` tags (e.g. `8.4-v5-apache`). The tags of older PHP patch versions (e.g. `8.4.26-v5-apache`) are
not fixed.
3. Use the `X.Y-v5-*` tags (e.g. `8.4-v5-apache`), or the tags of the fixed PHP patch versions (e.g.
`8.4.27-v5-apache`). The tags of older PHP patch versions (e.g. `8.4.26-v5-apache`) are not fixed.

PHP 7.4, 8.0 and 8.1 images still show 7.4.33, 8.0.30 and 8.1.34 in `php -v`: the fix does not change the version.
Their existing patch version tags (e.g. `7.4.33-v5-apache`) are kept unchanged and are **not** fixed: the fixed images
are tagged `7.4.33-php2shell-v5-*`, `8.0.30-php2shell-v5-*` and `8.1.34-php2shell-v5-*`.

## arm64 images

The images install PHP from the packages of [packages.sury.org](https://packages.sury.org/php/), which publishes the
fixed packages for amd64 first: the arm64 packages are still being built. Until they are published, all the arm64
images stay vulnerable, including those of the tags of the fixed PHP patch versions (on arm64, `8.4.27-v5-apache`
still contains PHP 8.4.26). The arm64 images will be rebuilt as soon as the packages are available.
## Check an image

Check the PHP version of your image: 8.2.35, 8.3.36, 8.4.27, 8.5.12 or newer are fixed. PHP 7.4, 8.0 and 8.1 keep
their version number, and are fixed when the PHP binary contains the fix:
Expand All @@ -43,9 +43,6 @@ $ docker run --rm thecodingmachine/php:8.1-v5-cli bash -c 'grep -c zend_mm_safe_

`0` means that the image is vulnerable.

In the meantime, an arm64 host can run the amd64 image through emulation (`--platform linux/amd64`, or
`platform: linux/amd64` in a Compose file), which is much slower.

## NodeJS 16 and older

The v5 images are not built with NodeJS 16 and older. Use a maintained NodeJS version (22, 24 or 26) when possible.
Expand Down
27 changes: 8 additions & 19 deletions tests-suite/php-security-patches.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,14 @@
# The end-of-life branches (7.4, 8.0, 8.1) only got a source backport that keeps the
# version number (7.4.33, 8.0.30, 8.1.34): it is detected with the zend_mm_safe_error_ex
# symbol it adds to the Zend engine, in every PHP SAPI shipped in the image.
# The fixed packages are not yet published for arm64: a vulnerable arm64 image is only a warning.
test_php2shellPatched() {
IMAGE="${REPO}:${TAG_PREFIX}${PHP_VERSION}-${BRANCH}-${BRANCH_VARIANT}${ARCH_SUFFIX}"
if [[ "$(printf '%s\n' "$PHP_VERSION" "8.2" | sort -V | head -n 1)" != "8.2" ]]; then
RESULT="$(docker run ${RUN_OPTIONS} --rm "${IMAGE}" \
bash -c 'dpkg --print-architecture
for BIN in /usr/bin/php${PHP_VERSION} /usr/sbin/php-fpm${PHP_VERSION} /usr/lib/apache2/modules/libphp${PHP_VERSION}.so; do
RESULT="$(docker run ${RUN_OPTIONS} --rm \
"${REPO}:${TAG_PREFIX}${PHP_VERSION}-${BRANCH}-${BRANCH_VARIANT}${ARCH_SUFFIX}" \
bash -c 'for BIN in /usr/bin/php${PHP_VERSION} /usr/sbin/php-fpm${PHP_VERSION} /usr/lib/apache2/modules/libphp${PHP_VERSION}.so; do
[ -e "${BIN}" ] || continue
grep -q zend_mm_safe_error_ex "${BIN}" && echo "patched ${BIN}" || echo "vulnerable ${BIN}"
done' 2>/dev/null)"
if [[ "$RESULT" == arm64* ]] && [[ "$RESULT" == *vulnerable* ]]; then
echo "::warning::${IMAGE} (arm64) is vulnerable to CVE-2026-109618: PHP SAPI without the backport"
return
fi
assert_matches "patched /usr/bin/php${PHP_VERSION}" "$RESULT" "PHP CLI not found or not patched"
assert_not_matches "vulnerable" "$RESULT" "PHP SAPI without the CVE-2026-109618 backport"
else
Expand All @@ -31,15 +25,10 @@ test_php2shellPatched() {
8.4) FIXED_VERSION="8.4.27" ;;
*) FIXED_VERSION="8.5.12" ;;
esac
RESULT="$(docker run ${RUN_OPTIONS} --rm "${IMAGE}" \
bash -c 'dpkg --print-architecture; php -r "echo PHP_VERSION;"' 2>/dev/null)"
ARCH="$(head -n 1 <<< "$RESULT")"
VERSION="$(tail -n 1 <<< "$RESULT")"
if [[ "$ARCH" == "arm64" ]] && [[ "$(printf '%s\n' "$VERSION" "${FIXED_VERSION}" | sort -V | head -n 1)" != "${FIXED_VERSION}" ]]; then
echo "::warning::${IMAGE} (arm64): PHP ${VERSION} is vulnerable to CVE-2026-109618 (fixed in ${FIXED_VERSION})"
return
fi
assert_equals "${FIXED_VERSION}" "$(printf '%s\n' "$VERSION" "${FIXED_VERSION}" | sort -V | head -n 1)" \
"PHP ${VERSION} is vulnerable to CVE-2026-109618 (fixed in ${FIXED_VERSION})"
RESULT="$(docker run ${RUN_OPTIONS} --rm \
"${REPO}:${TAG_PREFIX}${PHP_VERSION}-${BRANCH}-${BRANCH_VARIANT}${ARCH_SUFFIX}" \
php -r 'echo PHP_VERSION;' 2>/dev/null)"
assert_equals "${FIXED_VERSION}" "$(printf '%s\n' "$RESULT" "${FIXED_VERSION}" | sort -V | head -n 1)" \
"PHP ${RESULT} is vulnerable to CVE-2026-109618 (fixed in ${FIXED_VERSION})"
fi
}
7 changes: 3 additions & 4 deletions utils/README.blueprint.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@

# General purpose PHP images for Docker

> **Security: php2shell (CVE-2026-109618 and CVE-2026-109619, CVSS 9.2) is fixed in all the v5 amd64 images**
> **Security: php2shell (CVE-2026-109618 and CVE-2026-109619, CVSS 9.2) is fixed in all the v5 images**
>
> Pull the images again, recreate your containers and rebuild the images built from ours. The **arm64** images
> (Apple Silicon, AWS Graviton...) are **not fixed yet**: the fixed PHP packages for arm64 are still being built
> upstream, and the images will be updated as soon as they are published. The v4 images are **not** fixed: migrate to
> Pull the images again, recreate your containers and rebuild the images built from ours. **Update:** the arm64 images,
> first published without the fix, are now fixed too: pull them again. The v4 images are **not** fixed: migrate to
> v5. See [what to do](docs/security-php2shell.md).

This repository contains a set of developer-friendly, general purpose PHP images for Docker.
Expand Down
Loading