Kort sagt: Den, der vil opdatere afhængigheder, har brug for en proces for tre pakkeverdener: Composer-pakker i PHP-koden, npm-moduler i frontend-buildet og plugins eller themes i CMS'et. Dertil hører en fast rytme, en ansvarlig person, tests før udrulning og en plan for pakker uden opdatering. Mod PHP2Shell hjælper det ikke, for den sårbarhed sidder i selve PHP, men mod de mange sårbarheder i fremmed kode.
Tre pakkeverdener, ét blindt punkt
I ugen efter 21.10.2026 drejede alt sig om PHP-fortolkeren. Mange teams har herved opdaget, at de ikke kender versionerne af deres egne byggesten nøjagtigt. Websitet kører, bureauet tager sig af det, pluginet melder sig, når der er noget nyt: Sådan eller lignende lyder antagelserne, indtil nogen kigger efter.
Et typisk PHP-projekt består i dag af markant mere fremmed end egen kode. OWASP Top 10 fører sårbare og forældede komponenter som en egen risikokategori. Problemet er sjældent det manglende værktøj, men den manglende rutine: Opdateringer sker, når nogen har tid, og sikkerhedsmeddelelser havner i en postkasse, ingen læser.
Hvilke afhængigheder opdaterer I hvor?
Hver pakkeverden har egne værktøjer og egne faldgruber. Følgende oversigt hjælper med ikke at overse noget.
| Pakkeverden | Vis bestand | Kontrollér sårbarheder | Typisk faldgrube |
|---|---|---|---|
| Composer (PHP-biblioteker) | composer show |
composer audit |
indirekte pakker, som ingen kender |
| npm (frontend-build) | npm ls |
npm audit |
opdatering uden nybygning når aldrig serveren |
| CMS-plugins og themes | adminflade eller CLI | producentens henvisninger, sikkerhedstjenester | opgivne plugins, købsplugins uden opdateringskanal |
| PHP og udvidelser | pakkestyring | distributionens security-tracker | den viste version siger lidt om backports |
Den sidste række hører strengt taget ikke til applikationens afhængigheder, men glemmes ofte i samme åndedrag. Det samme gælder scripts, der indlæses direkte fra fremmede servere, f.eks. biblioteker fra et CDN, chat-widgets eller tracking-kode. De optræder i ingen lock-fil, men kører i jeres besøgendes browser. Tag dem med på listen, og kontrollér, om faste versioner er indlejret i stedet for "altid den nyeste". Detaljerne om composer audit, lock-fil og integration i buildet står i vejledningen Kontrollér Composer-afhængigheder for sårbarheder. Hvordan Composer grundlæggende fungerer, forklarer Composer: Pakkestyringen til PHP.
Vedligeholdelsescyklussen i seks trin
En bæredygtig proces behøver ikke være kompliceret. Denne rækkefølge har vist sig at fungere:
- Fastholde bestanden: For hvert projekt en liste over de direkte afhængigheder med version, oprindelse og formål. Lock-filer (
composer.lock,package-lock.json) hører hjemme i repositoryet. - Indsamle meddelelser: Kontrolværktøjer kører ved hvert build og desuden jævnligt på den leverede version, også uden kodeændring.
- Vurdere: Bruges den berørte pakke i produktionsdrift, kan den berørte funktion nås, findes der en rettet version?
- Opdatere og teste i staging: Først sikkerhedsopdateringer inden for samme hovedversion, spring til nye hovedversioner planlægges som eget projekt.
- Udrulle med vej tilbage: Den foregående version forbliver tilgængelig som pakke eller release, databasebackup før opdateringen.
- Dokumentere: Hvad blev opdateret hvornår, hvad bevidst ikke, og hvorfor.
Vær her opmærksom på versionsangivelserne i composer.json og package.json. For snævre krav forhindrer, at sikkerhedsrettelser overhovedet kan installeres. For vide krav henter derimod ukontrollerede nye hovedversioner ind i projektet. Det har vist sig at fungere at tillade opdateringer inden for hovedversionen og bevidst planlægge springet til den næste.
For plugins i CMS'et kan tilgængelige opdateringer ofte også vises på kommandolinjen, i WordPress f.eks. med WP-CLI:
# Vis tilgængelige opdateringer uden at ændre noget
wp plugin list --update=available
wp theme list --update=available
# Frontend-pakker: forældede versioner og kendte sårbarheder
npm outdated
npm audit --omit=dev
Automatiske plugin-opdateringer direkte på produktionssystemet er bekvemme, men risikable, hvis ingen kontrollerer bagefter. Slå dem kun til, hvis en backup før hver kørsel og en kontrol bagefter er sikret.
Hvis der ikke findes nogen opdatering
Ikke enhver meddelelse lader sig løse med et klik. OWASP Cheat Sheet om håndtering af sårbare afhængigheder skelner mellem flere tilfælde, der let kan overføres til hverdagen:
- Rettelse tilgængelig: indspil i staging, test, udrul. Går noget i stykker, så tilpas den egen kode i stedet for at lade opdateringen ligge.
- Rettelse annonceret, men endnu ikke der: gennemfør producentens workaround, slå den berørte funktion fra eller afskærm den, hvis muligt, fastholdt beslutningen.
- Ingen rettelse at vente: søg en erstatningspakke, eller bagportér rettelsen selv, med en test, der skelner sårbarheden før og efter rettelsen.
Ved CMS-plugins forekommer ofte et fjerde tilfælde: Pluginet er opgivet. Så hjælper kun erstatning eller fjernelse. Det samme gælder plugins fra uklare kilder, f.eks. "gratis" kopier af købsplugins. De får ingen opdateringer via den officielle kanal og indeholder ikke sjældent selv skadelig kode. Henvisninger til WordPress-driftsansvarlige samler WordPress og PHP2Shell.
Afklar ansvaret, før den næste meddelelse kommer
Den hyppigste grund til forældede pakker er ingen teknisk forhindring, men et åbent spørgsmål: Hvem gør det? Ved projekter, som et bureau har bygget, og som drives internt, føler ofte ingen sig ansvarlig. Fastlæg for hvert projekt, hvem der modtager meddelelser, hvem der vurderer, og hvem der godkender, og skriv det ned.
Afsæt desuden tid. En fast vedligeholdelsestermin om måneden, hvor afhængigheder kontrolleres og opdateres, forhindrer, at opdateringer hobes op over år. Jo længere et projekt ikke er blevet opdateret, desto større og mere risikabelt bliver det næste spring. Hvordan opdateringer af PHP og pakker passer ind i et overgribende forløb, beskriver Patchstyring som proces i stedet for brandslukning.
Hvordan hjælper PHP SOS konkret?
- Vi registrerer alle afhængigheder i jeres projekter fra Composer, npm og CMS og markerer forældede, sårbare og opgivne pakker.
- Vi indretter automatiske kontroller og fastlægger, hvem der vurderer hvilken meddelelse.
- Vi opdaterer i staging, tester de vigtigste forløb og udruller med vej tilbage.
- Som led i en security-vedligeholdelsesaftale overtager vi den månedlige cyklus varigt, PHP-opdateringer inkluderet.
Konklusion: Aktuelle afhængigheder er ikke et projekt, men rutine. Den, der én gang får ordnet bestand, rytme og ansvar, behøver ved den næste store meddelelse kun at kontrollere, ikke først at søge.
Ofte stillede spørgsmål
Hvor ofte bør man opdatere afhængigheder?
Sikkerhedsopdateringer så hurtigt som muligt efter vurdering, rutineopdateringer i en fast rytme, f.eks. månedligt. Vigtigere end den nøjagtige frekvens er, at terminen er fastlagt, og at nogen har ansvaret.
Beskytter et aktuelt plugin mod PHP2Shell?
Nej. PHP2Shell sidder i selve PHP-fortolkeren. Mod det hjælper kun en PHP-opdatering med genstart af alle PHP-processer. Aktuelle plugins og pakker er alligevel vigtige, fordi de lukker egne sårbarheder.
Hvad gør jeg med et plugin, der ikke længere vedligeholdes?
Erstat eller fjern det. Et opgivet plugin får ingen rettelser mere, selv om det i dag stadig fungerer. Indtil erstatningen bør I kontrollere, om funktionen virkelig er nødvendig, og dokumentere beslutningen.
Skal frontend med npm også opdateres på serveren?
Ofte findes npm-pakker kun i buildet og havner som færdige filer på serveren. En sårbarhed i en pakke kan alligevel sidde i det leverede JavaScript. Efter en opdatering skal der derfor bygges påny og leveres påny.