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

> 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.

- Published: 2026-09-17
- Last updated: 2026-09-20
- Severity: high
- Kind: 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.
- Ecosystems: Packagist
- Scope: 1 package, 4 compromised versions
- Tags: account-takeover, maintainer-takeover, credential-theft, infostealer, obfuscation, ci-cd-compromise
- Threat actor: PolinRider (DPRK / Contagious Interview cluster)
- Also known as: PolinRider Packagist wave (Sep 2026), Visanduma nova-two-factor dev-branch compromise, PolinRider Laravel Nova 2FA hijack
- Detected by: Socket
- Incident ID: packagist-2026-09-17-visanduma-nova-two-factor-polinrider

## Affected packages (1)

Only the exact versions listed were named by the source advisories. Other versions are not implicated.

| Package | Ecosystem | Compromised versions |
|---|---|---|
| [visanduma/nova-two-factor](https://dependencywatch.io/package/packagist/visanduma/nova-two-factor) | Packagist | dev-main, dev-nova4support, dev-using-inertia, dev-nova5 |

## 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)

| Branch | Composer constraint | Status |
|---|---|---|
| `dev-main` | `dev-main` | compromised |
| `dev-nova4support` | `dev-nova4support` | compromised |
| `dev-using-inertia` | `dev-using-inertia` | compromised |
| `dev-nova5` | `dev-nova5` | compromised |
| `3.0.1` (last stable, 2025-01-28) | `^3.0` | **NOT** compromised |
| `<= 2.2.15` | `^2.0` | **NOT** 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.

## 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. Grep 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. Remove 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. Treat 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. Audit 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. Extend 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. For 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

- [PolinRider Spreads Through Compromised GitHub Accounts and Packagist](https://socket.dev/blog/polinrider-github-packagist) - Socket
- [visanduma/nova-two-factor on Packagist (marked as malware, temporarily frozen)](https://packagist.org/packages/visanduma/nova-two-factor) - Packagist
- [Visanduma/nova-two-factor GitHub repository](https://github.com/Visanduma/nova-two-factor) - GitHub
- [PolinRider Malware Inserted Into Packagist Dev Branches via Compromised GitHub Org](https://mallory.ai/stories/01a0b077-fba7-7140-bc76-120c1cb9a662) - Mallory

---

Canonical page: https://dependencywatch.io/incident/packagist-2026-09-17-visanduma-nova-two-factor-polinrider
Markdown version: https://dependencywatch.io/incident/packagist-2026-09-17-visanduma-nova-two-factor-polinrider.md
Site index for agents: https://dependencywatch.io/llms.txt
DependencyWatch.io is operated by Precursor Security (https://precursorsecurity.com).
