My name is Jake Marsh.
I'm a developer, designer, and writer.

Everything That Broke On October 21st

 •  15 minutes to read

Yesterday (Wednesday, October 21st) was one of the strangest days in security I can remember. By lunchtime TechCrunch was running a story titled "The internet is having a very bad cybersecurity day". None of these incidents are connected to each other. They just kept landing, one after another, all day long.

Here's a rundown of what happened, roughly ordered by how much it should worry you, with as many technical details as I could dig up.

PHP2Shell

The big one. PHP shipped emergency releases (8.5.12, 8.4.27, 8.3.36 and 8.2.35) at 14:00 UTC to fix two bugs that allow unauthenticated remote code execution. Both are rated CVSS v4 9.2.

CVE-2026-109618 is out-of-memory handling interrupting PHP while internal request data is only partly initialized. Request cleanup then treats that half-built data as valid. CVE-2026-109619 is request-owned state that survives after its memory is freed, so the next request on the same worker uses it before initialization resets it. A classic use-after-free.

The php.net advisory says every PHP install serving web requests is affected: PHP-FPM, mod_php, php-cgi, FrankenPHP and LiteSpeed. They consider mod_php the riskiest.

Upwind traced one confirmed path to php_session_rfc1867_callback in ext/session/session.c, the code that tracks upload progress on multipart POSTs. PHP caches a couple of zval * pointers while it counts bytes, then a session re-read destroys the hash table those pointers live in. The only precondition is session.upload_progress.enabled=1, which is the default. A stock php.ini is enough. Exploiting it needs a build-specific offset and wrong guesses crash the worker, so a burst of 502s from behind nginx is a decent sign someone's knocking.

The release was originally planned for today (the 22nd). Details and screenshots of an exploit tool leaked on the 20th, so PHP pulled it forward a day. Amazon's MadPot honeypots logged an exploitation attempt on October 17th, four days before anything was public, and nobody knows yet how that person got the details.

Calif found the bugs using OpenAI's GPT-5.6 Sol, and Wiz found them independently.

Then governments started pulling sites. The NSA said to take a system offline if you can't patch it right away. The UK took 32 government services offline (and four more partially). The Netherlands, Finland, French local government sites, a Danish school platform and Australia's own cyber agency website went dark too. By that evening Pantheon alone had blocked over 60,000 suspicious requests, and Cloudflare was watching attackers mutate payloads to slip past its WAF rules.

If you can't upgrade yet, PHP lists stopgaps that shrink the attack surface (they're clear that only the update makes you safe). Put these in php.ini or your FPM pool config, since ini_set() and .user.ini apply too late:

session.upload_progress.enabled = 0
post_max_size = 8M         ; 32M if you need uploads
fatal_error_backtraces = 0 ; PHP 8.5 only

They also suggest php_admin_value[memory_limit] = -1 in the FPM pool. Restart every worker afterwards. Also watch out for fake "PoC" repos on GitHub. JFrog has already found some carrying malware.

LiteLLM 1.107.0

LiteLLM, the Python proxy a lot of folks use to put a bunch of LLM providers behind one API, had a trojanized release up on PyPI, Docker Hub and GHCR for about two hours. It's the project's second compromise this year.

StepSecurity's reconstruction is wild. The attacker had stolen GitHub CLI OAuth tokens belonging to three BerriAI engineers. An org owner's token overrode branch protection at 10:08:34 UTC (five seconds after protection rejected the change) and rewrote the private release workflow to build from a lookalike repo, Berri-AI/litellm. Note the hyphen. A second engineer's token approved the production deploy, and a third one deleted the workflow run records.

Since the attacker changed the trusted workflow itself, all the hardening LiteLLM added after its March incident (Trusted Publishing, immutable tags, signed images) still applied to the bad build. The malicious packages shipped with valid provenance.

The wheels drop a 12-byte file called cook.pth that contains import cook. Python's site module executes import lines in .pth files on every interpreter start, so the stealer runs whenever Python starts on that machine. You never have to import litellm at all. Clever, and gross.

It grabs SSH and GPG keys, cloud credentials, cloud metadata endpoints, CI secrets, every process's /proc/<pid>/environ, browser passwords, and the config for AI coding tools like Claude Code, Cursor and Codex. If DATABASE_URL is set it also dumps LiteLLM's own tables, which are full of upstream provider keys. Everything gets encrypted (AES-256, with the key wrapped in RSA-4096) and POSTed to http://www.litellm.dev/healthcheck.

A second hook in sitecustomize.py forks a daemon that checks a GitHub repo under the account letters9813 every hour for a hostname, then fetches whatever is at /codepy on that host and exec()s it. That GitHub account is gone now, but infected machines are still polling, and anyone who re-registers the name could run code on all of them.

Wiz estimates about 49,000 downloads. If you picked up 1.107.0 between 11:39 and 13:23 UTC (or pulled a floating Docker tag before 14:20), kill the loader process before you run pip again, because every Python start re-runs the stealer. Then rebuild the machine, pin litellm==1.106.2, and rotate every credential that box could reach.

BerriAI suspects the GitHub tokens leaked out of an internet-exposed internal LiteLLM deployment that logged response bodies, including responses where Claude Code had included the tokens. That part isn't confirmed. I use Claude Code all day, so this one hit close to home. Anything that shows up in an agent's output can end up sitting in somebody's logs.

Railway

Railway disclosed that someone got into the systems that store customer environment variables, and for some customers walked away with the decrypted values. Railway says it's part of a series of attacks on platform companies aimed at stealing keys for AI inference providers. They paused all deployments, invalidated API tokens and OAuth sessions, and warned upstream AI providers so they could revoke keys early. Researcher Taylor Monahan traced crypto theft back to at least two hours before the disclosure went up.

No root cause or customer count yet. If you're on Railway, rotate your secrets at the provider itself, since an old key keeps working until the provider revokes it. Their follow-up post specifically says to check your OpenRouter usage.

ConnectWise And Storm-0940

Microsoft published its attribution for last week's ConnectWise Cloud Backup compromise: Storm-0940, a China-aligned group. The attacker took control of the identities of ConnectWise's multi-tenant Microsoft 365 apps and then signed in as those apps to customer tenants, riding the trust each tenant had already granted. Nobody had to type a password or approve an MFA prompt. Microsoft counted sign-in attempts against more than 2,250 tenants, peaking around 2,900 attempts per minute.

They automated it with ARTEX, an open-source multi-agent LLM pentest framework (Go backend, Next.js frontend) that works with any model. In some victims it went from first contact to privileged cloud access in under three hours, and in one tenant a ConnectWise app assigned itself Global Administrator.

Microsoft's advice is to disable the ConnectWise apps (search by app ID, display names can lie) and hold off on deleting them so you keep the evidence. Disabling them won't remove credentials the attacker already added to your other apps, so go check those too. ConnectWise started a phased restore yesterday.

GitLab CVE-2026-110264

A CVSS 10.0. An integer overflow in the regex compiler lets an unauthenticated user run code on the server, and it affects every version back to 7.0. That's 2014! It's fixed in 18.11.13, 19.0.10, 19.1.9, 19.2.9, 19.3.6, 19.4.3 and 19.5.1. There are no workarounds.

GitLab hasn't published the full path. Secondary write-ups point at Onigmo (Ruby's regex engine), reached by rendering an Org-mode .org file, which lines up with GitLab's own detection rules being named "Onigmo native worker crash" and "Org mode render error burst." This is a different bug from the CVSS 10 that GitLab fixed on October 12th. Patched last week? You need to patch again. No exploitation reported so far.

eMudhra's Single-Byte CA Keys

This one technically broke a few days earlier, but the fallout peaked yesterday. eMudhra's stock fell about 20% after an exchange filing, and it was the #2 security story on Hacker News.

Eight eMudhra intermediate CAs (six for TLS, two for code signing), cross-signed by Sectigo's root, had P-384 private keys that were numbers between 0 and 255. Scott Helme's write-up lists all of them. One key is 4. Getting a private key back from its public certificate takes at most 255 tries.

