Kort sagt: Et Docker-image indeholder PHP i den status, det havde på byggetidspunktet, og forældes også uden kodeændringer. Den, der bygger images automatisk om, tidsstyret og ved sikkerhedsmeddelelser, kontrollerer PHP-versionen i pipelinen og udruller via digest, får patches som den mod PHP2Shell planbart ud i produktion. Et grønt build alene er dog intet bevis; det, der tæller, er versionen i den kørende container.
Hvorfor images forældes uden kodeændringer
I mange teams starter build-pipelinen kun, når nogen ændrer kode. For applikationen er det logisk. For sikkerheden er det et problem, for PHP i imaget stammer fra basisimaget på tidspunktet for det seneste build.
PHP2Shell har gjort det synligt. De rettede versioner 8.5.12, 8.4.27, 8.3.36 og 8.2.35 udkom den 21. oktober 2026. Et projekt, som ingen arbejdede på i de dage, fik ikke noget nyt build og kørte videre med den gamle PHP, selv om basisimaget for længst var opdateret. Den manuelle vej ud af situationen beskriver Patch PHP i Docker-containere. Dette indlæg viser, hvordan I automatiserer den.
Byg Docker-images automatisk om: tre udløsere
En robust proces kombinerer flere udløsere, så ingen skal bære alene.
| Udløser | Gennemførelse | Bemærk |
|---|---|---|
| Tidsplan | tidsstyret workflow, f.eks. ugentligt | henter patches også uden kodeændring |
| Nyt basisimage | værktøj, der overvåger basisimages og foreslår ændringer | virker især ved faste versionstags |
| Sikkerhedsmeddelelse | manuel start af pipelinen ved driftsteamet | kræver en klar ansvarlig |
Ved GitHub Actions overtager hændelsen schedule tidsplanen. Ifølge GitHub-dokumentationen bruger den cron-syntaks med fem felter, kører i UTC og kun på standard-branchen. Planlagte kørsler kan starte forsinket ved høj belastning, og i offentlige repositories slår GitHub dem fra efter 60 dage uden aktivitet. Netop det sidste rammer stille projekter, altså netop dem, der har mest brug for den automatiske genopbygning.
Til den anden udløser understøtter Dependabot ifølge GitHub-dokumentationen økosystemet docker og foreslår nye statusser for basisimages som pull request. To begrænsninger bør I kende. For det første skal nogen gennemgå pull requesten og flette den, ellers bliver den liggende. For det andet ændrer der sig ved et gren-tag som php:8.3-fpm i Dockerfilen intet, når basisimaget bygges om. Et værktøj, der foreslår tekstændringer, har så intet at foreslå. Netop derfor er der desuden brug for den tidsstyrede genopbygning.
Den tredje udløser lyder banal, men strander i praksis ofte på spørgsmålet om, hvem der udløser den. Fastlæg, hvem der følger sikkerhedsmeddelelser om PHP, og hvem der må starte pipelinen, også i weekenden. Ved PHP2Shell lå der kun en dag mellem forhåndsvarsel og patch.
En pipeline, der opfanger forældet PHP
Følgende eksempel til GitHub Actions bygger imaget ugentligt og ved tryk på en knap, kontrollerer PHP-versionen og afbryder, hvis den ligger under den rettede status. Registry, navne og minimumsversion tilpasser I.
name: php-image-rebuild
on:
schedule:
- cron: "0 3 * * 1" # mandage kl. 03:00 UTC
workflow_dispatch: {} # manuel start ved sikkerhedsmeddelelser
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Image ohne Cache und mit frischem Basis-Image bauen
run: docker build --pull --no-cache -t app:${{ github.run_id }} .
- name: PHP-Version prüfen (Mindeststand des Zweigs 8.3)
run: |
docker run --rm app:${{ github.run_id }} php -v
docker run --rm app:${{ github.run_id }} \
php -r 'exit(version_compare(PHP_VERSION, "8.3.36", ">=") ? 0 : 1);'
Versionskontrollen fungerer ved officielle PHP-images, hvis versionsnummer angiver den faktiske status. Bruger jeres image PHP-pakker fra en distribution, forbliver nummeret efter en backport ofte det samme. Så kontrollerer I i stedet for nummeret pakkens changelog for CVE-numrene, som beskrevet i indlægget Dokumentér CVE-numre i pakkens changelog.
Efter kontrollen følger i praksis yderligere tre skridt: scan imaget for kendte sårbarheder, skub det med dato og digest ind i registryet, og giv digestet videre til udrulningen. Hvilke tags og varianter der egner sig som basis, forklarer Officielle PHP Docker-images.
Fra build til kørende container
Den hyppigste tankefejl: Pipelinen er grøn, altså er alt patchet. I virkeligheden ligger det nye image blot i registryet. Patchen bliver først virksom, når hver container er oprettet på ny fra det nye image.
- Udrul via digest: Udrulningen refererer til det nye images digest, ikke til et vandrende tag.
- Først staging, så produktion: Automatiske tests på en kopi opfanger brud forårsaget af nye basisimages.
- Kontrollér i drift: Kør efter udrulningen
php -vi den kørende container, og sammenlign digestet med buildet. - Begræns tilbagevejen: Det gamle image forbliver tilgængeligt til en kort tilbagevej, men indeholder den sårbare PHP.
I Kubernetes gælder der egne regler hertil, f.eks. om pull-policy; de står under Patch PHP i Kubernetes.
Typiske huller i kæden
- Build-cache på runneren: Uden
--pullog--no-cachegenbruges det gamle basisimage. - Registry-spejl: Et internt mellemlager leverer fortsat den gamle status af basisimaget.
- Flertrinsbuilds: PHP-versionen i det sidste trin tæller, men ofte kontrolleres kun det første.
- Biimages: Queue-workers, cron-containere og interne værktøjer har egne pipelines eller slet ingen.
- Fastskrevne digests: Et engang fastskrevet digest for basisimaget bliver aldrig opdateret, hvis intet værktøj overvåger det.
En genopbygning erstatter PHP, ikke dataene. Skadelig kode, der før patchen er kommet ind i volumener, upload-mapper eller databasen, består og skal kontrolleres separat.
Hvem reagerer, når genopbygningen slår fejl?
En automatisk genopbygning er kun så god som reaktionen på dens fejl. Slår versionskontrollen til, eller afbrydes buildet på grund af et ændret basisimage, skal nogen opdage det. I mange teams havner sådanne meddelelser i en postkasse, som ingen læser, eller i en kanal, hvor røde builds for længst er hverdag.
En klar regel har vist sig at fungere: En mislykket sikkerhedsgenopbygning er en sag med en ansvarlig og en frist, ikke en bemærkning blandt mange. Notér desuden for hvert udrullet image dato, digest og kontrolleret PHP-version. Denne liste besvarer ved den næste meddelelse på minutter, hvilke applikationer der er berørt, og tjener over for revisorer eller forsikringsselskaber som bevis. Hvordan det bliver til et varigt forløb, beskriver Patch-management som proces i stedet for brandslukning.
Hvordan hjælper PHP SOS konkret?
- Gennemgå pipelines: Vi ser på jeres bygge- og udrulningskæder og viser, hvor en patch kan blive hængende.
- Automatisér genopbygningen: Vi sætter tidsstyrede builds, versionskontrol og udrulning via digest op.
- Registrér alle images: Vi knytter hver kørende container til dens pipeline, også bi- og ældre images.
- Betjen løbende: I security-vedligeholdelsesaftalen følger vi sikkerhedsmeddelelser og sætter genopbygninger i gang.
Ofte stillede spørgsmål
Hvor ofte bør et PHP-image bygges om?
Der findes intet fast tal. Et regelmæssigt tidsstyret build har vist sig at fungere, f.eks. ugentligt, plus et øjeblikkeligt build ved sikkerhedsmeddelelser. Afgørende er, at en ny patch ikke skal vente på den næste kodeændring.
Er et vellykket build nok som bevis?
Nej. Et build beviser kun, at der findes et nyt image. Først når de kørende containere er oprettet på ny fra dette image, og php -v deri viser den rettede version, er patchen virksom.
Hvorfor dukker den gamle PHP-version alligevel op efter genopbygningen?
Hyppige årsager er en build-cache, der genbruger det gamle basisimage, et registry-spejl med gammel status eller en anden FROM-linje i et flertrinsbuild. Byg med --pull og --no-cache, og kontrollér hvert trin.
Kan Dependabot opdatere basisimages?
Ifølge GitHub-dokumentationen understøtter Dependabot økosystemet Docker til versions- og sikkerhedsopdateringer. Det foreslår ændringer af basisimages som pull request. Genopbygningen ved uændret tag erstatter det ikke.