CVE-2023-45133 is a critical vulnerability in Babel where compiling attacker-crafted code can trigger arbitrary code execution during the compilation step itself, on the machine running Babel. It carries a CVSS v3.1 base score of 9.3 (Critical) and is fixed in @babel/traverse version 7.23.2 (and 8.0.0-alpha.4). The catch that trips people up: the vulnerable code runs at build time, not in your shipped application, so the real victims are systems that compile untrusted JavaScript — online playgrounds, CI runners that build third-party code, and any tool that transforms code it didn't author.
What CVE-2023-45133 actually does
Babel is the JavaScript compiler that transforms modern syntax into code older environments can run. Internally, some Babel plugins call path.evaluate() or path.evaluateTruthy(), methods that attempt to compute the value of an expression at compile time so the plugin can make optimization decisions.
The flaw in CVE-2023-45133 is that this evaluation could be tricked into executing attacker-controlled code. The published technique abuses the toString property: an attacker defines toString on an object as a function they control, and when Babel's evaluation logic coerces that object to a string during compilation, the malicious function runs. The result is arbitrary code execution in the context of the Babel process.
Crucially, this only happens when Babel compiles the malicious code. It is not a flaw in the code Babel produces. If you compile only your own trusted source, you were never at risk of exploitation — but you still want the patch, because "trusted" is a strong assumption in a world of copied snippets and generated code.
Which plugins are affected
The vulnerability manifests through plugins that depend on the vulnerable evaluation path. The Babel advisory names these as known-affected:
@babel/plugin-transform-runtime@babel/preset-envwhen itsuseBuiltInsoption is used- Any polyfill provider plugin built on
@babel/helper-define-polyfill-provider, includingbabel-plugin-polyfill-corejs3,babel-plugin-polyfill-corejs2,babel-plugin-polyfill-es-shims, andbabel-plugin-polyfill-regenerator
If your Babel configuration uses preset-env with useBuiltIns: "usage" or "entry" — an extremely common setup — you were relying on the vulnerable code path. That's why this CVE reached so many projects: preset-env is close to the default configuration for modern web builds.
Why it scores 9.3
The Critical rating reflects the payoff of the attack. Arbitrary code execution on a build machine is severe: build servers hold signing keys, deployment credentials, source for every project they touch, and network access to internal systems. Compromising one during compilation is a textbook supply-chain foothold.
The reason it isn't a perfect 10 is the required condition — the target must compile code the attacker controls. That narrows the exploit population to systems handling untrusted input. But that population is larger than it first appears: CI pipelines that build community pull requests, SaaS products that transpile user-submitted code, browser-based sandboxes, and any automated tool that runs Babel over dependencies it fetched.
How to fix CVE-2023-45133
The fix lives in @babel/traverse, the shared library the vulnerable evaluation logic belongs to. Upgrade it to 7.23.2 or later:
npm install @babel/traverse@^7.23.2
@babel/traverse is almost always a transitive dependency — you rarely install it directly. So the practical step is to force the resolved version. Check what you currently have:
npm ls @babel/traverse
If an old version shows up, pin the safe one:
{
"overrides": {
"@babel/traverse": "^7.23.2"
}
}
With Yarn, use resolutions instead. After applying the override, delete node_modules and your lockfile's stale entries by reinstalling, then re-run npm ls @babel/traverse to confirm every path resolves to a patched version. Upgrading your top-level Babel packages (@babel/core, @babel/preset-env) to current releases will usually pull a safe traverse automatically, which is the cleaner long-term move.
How to tell if you were exposed
Because the trigger is compiling untrusted code, working out your real exposure comes down to one question: did any Babel build in your organization ever process code you didn't write or fully control? Walk through the places that can happen.
Continuous integration is the first to check. If your CI builds pull requests from forks or external contributors and runs Babel over their code with preset-env or the transform-runtime plugin, that build was a candidate for exploitation. Look at your workflow triggers — a pull_request_target event that checks out and builds fork code with access to secrets is the dangerous combination.
Second, any product feature that transpiles user-submitted JavaScript. Online code editors, plugin systems that compile third-party extensions, and preview environments that build arbitrary branches all feed untrusted code into a compiler. These are the highest-risk deployments of the vulnerable path.
Third, generated code. If your toolchain generates JavaScript from some other source — a schema, a template, a low-code builder — and that input is user-controlled, the generated code is effectively untrusted from Babel's perspective even though a human never typed it.
If none of these apply and you only ever compiled your own committed source, your practical exposure was minimal. Either way, upgrading closes the question permanently, which is cheaper than continuing to reason about it.
The build pipeline is an attack surface
CVE-2023-45133 is a useful reminder that your build toolchain is production infrastructure with production-grade risk. Developers tend to scrutinize runtime dependencies — the code that ships to users — while treating build-time tools as inert. They aren't. A compiler, a bundler, or a test runner that processes untrusted input is an execution engine, and a flaw in it lands code on the machine with the most privileges in your CI environment.
Two practices reduce this exposure. First, isolate builds that process untrusted code — run community PR builds in a disposable sandbox with no secrets mounted, so a compromised compilation can't reach signing keys. Second, treat build-time dependencies with the same patch urgency as runtime ones. A software composition analysis tool such as Safeguard can flag a vulnerable @babel/traverse sitting transitively in your dev dependencies, which is exactly where a CVE like this hides. Our SCA overview explains how transitive detection surfaces build-tool CVEs that a package.json review would miss, and the Academy covers prioritizing them by actual exposure.
FAQ
Am I affected by CVE-2023-45133 if I only compile my own code?
Exploitation requires Babel to compile code an attacker controls, so if you exclusively build trusted first-party source, you have no practical exposure to the exploit. You should still upgrade @babel/traverse to remove the risk, since untrusted code can enter a build pipeline in ways that aren't obvious.
What version fixes CVE-2023-45133?
The vulnerability is fixed in @babel/traverse 7.23.2 and in the 8.0.0-alpha.4 pre-release. Pin or upgrade to 7.23.2 or higher.
Why is the vulnerability in @babel/traverse and not the plugins?
The unsafe evaluation logic lives in @babel/traverse, and the various plugins simply call into it. Patching the shared library fixes all of the affected plugins at once, which is why the fix targets traverse rather than each plugin.
Does upgrading @babel/core fix it automatically?
Usually, yes — upgrading @babel/core and @babel/preset-env to current versions pulls in a patched @babel/traverse through their dependency ranges. Confirm with npm ls @babel/traverse afterward, and add an overrides entry if any old copy remains.