Skip to content
Node.js Releases

cjs-module-lexer 2.2.0 removes eval. That matters.

cjs-module-lexer 2.2.0 removes eval. That matters. I’ve watched “dev-only” dependencies turn into real incidents in CI. This release strips eval out of cjs-module-lexer’s string parsing path. What actually changed (not the marketing version) Here’s the concrete bit. PR #118 replaces eval-based string decoding with an explicit string literal scanner. Eval went away: The lexer no […]

Jack Pauley January 8, 2026 6 min read
cjs-module-lexer 2.2.0

cjs-module-lexer 2.2.0 removes eval. That matters.

I’ve watched “dev-only” dependencies turn into real incidents in CI. This release strips eval out of cjs-module-lexer’s string parsing path.

What actually changed (not the marketing version)

Here’s the concrete bit. PR #118 replaces eval-based string decoding with an explicit string literal scanner.

  • Eval went away: The lexer no longer relies on (0, eval)(str) to interpret string literals during parsing. It now scans the source text and decodes escapes itself.
  • The public API stayed put: You still call parse(source). Integrators should not need to change call sites.
  • Tests got stricter: The project runs tests with NODE_OPTIONS=–disallow-code-generation-from-strings, which would have broken the old eval path.

Security impact: why I treat this as a real upgrade

Eval in a parser makes me nervous. Not because every use explodes, but because build systems ingest code you did not write.

If your CI builds pull in third-party packages, you already run untrusted input through tooling. Removing eval closes off an entire class of “code generation from strings” problems, and it also plays nicer with locked-down environments that disallow it.

If your security team ever asked “can we run builds with codegen-from-strings disabled?”, this release makes that question easier.

Am I even using cjs-module-lexer?

This part trips people up. You almost never depend on this directly.

  • npm: Run npm ls cjs-module-lexer to see who pulls it in, and whether your lockfile pins an older version.
  • yarn: Run yarn why cjs-module-lexer to find the parent dependency that drags it into your tree.
  • pnpm: Run pnpm why cjs-module-lexer and note which workspace depends on it, because monorepos love hiding this stuff.

How I’d upgrade it (including the annoying transitive case)

Upgrade it in staging first. Do not “just bump and ship” if your CI handles secrets.

  • Direct dependency: Install cjs-module-lexer@2.2.0, commit the lockfile, then run your full build and test pipeline.
  • Transitive dependency: Add an override so your tree actually picks up 2.2.0. npm uses overrides, Yarn uses resolutions, pnpm uses overrides too.
  • Verify the lockfile: After install, re-run npm ls cjs-module-lexer (or your yarn/pnpm equivalent). I’ve seen “successful installs” that changed nothing.

What to test after the bump

Run the boring stuff. Then run one targeted check.

At minimum, rebuild whatever generates bundles in your pipeline and make sure it finishes without new warnings. If you can, run one CI job with NODE_OPTIONS=–disallow-code-generation-from-strings to catch tooling that still sneaks in eval somewhere else.

  • Build smoke test: Clean install, clean build, then run the smallest “build and start” command you trust.
  • Cache reset: Blow away bundler caches once. I hate this advice, but lexer output changes can stick in caches in weird ways.
  • Rollback plan: If something breaks, pin the prior working version in your overrides and re-run the pipeline. Do not guess.

Known issues

The GitHub release notes do not list known issues for 2.2.0. That does not mean nobody hit a bug. It means nobody wrote it down.

Other stuff in this release: more tests, some script hardening, the usual.

Source links (so you can audit it)

Check the official tag and the PR that did the work. You should not trust my summary more than the diff.

  • GitHub release: https://github.com/nodejs/cjs-module-lexer/releases/tag/2.2.0
  • PR #118 (eval removal): https://github.com/nodejs/cjs-module-lexer/pull/118

Anyway.

Official sources and security context

Verify the changes yourself and understand the security context behind the eval removal:


Related editor updates worth checking: VS Code 1.109 release notes.

Related Reading

Check your version and upgrade

Here are the exact commands to find cjs-module-lexer in your project and upgrade it:

# Find it in your dependency tree
npm ls cjs-module-lexer
# Typical output:
# └─┬ @babel/register@7.25.0
#   └─┬ pirates@4.0.6
#     └── cjs-module-lexer@2.1.0  <-- needs upgrade

# Direct upgrade
npm install cjs-module-lexer@2.2.0

# If it's a transitive dep, use overrides in package.json:
# "overrides": { "cjs-module-lexer": "2.2.0" }
# Then: npm install

# Verify the upgrade stuck
npm ls cjs-module-lexer | grep "2.2.0"

Test with codegen disabled

The whole point of this release is eliminating eval. Verify it works in a locked-down environment:

# Run your test suite with codegen from strings disabled
NODE_OPTIONS="--disallow-code-generation-from-strings" npm test

# If this passes, your build pipeline is clean of eval-based parsing
# If it fails, something else in your dependency tree still uses eval

# You can also test it in a one-liner:
node --disallow-code-generation-from-strings -e "
  const { parse } = require('cjs-module-lexer');
  const result = parse('module.exports = { foo: 1 }');
  console.log('Exports:', result.exports);
  console.log('✅ cjs-module-lexer works without eval');
"

Override in monorepo setups

Monorepos with multiple workspaces often have different pinned versions. Here is how to force the upgrade across all workspaces:

# pnpm (monorepo override in root package.json)
{
  "pnpm": {
    "overrides": {
      "cjs-module-lexer": ">=2.2.0"
    }
  }
}

# Yarn (resolutions in root package.json)
{
  "resolutions": {
    "cjs-module-lexer": "2.2.0"
  }
}

# After adding the override:
pnpm install  # or yarn install
pnpm ls cjs-module-lexer -r  # check all workspaces

For a broader check of your Node.js dependencies, our free dependency EOL scanner will flag any packages that are approaching end-of-life or have known vulnerabilities. Just paste your package.json to get a report. Track the latest Node.js ecosystem releases on our Node.js release tracker.

🛠️ Try These Free Tools

📦 Dependency EOL Scanner

Paste your dependency file to check for end-of-life packages.

🗺️ Upgrade Path Planner

Plan your upgrade path with breaking change warnings and step-by-step guidance.

💰 Kubernetes Cost Estimator

Compare EKS, GKE, and AKS monthly costs side by side.

See all free tools →

Stay Updated

Get the best releases delivered monthly. No spam, unsubscribe anytime.

By subscribing you agree to our Privacy Policy.