In short: Anyone who wants to update dependencies needs a process for three package worlds: Composer packages in the PHP code, npm modules in the frontend build and plugins or themes in the CMS. This includes a fixed rhythm, a responsible person, tests before rollout and a plan for packages without an update. It does not help against PHP2Shell, because that vulnerability sits in PHP itself, but it does help against the many vulnerabilities in third-party code.
Three Package Worlds, One Blind Spot
In the week after 21 October 2026, everything revolved around the PHP interpreter. Many teams noticed in the process that they do not know the versions of their own building blocks exactly. The website runs, the agency takes care of it, the plugin will say something when there is something new: those or similar are the assumptions, until someone checks.
A typical PHP project today consists of considerably more third-party than its own code. The OWASP Top 10 lists vulnerable and outdated components as a risk category of their own. The problem is rarely the missing tool but the missing routine: updates happen when someone has time, and security notices land in a mailbox nobody reads.
Which Dependencies Do You Update Where?
Each package world has its own tools and its own pitfalls. The following overview helps to overlook nothing.
| Package world | Show inventory | Check for vulnerabilities | Typical pitfall |
|---|---|---|---|
| Composer (PHP libraries) | composer show |
composer audit |
indirect packages that nobody knows |
| npm (frontend build) | npm ls |
npm audit |
an update without a rebuild never reaches the server |
| CMS plugins and themes | admin interface or CLI | vendor notices, security services | abandoned plugins, purchased plugins without an update channel |
| PHP and extensions | package management | the distribution's security tracker | the displayed version says little about backports |
Strictly speaking, the last row does not belong to the application's dependencies, but it is often forgotten in the same breath. The same applies to scripts that are included directly from foreign servers, such as libraries from a CDN, chat widgets or tracking code. They appear in no lock file but run in your visitors' browsers. Add them to the list and check whether fixed versions are included instead of "always the latest". The details on composer audit, lock file and integration into the build are in the guide Checking Composer Dependencies for Vulnerabilities. How Composer works in general is explained in Composer: The Package Manager for PHP.
The Maintenance Cycle in Six Steps
A viable process does not have to be complicated. This order has proven itself:
- Record the inventory: For each project, a list of direct dependencies with version, origin and purpose. Lock files (
composer.lock,package-lock.json) belong in the repository. - Collect notices: Check tools run on every build and additionally at regular intervals on the delivered state, even without code changes.
- Assess: Is the affected package used in production, is the affected function reachable, is there a fixed version?
- Update and test in staging: First security updates within the same major version; plan jumps to new major versions as a project of their own.
- Roll out with a way back: The previous state remains available as a package or release, database backup before the update.
- Document: What was updated when, what deliberately was not, and why.
Pay attention to the version constraints in composer.json and package.json. Constraints that are too tight prevent security fixes from being installed at all. Constraints that are too wide, on the other hand, pull new major versions into the project unchecked. It has proven useful to allow updates within the major version and to plan the jump to the next one deliberately.
For plugins in the CMS, available updates can often also be displayed on the command line, in WordPress for example with WP-CLI:
# Show available updates without changing anything
wp plugin list --update=available
wp theme list --update=available
# Frontend packages: outdated versions and known vulnerabilities
npm outdated
npm audit --omit=dev
Automatic plugin updates directly on the production system are convenient but risky if nobody checks afterwards. Switch them on only if a backup before every run and a check afterwards are ensured.
When There Is No Update
Not every notice can be solved with one click. The OWASP cheat sheet on handling vulnerable dependencies distinguishes several cases that translate well into everyday practice:
- Patch available: apply it in staging, test, roll out. If something breaks, adapt your own code rather than leaving the update aside.
- Patch announced but not yet there: implement the vendor's workaround, switch off or shield the affected function if possible, record the decision.
- No patch to be expected: look for a replacement package or backport the fix yourself, with a test that distinguishes the vulnerability before and after the patch.
With CMS plugins, a fourth case is common: the plugin is abandoned. Then only replacement or removal helps. The same applies to plugins from unclear sources, such as "free" copies of purchased plugins. They receive no updates via the official channel and not infrequently contain malicious code themselves. Notes for WordPress operators are collected in WordPress and PHP2Shell.
Clarify Responsibility Before the Next Notice Arrives
The most common reason for outdated packages is not a technical hurdle but an open question: who does it? With projects built by an agency and operated internally, often nobody feels responsible. For each project, define who receives notices, who assesses and who approves, and write it down.
Also plan time. A fixed maintenance appointment each month at which dependencies are checked and updated prevents updates from piling up over years. The longer a project has not been updated, the bigger and riskier the next jump becomes. How updates of PHP and packages fit into an overarching process is described in Patch Management as a Process Instead of Firefighting.
How does PHP SOS help?
- We record all dependencies of your projects from Composer, npm and CMS and flag outdated, vulnerable and abandoned packages.
- We set up automatic checks and define who assesses which notice.
- We update in staging, test the most important flows and roll out with a way back.
- As part of a security maintenance contract, we take over the monthly cycle permanently, PHP updates included.
Conclusion: Up-to-date dependencies are not a project but a routine. Anyone who regulates inventory, rhythm and responsibility cleanly once only has to check at the next major notice, not search first.
Frequently asked questions
How often should dependencies be updated?
Security updates as soon as possible after assessment, routine updates in a fixed rhythm, for example monthly. More important than the exact frequency is that the date is fixed and someone is responsible for it.
Does an up-to-date plugin protect against PHP2Shell?
No. PHP2Shell sits in the PHP interpreter itself. Only a PHP update with a restart of all PHP processes helps against it. Up-to-date plugins and packages are still important because they close vulnerabilities of their own.
What do I do with a plugin that is no longer maintained?
Replace or remove it. An abandoned plugin no longer receives fixes, even if it still works today. Until it is replaced, you should check whether the function is really needed and document the decision.
Does the frontend with npm also have to be updated on the server?
Often npm packages exist only in the build and end up on the server as finished files. A vulnerability in a package can nevertheless be in the delivered JavaScript. After an update, you therefore have to rebuild and redeliver.