From db5772d7f500bcf244166b1aa3c0f4d974f805bd Mon Sep 17 00:00:00 2001 From: Francesco Picone Date: Wed, 21 Oct 2026 11:05:13 +0200 Subject: [PATCH] PHP fissato alla 8.3.36 (CVE-2026-109618, CVE-2026-109619) - Dockerfile: ARG PHP_VERSION=8.3.36 e FROM php:${PHP_VERSION}-fpm al posto del tag mobile php:8.3-fpm, che la cache di Docker poteva risolvere sulla 8.3.35 vulnerabile. Una build ora prende la versione corretta o fallisce. - phpredis da GitHub (versione fissata) invece di pecl.php.net, che il giorno della patch rispondeva 504 e bloccava la build. - Test contro il ritorno a un tag mobile o a una versione vulnerabile. - PHP_VERSION passabile dal compose solo per prove locali. Co-Authored-By: Claude Opus 5.5 --- HANDOFF.md | 25 +++++++++++++++++++ docker-compose.yml | 16 +++++++++++++ docker/php/Dockerfile | 32 ++++++++++++++++++++++--- tests/Unit/VersionePhpTest.php | 44 ++++++++++++++++++++++++++++++++++ 4 files changed, 114 insertions(+), 3 deletions(-) create mode 100644 tests/Unit/VersionePhpTest.php diff --git a/HANDOFF.md b/HANDOFF.md index b56332a..8e18628 100644 --- a/HANDOFF.md +++ b/HANDOFF.md @@ -10,6 +10,11 @@ Ultimo aggiornamento: **20 ottobre 2026** — si riprende da [Stato attuale](#st ## Stato attuale +**⚠️ 21 ottobre 2026 — PHP da aggiornare.** Produzione e demo girano su PHP +8.3.35, vulnerabile a CVE-2026-109618/109619 (esecuzione di codice da remoto). +Il Dockerfile ora richiede la 8.3.36, che esce alle 14:00 UTC del 21/10: vedi +[Sicurezza: PHP](#sicurezza-php-cve-2026-109618--cve-2026-109619-21-ottobre-2026). + **Produzione** (`main` → compose `termanager2-core-production`) in esercizio su Dokploy dal 19 ottobre 2026. Ultimo rilascio: `d3314a9` (proclamatori senza contatti, il link si copia o si condivide). Backup fatti prima dei rilasci in @@ -58,6 +63,26 @@ sistema visivo, prima suite di test) è in [Da dove veniamo](#da-dove-veniamo). Dal più recente. Le sezioni del 12-19 ottobre sono in produzione; quelle del 20 ottobre e i gruppi di servizio solo sulla demo. +### Sicurezza: PHP CVE-2026-109618 / CVE-2026-109619 (21 ottobre 2026) + +Due esecuzioni di codice da remoto nel core di PHP (CVSS v4 9.2), patch alle +14:00 UTC del 21/10/2026; versione corretta per il nostro ramo: **8.3.36**. +Il progetto girava su 8.3.35. + +- `docker/php/Dockerfile`: `ARG PHP_VERSION=8.3.36` e `FROM + php:${PHP_VERSION}-fpm`. Prima era `php:8.3-fpm`, un tag che si sposta ma + che Docker tiene in cache: una ricostruzione senza `--pull` (anche su + Dokploy) poteva riusare la base vulnerabile. Ora una build o prende la + 8.3.36 o fallisce. Test `tests/Unit/VersionePhpTest.php` contro il ritorno a + un tag mobile o a una versione inferiore. +- phpredis da GitHub (`ARG PHPREDIS_VERSION=6.3.0`) invece di `pecl install`: + quel giorno pecl.php.net rispondeva 504 e la build falliva. +- Solo per provare in locale prima che l'immagine sia su Docker Hub: + `PHP_VERSION=8.3.35 docker compose ...` (mai per un deploy). +- Da fare quando `php:8.3.36-fpm` è su Docker Hub: test sulla 8.3.36, poi + deploy di demo e produzione (vedi [Stato attuale](#stato-attuale)). Finché + restano su 8.3.35 sono esposte. + ### Assegna aperta dalla Home: senza l'elenco dei territori assegnati (20 ottobre 2026) Richiesta dell'utente: "quando provengo da un territorio dalla home, non diff --git a/docker-compose.yml b/docker-compose.yml index 1a91965..6863347 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -18,6 +18,10 @@ services: build: context: . dockerfile: docker/php/Dockerfile + # Vuota = la versione fissata nel Dockerfile (ARG PHP_VERSION). Si + # imposta solo per provare in locale una versione diversa. + args: + - PHP_VERSION restart: unless-stopped env_file: .env environment: @@ -46,6 +50,10 @@ services: build: context: . dockerfile: docker/php/Dockerfile + # Vuota = la versione fissata nel Dockerfile (ARG PHP_VERSION). Si + # imposta solo per provare in locale una versione diversa. + args: + - PHP_VERSION restart: unless-stopped user: www-data env_file: .env @@ -89,6 +97,10 @@ services: build: context: . dockerfile: docker/php/Dockerfile + # Vuota = la versione fissata nel Dockerfile (ARG PHP_VERSION). Si + # imposta solo per provare in locale una versione diversa. + args: + - PHP_VERSION restart: unless-stopped user: www-data env_file: .env @@ -207,6 +219,10 @@ services: build: context: . dockerfile: docker/php/Dockerfile + # Vuota = la versione fissata nel Dockerfile (ARG PHP_VERSION). Si + # imposta solo per provare in locale una versione diversa. + args: + - PHP_VERSION # Senza questo si costruirebbe l'immagine di produzione, che essendo # installata senza dipendenze di sviluppo non contiene phpunit. target: test diff --git a/docker/php/Dockerfile b/docker/php/Dockerfile index 382ec10..e891894 100644 --- a/docker/php/Dockerfile +++ b/docker/php/Dockerfile @@ -1,5 +1,21 @@ # syntax=docker/dockerfile:1 +# Versione di PHP, fissata alla patch. Va dichiarata prima del primo FROM per +# poterla usare nel FROM dello stage `base`. +# +# Fissata e non "8.3": quel tag si sposta, ma Docker tiene in cache la base già +# scaricata, e una ricostruzione senza --pull (anche su Dokploy) poteva uscire +# con un PHP vecchio senza che nessuno se ne accorgesse. Con la patch scritta +# qui, una build o prende questa versione o fallisce. +# +# 8.3.36: corregge CVE-2026-109618 e CVE-2026-109619 (esecuzione di codice da +# remoto nel core di PHP, CVSS 9.2, rilascio del 21/10/2026). Non scendere +# sotto. Aggiornala a ogni rilascio di sicurezza del ramo 8.3. +# +# Solo per provare in locale prima che l'immagine corretta sia su Docker Hub: +# PHP_VERSION=8.3.35 docker compose ... (mai per un deploy). +ARG PHP_VERSION=8.3.36 + # ============================================================================= # Stage 1 — PHP dependencies (no dev, production autoloader) # ============================================================================= @@ -65,7 +81,7 @@ RUN npm run build # estensioni e sullo stesso php.ini della produzione: un test che passa qui # non puo' passare grazie a un ambiente diverso da quello vero. # ============================================================================= -FROM php:8.3-fpm AS base +FROM php:${PHP_VERSION}-fpm AS base # nginx + supervisor run in-image alongside php-fpm: a separate nginx container # would need its own copy of public/ plus the storage volume just to serve @@ -76,6 +92,11 @@ FROM php:8.3-fpm AS base # are named per Debian release (libicu72 vs libicu76, libzip4 vs libzip5), so # purging means pinning package names that break whenever the php base image # moves to a new Debian. A few tens of MB is worth not having that breakage. +# +# phpredis si scarica da GitHub, versione fissata, e non con `pecl install`: +# il 21/10/2026, giorno della patch di sicurezza di PHP, pecl.php.net +# rispondeva 504 e la build falliva proprio quando bisognava aggiornare. +ARG PHPREDIS_VERSION=6.3.0 RUN apt-get update && apt-get install -y --no-install-recommends \ curl \ netcat-openbsd \ @@ -101,8 +122,13 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ intl \ zip \ opcache \ - && pecl install redis \ - && docker-php-ext-enable redis \ + && mkdir -p /usr/src/php/ext/redis \ + && curl -fsSL --retry 5 --retry-delay 5 \ + "https://github.com/phpredis/phpredis/archive/refs/tags/${PHPREDIS_VERSION}.tar.gz" \ + | tar xz --strip-components=1 -C /usr/src/php/ext/redis \ + && echo redis >> /usr/src/php-available-exts \ + && docker-php-ext-install -j"$(nproc)" redis \ + && docker-php-source delete \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* diff --git a/tests/Unit/VersionePhpTest.php b/tests/Unit/VersionePhpTest.php new file mode 100644 index 0000000..40a157b --- /dev/null +++ b/tests/Unit/VersionePhpTest.php @@ -0,0 +1,44 @@ +assertMatchesRegularExpression('/^ARG PHP_VERSION=(\d+\.\d+\.\d+)\s*$/m', $this->dockerfile()); + + preg_match('/^ARG PHP_VERSION=(\d+\.\d+\.\d+)\s*$/m', $this->dockerfile(), $trovata); + + $this->assertTrue( + version_compare($trovata[1], self::MINIMA, '>='), + "PHP {$trovata[1]} è vulnerabile a CVE-2026-109618/109619: serve almeno " . self::MINIMA . '.', + ); + } + + public function test_l_immagine_usa_la_versione_fissata_e_non_un_tag_mobile(): void + { + preg_match_all('/^FROM php:(\S+)/m', $this->dockerfile(), $basi); + + $this->assertNotEmpty($basi[1]); + foreach ($basi[1] as $tag) { + $this->assertStringStartsWith('${PHP_VERSION}', $tag, "FROM php:{$tag}: usa ARG PHP_VERSION, non un tag che si sposta."); + } + } +}