What to patch now: PHP, GitLab, Node.js, Brotli and eMudhra
Mid-October was rough. Within two weeks, PHP, GitLab and Node.js all shipped emergency fixes. An out-of-bounds write turned up in the reference Brotli decoder and spread from there into Node.js, Bun, Python libraries and proxies. And the private keys of the eMudhra certificate authority turned out to be crackable in a fraction of a second. Here's what happened, which versions to install and what to do if you can't update right now — all in one place.
| What | Update to | How urgent |
|---|---|---|
| PHP | 8.5.12, 8.4.27, 8.3.36, 8.2.35 | Today: unauthenticated code execution, attacks are already underway |
| GitLab (self-managed) | 19.5.1, 19.4.3, 19.3.6, 19.2.9, 19.1.9, 19.0.10, 18.11.13 | Today: rated 10 out of 10, every version since 7.0 is affected |
| Node.js | 26.12.1, 24.22.1, 22.23.4 | Today: code execution through Brotli plus nine more vulnerabilities |
| Brotli in libraries and proxies | libbrotli 1.2.1, Python Brotli 1.2.1, Bun 1.4.4, Envoy, Istio | This week: check your dependencies and rebuild images |
| eMudhra certificates | up-to-date ca-certificates in the OS, Go 1.27.3 or 1.26.10 | This week: update your root certificate stores |
| nginx | 1.30.6, or 1.31.7 and later | If you use alias with rewrite, SSI with AIO, or HTTP/3 |
Why this matters for tunnels
A tunnel makes a local service reachable from the internet, so everything below applies to it too. A test site on PHP, a Node.js dev server or a home lab GitLab behind a tunnel is just as vulnerable as a production server. It just tends to get updated less often.
Two habits go a long way toward reducing the risk:
- Update your local environment along with production. A vulnerable PHP on a developer's laptop, exposed through a tunnel, is just as much an entry point for an attack.
- Don't open a service to everyone if only two people need it. You can lock a tunnel down with a password, a key in a header or a subnet allowlist. A request that fails the check never reaches your app. For more complex rules, there are traffic policies and Apps with SSO sign-in. We compared all the options in our post "5 ways to put authorization in front of a service".
tuna http 8080 --basic-auth="anna:s3cret" --cidr-allow="203.0.113.0/24"
PHP2Shell: unauthenticated code execution
What happened: On October 21, PHP shipped an out-of-band release fixing two critical vulnerabilities in the interpreter itself. Both are rated 9.2 on CVSS 4.0, and both can be exploited without authentication:
- CVE-2026-109618. If a request hits
memory_limitat the wrong moment, internal data is left half-initialized, and request cleanup then treats it as valid. The result is memory corruption. - CVE-2026-109619. Request state outlives the memory it lives in and gets picked up by the next request on the same worker. This is a use-after-free.
Who is affected: Every way of running PHP for the web is vulnerable: PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed. mod_php is the worst case, because the attack fires before any application code runs. The bug lives in the interpreter, so any site on a vulnerable version is at risk — WordPress, Bitrix, Laravel or custom-built. You need to update PHP itself; updating your CMS won't help.
Why it's urgent: The CVE IDs leaked on October 20, and the release had to ship a day ahead of schedule. Amazon spotted the first exploitation attempt against its honeypots as early as October 17, four days before the fix, and now reports broad exploitation in the wild. Public exploits are out as well. Government agencies are sounding the alarm too: the UK's NCSC advises taking systems offline if you can't patch or mitigate them, and on October 22 Russia's NCIRCC told critical infrastructure operators to update urgently and to cut off from external access or shut down any servers they can't patch in time.
What to do:
- Update to 8.5.12, 8.4.27, 8.3.36 or 8.2.35, or install your distribution's package with the backported fix. After updating, restart all workers: php-fpm, Apache. If PHP runs in a container, rebuild your app image on top of the official php image with a fixed version, such as
php:8.4.27-fpmorphp:8.3.36-apache. - PHP 8.1 and older won't get official releases. The PHP team has published minimal patches for the 7.4–8.1 branches, but you have to build them from source. Otherwise, your options are moving to a supported branch or turning to an LTS vendor. Keep in mind that PHP 8.2 reaches end of life on December 31, 2026.
- If you can't update right away, apply the temporary mitigations from the PHP advisory. They narrow the attack paths but don't fully close the vulnerabilities.
In php.ini or the FPM pool settings — but not via ini_set() and not in .user.ini:
; CVE-2026-109619
session.upload_progress.enabled = 0
In the PHP-FPM pool — via php_admin_value, so the application can't override it:
; CVE-2026-109618
php_admin_value[memory_limit] = -1
Also cap the request size: post_max_size = 8M for sites without file uploads and 32M for sites with them. On PHP 8.5, also set fatal_error_backtraces = 0. Restart the workers after making changes.
On October 23, PHP published another advisory, CVE-2026-115560, also related to upload progress. The scenario is unusual: the application has to switch session.serialize_handler at runtime. The fix will come in a regular release, and until then it's best to keep session.upload_progress.enabled = 0.
Learn more:
- PHP advisory of October 21 and advisory of October 23
- PHP Foundation post and GitHub advisories: CVE-2026-109618, CVE-2026-109619
- Tenable FAQ and Rapid7 analysis
- NCSC alert and the NCIRCC demand (news on Habr, in Russian)
GitLab: two 10-out-of-10 vulnerabilities in one month
What happened: On October 12, GitLab fixed CVE-2026-97229, rated 10.0 on CVSS. A specially crafted regular expression in a CI/CD configuration could execute code on the server without authentication. Versions from 19.2 onward were affected.
On October 21, another out-of-band release followed. Its headline vulnerability, CVE-2026-110264, is also rated 10.0: an integer overflow in the regular expression compiler once again allows unauthenticated code execution. It affects Community and Enterprise Edition across every version since 7.0, which dates back to 2014. The same release fixed 11 more vulnerabilities, including takeover of LDAP accounts through OmniAuth auto-linking (8.2) and OAuth/OIDC discovery cache poisoning (7.5).
The October 12 release fixed a different vulnerability. Only the October 21 release protects against CVE-2026-110264.
What to do:
- Self-managed: update to 19.5.1, 19.4.3, 19.3.6, 19.2.9, 19.1.9, 19.0.10 or 18.11.13. There are no fixes for versions older than 18.11; you'll need to move to a supported branch.
- If you're far behind, you can't jump straight to the latest version: GitLab requires going through mandatory intermediate versions. Upgrade Path helps you plan the route. Enter your current version, and the tool shows which versions to go through to reach the latest, what breaking changes they contain and which features will start behaving differently.
- GitLab in Docker is updated by changing the tag of the gitlab/gitlab-ce or gitlab/gitlab-ee image:
19.5.1-ce.0,19.5.1-ee.0and so on. Pin the version explicitly instead of usinglatest, or you'll skip the intermediate versions. - On a single-node installation, the migrations in this release can cause downtime, so plan the update. Multi-node installations can be updated without downtime using the standard procedure.
- GitLab.com and GitLab Dedicated are already patched; there's nothing you need to do.
Learn more:
- 19.5.1 release of October 21 and 19.4.2 release of October 12
- Plan your upgrade path — GitLab documentation
- SecurityOnline coverage
Brotli: a vulnerability in a decoder that's almost everywhere
What happened: CVE-2026-111497 is an out-of-bounds write in the reference google/brotli decoder, versions 1.0.3 through 1.2.0. A specially crafted compressed stream makes the decoder write past its allocated memory. The impact ranges from a process crash and a memory leak to code execution. It's rated 9.2 on CVSS 4.0. The vulnerability doesn't have a settled name yet: it goes by Node2Shell, Broccoli2Shell and HTTP2Shell.
Why it's dangerous: Brotli decompression is often on by default, and developers may not even know it:
- Node.js. The built-in
fetch()asks HTTPS servers for Brotli on its own and decompresses the responses. Express 5 and body-parser 2.x decompress request bodies withContent-Encoding: br. - Python. urllib3, requests, httpx and aiohttp decompress Brotli if the
Brotliorbrotlicffipackage is installed in the environment. You don't need to import it in your code — it's enough for it to be installed as a dependency. - Bun, Envoy and Istio with the Brotli decompression filter, and curl with the
--compressedflag.
nginx and Apache don't decompress incoming Brotli by default.
Update first the services that fetch user-supplied URLs (webhooks, link previews, scrapers) and the services that accept compressed request bodies.
What to do:
| Component | Fixed versions | Docker Hub image |
|---|---|---|
| libbrotli (google/brotli) | 1.2.1, 1.1.1, 1.0.10 | base image package |
| Python: Brotli | 1.2.1 | — |
| Python: brotlicffi | 1.2.1.0 | — |
| Node.js | 26.12.1, 24.22.1, 22.23.4 | node |
| Bun | 1.4.4 | oven/bun |
| Envoy | 1.40.0, 1.39.3, 1.38.6, 1.37.8 | envoyproxy/envoy |
| Istio | 1.31.2, 1.30.6, 1.29.9 | istio/proxyv2 |
| Go: andybalholm/brotli | v1.2.7 | — |
- The system libbrotli is updated with your distribution's package. Check whether the fix has landed for your base image, then rebuild your image. A statically compiled copy can only be updated by rebuilding. That includes executables built with
bun build --compile. - In containers, pin the fixed version in the tag explicitly or pull the image again with
docker pull. A floating tag likenode:24in your local cache may still point to an old build. - Brotli is also embedded in other projects: .NET, PHP and Ruby extensions, ClickHouse, DuckDB. According to OpenNet (in Russian), not all of them had shipped fixes when the news came out. Keep an eye on the advisories for your stack.
- As a stopgap, you can reduce the risk by disabling Brotli decompression or rejecting requests with
Content-Encoding: brat the proxy. This is not a substitute for updating.
Learn more:
- Wiz analysis with a table of affected products
- Aikido analysis of Python libraries and automatic decompression
Node.js: nine more vulnerabilities
On October 21, Node.js 26.12.1, 24.22.1 and 22.23.4 came out. Besides Brotli, the release fixes nine more vulnerabilities. The most important ones:
- CVE-2026-105483 and CVE-2026-106069 (High). The hostname check against a TLS certificate can be bypassed by writing an IP address in a non-standard form: with fullwidth digits or leading zeros.
- CVE-2026-105482 (High).
dns.resolve*()truncates a name at a NUL byte, soattacker.example\0.trusted.exampleresolves asattacker.example. This is dangerous for applications that check a host against an allowlist and then resolve it. - CVE-2026-106074 (Medium). The entropy cache of
crypto.randomUUID()andcrypto.randomInt()ends up in snapshots (--build-snapshot) and single executable applications (SEA). Every process started from the same snapshot produces the same UUIDs. Updating Node.js alone isn't enough here: snapshots and SEAs built with a vulnerable version need to be rebuilt.
The same release includes updates to OpenSSL, c-ares, undici and the bundled root certificate store, which drops the compromised eMudhra certificates (more on those below). Node.js 20 and older are no longer supported and won't get fixes.
The fixed versions are already available in the official node image: 26.12.1, 24.22.1 and 22.23.4.
Learn more:
- Node.js advisory
- How to find vulnerable runtimes — Qualys
- Aikido on Node2Shell — how
fetch()and Express end up decompressing Brotli
eMudhra: certificate authority keys cracked in under a second
What happened: On October 17, a researcher going through the CCADB certificate authority database discovered that the private keys of eight intermediate certificates from the Indian CA eMudhra could be recovered from the public ones in under a second. Each key turned out to be a number below 256, and one was literally 4. Six of these certificates were meant for issuing TLS certificates for websites, and two for code signing. The chains led to root certificates trusted by Apple, Google, Microsoft and Mozilla. That means anyone with these keys could issue a valid certificate for any domain and intercept HTTPS traffic.
The response: Chrome and Firefox blocked the certificates on the day of the report, Apple on October 19, and Microsoft on the 20th. Mozilla stopped trusting the root certificate that signed the compromised intermediates. Google is removing the emSign ECC Root CA – G3 root from Chrome. On October 22, eMudhra announced it was leaving the global TLS certificate business. Around 30,000 customer certificates will need to be reissued. No forged certificates issued with these keys have been reported so far. According to the Indian authorities, Indian digital signature certificates (DSC) and the eSign service are not affected.
What to do: Browsers and operating systems are already protected; installing updates is enough. It's trickier with software that has its own root certificate store:
- Servers and containers. Update the
ca-certificatespackage. Rebuild your images on a fresh base image — debian, ubuntu, alpine — and check that it ships the updatedca-certificates. - Go. Versions 1.27.3 and 1.26.10, released October 19, reject chains that go through the compromised certificates (CVE-2026-111943). The block lives in the standard library, so Go applications need to be rebuilt with the new compiler version. In a multi-stage Docker build, bump the golang image to
1.27.3or1.26.10. - Node.js. The updated bundled root certificate store is part of the October 21 release.
- Java, Python certifi, mTLS stores and certificate bundles embedded in applications. Check each one separately.
- Sites with an eMudhra certificate. Reissue the certificate with a different CA.
If something stops loading over HTTPS after the updates, don't "fix" it with --insecure, InsecureSkipVerify or NODE_TLS_REJECT_UNAUTHORIZED=0. That opens the door to exactly the attack the block protects against.
Learn more:
- Incident report in Mozilla Bugzilla
- Cloudflare analysis with advice for servers, containers and mTLS
- Scott Helme's analysis and the Help Net Security timeline
- BleepingComputer coverage
What else came out in October
- nginx 1.30.6 and 1.31.7 (October 14). Five vulnerabilities that only show up with specific configurations:
aliascombined withrewrite, evaluation of string expressions with variables, SSI combined with AIO, HTTP/3, and TLS session ticket key rotation. nginx itself rates them as medium, but if you recognize your config, update. The full list is in the nginx security advisories. The fixed versions are available in the official nginx image:1.30.6(stable) and1.31.7or later (mainline). - Go 1.27.2 and 1.26.9 (October 8). Security fixes in
crypto/tls,net/http,html/template,net/textproto,osand thegocommand. Details are in the Go release history. - Collabora Online in Nextcloud (CVE-2026-110447). OS command execution through the built-in CODE server — the
richdocumentscodeapp before version 26.4.303. The vulnerability is already being used in attacks to plant web shells on Nextcloud servers. On October 23, CISA added it to its Known Exploited Vulnerabilities catalog. Update the app to 26.4.303 or remove it — just disabling it is not enough (more on BleepingComputer).
What we've done
Tuna users' data is safe, and there's no threat to it. The base images of our server applications have already been updated. New versions of tuna-cli and Tuna Desktop are coming out this week — watch the changelog.
Checklist
- Find every PHP installation — production, test, local — and update it. If you can't, apply the temporary mitigations.
- Update self-managed GitLab to the October 21 release. If you're on an old version, plan the route with Upgrade Path.
- Update Node.js, Bun and the
BrotliandbrotlicffiPython packages. Rebuild container images, snapshots and SEAs. - Update
ca-certificates, rebuild Go applications with Go 1.27.3 or 1.26.10, and check your own certificate stores. - Check your nginx configuration and update Collabora in Nextcloud.
- Lock down anything published through a tunnel that not everyone needs with a password, a key or an IP allowlist.
Leave feedback
If you enjoy using Tuna, or on the contrary you are not happy with something, please leave feedback.
News
We announce new features and posts on our Telegram channel. Subscribe so you don't miss anything.
Help
We value our users and carefully review every request. If you have any problems with tuna, please contact us in one of the following ways: