The Patch You Do Not Wait For
October 22, 2026
Six security incidents in nine October days: PHP, GitLab, Node.js, LiteLLM, Railway and Zeabur. They share two moves: turn a published fix into an exploit, and steal a key that never expires. Here is how the agent-ops at A40 Labs answers: an exploited or Critical vulnerability gets a pull request within 4 hours and reaches production within 24.
The race starts when a vendor publishes a security patch. An attacker can have an exploit within hours; a Critical fix runs Scan, Patch, Gate and Release, with 24 hours as its target.
In The Cluster You Do Not Watch I described our SRE/Infra agent-ops, which runs most of our infrastructure. Before, it only watched two things: whether the cluster was healthy and whether it was wasteful. The incidents of 14 to 22 October added a third question: whether what we run is known to be vulnerable, and how fast the fix reaches production.
Nine days, six incidents
| Who | When | What happened |
|---|---|---|
| Zeabur | 14–15 Oct | Long-lived admin credentials stored in plain text. The attacker read 3,218,965 environment variables and 321,810 accounts, ran commands in 865 databases, and was mostly after AI API keys. |
| PHP | 21 Oct | Two unauthenticated remote code execution bugs, CVSS 9.2. Fixed in 8.2–8.5; 8.1 and older get no fix. Proof-of-concept code is circulating. |
| GitLab | 21 Oct | CVSS 10.0: an integer overflow in the regex engine allows code execution without logging in, under certain conditions. Every version from 7.0 (2014) is affected. |
| Node.js | 21 Oct | Ten fixes, four rated High, including a Brotli bug that could allow code execution. |
| LiteLLM | 21 Oct | Release 1.107.0 was poisoned for about 1¾ hours on PyPI and Docker. The malware steals cloud credentials, AI keys, SSH and Git tokens, and browser passwords. GitHub tokens had leaked from an internal log. |
| Railway | 21–22 Oct | An attacker may have read customers’ environment variables, decrypted for some: API keys, database and registry passwords. Every API token was revoked. |
Two moves, both far more efficient with AI
Strip the product names away and the week has two attacks in it.
Read the fix, write the exploit. PHP, GitLab and Node.js all published patches. A patch tells you exactly which lines were wrong, and turning that diff into a working exploit used to take a skilled person days. A language model reads a diff and drafts the exploit in a fraction of that. The gap between “the fix exists” and “the exploit exists” has been closing for years, from an average time-to-exploit of 63 days in 2018–19 to five days in 2023 (Mandiant, 2024), and models push it further. The gap between “the fix exists” and “the fix is running” has not closed at all. A person still has to notice the advisory, file a ticket and wait for a release, and organisations take a median of 43 days to fully remediate a vulnerability on CISA’s Known Exploited list (Verizon DBIR, 2026). Everything between those two moments is exposure (Fig. 1).
Take the key, not the server. Zeabur, Railway and LiteLLM were not about a clever bug. They were about a secret that lived too long in a place too many things could read: a plain-text admin credential, environment variables, a token in a log. And the prize has changed. Zeabur’s attacker was mostly after AI API keys, which turn straight into money. LiteLLM is an AI gateway, the one service in a stack that holds every model provider’s key, so poisoning it reaches all of them at once.
The defence against the first move is speed. The defence against the second is having nothing worth stealing that lasts.
Our countermeasures
The CVE loop has the same shape as everything else in our agent-ops: the agent reads, a pull request is the only thing it writes, and CI is the gate (Fig. 2).
- Scan. An hourly watch reads CISA’s Known Exploited Vulnerabilities list and the GitHub and OSV advisory feeds, and matches each new advisory
against what we last recorded we run. A match that is Critical or exploited fires the patch step within the hour. Behind it, a daily sweep scans
every lockfile, image digest and pinned chart;
govulncheckreads the Go call graph, so a finding in a function we never call drops one step in severity instead of raising an alarm. - Patch. An agent runs in each repository on its own CI runner, bumps the package with the ecosystem’s own tool, runs the repository’s checks and opens one signed pull request per finding. It may touch manifests, lockfiles and Dockerfiles. It may not touch application code or workflows; a fix that needs code stops and asks for a person.
- Gate. A same-major bump on a repository that only reaches staging merges itself when CI is green. A major bump, a chart, or anything in Terraform waits for a person.
- Release. Production’s gate does not move: a person merges the production pin. What changed is that severity now sets a deadline: a Critical pages the owner and forces a release of its own, and when no patch exists yet, a mitigation (a block rule, a feature switched off) goes in within 4 hours.
| Severity | PR opened | Merged | In production |
|---|---|---|---|
| Critical (CVSS ≥ 9, or exploited) | 4 hours | 12 hours, in staging | 24 hours |
| High (7.0–8.9) | 48 hours | 7 days | 14 days |
| Medium | 7 days | 30 days | next release |
| Low | monthly batch | the month | next release |
For the second move, the keys: push protection refuses a committed credential at GitHub before it lands, even from a laptop that skipped its hooks, and gitleaks reads every pull request behind it. The scanner itself keeps no long-lived key on disk: it signs in as two GitHub Apps, one that can only read code and one that can only post the scan results, whose private keys stay in a secrets store, and it reads the registry with short-lived tokens through workload identity federation, so no cloud key exists to steal. A secret finding never goes into a report, a pull request or Slack. The run log records only its file and line, never the value, and the owner rotates it.
The same model, on our side
If attackers point models at our code, we want to read it first (Fig. 3). So we adopted Strix, an open-source AI penetration tester that we host ourselves. Besides reading code, it can attack running services. Strix reads a repository the size of our backend in about 25 minutes, and it finds two kinds of problem. Some are known CVEs, which an ordinary scanner would catch too. The rest are access-control bugs we wrote ourselves, which no CVE scanner can ever see. Those are the reason we run it.
What it changes
GitLab’s bug, code execution without a login, had been there since version 7.0 in 2014 and was only patched this month. Whether a bug like that gets written is beyond our CVE loop. What the loop controls is how long we keep running the vulnerable version once the patch is out. For a Critical, our target is 24 hours; the industry median is 43 days.