Feed
HighCompromisePublished 17 Sept 2026Updated 20 Sept 20261 package · 4 versions

visanduma/nova-two-factor - PolinRider malware planted in four dev-* branches via compromised Visanduma GitHub org

Summary

Socket disclosed on 2026-09-17 that the DPRK-linked PolinRider operators compromised the Visanduma GitHub organisation and implanted staged infostealer code in the dev-main, dev-nova4support, dev-using-inertia, and dev-nova5 branches of visanduma/nova-two-factor, a Laravel Nova 2FA package on Packagist with ~700K cumulative downloads. No stable release is affected; Packagist has frozen the package.

account-takeovermaintainer-takeovercredential-theftinfostealerobfuscationci-cd-compromise
Incident type
Compromise. A legitimate, already-used package, maintainer account, CI pipeline, or release tag was hijacked and a malicious version was published under a name people already depend on.
Threat actor
PolinRider (DPRK / Contagious Interview cluster)
Detected by
Socket
Also known as
PolinRider Packagist wave (Sep 2026) · Visanduma nova-two-factor dev-branch compromise · PolinRider Laravel Nova 2FA hijack
Ecosystems
Packagist
Packages tracked
1

What happened

On 2026-09-17 Socket Threat Research published an analysis attributing malicious code in four development branches of visanduma/nova-two-factor - a Laravel Nova 2FA extension on Packagist with more than 700,000 cumulative installs - to the PolinRider campaign. PolinRider is the long-running DPRK-linked cluster tracked by Socket, StepSecurity, and others as an extension of the Contagious Interview / Famous Chollima operation; a July 2026 Socket report enumerated 108 malicious packages and browser extensions spread across npm, Packagist, Go modules, and Chrome extensions in the same campaign.

Affected branches (Packagist)

BranchComposer constraintStatus
dev-maindev-maincompromised
dev-nova4supportdev-nova4supportcompromised
dev-using-inertiadev-using-inertiacompromised
dev-nova5dev-nova5compromised
3.0.1 (last stable, 2025-01-28)^3.0NOT compromised
<= 2.2.15^2.0NOT compromised

Attack primitive

PolinRider operators gained push access to the Visanduma GitHub organisation (Socket suggests since roughly mid-June 2026) and modified the target repository directly. The tradecraft is consistent with the wider campaign:

  • Git history rewriting - malicious commits are amended into branches so a git log diff between the "before" and "after" doesn't obviously show new commits
  • Payload concealment - obfuscated JavaScript loaders hidden inside configuration files (.eslintrc.*, TypeScript config) or, in some variants, font files that get resolved by build tooling
  • Dead-drop C2 - EtherHiding (payload URL fetched from an Ethereum contract read) or NullReceiver (payload URL resolved indirectly via a compromised registry lookup) - either way there is no static domain the operator has to defend
  • Staged delivery - the first-stage script fetches the second-stage infostealer, then the second stage harvests SSH keys, browser data, GitHub / npm / cloud tokens, and crypto wallets

A newer PolinRider variant, cross-referenced by Socket to earlier campaign packages, invokes the obfuscated JavaScript from PHP via shell_exec - which turns the compromise from an install-time attack into a request-time RCE any time the vendor tree is autoloaded on a Laravel request.

What is safe

Socket explicitly notes that no stable tagged release was compromised. Users with composer.json constraints like "visanduma/nova-two-factor": "^3.0" (which resolves to 3.0.1, published 2025-01-28) are not exposed. Exposure is limited to projects that resolve from a dev-* branch, which typically only happens in three scenarios: (1) developers tracking a Nova 5 preview via dev-nova5, (2) forks that vendored the source directly from GitHub instead of Packagist, and (3) CI pipelines with minimum-stability: dev and prefer-stable: false that resolve dev-main for missing tags.

Packagist response

Packagist has flagged versions of visanduma/nova-two-factor as malware and marked the package as "temporarily frozen". The underlying GitHub organisation ownership had not been recovered as of Socket's writeup, so the four branches on the repo remain in the attacker's hands - Packagist's freeze is the durable mitigation until upstream ownership is restored.

