
Today’s issue: Stability in TanTown, the old Chinese proverb about syntax highlighting, and the politically correct way to pronounce “dquickts”.
Welcome to #532.


Remembering our PHP homies in their darkest hour.
It’s been a rough week for PHP developers, and since there are about 24 loyal Laravel / WordPress devs who read Bytes, we’re dedicating this issue to commiserating with our <?= brethren ?>.
So what happened? Well, if you don’t know, you probably have healthier internet consumption habits than me, but the TL;DR is that PHP got hacked… badly. The vulnerabilities are called php2shell, and they can give attackers access to a shell on a vulnerable server, where they could access your database, API keys, and environment variables… or just mine for crypto (if that’s still a thing). Pretty bad, especially considering that the flaws are in PHP itself, putting unpatched servers at risk regardless of the application running on them.
How does php2shell work?
First, an attacker sends a multipart/form-data POST request to any page on the server, hiding a shell command and the fake data structures needed to execute it in the field values. The request is padded with a huge number of headers and thousands of empty file fields, with content-length conveniently omitted. PHP runs out of memory while parsing the request, leaving the malicious payload in memory when the shutdown routine runs.
Then, during shutdown of that same request, the cleanup code walks the half-built state, follows a pointer the attacker planted in it, and executes the payload with the server’s own permissions 😬.
What’s the fix?
PHP sites need to update to a patched release: 8.5.12, 8.4.27, 8.3.36, or 8.2.35. Which, if we’re being honest, could be a challenge for sites still running legacy versions. Cloudflare’s WAF protections can block known exploit attempts while those sites patch, but PHP says updating is the only complete fix.
Where do we go from here?
While it might be tempting to breathe a sigh of relief, our day of reckoning as JavaScript developers is coming because Node.js just got hit with a high-severity CVE impacting its Brotli decoder. And if I had to guess, this is only the beginning of this new era of software development which is so fun. I love it here.
Bottom line: Looks like your PM is going to have to drop all the features they wanted to ship in Q4 in order to keep up with all the security patches coming down the pipe.


When you're just trying to find that one customer session but there's too much noise
Sentry’s session replays are great for seeing exactly what a user experienced during a session, but how do you comb through millions of sessions to get what you need?
That’s why Sentry is hosting a free workshop on Nov 5 on how to tune your session replay setup.
You’ll learn about:

Run by Apify brings AI agent builders to San Francisco on November 10. Come network, catch live demos, and hear from experts at OpenAI, Stripe, and Coinbase. Use code BYTESRUN for 50% off your ticket.
class TreeNode {
constructor(value) {
this.value = value;
this.left = null;
this.right = null;
}
}
function treeDepth(node) {
let leftDepth = treeDepth(node.left);
let rightDepth = treeDepth(node.right);
return Math.max(leftDepth, rightDepth) + 1;
}
let root = new TreeNode(1);
root.left = new TreeNode(2);
root.right = new TreeNode(3);
root.left.left = new TreeNode(4);
root.left.right = new TreeNode(5);
console.log("Depth of the tree:", treeDepth(root));

We wanted AI to cure cancer, but instead of Light The Night, we got Patch the Planet, an OpenAI initiative to disclose security vulnerabilities to package maintainers before they are announced to the public.
Sentry donated one miliiiiiion dollars to open source maintainers this year, which is objectively awesome. I’m glad some people still believe in open source 🥺.
Built an app with Expo? Enter it in the Expo App Awards by October 31. Winners get a handcrafted metal cube, a prize you can’t explain to your family but will 100% keep on your desk. [sponsored]
Speaking of paying open source maintainers, The Open Source Pledge is an initiative to raise funds from companies to support important open source projects. Maybe tell your boss.
The artist formerly known as Framer Motion added scopeMotion and useScopeMotion in its 14.5 release for easy cleanup, media query matching, setting default transitions, and scoping to an element.
TanStack AI published its first stable release with version 1.0. Lots of stability happening right now in TanTown.
SerpApi’s new Extract API lets your agents fetch a public web page and return the whole thing as structured JSON or as clean Markdown. Check out the interactive demo. [sponsored]
Colin McDonnell built a library called Reylo that lets you import .sql files into TypeScript with full type inference. I think this was the final nail in the coffin for the ORM startup era.
Stencil Labs open sourced dquickts, a fork of QuickJS that can natively run TypeScript with a durable execution engine. Can we get Michael Key to teach us all how to pronounce dquickts?
Greptile built the ultimate AI Code Review tool with AI agent swarms that review and test pull requests with full context of your codebase. [sponsored]
Kimi K3.1 Pro was just released and it appears to hold its own against Fable, Opus, and Astra on several benchmarks.
Shu Ding wrote about some of the ideas behind his GPU lexer, which is a fancy (but slower than regex) way to do syntax highlighting in the browser. There’s also a Chinese proverb about why throwing bricks is good (unless you live in France, in which case maybe hold on to those bricks).
The code will throw a TypeError because the treeDepth function is not handling the base case. The base case should be when the node is null, in which case the function should return 0.
class TreeNode {
constructor(value) {
this.value = value;
this.left = null;
this.right = null;
}
}
function treeDepth(node) {
if (node === null) return 0;
let leftDepth = treeDepth(node.left);
let rightDepth = treeDepth(node.right);
return Math.max(leftDepth, rightDepth) + 1;
}
let root = new TreeNode(1);
root.left = new TreeNode(2);
root.right = new TreeNode(3);
root.left.left = new TreeNode(4);
root.left.right = new TreeNode(5);
console.log("Depth of the tree:", treeDepth(root));