From 316d7722d3b20672d584034edef033f22dc160dc Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Wed, 21 Oct 2026 11:56:01 -0300 Subject: [PATCH 1/6] fix(security): require PHP patched for critical RCEs Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- .docker/wordpress/Dockerfile | 5 +++++ .github/workflows/docker-publish.yml | 2 ++ 2 files changed, 7 insertions(+) diff --git a/.docker/wordpress/Dockerfile b/.docker/wordpress/Dockerfile index 133759a..a7cb34b 100644 --- a/.docker/wordpress/Dockerfile +++ b/.docker/wordpress/Dockerfile @@ -2,6 +2,11 @@ ARG VERSION_WORDPRESS ARG VERSION_PHP FROM wordpress:${VERSION_WORDPRESS}-php${VERSION_PHP}-fpm +# Stop builds before publication when upstream PHP still lacks the October 2026 RCE fixes. +# CVE-2026-109618 / CVE-2026-109619; unsupported PHP branches fail closed. +RUN php -r '$minimum = ["8.2" => "8.2.35", "8.3" => "8.3.36", "8.4" => "8.4.27", "8.5" => "8.5.12"]; $series = PHP_MAJOR_VERSION . "." . PHP_MINOR_VERSION; if (!isset($minimum[$series]) || version_compare(PHP_VERSION, $minimum[$series], "<")) { fwrite(STDERR, "Unpatched or unsupported PHP runtime: " . PHP_VERSION . PHP_EOL); exit(1); }' + + RUN apt-get update RUN apt-get install -y \ rsync \ diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 1e68340..1bd4f2f 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -54,6 +54,7 @@ jobs: context: .docker/wordpress file: .docker/wordpress/Dockerfile platforms: linux/amd64,linux/arm64 + pull: true push: false build-args: | VERSION_WORDPRESS=${{ env.VERSION_WORDPRESS }} @@ -70,6 +71,7 @@ jobs: context: .docker/wordpress file: .docker/wordpress/Dockerfile platforms: linux/amd64,linux/arm64 + pull: true push: true build-args: | VERSION_WORDPRESS=${{ env.VERSION_WORDPRESS }} From 9f54e156637f149db2e34677085b2fb8741e59d7 Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Wed, 21 Oct 2026 12:02:27 -0300 Subject: [PATCH 2/6] test(ci): verify patched PHP before registry publication Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- .github/workflows/docker-publish.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 1bd4f2f..a00f3ac 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -1,6 +1,9 @@ name: Docker WordPress Publish on: + pull_request: + branches: + - main push: branches: - main @@ -42,6 +45,7 @@ jobs: wordpress-buildx- - name: Log in to GitHub Container Registry + if: github.event_name != 'pull_request' uses: docker/login-action@v3 with: registry: ghcr.io From a3114d33f817e6abf9529fbfbaa6bfe7267b1f54 Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Thu, 22 Oct 2026 14:15:00 -0300 Subject: [PATCH 3/6] fix(deps): pin patched WordPress image for Dependabot Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- .docker/wordpress/Dockerfile | 7 +------ .github/dependabot.yml | 6 ++++++ .github/workflows/docker-publish.yml | 11 ----------- common-services.yml | 2 -- 4 files changed, 7 insertions(+), 19 deletions(-) create mode 100644 .github/dependabot.yml diff --git a/.docker/wordpress/Dockerfile b/.docker/wordpress/Dockerfile index a7cb34b..52572a8 100644 --- a/.docker/wordpress/Dockerfile +++ b/.docker/wordpress/Dockerfile @@ -1,10 +1,5 @@ -ARG VERSION_WORDPRESS -ARG VERSION_PHP -FROM wordpress:${VERSION_WORDPRESS}-php${VERSION_PHP}-fpm +FROM wordpress:7.1.3-php8.3-fpm@sha256:788d6b34cb89997483ff2a08e2e04d1df28ce284ca046cd7990b0be10828c5b9 -# Stop builds before publication when upstream PHP still lacks the October 2026 RCE fixes. -# CVE-2026-109618 / CVE-2026-109619; unsupported PHP branches fail closed. -RUN php -r '$minimum = ["8.2" => "8.2.35", "8.3" => "8.3.36", "8.4" => "8.4.27", "8.5" => "8.5.12"]; $series = PHP_MAJOR_VERSION . "." . PHP_MINOR_VERSION; if (!isset($minimum[$series]) || version_compare(PHP_VERSION, $minimum[$series], "<")) { fwrite(STDERR, "Unpatched or unsupported PHP runtime: " . PHP_VERSION . PHP_EOL); exit(1); }' RUN apt-get update diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..8798b14 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: docker + directory: /.docker/wordpress + schedule: + interval: daily diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index a00f3ac..f0939bc 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -8,8 +8,6 @@ on: branches: - main workflow_dispatch: - schedule: - - cron: '0 2 * * *' concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} @@ -19,9 +17,6 @@ jobs: build-and-push: name: Build and push image runs-on: ubuntu-latest - env: - VERSION_WORDPRESS: "7.1.3" - VERSION_PHP: "8.3" permissions: contents: read packages: write @@ -60,9 +55,6 @@ jobs: platforms: linux/amd64,linux/arm64 pull: true push: false - build-args: | - VERSION_WORDPRESS=${{ env.VERSION_WORDPRESS }} - VERSION_PHP=${{ env.VERSION_PHP }} tags: | ghcr.io/librecodecoop/wordpress-docker:${{ github.sha }} cache-from: type=local,src=/tmp/.buildx-cache @@ -77,9 +69,6 @@ jobs: platforms: linux/amd64,linux/arm64 pull: true push: true - build-args: | - VERSION_WORDPRESS=${{ env.VERSION_WORDPRESS }} - VERSION_PHP=${{ env.VERSION_PHP }} tags: | ghcr.io/librecodecoop/wordpress-docker:${{ github.sha }} ghcr.io/librecodecoop/wordpress-docker:latest diff --git a/common-services.yml b/common-services.yml index b8c2e4b..21010a0 100644 --- a/common-services.yml +++ b/common-services.yml @@ -4,8 +4,6 @@ services: # build: # context: .docker/wordpress # args: - # VERSION_WORDPRESS: ${VERSION_WORDPRESS:-6.9} - # VERSION_PHP: ${VERSION_PHP:-8.3} restart: unless-stopped volumes: - ./volumes/wordpress:/var/www/html From 5e899d35d73367f4400d13a68015553f4e1aec81 Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Thu, 22 Oct 2026 15:54:44 -0300 Subject: [PATCH 4/6] fix(build): restore configurable WordPress and PHP versions Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- .docker/wordpress/Dockerfile | 7 ++-- .github/dependabot.yml | 6 ---- .github/workflows/docker-publish.yml | 9 +++++ common-services.yml | 2 ++ renovate.json | 37 +++++++++++++++++++++ tests/security/image-version-selection.bats | 21 ++++++++++++ 6 files changed, 74 insertions(+), 8 deletions(-) delete mode 100644 .github/dependabot.yml create mode 100644 renovate.json create mode 100644 tests/security/image-version-selection.bats diff --git a/.docker/wordpress/Dockerfile b/.docker/wordpress/Dockerfile index 52572a8..8312cee 100644 --- a/.docker/wordpress/Dockerfile +++ b/.docker/wordpress/Dockerfile @@ -1,6 +1,9 @@ -FROM wordpress:7.1.3-php8.3-fpm@sha256:788d6b34cb89997483ff2a08e2e04d1df28ce284ca046cd7990b0be10828c5b9 - +ARG VERSION_WORDPRESS +ARG VERSION_PHP +FROM wordpress:${VERSION_WORDPRESS}-php${VERSION_PHP}-fpm +# Reject PHP runtimes affected by the October 2026 security advisories. +RUN php -r '$minimum = ["8.2" => "8.2.35", "8.3" => "8.3.36", "8.4" => "8.4.27", "8.5" => "8.5.12"]; $series = PHP_MAJOR_VERSION . "." . PHP_MINOR_VERSION; if (!isset($minimum[$series]) || version_compare(PHP_VERSION, $minimum[$series], "<")) { fwrite(STDERR, "Unpatched or unsupported PHP runtime: " . PHP_VERSION . PHP_EOL); exit(1); }' RUN apt-get update RUN apt-get install -y \ diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index 8798b14..0000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,6 +0,0 @@ -version: 2 -updates: - - package-ecosystem: docker - directory: /.docker/wordpress - schedule: - interval: daily diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index f0939bc..501fd43 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -17,6 +17,9 @@ jobs: build-and-push: name: Build and push image runs-on: ubuntu-latest + env: + VERSION_WORDPRESS: "7.1.3" + VERSION_PHP: "8.3" permissions: contents: read packages: write @@ -55,6 +58,9 @@ jobs: platforms: linux/amd64,linux/arm64 pull: true push: false + build-args: | + VERSION_WORDPRESS=${{ env.VERSION_WORDPRESS }} + VERSION_PHP=${{ env.VERSION_PHP }} tags: | ghcr.io/librecodecoop/wordpress-docker:${{ github.sha }} cache-from: type=local,src=/tmp/.buildx-cache @@ -69,6 +75,9 @@ jobs: platforms: linux/amd64,linux/arm64 pull: true push: true + build-args: | + VERSION_WORDPRESS=${{ env.VERSION_WORDPRESS }} + VERSION_PHP=${{ env.VERSION_PHP }} tags: | ghcr.io/librecodecoop/wordpress-docker:${{ github.sha }} ghcr.io/librecodecoop/wordpress-docker:latest diff --git a/common-services.yml b/common-services.yml index 21010a0..1d45bfc 100644 --- a/common-services.yml +++ b/common-services.yml @@ -4,6 +4,8 @@ services: # build: # context: .docker/wordpress # args: + # VERSION_WORDPRESS: ${VERSION_WORDPRESS:-7.1.3} + # VERSION_PHP: ${VERSION_PHP:-8.3} restart: unless-stopped volumes: - ./volumes/wordpress:/var/www/html diff --git a/renovate.json b/renovate.json new file mode 100644 index 0000000..1b69c6d --- /dev/null +++ b/renovate.json @@ -0,0 +1,37 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "enabledManagers": [ + "custom.regex" + ], + "dependencyDashboard": false, + "customManagers": [ + { + "customType": "regex", + "managerFilePatterns": [ + "/^\\.github\\/workflows\\/docker-publish\\.yml$/" + ], + "matchStrings": [ + "VERSION_WORDPRESS:\\s*\"(?\\d+\\.\\d+\\.\\d+)\"" + ], + "datasourceTemplate": "docker", + "depNameTemplate": "wordpress", + "versioningTemplate": "semver-coerced", + "extractVersionTemplate": "^(?\\d+\\.\\d+\\.\\d+)$" + } + ], + "packageRules": [ + { + "matchManagers": [ + "custom.regex" + ], + "matchPackageNames": [ + "wordpress" + ], + "matchUpdateTypes": [ + "major", + "minor" + ], + "enabled": false + } + ] +} diff --git a/tests/security/image-version-selection.bats b/tests/security/image-version-selection.bats new file mode 100644 index 0000000..81d7828 --- /dev/null +++ b/tests/security/image-version-selection.bats @@ -0,0 +1,21 @@ +#!/usr/bin/env bats + +setup() { + cd "$BATS_TEST_DIRNAME/../.." +} + +@test "WordPress and PHP versions remain configurable Docker build arguments" { + grep -Fxq 'ARG VERSION_WORDPRESS' .docker/wordpress/Dockerfile + grep -Fxq 'ARG VERSION_PHP' .docker/wordpress/Dockerfile + grep -Fxq 'FROM wordpress:${VERSION_WORDPRESS}-php${VERSION_PHP}-fpm' .docker/wordpress/Dockerfile +} + +@test "both CI image builds forward the selected WordPress and PHP versions" { + run grep -Fc 'VERSION_WORDPRESS=${{ env.VERSION_WORDPRESS }}' .github/workflows/docker-publish.yml + [ "$status" -eq 0 ] + [ "$output" -eq 2 ] + + run grep -Fc 'VERSION_PHP=${{ env.VERSION_PHP }}' .github/workflows/docker-publish.yml + [ "$status" -eq 0 ] + [ "$output" -eq 2 ] +} From c7ac7f72f37826910e1afb56971b93efd291aaab Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Thu, 22 Oct 2026 16:32:28 -0300 Subject: [PATCH 5/6] fix(deps): manage selectable WordPress base with Renovate Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- .docker/wordpress/Dockerfile | 6 ++---- .github/workflows/docker-publish.yml | 14 ++++++++------ README.md | 7 +++++++ renovate.json | 6 +++--- tests/security/image-version-selection.bats | 13 +++++++------ 5 files changed, 27 insertions(+), 19 deletions(-) diff --git a/.docker/wordpress/Dockerfile b/.docker/wordpress/Dockerfile index 8312cee..109861a 100644 --- a/.docker/wordpress/Dockerfile +++ b/.docker/wordpress/Dockerfile @@ -1,9 +1,7 @@ ARG VERSION_WORDPRESS ARG VERSION_PHP -FROM wordpress:${VERSION_WORDPRESS}-php${VERSION_PHP}-fpm - -# Reject PHP runtimes affected by the October 2026 security advisories. -RUN php -r '$minimum = ["8.2" => "8.2.35", "8.3" => "8.3.36", "8.4" => "8.4.27", "8.5" => "8.5.12"]; $series = PHP_MAJOR_VERSION . "." . PHP_MINOR_VERSION; if (!isset($minimum[$series]) || version_compare(PHP_VERSION, $minimum[$series], "<")) { fwrite(STDERR, "Unpatched or unsupported PHP runtime: " . PHP_VERSION . PHP_EOL); exit(1); }' +ARG WORDPRESS_BASE_IMAGE=wordpress:${VERSION_WORDPRESS}-php${VERSION_PHP}-fpm +FROM ${WORDPRESS_BASE_IMAGE} RUN apt-get update RUN apt-get install -y \ diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 501fd43..26577a7 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -8,6 +8,11 @@ on: branches: - main workflow_dispatch: + inputs: + wordpress_base_image: + description: 'Override the official WordPress base image (version and PHP series)' + required: false + type: string concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} @@ -18,8 +23,7 @@ jobs: name: Build and push image runs-on: ubuntu-latest env: - VERSION_WORDPRESS: "7.1.3" - VERSION_PHP: "8.3" + WORDPRESS_BASE_IMAGE: wordpress:7.1.3-php8.3-fpm@sha256:788d6b34cb89997483ff2a08e2e04d1df28ce284ca046cd7990b0be10828c5b9 permissions: contents: read packages: write @@ -59,8 +63,7 @@ jobs: pull: true push: false build-args: | - VERSION_WORDPRESS=${{ env.VERSION_WORDPRESS }} - VERSION_PHP=${{ env.VERSION_PHP }} + WORDPRESS_BASE_IMAGE=${{ inputs.wordpress_base_image || env.WORDPRESS_BASE_IMAGE }} tags: | ghcr.io/librecodecoop/wordpress-docker:${{ github.sha }} cache-from: type=local,src=/tmp/.buildx-cache @@ -76,8 +79,7 @@ jobs: pull: true push: true build-args: | - VERSION_WORDPRESS=${{ env.VERSION_WORDPRESS }} - VERSION_PHP=${{ env.VERSION_PHP }} + WORDPRESS_BASE_IMAGE=${{ inputs.wordpress_base_image || env.WORDPRESS_BASE_IMAGE }} tags: | ghcr.io/librecodecoop/wordpress-docker:${{ github.sha }} ghcr.io/librecodecoop/wordpress-docker:latest diff --git a/README.md b/README.md index 9cc7eac..d14fc77 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,13 @@ It is useful when you need to: Prerequisite: [Docker](https://docs.docker.com/get-docker/) must be installed on your operating system. +## Base image updates + +Renovate opens PRs for the default WordPress image's version and digest in +`.github/workflows/docker-publish.yml`. Builds use that immutable image by +default. For another version, supply `wordpress_base_image` to the manual +workflow or use `VERSION_WORDPRESS` and `VERSION_PHP` as local Docker build args. + ## Setup ### Production diff --git a/renovate.json b/renovate.json index 1b69c6d..1ac139d 100644 --- a/renovate.json +++ b/renovate.json @@ -4,6 +4,7 @@ "custom.regex" ], "dependencyDashboard": false, + "separateMinorPatch": true, "customManagers": [ { "customType": "regex", @@ -11,12 +12,11 @@ "/^\\.github\\/workflows\\/docker-publish\\.yml$/" ], "matchStrings": [ - "VERSION_WORDPRESS:\\s*\"(?\\d+\\.\\d+\\.\\d+)\"" + "WORDPRESS_BASE_IMAGE: wordpress:(?\\d+\\.\\d+\\.\\d+-php\\d+\\.\\d+-fpm)@(?sha256:[a-f0-9]{64})" ], "datasourceTemplate": "docker", "depNameTemplate": "wordpress", - "versioningTemplate": "semver-coerced", - "extractVersionTemplate": "^(?\\d+\\.\\d+\\.\\d+)$" + "versioningTemplate": "docker" } ], "packageRules": [ diff --git a/tests/security/image-version-selection.bats b/tests/security/image-version-selection.bats index 81d7828..e56dd7e 100644 --- a/tests/security/image-version-selection.bats +++ b/tests/security/image-version-selection.bats @@ -4,18 +4,19 @@ setup() { cd "$BATS_TEST_DIRNAME/../.." } -@test "WordPress and PHP versions remain configurable Docker build arguments" { +@test "WordPress and PHP versions remain selectable" { grep -Fxq 'ARG VERSION_WORDPRESS' .docker/wordpress/Dockerfile grep -Fxq 'ARG VERSION_PHP' .docker/wordpress/Dockerfile - grep -Fxq 'FROM wordpress:${VERSION_WORDPRESS}-php${VERSION_PHP}-fpm' .docker/wordpress/Dockerfile + grep -Fxq 'ARG WORDPRESS_BASE_IMAGE=wordpress:${VERSION_WORDPRESS}-php${VERSION_PHP}-fpm' .docker/wordpress/Dockerfile + grep -Fxq 'FROM ${WORDPRESS_BASE_IMAGE}' .docker/wordpress/Dockerfile } -@test "both CI image builds forward the selected WordPress and PHP versions" { - run grep -Fc 'VERSION_WORDPRESS=${{ env.VERSION_WORDPRESS }}' .github/workflows/docker-publish.yml +@test "CI defaults to Renovate-managed image and allows an override" { + run grep -Fc 'WORDPRESS_BASE_IMAGE=${{ inputs.wordpress_base_image || env.WORDPRESS_BASE_IMAGE }}' .github/workflows/docker-publish.yml [ "$status" -eq 0 ] [ "$output" -eq 2 ] - run grep -Fc 'VERSION_PHP=${{ env.VERSION_PHP }}' .github/workflows/docker-publish.yml + run grep -Ec 'WORDPRESS_BASE_IMAGE: wordpress:[0-9]+\.[0-9]+\.[0-9]+-php[0-9]+\.[0-9]+-fpm@sha256:[a-f0-9]{64}' .github/workflows/docker-publish.yml [ "$status" -eq 0 ] - [ "$output" -eq 2 ] + [ "$output" -eq 1 ] } From 76180d8d9556bea1d25f47d76433aec44a99f1f5 Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Thu, 22 Oct 2026 16:41:28 -0300 Subject: [PATCH 6/6] docs: remove redundant dependency update instructions Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- README.md | 7 ------- 1 file changed, 7 deletions(-) diff --git a/README.md b/README.md index d14fc77..9cc7eac 100644 --- a/README.md +++ b/README.md @@ -12,13 +12,6 @@ It is useful when you need to: Prerequisite: [Docker](https://docs.docker.com/get-docker/) must be installed on your operating system. -## Base image updates - -Renovate opens PRs for the default WordPress image's version and digest in -`.github/workflows/docker-publish.yml`. Builds use that immutable image by -default. For another version, supply `wordpress_base_image` to the manual -workflow or use `VERSION_WORDPRESS` and `VERSION_PHP` as local Docker build args. - ## Setup ### Production