Notes on coding agents and the pages they leave behind, on moving between notes apps, and on the plain mechanics of keeping what you think. Written and published from a Sumibako vault.
A developer's security checklist for the next bad week
Nine habits that keep a small site out of a week like this one: supported runtimes, something that nags, lockfiles, short-lived tokens and scoped secrets.
Prashant Shaw
Founder, Sumibako
11 min read
This week the internet had a bad day, and then kept having it. PHP itself had two critical holes, exploited before they were announced. A deployment platform lost its customers' environment variables. Next.js and Node.js both shipped remote code execution fixes. A popular AI proxy was replaced on the package registries by a version that stole credentials. A certificate authority's keys turned out to be guessable. I spent the week reading advisories and found my own site on one of them.
Every one of those stories ends with the same instruction, patch now, and none of them tells you how to be the person who already had. This is that list. It is written for someone who runs a small product or a side project, has a GitHub account and a hosting plan, and would like the next week like this to be somebody else's problem. I have tried to follow it myself, with the humility of someone who was three security releases behind on Monday while writing posts about how other people should use Claude.
This week
The habit it tested
PHP2Shell: exploit attempts four days before the fix
Patch the day the fix ships, and know which PHP actually serves requests
Railway, Zeabur, TiDB Cloud
Every secret on a platform is lent: scope it, rotate it at the issuer
Next.js and Node: three releases missed
Something has to nag; a pinned version needs a watcher
Know who vouches for you, and keep every trust store updated
Plex2Shell, BeyondTrust, the 2015 bugs in CISA's list
An inventory: the fix existed for weeks before the exploit
Cairn, about fifty dollars a site
Same-day patching has to be automatic, because the attack is
🗂️ 1. Know what you run
You cannot patch what you have not listed. Mine took ten minutes and fitted on one page: the framework and its version, the runtime and who patches it, the host, the database, the auth provider, the email provider, the certificate authority my domain happens to use, and every place a secret lives. Next to each, how I would find out it had a problem.
That last column is the useful one. For Next.js the answer is the release blog and npm audit. For Node it is the host, if the host patches minor versions, or you, if it does not. For the certificate authority it is nothing at all, because you did not choose it and nobody will email you; your users' browsers will simply stop trusting it, which is how this week's eMudhra story reached most people.
🪜 2. Stay on a supported line, and know who patches it
Each runtime publishes its rules, and they are shorter than you fear. Node's is one sentence: "Production applications should only use Active LTS or Maintenance LTS releases." The release page says which those are. PHP's support page explains that "Each release branch of PHP is fully supported for two years from its initial stable release." After that comes two years of security fixes only, and PHP 8.2's end that way on 31 December 2026. If your host still runs it in January, that is a conversation to have in December.
Then find out who takes the patch. On Vercel, where this site lives, the answer is reassuring: "Only major versions are available. Vercel automatically rolls out minor and patch updates when needed, such as to fix a security issue." On a machine I own, the answer is me, and the machine I am typing on was still on a Node 22 from last year when I checked, which is the kind of fact a checklist exists to make embarrassing. Managed hosting is worth paying for mostly because of this paragraph.
For frameworks, endoflife.date keeps the table so you do not have to. Its advice is blunt: "You should be running one of the supported release numbers listed above in the rightmost column." Next.js 15 fell off that table on 21 October.
🔔 3. Let something nag you
I missed a month of Next.js security releases because nothing told me about them. Three things would have.
Dependabot alerts are free on every GitHub repository: "Dependabot alerts notify you about vulnerable dependencies so you can upgrade to secure versions and protect your project." They fire when a new vulnerability is added to the GitHub Advisory Database or when your dependency graph changes. Turn them on, and let the pull requests they open embarrass you in public.
npm audit is the same database read from your terminal. It is good, and it is late: an advisory without a CVE can take days to be reviewed in, and two of the three Next.js bugs of 14 October were missing from it for a while. Run it anyway, every time you install, and read the vendor's blog in the week after a release. Its less famous sibling is worth a line too: "The audit signatures command will also verify the provenance attestations of downloaded packages." That is the command that would notice a package swapped on the registry by someone with a stolen token.
The third nag is new. Next.js 16.4 added an agentUpgrade setting whose default policy is to remind you "about upgrades that address known vulnerabilities affecting your installed version". A framework that tells you when it has a hole is a framework behaving well. It only works once you are on 16.4, which is the kind of joke the week specialised in.
For the bigger picture, the American government keeps a list of vulnerabilities that are actually being exploited, and its advice is sensible for a one-person shop too: "Organizations should use the KEV catalog as an input to their vulnerability management prioritization framework." Twenty-six entries were added this month, four of them Plex bugs that had been patched since August.
📌 4. Install exactly what you meant to
A lockfile is a promise that the build on the server is the build on your laptop. Keep that promise with npm ci rather than npm install in anything automated. The docs are clear about what it refuses to do: "It will never write to package.json or any of the package-locks: installs are essentially frozen." If someone changes a dependency without changing the lockfile, "npm ci will exit with an error, instead of updating the package lock."
Pin the version of the thing your site is made of. Mine says "next": "16.4.3", not a range, so an install never surprises me with a minor version. The honest cost of that pin is step 3: a pinned version does not move to the fixed one on its own, so the nag has to come from somewhere else. A pin without a nag is how you spend a month on 16.3.3.
🔑 5. Publish so your token cannot be stolen
Two of this week's attacks did not break any code. They borrowed a maintainer's credentials and published malware as the next version. LiteLLM's went to PyPI and Docker Hub. OVHcloud's command line tool had five existing releases swapped under a compromised GitHub account. If you publish anything, you are a target of exactly this shape.
Start with the account. GitHub has required two-factor authentication for contributors since March 2023, and now adds "Optionally, you can add a passkey to your account." Do that. Then look at the tokens. GitHub's own words on personal access tokens: "Treat your access tokens like passwords." And: "GitHub recommends that you use fine-grained personal access tokens instead of personal access tokens (classic) whenever possible." A fine-grained token that can read one repository is a much smaller thing to lose.
Then stop using long-lived publish tokens at all. npm's trusted publishing "creates a trust relationship between npm and your CI/CD provider using OIDC", so your release workflow proves who it is each time instead of carrying a secret that can be copied. PyPI describes the same mechanism as exchanging "short-lived identity tokens between a trusted third-party service and PyPI". Short-lived is the whole point. A stolen token that expired an hour ago is a souvenir.
Trusted publishing is not the whole answer, and this week proved it. LiteLLM published through a trusted pipeline, and the attacker, holding an owner's token, edited the pipeline's own workflow so the poison came out signed. StepSecurity's write-up puts it in one clause: "the attacker did not bypass the pipeline." So lock the release workflow to approved source repositories, and turn on GitHub's release immutability, the setting OVHcloud had off, remembering that it protects only releases created after you turn it on.
Finally, let the repository refuse secrets. GitHub's push protection "is a secret scanning feature designed to prevent hardcoded credentials, such as secrets or tokens, from ever being pushed to your repository." LiteLLM's October began with a master key committed to a public repository in May and never revoked. Zeabur's began with admin tokens that, in its own words, "had no expiry, had not been rotated since they were created in January 2024, and were not included in the post-August rotation." A secret nobody lists is a secret nobody rotates.
🧳 6. Treat every secret as lent
Railway's customers learned this week that an environment variable on a platform is a secret you have handed to the platform, and the platform can lose it. The honest version of the lesson is not to leave Railway. Every host has the same shape, mine included: Sumibako's keys sit in Vercel's and Convex's environment settings, which is a database somewhere that I do not run.
What you control is the blast radius. The OWASP secrets management cheat sheet puts the problem plainly: "Often, services share the same secrets, which makes identifying the source of compromise or leak challenging." So: one key per service and per purpose. Keys that can only do the one thing, a mail key that only sends, a payment key that only reads. Keys you can rotate in ten minutes, because on the day you will have ten minutes. Railway says its attackers were after AI provider keys, to run models on other people's accounts, and a user's OpenAI key taken from Zeabur was spent on about 1,100 image generations the next day. A key like that can be replaced and the bill disputed. So nothing goes on a platform that you cannot rotate at all. A cryptocurrency wallet key is not a secret. It is the money.
Store your own users' secrets the same way you would want yours stored. Sumibako keeps the hash of an agent's token and never the token, so a read of the database yields nothing to log in with. It is not clever. It is the minimum, and it is the difference between a breach and a bad week.
🪪 7. Know who vouches for you
Your HTTPS certificate was issued by a certificate authority, and until this week most people could not have named theirs. eMudhra's intermediate certificates were revoked within a day of a researcher finding that their private keys were small integers, one of them the number 4. None of the eight had issued a certificate to anyone, so no site broke from that. What breaks sites is the step after: the browsers are removing the root above them, about 30,000 certificates chain to it, nearly all at universities through InCommon, and they must be replaced before Chrome's removal on 27 October. Nobody emails the site owner first.
Find yours now: the padlock in your browser shows the chain, and it takes a minute. So does a terminal:
LiteLLM 1.107.0 and the OVHcloud CLI: two stolen tokens, two poisoned downloads, one pinned hash
A key committed in May became a credential stealer on PyPI in October; five OVHcloud CLI releases were swapped for 94 minutes. What to do if you got either.
10 min read
shellscript
# The versions that matter are the ones on the machine that serves, not the laptopnpx next --versionnode -vphp -v && php-fpm -v
shellscript
npm audit # what the advisory database knows about your treenpm audit signatures # whether what you downloaded is what the registry signed
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | grep -i issuer``` Most small sites are on Let's Encrypt or whatever the host issues, and the host will handle a replacement. Then make sure the fix can reach you and your users at all. Distrust travels in updates: Chrome's and Firefox's blocklists within hours, Apple's and Microsoft's within days, Node's trust store in its 21 October release, Go in 1.27.3. A container image or a command line tool with its own certificate bundle trusts a dead authority until someone rebuilds it.## ⏱️ 8. Assume the exploit arrives before the headlineThe habits above are about preparation. This one is about tempo. PHP's bugs were [attacked four days before](https://sumibako.com/blog/php2shell) they were announced. Plex's four bugs were [fixed on 3 August](https://thehackernews.com/2026/10/hackers-exploit-plex2shell-flaws-to.html) and exploited within a day of a write-up on 16 October. One person with an AI agent platform [broke into more than a hundred websites](https://thenextweb.com/news/ai-agents-hacker-cairn-100-sites-deere-norforge) at a researcher's estimate of about fifty dollars each.The attacker's cost per site has fallen to lunch money. So a month between a fix and your install is no longer a delay; it is the window. For anything that faces the internet, treat a critical advisory as same-day work, and build so that same-day is possible: a test suite you trust, a deploy that takes minutes, and no one person who has to be awake.## 📝 9. Write it downThe last habit is the one this blog exists for. Keep a page for each incident that touched you: what you run, what you checked, what you changed, when, and what you decided not to do and why. Mine for this week says that two of three Next.js bugs did not apply and gives the reasons, so that in March I do not have to work it out again. If you use a coding agent, it can [file that page](https://sumibako.com/agents) while you are doing the patching, which is the one time you will not feel like writing.None of this is new. Patch, pin, scope, rotate, verify, record. What changed this week is that all of it got tested at once, and the people it caught were not careless. They were a month behind, like me. Be less than a month behind.## 📚 Sources and credits- Node.js: [Releases](https://nodejs.org/en/about/previous-releases) and the [21 October 2026 security releases](https://nodejs.org/en/blog/vulnerability/october-2026-security-releases). Vercel: [Supported Node.js versions](https://vercel.com/docs/functions/runtimes/node-js/node-js-versions). PHP: [Supported Versions](https://www.php.net/supported-versions.php). [Next.js on endoflife.date](https://endoflife.date/nextjs).- GitHub Docs: [Dependabot alerts](https://docs.github.com/en/code-security/dependabot/dependabot-alerts/about-dependabot-alerts), [About two-factor authentication](https://docs.github.com/en/authentication/securing-your-account-with-two-factor-authentication-2fa/about-two-factor-authentication), [Managing your personal access tokens](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens), [Push protection](https://docs.github.com/en/code-security/secret-scanning/introduction/about-push-protection).- npm Docs: [npm audit](https://docs.npmjs.com/cli/v11/commands/npm-audit), [npm ci](https://docs.npmjs.com/cli/v11/commands/npm-ci), [Trusted publishing](https://docs.npmjs.com/trusted-publishers). PyPI: [Trusted Publishers](https://docs.pypi.org/trusted-publishers/).- [Next.js 16.4](https://nextjs.org/blog/next-16-4), on agentUpgrade. [CISA's Known Exploited Vulnerabilities](https://www.cisa.gov/known-exploited-vulnerabilities).- [OWASP Secrets Management Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html).- [LiteLLM 1.107.0 compromised](https://www.stepsecurity.io/blog/litellm-1-107-0-compromised-pypi-backdoored-wheels-credential-stealer), Sai Likhith, StepSecurity; [Zeabur's October 2026 incident report](https://zeabur.com/blogs/october-2026-security-incident), Yuanlin Lin.- [Hackers Exploit Plex2Shell Flaws](https://thehackernews.com/2026/10/hackers-exploit-plex2shell-flaws-to.html), The Hacker News; [AI agents broke into 100+ sites for one hacker at $50 each](https://thenextweb.com/news/ai-agents-hacker-cairn-100-sites-deere-norforge), The Next Web, reporting Reuters.- The six incident posts linked above carry their own source lists.