A bug in the April 2025 key ceremony script created a second, weak key pair on the HSM, and similar key names meant the wrong one got used for the CSR. These keys have effectively been public for about 17 months. Chrome found no TLS certs chaining to them in CT logs, and browsers blocked them within hours of the report. The real exposure is non-browser clients (curl, Python, Go, Java, package managers) that check neither CT nor revocation. Update your CA bundles (ca-certificates, certifi, Node, Homebrew) and rebuild your container images.

Node.js

Node.js 22.23.4, 24.22.1 and 26.12.1 fix CVE-2026-111497, an out-of-bounds write in the Brotli decoder that allows remote code execution. OpenAI's Codex Security was one of the reporters. Anything that decompresses Brotli from an attacker (request bodies, fetched responses) is exposed, and Vercel pushed emergency firewall rules.

Also in that release: CVE-2026-106074, where crypto.randomUUID() and randomInt() had their entropy caches baked into user-land startup snapshots and single executable apps. Every process launched from one of those produced the same "random" values. Yikes. The release drops eMudhra from Node's CA bundle too.

GMO Onamae.com Desktop Cloud

Over in Japan, GMO started shutting down every Onamae.com Desktop Cloud server at 04:00 JST after finding malware planted on customer machines. Up to 26,739 servers could be affected. The service is mostly Windows desktops running automated forex trading, and customers have reported unauthorized trades on their accounts. GMO hasn't published any malware details or IOCs yet.

The Rest Of The Day

Holy cow. Go patch your stuff, y'all.


▸ Little Bites of Cocoa 🍫

 •  5 minutes to read

I suppose it's about time I wrote about Little Bites of Cocoa. I've been having a blast with it. Here's a little about how it came to be:

The idea was simple. Daily bite-sized (get it?) tips and tricks to give readers a brief overview or explanation of a particular concept, technique, or tool.

I drew tons of inspiration from some of my favorite publications and content like Railscasts and NSHipster.

Originally I was planning on making Little Bites of Cocoa as a series of very short screencasts, but I quickly realized just how much work that was going to be. I'm lazy. I thought there might be a way I could communicate the same information, but without all the effort of video production.

Around the same time, I was experimenting with what it might be like to publish content "natively" on Twitter. I'm a big Twitter user, and I knew there was a huge community of iOS developers there. I found an image size that Twitter would display without cropping, and got to work.

The idea of each "bite" existing as a simple image file that could be shared around the web seemed very interesting, and I found it to be a very fun medium.

I composed each of the images by hand in Sketch using Symbols for things like lower thirds. Yes, I still do it this way, even now. It's the only way I can ensure the quality level. I often make fine-tune adjustments to the content to accomodate for showing it in such a contrained medium.

The process of simplifying a particular concept or set of steps to fit in the 1024 x 412 area available in each bite can be extremely challenging, but it's also very rewarding once I finally 'crack' the code. Composing each one becomes a sort of puzzle where I just need to find a way to express the concepts in their purest forms, with as little distraction or 'fluff' as possible.

I created a Twitter account: @lilbitesofcocoa and began posting my bites. The response was humbling, to say the least. So many awesome reactions and pieces of feedback. The biggest complaint at first was readers who wanted a better format for reading on their phones. The widescreen images just weren't cutting it for people trying to pinch and zoom their way around each bite. I began converting each bite into Markdown and posting them to a Tumblr.

Since I now had all the content in Markdown, and by extension HTML, I decided to offer a daily email format as well. I used Mailchimp to create a mailing list and to my surprise folks started signing up!

By now, I was having a ton of fun and looking for more places to share the content. I'd been a reader and subscriber of the /r/iOSProgramming subreddit for years and thought the community there would appreciate the concise image-based tips. It seems I was correct, the folks there loved it so much that the awesome moderators even gave me my own LBoC flair to use for my posts. Neat!

I continued publishing bites and eventually began to realize that I was outgrowing the Tumblr account I'd setup to host the 'web version' of bites. I decided to create my own site and CMS from scratch. This allowed me to have complete control over the presentation and organization of the content. I was also able to automate a fair amount of the work I was doing by hand.

