Dev.to Security 🔐 Cybersecurity 👁 0 📖 5 min read

I Read Every Security Advisory This Week So You Don’t Have To. This is the most personal and human-sounding. Use it only if it’s true for you.

I spent most of this week reading security advisories so you don't have to. It was not a quiet week. Node.js, PHP and Python's favourite image library all shipped fixes for bugs where untrusted input could end up runnin

I Read Every Security Advisory This Week So You Don’t Have To. This is the most personal and human-sounding. Use it only if it’s true for you.

I spent most of this week reading security advisories so you don't have to. It was not a quiet week.

Node.js, PHP and Python's favourite image library all shipped fixes for bugs where untrusted input could end up running code on your server. CISA added two more actively exploited flaws to its must-patch list. And somewhere in the middle of all that, a volunteer in Czechia quietly kept a large chunk of the internet running.

If you run a backend in any of these languages, here's the short version of each one. For every bug I've included the one command that tells you whether you're affected, plus a link to the full write-up I did on ByteMuni if you want the details.

1. Node.js: your fetch() decodes Brotli whether you asked or not

CVE-2026-111497, nicknamed Node2Shell. It's an out-of-bounds write in the Brotli decoder that ships inside the node binary.

The part that got me: you don't have to "use Brotli" to be exposed. Built-in fetch() decompresses any response with Content-Encoding: br, no matter what your request asked for. Express 5's body parsers also decode Brotli request bodies by default. So a link-preview service, a webhook sender or an AI agent that fetches URLs is a target, even if nobody on the team has ever typed the word Brotli.

Check it:

node -v
# need v22.23.4+, v24.22.1+ or v26.12.1+

node -p "require('zlib').constants.BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH || 'missing'"
# -17 = patched build, missing = not patched

Node 20 and older get no fix at all.

I wrote up who's exposed, the pm2 and Docker traps, and stopgaps if you can't upgrade today.

2. PHP2Shell: millions of attempts, (so far) zero confirmed breaches

CVE-2026-109618 and CVE-2026-109619. These are memory bugs in the PHP engine itself, so a perfectly clean WordPress or Laravel app is still exposed if the PHP underneath is old.

Details leaked before the patch was ready. Cloudflare saw tens of thousands of exploit attempts within 45 minutes of the announcement, and millions by the next day. A Mirai botnet tried to jump on it too. The interesting bit is that nobody has confirmed a successful break-in yet, because reliable exploitation turned out to be hard. VulnCheck has since shown that the main obstacle can be beaten, so I wouldn't count on that luck lasting.

Check it (and be careful which PHP you're checking):

php -v
# need 8.5.12, 8.4.27, 8.3.36 or 8.2.35+
# BUT this is the CLI. Your web server might run a different PHP-FPM build.

The PHP2Shell explainer covers the bugs themselves, and the server patching guide walks through actually rolling it out.

3. The volunteer who patched PHP for everyone

This is the story from the week I liked most.

PHP's fix arrived as source code. Most servers don't compile PHP; they apt install it. On Debian and Ubuntu, a lot of those packages come from one person: Ondřej Surý, who has maintained ppa:ondrej/php and packages.sury.org in his spare time for over 20 years. He shipped patched builds the same day, and then backported the fix all the way to PHP 5.6, versions PHP itself no longer supports.

He doesn't even run PHP himself. His words: "I feel a responsibility toward the users of the internet."

If you've ever typed add-apt-repository ppa:ondrej/php, you've relied on his work. Check whether you still do:

apt policy php8.3   # swap in your version

Who Ondřej Surý is and what his week looked like. It's also a pretty good argument for funding the open-source people your stack depends on.

4. Pillow: one crafted image, code on your server

Pillow 13.0.0 fixes a pile of bugs. The two that worry me most:

  • CVE-2026-112398: a crafted FlashPix file can run code from a single Image.open() call if olefile is installed. Pillow detects formats by content, so renaming the upload to .png doesn't save you.
  • CVE-2026-96639: multi-frame images (PSD, MPO, DCX, MIC) can make Pillow write past a buffer when you seek() through frames.

And here's a trap I think a lot of people will fall into:

python -c "import PIL; print(PIL.__version__)"

# On Python 3.10 this "succeeds" but quietly installs a vulnerable 12.x:
pip install -U pillow

# This fails loudly instead, which is what you actually want:
pip install -U "Pillow>=13.0.0"

Pillow 13 needs Python 3.11+. pip won't warn you; it just picks the newest version that runs on your Python.

The full write-up has a cheat sheet mapping risky Pillow calls to each CVE, plus hardening code for when you can't upgrade yet.

5. CISA KEV: Nextcloud web shells and a VeloCloud takeover

On Friday CISA added two flaws to its Known Exploited Vulnerabilities list, which means people are already using them.

  • CVE-2026-110447 in Collabora Online's built-in server for Nextcloud (richdocumentscode). Attackers planted PHP web shells and went looking for KeePass files and crypto wallets. Disabling the app doesn't fix it; you have to update to 26.4.303+ or remove it.
  • CVE-2026-114625 in Arista VeloCloud Orchestrator. SQL injection that lets the lowest read-only user become a full operator.

If you run Nextcloud, look for leftover shells even if you've patched:

find /path/to/nextcloud -name 'shx*.php'

I covered both KEV additions, with log checks and fix versions.

The pattern I can't stop noticing

Three of these five are the same bug wearing different clothes: native code decoding untrusted bytes. A Brotli stream, a PHP request body, an image file. Your code can be clean TypeScript or Python and still hand attacker-controlled data to C code you've never looked at.

The other two are a reminder that "patched" and "safe" aren't the same thing. The Collabora fix shipped a month before anyone called it a security fix, and patching doesn't remove a web shell someone planted before you updated.

So my takeaways for the week:

  1. Know what's actually decoding your inputs, not just what's in package.json or requirements.txt.
  2. Check the runtime that serves traffic, not the one in your terminal.
  3. After you patch, look for anything that got in before you did.
  4. Throw a few dollars at the maintainers your stack quietly depends on.

I post this kind of breakdown regularly on ByteMuni, mostly security, plus some dev tools and AI stuff. If one of these bit you this week, I'd genuinely like to hear how you found out. Drop it in the comments.

📰 Read the original article on Dev.to Security

Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.