Downstream forks / alternates

Active forks and alternates that appear clean at time of writing:

  • outl1ne/nova-two-factor - actively maintained fork under a different maintainer, no PolinRider indicators reported
  • elsayed85/nova-two-factor - separate maintainer, not implicated

Any fork that pulled from the compromised Visanduma org after mid-June 2026 should be audited against the last known-clean tag before rebasing further work on top.

Registry state

Packagist: flagged as malware, temporarily frozen. GitHub Visanduma/nova-two-factor: dev-* branches still contain malicious code at the time of writing. No CVE assigned; Socket's blog post is the primary public disclosure.

Discovery credit

Socket Threat Research - the campaign identification and dev-branch enumeration.

Affected packages (1)

These are usually pulled in as transitive dependencies rather than installed directly. Check your whole tree at once - it runs in your browser and nothing is uploaded.

Impact

  • Any Composer project resolving visanduma/nova-two-factor from dev-main, dev-nova4support, dev-using-inertia, or dev-nova5 pulls a PolinRider stager - concealed JavaScript reconstructed from configuration/font files, dead-drop C2 resolution via EtherHiding / NullReceiver, and staged infostealer delivery targeting SSH keys, browser data, npm/GitHub PATs, cloud credentials, and crypto wallets
  • Legitimate stable tags (3.0.1, 3.0, 2.2.15 and below) are NOT compromised at time of writing - the malicious code lives only in the dev-* branches - but any developer following a dev-main constraint ("visanduma/nova-two-factor": "dev-main" in composer.json, or a Nova 5 preview installer) resolves the poisoned tree
  • A newer PolinRider variant invokes obfuscated JavaScript from PHP via shell_exec, so a Laravel app that autoloaded the malicious vendor tree exposes not just install-time but request-time RCE on the web tier
  • Attribution: PolinRider is the ongoing DPRK / Contagious Interview cluster (same operators behind the 108-package cross-ecosystem campaign against npm, PyPI, Go modules, Packagist, and Chrome extensions); Socket ties this compromise to the same tradecraft as prior PolinRider drops (Git history rewriting, payload concealment in configuration/font files, IDE-task autolaunch)
  • Packagist has marked the package as frozen and flagged versions as malware; the underlying GitHub org (Visanduma) is believed to have been under attacker control since roughly mid-June 2026 per Socket, so any downstream fork that pulled from these branches over the past three months should be audited

What to do

  1. 1Grep every composer.json and composer.lock in your org for visanduma/nova-two-factor - especially any constraint containing dev-main, dev-nova4support, dev-using-inertia, dev-nova5, or a floating semver like dev-* or @dev
  2. 2Remove the package from any project resolving it from a dev-* branch and pin to 3.0.1 or an earlier stable tag until the maintainer confirms upstream cleanup, or migrate to the actively maintained outl1ne/nova-two-factor fork
  3. 3Treat any developer workstation or CI runner that ran composer install/update against a dev-* constraint since roughly 2026-06-15 as fully compromised: rotate SSH keys, GitHub PATs, npm tokens, cloud provider credentials, database URLs, and any credential accessible from that host
  4. 4Audit web-tier hosts for unexpected shell_exec invocations in Laravel bootstrap paths and outbound traffic to unfamiliar hosts; the PolinRider request-time variant executes JavaScript via node invoked from PHP, so an unexpected node child of php-fpm is a high-fidelity IOC
  5. 5Extend your dependency policy to reject dev- branch resolution on production builds - Composer's minimum-stability: dev combined with prefer-stable: true should be the only* posture on any deployable app; better yet forbid dev constraints outright in CI
  6. 6For orgs that had previously vendored Visanduma/* sources: audit for any repository fork/mirror pulled since mid-June 2026, and rebase off the last known-clean upstream commit (pre-June 2026 tag hashes) rather than a branch tip

References

packagist-2026-09-17-visanduma-nova-two-factor-polinrider