It was around this time that I formed a partnership with my great friends over at the Spec Network. They were looking to broaden the content they provided and Little Bites seemed like a great fit. If you haven't checked out all the great stuff over there, you're missing out.

Finally: I'm proud to say that as of today, the new site is now live, complete with the first Sponsor!


Things I Learned at WWDC Today

 •  3 minutes to read

One of the best kept secrets of WWDC is that random conversations and run-ins as well as the official Labs at the conference are where much of the ticket value lies.

You can often learn tons of interesting details just by talking shop with the Apple employees hanging around.

Here's a summary of all the interesting details I learned today:

HomeKit

The new HomeKit triggers don't let you run arbitrary code, you schedule things like "when the garage opens, turn the thermostat to 70 degrees", and then everything happens out of process from your app.

Notifications about property changes on HomeKit devices are only delivered if your app is in the foreground. Great for privacy, but boo.

ReplayKit

Apple is totally fine with developers using this framework to record anything, not just Games. Wondering what interesting use cases (besides the obvious: user testing). This could get really fun.

Developers never get access directly to the video files. They're stored in a system directory and the user is offered the chance to share them with a standard activity view controller once recording completes. You can add custom actions that will appear in the activity view controller that appears though.

GameplayKit

Just like ReplayKit, you're free to use all of the features of GameplayKit for things other than games. Hey look, a free state machine implementation. Thanks Apple! (GameplayKit has a ton of incredbly useful and awesome features, I was just curious about this particular use case.)

Search

Apple has already been crawling the web and looking at things such as existing meta tags that are commonly included on popular websites. They're also noticing if sites have the old (but still great) Smart App Banners feature. When possible, they're tying the information together. If your app is installed, when a user taps on a search result, it deep links you into the app, otherwise, the website and Smart App Banner are shown.

In fact, this system is so far along that I was actually shown a demo of one of the apps I work on completely working as described above already on iOS 9 (since Apple already crawled the website and the meta tags were already configured correctly.) Neat!

Other

Mango Odwalla is delicious.


Cover header some interesting hints about ios 9

Some Interesting Hints About iOS 9

Today on Twitter, some clever sleuths discovered some interesting info tucked away in the latest WebKit source code.

Specifically, references to iOS 9 and OS X 10.11 were found.

Here are some of the highlights:

App Links

References such as LSAppLinkOpenCompletionHandler could point to a few different sorts of things.

A fair amount of hub-ub has been bustling about lately in regards to UIKit's canOpenURL: methods and the way some developers were trying to be sneaky and use the API for what it was designed to do. (I kid, I kid). App Links could be Apple revamping the URL handling systems in iOS and OS X to be more "safe" (more restricted to be sure).

Another idea that comes to mind is something closer to what Facebook and applinks.org have attempted. Encouraging and supporting more iOS and Mac developers to create indexable content URLs seems like a smart strategic move on Apple's part. Plus, with all the reports of their recent search efforts, who knows what sorts of things they could be working on.

Dynamic Type

More platform feature-parity happening here. Dynamic Type is a fantastic system and I'm quite happy to see it making its way to the Mac and specifically into WebKit.

There's bound to be more undiscovered goodies littered around the WebKit codebase. If you'd like to poke around yourself, here's a good place to start.

If you find anything interesting, drop me a line.


▸ ComponentKit

ComponentKit takes a functional, declarative approach to building UI. It lets you focus on what your UI should look like, not the steps necessary to build it. It emphasizes a one-way data flow from immutable models to immutable components that describe how views should be configured. It does the heavy lifting of building a view hierarchy from this description.

I've been waiting to play around with this library since I saw this fantastic talk from Adam Ernst and Ari Grant late last year.

There's many pieces to ComponentKit, but one of the most interesting (to me at the moment) is it's declarative layout system:

This is random code I copy/pasted together to show some examples of layout inside ComponentKit. Please refer to their excellent documentation to see the real thing.

[CKInsetComponent
    newWithInsets:{.top = 70, .bottom = 25, .left = 20, .right = 20}
    component:
        [CKStackLayoutComponent 
            newWithStyle:{
                .direction = CKStackLayoutComponentDirectionVertical,
            } 
            children:{
                {[HeaderComponent newWithArticle:article]},
                {[MessageComponent newWithArticle:article]},
                {[FooterComponent newWithArticle:article]},
            }
        ]
];

