On October 21, 2026, the PHP team shipped fixes for two flaws in the core of the language, which Wiz named PHP2Shell. Researchers at the security firms Wiz and Calif had found them with AI tools, and the underlying bugs had been in PHP for more than a decade. They were rated as high as 9.2 out of 10, and they let an attacker run code on a server without logging in. Wiz demonstrated working attacks against WordPress, Drupal and Joomla. Nothing was wrong with the sites’ own code.
PHP runs 69.3 percent of the sites whose server language is known, according to W3Techs, which tracks the technologies websites use. The UK’s National Cyber Security Centre (NCSC) told organizations to update, apply the PHP team’s mitigations, or take the system offline until it was fixed. Several governments pulled sites offline as a precaution.
Think about what your test suite would have said that morning. Every test passes. Nothing in the application changed. The defect was below the code you test.
That is not a new kind of problem, but it is the part of QA most teams leave to someone else. In 5 Signs Your QA Process is Failing, the third sign was testing that is mostly manual. These are the four checks I would add first. Most of them can run on a schedule, and none of them runs in CI.
1. Know Everywhere Your Runtime Runs
The first step in the NCSC’s guidance was to find every PHP installation, and not to limit the search to old versions. That sounds easy until you try it. The production app is usually on the list. The staging server from two years ago, the marketing microsite, the form handler behind a static site, and the admin tool someone built for one quarter often are not.
What to do about it. Keep a list of every place a runtime like PHP, Node or Python is deployed, with its version, and check it on a schedule against the supported releases. Then write down, before you need it, the rule for when you patch in place and when you take something offline. When the advisory lands, nobody should be debating that rule at midnight.

2. Diff What Every Live Page Loads
Some of the most damaging problems we have cleaned up on sites we maintain sat in the same blind spot. One well-documented pattern starts with an outdated plugin. The attacker gets onto the server and leaves code behind that does not carry its own instructions. It reads them from a smart contract on a public blockchain. Google’s threat researchers call this technique EtherHiding and describe it as turning the blockchain into “a decentralized and highly resilient command-and-control (C2) server.” The attacker can change what the site does at any time without touching the server again. Pieces of it can live in the database, so removing the files is not the end of it.
You will not find that by reading your repository, because it is not in your repository. You find it by looking at what a visitor’s browser actually loads.
What to do about it. Crawl your key pages on a schedule, record every script each one loads and where it comes from, and compare that list to last week’s. A script nobody added is a defect, whether or not anything looks broken.

3. Review the Accounts in Front of the Server
The second pattern never touches the server. If someone gets into the account that manages a site’s DNS and CDN, they can add a script to every page as it is served. In the version we have seen, the script shows a fake “verify you are human” check. After the visitor clicks the box, it says they passed and tells them to press Ctrl+V or Command+V and paste into a terminal or the Run dialog. The page has already put a malicious command on their clipboard. Security researchers call this technique ClickFix. The same fake check also turns up on hacked WordPress sites, but when it is delivered from the edge, the server is untouched, so every scan of the server comes back clean.
What to do about it. Treat the accounts in front of the server as part of the system under test. Review edge rules and DNS records on a schedule, keep a short list of who holds credentials, end shared logins, and require multi-factor authentication on every account that can change what a visitor sees.

4. Scan the Content Itself, With AI
Cleaning up an injection does not undo what it already did. An injector can write into pages and database entries for weeks, and some of what it wrote stays. It might be a link to a betting site inside an old event page, a line of text in a footer that reads like graffiti, or a malicious URL that looks harmless. There is no pattern match for “this does not belong here,” and on a site with years of content, reading every page by hand takes a week.
This is where AI earns a place in QA. Crawl every URL, give each page to a model along with a description of what the organization actually publishes, and get back a rating of how likely each page is to contain injected content. A person then reads the pages that score high instead of all of them. Before these tools, content integrity was not something you could realistically test. Now it is.
AI tools also found the PHP flaws, which had sat in the language for more than a decade despite years of human review. Attackers have the same tools, which is the best argument for using them on your own systems first.

The Questions I Would Ask Your Team
- If a flaw in your language runtime were announced tonight, how long would it take to list every system running it?
- Who decides whether something gets patched in place or taken offline, and is that written down anywhere?
- What does a visitor’s browser load from your site right now, and when did someone last compare that list to the one from a month ago?
- Who can change your DNS and CDN settings today, and does every one of those accounts require a second factor?
None of these is a test in your test suite. All of them are QA.
If you want help answering them for your own team, talk to us about a QA and release review.
