babel-core is safe to use when you keep it current, but the interesting security risks live in the packages it depends on — and one of them lets crafted source code execute during your build. The package published as @babel/core (the modern name; the old babel-core package on npm is deprecated) is the heart of the Babel toolchain that most JavaScript and TypeScript projects run on every build. That central position is exactly why its dependency tree deserves attention.
If you type "babel core" into a search, you land on @babel/core. The legacy babel-core package predates the Babel 7 scoped-package rename and should not be used for new work. Everything below refers to the maintained @babel/core and the helper packages it pulls in.
The build-time code execution issue
The most serious advisory to touch the Babel ecosystem is CVE-2023-45133. It lived in @babel/traverse, a core dependency of @babel/core, and it is unusual because it fires at compile time rather than runtime. Using Babel to compile specifically crafted malicious code could lead to arbitrary code execution during compilation when a plugin relied on the internal path.evaluate() or path.evaluateTruthy() methods.
The trigger conditions matter. You are exposed if you compile untrusted source with a plugin that uses those internals — for example @babel/preset-env with its useBuiltIns option, @babel/plugin-transform-runtime, or any polyfill-provider plugin built on @babel/helper-define-polyfill-provider. The fix landed in @babel/traverse 7.23.2 (and 8.0.0-alpha.4).
Because @babel/traverse is transitive, upgrading @babel/core alone may not pull the fixed version. Confirm what actually resolved:
npm ls @babel/traverse
If an old version is still present, force it:
{
"overrides": {
"@babel/traverse": "7.23.2"
}
}
The practical takeaway: build servers that compile code from pull requests, forks, or any untrusted source are a real target for this class of issue. Treat your CI compiler as an execution boundary.
The ReDoS in generated code
The second issue to know is CVE-2025-27789, a regular-expression denial-of-service (ReDoS) problem. Here Babel generates a .replace polyfill with quadratic complexity for certain replacement patterns when compiling regular expressions that use named capturing groups. The vulnerable output triggers only under specific conditions: your code uses named capturing groups, calls .replace on such a regex, and passes an untrusted string as the second argument.
It was fixed in @babel/helpers and @babel/runtime 7.26.10 (and 8.0.0-alpha.17). This one has a catch that trips people up: upgrading the dependency is not enough. Because the vulnerable code was emitted by Babel into your compiled bundle, you must also re-compile your project after upgrading so the fixed helper replaces the bad one already baked into your build output.
As a stopgap, if you pass user-provided strings as the second argument to .replace on a regex with named groups, validate that the input does not contain the substring $< unless it is properly followed by >.
How babel-core fits your supply chain
Build tools are an underrated part of the software supply chain. They run with full access to your source, your environment variables, and often your registry credentials. A vulnerability in @babel/core or its dependencies is not a runtime bug in your shipped app — it is a compromise of the machine that builds your app, which is arguably worse.
That framing changes how you should treat Babel updates:
- Pin and lock. Commit your lockfile so builds are reproducible and you know exactly which
@babel/*versions resolved. - Audit the transitive tree, not just direct dependencies. Both CVEs above lived in packages you probably never named in
package.json. - Watch the GitHub Advisory Database for the
@babelscope rather than waiting for a scanner to surface it weeks later.
An SCA tool such as Safeguard can flag a vulnerable @babel/traverse even when it is buried several levels deep, which is where these issues typically hide. For the broader picture of how transitive dependency risk works, our SCA product overview covers the mechanics.
A sensible patching routine
Babel moves fast and its packages version in lockstep, so a little discipline prevents drift:
# See what you have
npm ls @babel/core @babel/traverse @babel/helpers
# Update the whole scope together
npm update @babel/core @babel/preset-env @babel/traverse @babel/helpers
# Re-run resolution to confirm fixed versions landed
npm ls @babel/traverse @babel/helpers
After any update that touches @babel/helpers or @babel/runtime, do a clean rebuild so the corrected generated code actually ships. Then run your test suite — Babel upgrades occasionally change output in subtle ways, and you want to catch that in CI, not in production.
FAQ
Is babel-core the same as @babel/core?
Effectively, yes, for anyone searching today. The maintained package is @babel/core. The old unscoped babel-core package on npm predates the Babel 7 rename and is deprecated; new projects should depend on @babel/core.
What is CVE-2023-45133 and does it affect me?
It is an arbitrary-code-execution issue in @babel/traverse (a dependency of @babel/core) that fires during compilation of crafted code when certain plugins are used. It was fixed in @babel/traverse 7.23.2. You are most at risk if your build compiles untrusted source. Confirm the fixed version resolved with npm ls @babel/traverse.
Why do I have to re-compile after fixing CVE-2025-27789?
Because the vulnerable code was generated by Babel and written into your build output. Upgrading @babel/helpers or @babel/runtime to 7.26.10 updates the source of the fix, but your existing bundle still contains the old, vulnerable helper until you rebuild.
How do I find vulnerable Babel packages buried in my dependency tree?
Use npm ls @babel/traverse @babel/helpers to see resolved versions, run npm audit, or use a software composition analysis tool that inspects the full transitive tree. Both major Babel CVEs lived in packages you would not find in your direct dependencies.