I've been working in WatchKit quite a bit lately, and I've come to really enjoy it's layout system a lot. It's certainly limiting, but it's fantastic for quickly putting things together when you have an idea. I've been wishing a library would come along that emulated this sort of system for iOS in general, and ComponentKit fits the bill.

Even though some of the ideas and foundations in ComponentKit clash pretty heavily with UIKit's philosophies, I'm encouraged by the pure usability of their system. Even their choice of Objective-C++ as a language was made to make the end-resulting code that uses the library as readable as possible.

It's certainly not meant to be a catch-all and won't be the right choice for every app, but in the cases where it makes sense, ComponentKit seems like a slam dunk.


▸ Apple TV Service Coming in June

Looks like it's finally happening.

The subscription will allegedly cost $30-$40 month, which is a tad pricer than Sling TV’s core $20 package. 25 channels may sound like not that many, but Sling TV’s cable-free subscription only offers 14 with $5 add-on packs like “Kids Extra” and “News & Info Extra.”


According to the Journal, the likes of ABC, CBS and Fox are lined up as partners with Apple. But NBCUniversal is not on board because Apple has interestedly had a falling out with the network’s parent company, Comcast.

I've been thinking about Apple's TV service for long time now, and this seems about on par with what I was expecting out of a first generation product.

In the wake of the apparent success of iCloud Photo Library and CloudKit itself, (in that we haven't heard much about them in the press) I'm happy to see Apple has gotten back on the proverbial horse when it comes to launching new services.

Also, I've heard similar things about the Apple/Comcast relationship. I'd be surprised if Comcast isn't already planning to cave a few months after the new device launches.


Confirmed: Apple Watch Runs iOS

 •  6 minutes to read

Today's release of WatchKit definitely had a few developers scratching their heads.

While on the one hand, many of us weren't expecting as many different integrations points as we got in this first release, the APIs that were announced certainly leave a bit to be desired. Specifically for those of us with aspirations to build full-fledged native apps for the Apple Watch.

Apple has of course said that "full" support for building "full" apps will come later this year, but some enterprising developers are already starting to poke around and discover what it might be like.

Many have speculated about what sort of operating system Apple Watch will run, with not much data to pull from. Now that WatchKit has been made (at least partially) public, we seem to have some much more solid evidence for that operating system being iOS.

Here's a stream of tweets from Steve Troughton-Smith (everyone's favorite neighborhood tinkerer), as well as Andrew Pouliot (iOS at Facebook), regarding WatchKit:

It seems that the framework powering the more elaborate Apple Watch apps is called PepperUICore (at least internally). The framework is still private and will likely remain that way until WWDC where I imagine it may gain a much more public-friendly name.

PepperUICore contains some fun classes like PUICCrownView and PUICNavigationController. You can rummage through the full private headers here if you'd like.

Also of note are all the other private Apple Watch-related frameworks present in the iOS 8.2 beta. There's a new Nano prefix with frameworks that have intriguing names like NanoLeash (seems to enable some kind of "find my device" functionality), and NanoTimeKitCompanion, which contains references to "monograms" (my guess here is this is the internal name for Watchfaces, and Apple is likely planning some sort of special App Store section for these, there's a huge market there. Watchfaces will be the new Ringtones).

For fun I decided to read through some of the PUICTableView classes and see what sorts of goodies I could find.

It seems that PUICTableView (you can view the full file here) is primarly used as a way to tie together the familiar scrolling workhorse that is UITableView with the new Digital Crown hardware found on the Apple Watch:

- (void)crownInputSequencer:(id)arg1 previousDetent:(id *)arg2 nextDetent:(id *)arg3 forOffset:(double)arg4;
- (void)_crownInputSequencerIdleDidChangeNotification:(id)arg1;
- (void)_crownInputSequencerOffsetDidChangeNotification:(id)arg1;

sidenote: I love the name 'detent' for describing the "steps" along a 'notched' wheel like the Digital Crown.

