{"id":5,"date":"2026-10-21T10:59:44","date_gmt":"2026-10-21T10:59:44","guid":{"rendered":"https:\/\/adnancanturk.com\/blog\/php-nodejs-security-releases-2026-server-checklist\/"},"modified":"2026-10-23T09:50:27","modified_gmt":"2026-10-23T09:50:27","slug":"php-nodejs-security-releases-2026-server-checklist","status":"publish","type":"post","link":"https:\/\/adnancanturk.com\/blog\/php-nodejs-security-releases-2026-server-checklist\/","title":{"rendered":"PHP and Node.js in 2026: the security releases and what to do on your servers"},"content":{"rendered":"<p class=\"lead\">Most production stacks run PHP and Node.js side by side: PHP for the CMS, billing or panel, Node.js for the API, the build pipeline or a real-time service. Both runtimes shipped high-severity security releases in 2026, and the servers that host them need attention on both fronts at once.<\/p>\n<div class=\"tldr\">\n<p class=\"tldr-label\">TL;DR<\/p>\n<ul>\n<li>PHP fixed around a dozen CVEs on 24 September 2026 (8.2.34, 8.3.35, 8.4.26, 8.5.11); Node.js shipped security releases in June and July.<\/li>\n<li>PHP 8.1 and Node.js 20 are end of life and received none of these fixes; PHP 8.2 follows on 31 December 2026.<\/li>\n<li>On cPanel, <code>php -v<\/code> is not proof of what a site runs: check MultiPHP, the handler and CloudLinux PHP Selector, then confirm from inside the site.<\/li>\n<li>Node.js can run in several places at once on one server, including containers and CI images, and each copy needs its own update.<\/li>\n<li>Every fix takes effect only after FPM pools, Apache with mod_php and Node.js processes restart.<\/li>\n<\/ul>\n<\/div>\n<p>This post covers what each project fixed between June and September, why the version line you are on matters more than any single patch, how to find out which PHP a site is really running on a cPanel server, and an eight-step checklist. The emergency PHP2Shell release of 21 October has its own <a href=\"\/blog\/php2shell-patch-day-runbook-php-nodejs-cloudlinux-cpanel\/\">patch-day runbook<\/a>.<\/p>\n<h2>What did PHP fix in September 2026?<\/h2>\n<p>On 24 September 2026 the PHP project released 8.2.34, 8.3.35, 8.4.26 and 8.5.11 as a coordinated security update covering around a dozen CVEs. The issue most likely to reach a public web server is CVE-2026-91765, unbounded recursion in the SOAP extension that lets an unauthenticated request crash an exposed SoapServer endpoint. CVE-2026-91766 matters to any application that calls remote APIs: when the HTTP stream wrapper followed a redirect to another host, credentials meant for the first host could travel with it.<\/p>\n<p>Two TLS fixes, CVE-2026-91769 and CVE-2026-91767, stop hostname verification from falling back to the certificate CN after a SAN mismatch and close a heap overflow on crafted wildcard names. On the server side, CVE-2026-91768 is the one to check first if you run PHP-FPM on an IPv6 TCP socket, because <code>listen.allowed_clients<\/code> compared only part of the address and could be bypassed. Phar archives received a fix for CVE-2026-6103, an integer overflow in TAR header parsing that allowed entries to be injected.<\/p>\n<h2>What did Node.js fix in June and July 2026?<\/h2>\n<p>Node.js shipped two security releases in quick succession. The June release (v22.23.0, v24.17.0, v26.3.1) fixed twelve issues, among them CVE-2026-48618, a TLS wildcard-depth authentication bypass caused by inconsistent Unicode dot handling. The July release (v22.23.2, v24.18.1, v26.5.1) followed with eleven more, three of them rated high.<\/p>\n<p>Two of the July high-severity bugs sit in HTTP\/2: CVE-2026-56846 lets retained header blocks slip past <code>maxSessionMemory<\/code> so a remote client can exhaust server memory, and CVE-2026-56848 is a heap use-after-free in nghttp2. The third, CVE-2026-58043, lets a filesystem grant in the Permission Model reach paths outside the allowlist. A further release with high-severity fixes for the 22, 24 and 26 lines followed on 21 October 2026.<\/p>\n<h2>Why is the version line a bigger risk than any single patch?<\/h2>\n<p>A patch only helps if your version line still receives it. PHP 8.1 left security support at the end of 2025 and Node.js 20 reached end of life on 30 April 2026, so servers still running either received none of the fixes above. PHP 8.2 follows on 31 December 2026, which makes it a poor target for an upgrade planned today.<\/p>\n<figure class=\"wp-block-image size-full gitm-figure\"><svg role=\"img\" aria-label=\"Security support windows for PHP 8.1 to 8.5 and Node.js 20 to 26, 2025 to 2029\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 1600 820\">\n  <rect width=\"1600\" height=\"820\" fill=\"#ffffff\"\/>\n  <g font-family=\"Arial, Helvetica, sans-serif\" fill=\"#171717\">\n    <text x=\"80\" y=\"80\" font-size=\"40\" font-weight=\"700\" letter-spacing=\"-1.5\">Which runtime lines still receive security fixes<\/text>\n    <text x=\"80\" y=\"122\" font-family=\"Menlo, monospace\" font-size=\"18\" letter-spacing=\"2\" fill=\"#858585\">SECURITY SUPPORT WINDOW, 2025 TO 2029<\/text>\n  <\/g>\n  <g font-family=\"Menlo, monospace\" font-size=\"17\" fill=\"#858585\">\n    <line x1=\"260\" y1=\"170\" x2=\"260\" y2=\"720\" stroke=\"#e8e5df\"\/><text x=\"242\" y=\"752\">2025<\/text>\n    <line x1=\"508\" y1=\"170\" x2=\"508\" y2=\"720\" stroke=\"#e8e5df\"\/><text x=\"490\" y=\"752\">2026<\/text>\n    <line x1=\"756\" y1=\"170\" x2=\"756\" y2=\"720\" stroke=\"#e8e5df\"\/><text x=\"738\" y=\"752\">2027<\/text>\n    <line x1=\"1004\" y1=\"170\" x2=\"1004\" y2=\"720\" stroke=\"#e8e5df\"\/><text x=\"986\" y=\"752\">2028<\/text>\n    <line x1=\"1252\" y1=\"170\" x2=\"1252\" y2=\"720\" stroke=\"#e8e5df\"\/><text x=\"1234\" y=\"752\">2029<\/text>\n    <line x1=\"1500\" y1=\"170\" x2=\"1500\" y2=\"720\" stroke=\"#e8e5df\"\/><text x=\"1482\" y=\"752\">2030<\/text>\n  <\/g>\n  <g font-family=\"Menlo, monospace\" font-size=\"19\" font-weight=\"600\" fill=\"#171717\">\n    <text x=\"80\" y=\"205\" fill=\"#858585\" font-size=\"15\" letter-spacing=\"2\">PHP<\/text>\n    <text x=\"80\" y=\"232\">8.1<\/text><rect x=\"260\" y=\"214\" width=\"248\" height=\"24\" fill=\"#d9d5ce\"\/>\n    <text x=\"80\" y=\"284\">8.2<\/text><rect x=\"260\" y=\"266\" width=\"496\" height=\"24\" fill=\"#f05a28\"\/>\n    <text x=\"80\" y=\"336\">8.3<\/text><rect x=\"260\" y=\"318\" width=\"744\" height=\"24\" fill=\"#f05a28\"\/>\n    <text x=\"80\" y=\"388\">8.4<\/text><rect x=\"260\" y=\"370\" width=\"992\" height=\"24\" fill=\"#f05a28\"\/>\n    <text x=\"80\" y=\"440\">8.5<\/text><rect x=\"478\" y=\"422\" width=\"1022\" height=\"24\" fill=\"#f05a28\"\/>\n    <text x=\"80\" y=\"500\" fill=\"#858585\" font-size=\"15\" letter-spacing=\"2\">NODE.JS<\/text>\n    <text x=\"80\" y=\"527\">20<\/text><rect x=\"260\" y=\"509\" width=\"330\" height=\"24\" fill=\"#d9d5ce\"\/>\n    <text x=\"80\" y=\"579\">22<\/text><rect x=\"260\" y=\"561\" width=\"578\" height=\"24\" fill=\"#171717\"\/>\n    <text x=\"80\" y=\"631\">24<\/text><rect x=\"260\" y=\"613\" width=\"826\" height=\"24\" fill=\"#171717\"\/>\n    <text x=\"80\" y=\"683\">26<\/text><rect x=\"582\" y=\"665\" width=\"752\" height=\"24\" fill=\"#171717\"\/>\n  <\/g>\n  <line x1=\"706\" y1=\"160\" x2=\"706\" y2=\"722\" stroke=\"#f05a28\" stroke-width=\"3\" stroke-dasharray=\"8 6\"\/>\n  <text x=\"716\" y=\"168\" font-family=\"Menlo, monospace\" font-size=\"16\" font-weight=\"600\" fill=\"#f05a28\">TODAY<\/text>\n  <g font-family=\"Menlo, monospace\" font-size=\"15\" fill=\"#858585\">\n    <rect x=\"80\" y=\"782\" width=\"18\" height=\"12\" fill=\"#d9d5ce\"\/><text x=\"108\" y=\"793\">END OF LIFE<\/text>\n    <rect x=\"270\" y=\"782\" width=\"18\" height=\"12\" fill=\"#f05a28\"\/><text x=\"298\" y=\"793\">PHP SUPPORTED<\/text>\n    <rect x=\"480\" y=\"782\" width=\"18\" height=\"12\" fill=\"#171717\"\/><text x=\"508\" y=\"793\">NODE.JS SUPPORTED<\/text>\n    <text x=\"1100\" y=\"793\">SOURCES: PHP.NET, NODEJS.ORG<\/text>\n  <\/g>\n<\/svg><figcaption>Security support windows for PHP 8.1 to 8.5 and Node.js 20 to 26, 2025 to 2029<\/figcaption><\/figure>\n<p>The two projects reach end of life in different ways, and that changes how you plan. The table below is the short version.<\/p>\n<div class=\"table-wrap\">\n<table>\n<thead>\n<tr>\n<th>Question<\/th>\n<th>PHP<\/th>\n<th>Node.js<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>How long a branch gets security fixes<\/td>\n<td>About four years from its first release (8.2: December 2022 to December 2026)<\/td>\n<td>Even-numbered majors become LTS and get fixes for about 30 months after that (22: October 2024 to April 2027)<\/td>\n<\/tr>\n<tr>\n<td>Branches supported in October 2026<\/td>\n<td>8.2, 8.3, 8.4, 8.5<\/td>\n<td>22, 24, 26<\/td>\n<\/tr>\n<tr>\n<td>Next end of life<\/td>\n<td>8.2 on 31 December 2026<\/td>\n<td>22 on 30 April 2027<\/td>\n<\/tr>\n<tr>\n<td>How a fix usually arrives on a hosting server<\/td>\n<td>Panel or distribution packages, often with backported fixes and an unchanged version number<\/td>\n<td>A new upstream build, a panel package or a container image<\/td>\n<\/tr>\n<tr>\n<td>What has to restart afterwards<\/td>\n<td>PHP-FPM pools, Apache with mod_php, long-running PHP workers<\/td>\n<td>Every Node.js process, including process managers such as PM2<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>Check your own lines here:<\/p>\n<div class=\"gitm-widget\" data-widget=\"support\"><\/div>\n<h2>How do you find which PHP a site really runs on cPanel?<\/h2>\n<p>Do not trust the shell. On a cPanel server <code>php -v<\/code> reports the default command-line build, while each domain can be served by a different branch chosen in MultiPHP Manager, by a handler line in its <code>.htaccess<\/code>, or by CloudLinux PHP Selector, which can override both. On one of our own servers nine PHP branches are registered with the web server, from 7.2 to 8.5, and the default is not what most sites use.<\/p>\n<p>Three checks give the real answer. <code>whmapi1 php_get_vhost_versions<\/code> lists the version and handler WHM believes each domain uses. For accounts on CloudLinux, <code>selectorctl --user-current --user=&lt;account&gt;<\/code> shows whether the Selector overrides it. And the final proof is a temporary script in the site that prints <code>PHP_VERSION<\/code> and <code>php_sapi_name()<\/code>, deleted immediately after it is read. When we moved this blog from a CGI handler to PHP-FPM, that third check was the only one that showed the switch had worked.<\/p>\n<h2>Where does Node.js hide on a hosting server?<\/h2>\n<p>Node.js is easy to miss because it rarely runs as a single system service. It can come from cPanel&#8217;s own packages for the Application Manager, from a distribution package, from a version manager in a user&#8217;s home directory, from a vendor bundle inside an application, or from a container image. A server can therefore run three Node.js versions at once, and updating the system package fixes only one of them.<\/p>\n<p>The practical inventory is to list every process with <code>ps -eo pid,user,args | grep -i node<\/code>, then ask each binary for its version. Anything managed by PM2 or systemd keeps its old runtime until it restarts, so an update without a restart leaves the vulnerable code in memory.<\/p>\n<p>Containers add one more layer. A Node.js service inside a container uses whatever runtime its image was built with, regardless of what the host has installed, so the fix arrives only when the image is rebuilt from a patched base and the container is recreated. The same is true for CI runners, which are easy to forget because they rarely appear in a server inventory at all. If your build pipeline runs on an old image, every artifact it produces carries that old runtime forward.<\/p>\n<h2>A worked example: moving a site from PHP 8.1 to 8.4<\/h2>\n<p>This blog itself started on PHP 8.1, served through a CGI handler, because that was the account default. Moving it was a useful reminder that a version change is also a handler change. We switched the domain to PHP 8.4 under PHP-FPM with <code>whmapi1 php_set_vhost_versions<\/code>, which also rewrote the handler line in the site&#8217;s <code>.htaccess<\/code>.<\/p>\n<p>Two things changed besides the version. Under the CGI handler PHP had been running as the web server&#8217;s own user, so the configuration file had to be readable by that user; under FPM it runs as the account owner, which let us tighten <code>wp-config.php<\/code> back to mode 600 and let WordPress write its own uploads and updates. And the first check after the switch, a temporary script printing <code>php_sapi_name()<\/code> and the process user, was the only evidence that the new handler was really in use. Plan for both on every site you move, and test the switch on one site before the rest.<\/p>\n<h2>What should you do on your servers?<\/h2>\n<ol class=\"checklist\">\n<li><strong>Inventory every runtime, not just the default.<\/strong> Run <code>php -v<\/code> for each installed PHP build and check which version each site or FPM pool actually uses. For Node.js, check every service, container image and CI runner with <code>node --version<\/code>.<\/li>\n<li><strong>Move off end-of-life lines first.<\/strong> Upgrade PHP 8.1 and older to 8.4 or 8.5, and Node.js 20 to 24 LTS. This step closes more risk than any single patch.<\/li>\n<li><strong>Patch supported lines to the current release.<\/strong> At least the September PHP builds and Node.js 22.23.2, 24.18.1 or 26.5.1, then the October releases.<\/li>\n<li><strong>Restart what loaded the old binary.<\/strong> PHP-FPM pools, long-running PHP workers and every Node.js process keep the vulnerable code in memory until they restart.<\/li>\n<li><strong>Review FPM sockets.<\/strong> Prefer Unix sockets; if a pool listens on TCP, bind it to loopback and do not rely on <code>listen.allowed_clients<\/code> alone.<\/li>\n<li><strong>Disable what you do not use.<\/strong> If no site needs SOAP or Phar, remove the extensions from the build or the pool.<\/li>\n<li><strong>Put a limit in front of HTTP\/2.<\/strong> A reverse proxy with request size and connection limits absorbs memory-exhaustion attempts before they reach a Node.js process.<\/li>\n<li><strong>Subscribe to the announcements.<\/strong> The php.net release feed and the nodejs-sec mailing list give you advance notice of planned releases.<\/li>\n<\/ol>\n<p>The kernel underneath both runtimes needs the same discipline; the settings we keep on shared servers are in <a href=\"\/blog\/kernel-hardening-shared-linux-server-five-settings\/\">five kernel settings for a shared Linux server<\/a>.<\/p>\n<h2 id=\"faq-php-nodejs-security-releases-2026\">FAQ: PHP and Node.js security releases in 2026<\/h2>\n<h3 id=\"faq-php-81-still-safe-2026\">Is PHP 8.1 still safe to run on a production server in 2026?<\/h3>\n<p>No. PHP 8.1 stopped receiving security fixes from the PHP project at the end of 2025, so none of the 2026 fixes were released for it upstream. Some vendors backport selected fixes, which helps, but the supported path is 8.4 or 8.5.<\/p>\n<h3 id=\"faq-node-20-end-of-life-2026\">When did Node.js 20 reach end of life, and what does that mean in 2026?<\/h3>\n<p>Node.js 20 reached end of life on 30 April 2026. Since then it receives no security releases, so every Node.js fix published later in 2026 is missing from it. Upgrade to 24 LTS, or to 22 if you need more time, since 22 is supported until April 2027.<\/p>\n<h3 id=\"faq-php-82-vs-84-upgrade-target\">PHP 8.2 vs PHP 8.4: which is the better upgrade target today?<\/h3>\n<p>PHP 8.4. Branch 8.2 reaches end of life on 31 December 2026, which leaves only weeks of security fixes, while 8.4 is supported until the end of 2028. Upgrading twice in a few months costs more testing than going straight to 8.4.<\/p>\n<h3 id=\"faq-node-22-vs-24-lts\">Node.js 22 vs Node.js 24: which LTS line should a server use?<\/h3>\n<p>For new deployments, Node.js 24. Both are supported LTS lines, but 24 is supported until April 2028 and 22 only until April 2027. Keep 22 where a dependency is not yet ready, and plan its replacement now.<\/p>\n<h3 id=\"faq-php-v-shows-wrong-version-cpanel\">Why does php -v show a different version than my website uses on cPanel?<\/h3>\n<p>Because the command line and the web server are configured separately. A domain can be served by another branch through MultiPHP Manager, an <code>.htaccess<\/code> handler or CloudLinux PHP Selector. A temporary script that prints <code>PHP_VERSION<\/code> and <code>php_sapi_name()<\/code> shows what the site really runs.<\/p>\n<h3 id=\"faq-restart-after-php-update\">If I update PHP packages, do I need to restart anything for the fix to apply?<\/h3>\n<p>Yes. PHP-FPM pools and long-running PHP workers keep the old code in memory until they restart, and Apache with mod_php needs a full restart rather than a graceful reload. Updating the package without restarting leaves the vulnerable code running.<\/p>\n<h3 id=\"faq-fpm-tcp-socket-ipv6-risk\">Is a PHP-FPM pool listening on an IPv6 TCP socket a risk after CVE-2026-91768?<\/h3>\n<p>It was, until the September builds. The allowed-clients check compared only part of an IPv6 address, so the list could be bypassed. Update, and prefer a Unix socket or a loopback-only TCP listener so the pool is not reachable from the network at all.<\/p>\n<h3 id=\"faq-soap-phar-disable-shared-hosting\">Should shared hosting servers disable the SOAP and Phar extensions in 2026?<\/h3>\n<p>Where no site uses them, yes. Both were the subject of 2026 fixes, and an extension that is not loaded cannot be attacked. Check first, because some billing systems and integrations still rely on SOAP.<\/p>\n<h3 id=\"faq-node-http2-memory-exhaustion\">How do you protect a Node.js HTTP\/2 service from memory exhaustion attacks?<\/h3>\n<p>Update to a patched release first, since CVE-2026-56846 bypassed the session memory limit. Then put a reverse proxy in front with request size, header and connection limits, so abusive clients are cut off before they reach the Node.js process.<\/p>\n<h3 id=\"faq-how-get-advance-notice-releases\">How can a server team get advance notice of PHP and Node.js security releases?<\/h3>\n<p>Follow the php.net release announcements and subscribe to the nodejs-sec mailing list. Node.js publishes a pre-announcement days before each security release, which leaves time to plan maintenance windows and restarts.<\/p>\n<h2>Sources<\/h2>\n<ul class=\"sources\">\n<li><a href=\"https:\/\/www.php.net\/ChangeLog-8.php\" rel=\"noopener\" target=\"_blank\">PHP 8 ChangeLog<\/a>, php.net<\/li>\n<li><a href=\"https:\/\/www.php.net\/supported-versions.php\" rel=\"noopener\" target=\"_blank\">Supported versions<\/a>, php.net<\/li>\n<li><a href=\"https:\/\/nodejs.org\/en\/blog\/vulnerability\/june-2026-security-releases\" rel=\"noopener\" target=\"_blank\">June 2026 security releases<\/a>, nodejs.org<\/li>\n<li><a href=\"https:\/\/nodejs.org\/en\/blog\/vulnerability\/july-2026-security-releases\" rel=\"noopener\" target=\"_blank\">July 2026 security releases<\/a>, nodejs.org<\/li>\n<li><a href=\"https:\/\/github.com\/nodejs\/release#release-schedule\" rel=\"noopener\" target=\"_blank\">Node.js release schedule<\/a>, GitHub<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>PHP and Node.js both shipped high-severity security fixes in 2026. Here is what changed, which versions are still supported, and a checklist for the servers that run them.<\/p>\n","protected":false},"author":0,"featured_media":29,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[6,7,3,9,2,5,4,8],"class_list":["post-5","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-security","tag-cpanel","tag-end-of-life","tag-node-js","tag-patch-management","tag-php","tag-php-fpm","tag-security-updates","tag-server-hardening"],"_links":{"self":[{"href":"https:\/\/adnancanturk.com\/blog\/wp-json\/wp\/v2\/posts\/5","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/adnancanturk.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/adnancanturk.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/adnancanturk.com\/blog\/wp-json\/wp\/v2\/comments?post=5"}],"version-history":[{"count":2,"href":"https:\/\/adnancanturk.com\/blog\/wp-json\/wp\/v2\/posts\/5\/revisions"}],"predecessor-version":[{"id":44,"href":"https:\/\/adnancanturk.com\/blog\/wp-json\/wp\/v2\/posts\/5\/revisions\/44"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/adnancanturk.com\/blog\/wp-json\/wp\/v2\/media\/29"}],"wp:attachment":[{"href":"https:\/\/adnancanturk.com\/blog\/wp-json\/wp\/v2\/media?parent=5"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/adnancanturk.com\/blog\/wp-json\/wp\/v2\/categories?post=5"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/adnancanturk.com\/blog\/wp-json\/wp\/v2\/tags?post=5"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}