CVE-2023-28154 - How an ImportParserPlugin Bug in Webpack 5 Opened the Door to Cross-Realm Global Object Access

In the fast-evolving world of web development, Webpack stands as an industry-standard tool for bundling JavaScript applications. But with great power comes great responsibility—and sometimes, critical security vulnerabilities. In this long read, we dissect CVE-2023-28154, an issue affecting Webpack 5 (prior to 5.76.) that could give attackers access to the real global object by exploiting a bug in the way magic comments were handled in the ImportParserPlugin.

Let’s break this down in simple, practical terms—exploring how the bug works, examining the vulnerable code, understanding what’s at stake, and looking at patches and prevention.

What is CVE-2023-28154?

CVE-2023-28154 is a vulnerability affecting Webpack 5, specifically before version 5.76., in file lib/dependencies/ImportParserPlugin.js. The vulnerability occurs because Webpack doesn't properly restrict cross-realm object access when handling magic comments in dynamic imports. This allows an attacker, under certain conditions, to get access to the global object (globalThis or equivalents in various contexts), leading to possible code execution, data theft, or worse.

Magic comments in Webpack let developers give extra hints by writing comments like this

import(/* webpackChunkName: "myChunk" */ './myModule');

But the bug was how Webpack handled _untrusted_ objects when reading or parsing these magic comments.

Cross-Realm Objects: What Are They?

JavaScript environments (like iframes or Node.js VMs) use realms—isolated global environments. Ideally, code in one realm can't directly access global objects (like window or globalThis) from another. But if a misconfigured tool gives an attacker access to cross-realm objects, security boundaries break down.

How the Bug Happens

1. Webpack 5's ImportParserPlugin reads magic comments by calling Object.keys() and looking up properties on the comment object.
2. When the input object is from another realm (e.g., attacker-created iframe object), property access could return cross-realm references.
3. If an attacker controls a property (like a getter), they can leak references to their own global object, or even gain access to the host realm's globalThis.

Vulnerable Code Snippet

Here’s a simplified illustration based on the public Webpack 5 source code:

// Bad: This doesn't check if the object comes from a trusted realm
for (const key in magicCommentObject) {
  let value = magicCommentObject[key]; // attacker-controlled getter here
  // ...process value
}

If magicCommentObject is attacker-supplied and contains a property like

Object.defineProperty(obj, 'leak', {
  get() {
    // This runs in attacker's context, but may leak host's global object
    return this.globalThis || this;
  }
});

Webpack's plugin would blindly evaluate that getter, and the attacker can bridge contexts.

Proof of Concept (POC)

Suppose our application uses dynamic imports with source objects provided by an iframe or an external input:

// In an attacker-controlled iframe
const crossRealmObj = Object.create(null);
Object.defineProperty(crossRealmObj, 'malicious', {
  get() {
    // Attacker code to leak the global object
    return window; // Returns attacker's window, but could lead to host context in other scenarios
  }
});

// Inject the object into Webpack's import
import(/* webpackChunkName: crossRealmObj */ './someModule');

Because of how ImportParserPlugin handled the magic comment object, this could leak sensitive global references.

App must allow dynamic import() where comments can be attacker-controlled.

- Running in an environment where code boundaries matter (multi-tenant server, browser with iframes, etc.)

Access secrets stored in the global context.

- Escalate privileges, read user data, or run arbitrary code in the context of the bundler/host.

This issue is especially concerning in projects using Webpack in server-side rendering or shared hosting environments.

References and Writeups

- Original Webpack Advisory
- CVE Details on NVD
- Commit That Fixed the Issue (5.76.)

How Was It Fixed?

Webpack maintainers fixed this in release 5.76. by strictly validating the type and origin of objects passed as magic comment options. The fix ensures only plain objects from the same realm are permitted—preventing execution of attacker-controlled getters/cross-realm objects.

The patch boiled down to

if (!isPlainObject(magicCommentObject)) {
  throw new Error('Invalid magic comment object!');
}

1. Upgrade!

If you use Webpack 5, update to at least version 5.76..

npm install webpack@^5.76.

2. Sanitize Inputs

Never allow untrusted objects to be passed to dynamic imports or magic comments.

3. Review Dependencies

If you use frameworks/wrappers that handle dynamic imports, ensure they also updated Webpack.

Conclusion

CVE-2023-28154 is another reminder: *even trusted developer tooling can be a vector for creative attacks*. Always keep your build tools up-to-date, and be vigilant before trusting inputs that cross realm or context boundaries.

- Webpack's Security Advisory for CVE-2023-28154
- Official Patch on GitHub
- NIST CVE Entry

Timeline

Published on: 03/13/2023 01:15:00 UTC
Last modified on: 04/22/2023 03:15:00 UTC