It seems that the Watch reports itself to be in what's called UIDeviceFamily "4". iPhone reports "1", iPad reports "2", and Apple TV reports itself as "3".

That's about as conclusive as it gets and I must say is actually quite reassuring that the Apple Watch is built on the solid foundation of iOS.

The limitations of many of the APIs in today's WatchKit release definitely felt like a temporary measure, and I'm happy to see that there's tons of good stuff in the pipeline, it's just not ready for public consumption just yet.

It's not hard to be reminded of the conversations (before it's announcement) of the possibility of the iPhone running OS X. (A seemingly unlikely feat at the time).

But as Apple has done for many years now, they managed to leverage their earlier hard work and solid foundations to leapfrog themselves forward with their next product. OS X's Foundation, CFNetwork, and countless other battle-tested APIs gave both Apple's first and third party developers firm starting points to build upon.

Well that was almost 7 years ago. It seems that iOS (then iPhone OS) is now all grown up, and ready to help it's new little brother, the Watch, find success.


▸ Apple Releases First Beta of WatchKit

Apple:

WatchKit apps have two parts: A WatchKit extension that runs on iPhone and a set of user interface resources that are installed on Apple Watch. When your app is launched on Apple Watch, the WatchKit extension on iPhone runs in the background to update the user interface and respond to user interactions. WatchKit provides three opportunities to extend your iPhone app to Apple Watch: WatchKit apps, Glances, and actionable notifications.

Extremely excited for the opportunities WatchKit and the Apple Watch will open up for third-party developers and users.

Also nice that we get more than just simple notifications out of the gate. Although it does seem that communication is only one-way for now:

One fun note is that Apple has also released the system font for Apple Watch, called San Francisco. Gruber points out another memorable typeface with that name.

Make sure you check out the WatchKit Human Interface Guidelines, the WatchKit Programming Guide and the WatchKit Framework Reference.


▸ Apple Releases Xcode 6.1.1 GM

Chris Lattner on the Apple Dev Forums:

We care a lot about the pain that is affecting you now, and Xcode 6.1.1 available now as a GM Seed should address the worst of the SourceKit, DerivedData and module cache issues (among other bugs).

It has been wonderful to see Chris Lattner (father of Swift) taking such an active role in the developer forum discussions about the language and platform. It's a big step away from Apple's notoriously quiet attitude about works-in-progress.

Today's release of Xcode has seemingly eliminated many of the nagging issues that have been plaguing Swift development for a while. I haven't seen any SourceKit crashes and haven't had the module cache issues that previously had been wreaking havoc.

Twitter seems to agree, here are some reactions from other developers:

It appears that the Swift tooling is finally becoming stable enough to work with on a regular basis. With this latest release, I've been able to debug Swift code and work without any issues for a few hours.

I'd like to say thanks to the all the teams at Apple for their hard work getting things up and running.


▸ Amazon Echo

Amazon:

Amazon Echo is designed around your voice. It's always on—just ask for information, music, news, weather, and more. Echo begins working as soon as it hears you say the wake word, "Alexa." It's also an expertly-tuned speaker that can fill any room with immersive sound.

Very interesting move from Amazon. This will be their fifth major consumer hardware product category, and one that certainly makes the future seem exciting.

Although it has a bit of an informercial vibe, Amazon's video does a nice job explaining the product, and the use cases it might have:


The response time demonstrated in the device's promotional video is impressive. The biggest user-facing problem with systems like this is the lag time between when you say your ‘key phrase’ and when the device begins listening for speech that it can interpret as some kind of input.

In the video, Amazon makes it seem as if this “waiting” time is not needed with the Echo. If this is the in fact the case, it will be a huge breakthrough for speech recognition consumer electronics products.

It may have been a good idea to set the default ‘wake word’ (as Amazon calls it) ‘Echo’, and not ‘Alexa’ (the apparent ‘wake word’ that the device ships with as default). Two different names just seems unnecessarily confusing.

I can’t help but wonder if Apple is working on a device like this. Would be a perfect fit for a future Home Kit-enabled, Cable-box-replacing, always-on Apple TV.