OpenAI's response to the Axios developer tool compromise
openai.com64 points by shpat 7 hours ago
64 points by shpat 7 hours ago
Using TS/JS in the backend is irresponsible in 2026. We have better languages and ecosystems
Axios, like Express, is something I'm shocked to see used in any modern codebase. I loved both in the 2010s. In JS/TS-land there are much simpler and better options these days. Depending on Axios suggests the devs don't know how to use fetch. I can't think of another reason it would be a necessary dependency
> Depending on Axios suggests the devs don't know how to use fetch.
You could equally say that using fetch means that the developers don't know how to use axios.
They do the same thing, except axios does it a little better, when it doesn't pwn you.
Axios predates the availability of fetch in node by 2 years, and fetch has never caught up with axios so there was no reason to switch to fetch, unless you need to run on both client and server then of course you use fetch.
In what ways has fetch never caught up to axios? I have not encountered a situation where I could not use fetch in the last 5 years so I'm just curious what killer features axios has that are still missing in fetch (I certainly remember using axios many moons ago).
Simple examples are interceptors and error handling.
Fetch is one of those things I keep trying to use, but then sorely regret doing so because it's a bit rubbish.
You're probably reinventing axios functionality, badly, in your code.
It's especially useful when you want consistent behaviour across a large codebase, say you want to detect 401s from your API and redirect to a login page. But you don't want to write that on every page.
Now you can do monkey patching shenanigans, or make your own version of fetch like myCompanyFetch and enforce everyone uses it in your linter, or some other rubbish solution.
Or you can just use axios and an interceptor. Clean, elegant.
And every project gets to a size where you need that functionality, or it was a toy and who cares what you use.
Forcing everyone to use ourFetch is rubbish, but forcing everyone to use axios is clean and elegant? You might want to elaborate just a little more.
ourFetch is more likely to be buggy, unmaintained, undocumented and nobody knows it well because the guy who wrote it left the org 2 years ago and so you have to waste time reading and maintaining it yourself.
Axios is something where you get most of that work done for you by the community for free, and a lot of people know it. As long as you don’t get pwned due to it. Oh and you will actually find community packages that integrate with it, vs ourFetch, which again, nobody knows or even cares that it exists.
Applies to web frameworks, databases and other types of software and dependencies - if you work with brilliant people, you might succeed rolling your own, but for most people taking something battle tested, something off the shelf is a pretty sane way to go about it.
In this case it’s a relatively small dependency so it’s not the end of the world, but it’s the exact same principle.
Exactly, I completely agree.
It's the difference between using a SQL library and some person on your team writing their own SQL library and everyone having to use it. There's a vast gulf between the two, professionally speaking.
People dissing axios probably suffer from other NIH problems too.
I usually reach for ky these days since it's an extremely lightweight wrapper over `fetch` - basically just adds a few niceties
https://github.com/sindresorhus/ky
From the readme:
- Simpler API
- Method shortcuts (ky.post())
- Treats non-2xx status codes as errors (after redirects)
- Retries failed requests
- JSON option
- Timeout support
- Upload and download progress
- Base URL option
- Instances with custom defaults
- Hooks
- Response validation with Standard Schema (Zod, Valibot, etc.)
- TypeScript niceties (e.g., .json() supports generics and defaults to unknown, not any)
Of course, this is only for projects where I have to make a lot of HTTP requests to a lot of different places where these niceties make sense. In most cases, we're usually using a library generated from an OpenAPI specification and fall back to `fetch` only as an escape hatch.
I compare this to the request and httplib in python, request library is vastly superior in usability but both do the same..
I wouldn't go that far. Right tool for the job as always. Axios offers a lot over fetch for all but the simplest use cases plus you get to take advantage of the ecosystem. Need offline, axios-cache-interceptor already exists. Sure you can do all of those things with fetch but you need more to go with it taking you right back to just using axios. Also is no one annoyed that you can't replay fetch like the xhr? Same with express: solves a problem reliably.
If you want a fully built out network layer, with auth, logging, monitoring, policies, etc, then `fetch` doesn't really help. Axios and other libraries provide much more for building that sort of framework.
Any sufficiently competent typescript developer can build out an adhoc wrapper (that just inherits the type definition and passes along whatever it is passed after altering it however needed) in under a hour. It doesn't scale in the sense that you don't expose a configuration, but config as code is king.
(Source: have built out much more scuffed variants of this than the one I just described like https://github.com/boehs/ajar)
I guess a LLM can do as well. Although that's not something I'm quite ready to admit.
I've wrapped fetch a few times but i don't think I'd blame someone if they got tired of wrapping it and wanted a consistent interface across all the projects they work on.
I do "just use fetch" nowadays -- but I have to say, axios definitely has better ergonomics than fetch, especially for calling APIs.
I drag a tiny fetch wrapper around with error/json handling, timeouts and basic interceptor support. It doesn't cover everything axios does but it's nice enough and I haven't had to touch it in a couple years.
For reference: https://github.com/sampullman/fetch-api/blob/main/lib/fetchA...
When the vulnerability was announced, it took me two minutes to one-shot convert an entire legacy project from axios to fetch (it already wrapped api calls neatly), react cra to vite, update all dependencies, convert to deep imports to reduce bundle size and get zero npm warnings while fetching coffee. There is just no excuse to use it.
Move from a tested library where when a vulnerability is discovered everyone in the world is made aware to an untested one shot llm output that if a vulnerability is discovered will never come to light .
What's the reason to switch to something less stable short/long term? Because its older and newer code is always better?
What's wrong with Express?
Just slow and convoluted internals due to the accumulation of cruft over time
ChatGPT in general recommends axios over fetch. (At least it did about 2 months ago)
This is why people still need to know how to write code and why it is asinine to have an LLM write code without a human reading it. Good developers should know what good code looks like and push back when what they're fed is wrong.
jQuery is still useful too. May you never work in heathcare / government / defense where you need to support legacy browsers far past their expiration date.
Interesting that (1) this blog post published on April 10th, 10 days after the Axios compromise, and (2) this was emailed to ChatGPT / Codex users yesterday, April 21st, 11 days after the blog post...
After an incident as widely publicized as Axios, I'd expect dependency auditing, credential rotation, and public incident communication to all be carried out with much more urgency. And if they were going to send this out to all of their users (as they should), I would expect _that_ to happen shortly after publishing the post (why wait 11 days???).
As others said, no one should be using axios in 2026, fetch has been available in node v18 (experimental) in 2022 [0], stable since v21 in 2023 [1], although Claude Code sometimes will suggest it, probably worth adding a rule.
Side note. I'm sure many of you know this, but for those who don't, setting min-release-age=7 in .npmrc (needs npm 11.10+), would have made the malicious axios (@1.14.1 and @0.30.4) invisible to npm install (removed within ~3h). Same for ua-parser-js (caught within hours) and node-ipc (caught in days). It wouldn't have prevented event-stream (over 2 months), but you can't win them all.
Some examples (hat tip to [2]):
~/.config/uv/uv.toml
exclude-newer = "7 days"
~/.npmrc
min-release-age=7 # days
~/Library/Preferences/pnpm/rc
minimum-release-age=10080 # minutes
~/.bunfig.toml
[install]
minimumReleaseAge = 604800 # seconds
p.s. sorry for the plug, but we released a free tool ([3]) to gather all these settings + a cli to auto configure them. You can set these settings without it, but if you are confused (like me) with what is in minutes, what's in seconds, what is in days and where each of them is located, this might save you a few keystrokes / prompts (it also ensures you have the right min version for the package manager, otherwise you'll have the settings but they would be ignored...)[0] https://nodejs.org/en/blog/announcements/v18-release-announc...
[1] https://nodejs.org/en/blog/release/v21.0.0
[dead]
[dead]
Above and beyond post. This is good.