Back to Intelligence

PolinRider Infostealer: Compromised GitHub Accounts Poison Packagist Supply Chain — OTX Detection Pack

SA
Security Arsenal Team
October 18, 2026
10 min read

Threat Summary

AlienVault OTX pulse data confirms an active supply chain intrusion campaign tracked as PolinRider, targeting the software development ecosystem itself as an infiltration vector. Operators compromised a legitimate GitHub account and used it to inject malicious code into development builds of visanduma/nova-two-factor — a Laravel Nova two-factor authentication package on Packagist with over 700,000 downloads. The choice of target is deliberate and dangerous: a security-focused package that sits directly in authentication flows, giving the attacker a trusted foothold inside application login pipelines.

The attack chain observed across this campaign follows a consistent pattern:

  1. Account compromise — developer/maintainer credentials are harvested (likely via prior infostealer infections, phishing, or credential stuffing against GitHub).
  2. Git history rewriting — malicious commits are injected and history is manipulated (git push --force, rebasing, amended commits) to conceal the tampering from casual repository review.
  3. Payload staging in package registries — poisoned development versions are published to Packagist and, per the campaign's broader footprint, npm, PyPI, Go modules, and Chrome extension channels.
  4. Downstream execution — CI/CD pipelines and developer workstations pull the compromised dependency, executing the infostealer payload during install/build hooks.
  5. Credential harvesting — browser credential stores, session tokens, SSH keys, .env files, and cloud provider credentials are staged and exfiltrated to actor-controlled infrastructure.

The objective is clear: harvest developer and enterprise credentials at scale, then monetize or pivot — stolen maintainer credentials feed the next round of package poisoning, creating a self-propagating supply chain worm effect across ecosystems.

Threat Actor / Malware Profile

Actor: PolinRider (infostealer operator collective, multi-ecosystem supply chain focus) Family: PolinRider infostealer Targeted sector: Technology — specifically developer workstations, CI/CD runners, and organizations consuming open-source PHP dependencies

Distribution method: Compromised maintainer accounts on GitHub used to push backdoored releases to Packagist. Campaign infrastructure extends to npm, PyPI, Go modules, and Chrome Web Store extensions, indicating a mature multi-registry operation rather than a one-off compromise.

Payload behavior: The malicious code rides inside the package's development branch and executes during Composer install/update hooks or at application runtime. Primary objectives on the endpoint:

  • Enumeration and extraction of browser credential databases (Chrome/Edge/Firefox Login Data, cookies, autofill)
  • Theft of SSH private keys (~/.ssh/), Git credentials (~/.git-credentials, credential helper stores), and cloud CLI tokens (~/.aws/, ~/.azure/, gcloud config)
  • Harvesting of .env files and project-level secrets — directly weaponized for further supply chain compromise
  • Session token theft enabling MFA bypass against GitHub, npm, and Packagist maintainer accounts

C2 communication: HTTPS-based exfiltration to rotating actor infrastructure, typically disguised as telemetry or analytics beacons. Exfiltration commonly occurs via POST requests with compressed/encrypted archives shortly after payload execution.

Persistence: On developer endpoints, persistence is secondary to speed — the payload prioritizes rapid credential theft. However, dropped artifacts may register scheduled tasks or modify shell profiles to re-execute on login if the host is deemed high-value (e.g., a maintainer's machine).

Anti-analysis: Git history rewriting to erase malicious commits from visible history, payload obfuscation within legitimate-looking package code, and execution gated behind install hooks that blend into normal Composer dependency resolution noise.

IOC Analysis

This pulse contains 5 FileHash-SHA256 indicators — file artifacts associated with the PolinRider malicious package payloads:

  • 7d47c430e6e404dc2fa8b4837678d1cbdb4d0aeacec9b405655cab79d54a2ad9
  • b7ede935d4979146b55f12b9eec7c83b61962b478f5dc9b8db251e539ec2abd3
  • ccb187dc9de0cc7477c9817ae53365d273e121407c0305f863e2ab67c35d6395
  • 139ea03dcddf4aa810d55740be3cf6c92ce7a9f3cbcbbb35440e25b769a87683
  • 515a53291d25d229e1f9fa72e66407e1cfd7e77c91478400b24d5185af68531a

Operationalization guidance for SOC teams:

  1. EDR hash blocking — push all five SHA256 values into your EDR blocklist (CrowdStrike, Defender for Endpoint, SentinelOne). Hash indicators are high-fidelity here because poisoned package payloads are identical across all victims who pulled the compromised version.
  2. Build artifact scanning — sweep vendor/ directories (Composer), build caches, and CI runner workspaces for files matching these hashes. Tools: Get-FileHash (PowerShell), sha256sum, or enterprise file integrity monitoring.
  3. Dependency audit — run composer show visanduma/nova-two-factor across codebases and container images to identify deployments on the compromised dev branch. Cross-reference lock file commit hashes against known-good releases.
  4. Git forensics — audit repositories for force-push events, rewritten history, and commits from maintainer accounts at unusual hours or from unfamiliar IPs. GitHub audit log and git reflog are your primary sources.
  5. Detonation — submit hashes to any sandbox for behavioral extraction of C2 endpoints if your team needs network IOCs; the OTX pulse reference (socket.dev analysis) provides additional payload context.

Detection Engineering

YAML
---
title: Suspicious Composer/Packagist Install Hook Spawning Credential Access
id: 9f2c1a7e-polin-0001-0001-000000000001
status: experimental
description: Detects Composer/PHP package install hooks spawning child processes that access browser credential stores, SSH keys, or cloud credential files — behavior consistent with PolinRider poisoned package execution.
author: Security Arsenal Threat Intel
references:
    - https://socket.dev/blog/polinrider-github-packagist
date: 2026/10/18
logsource:
    category: process_creation
    product: windows
    definition: windows
 detection_placeholder: null
detection:
    selection_parent:
        ParentImage|endswith:
            - '\php.exe'
            - '\composer.phar'
            - '\composer.exe'
    selection_target:
        CommandLine|contains:
            - 'Login Data'
            - 'Cookies'
            - '.ssh'
            - 'id_rsa'
            - 'id_ed25519'
            - '.git-credentials'
            - '.aws\credentials'
            - '.azure'
            - '.env'
    condition: selection_parent and selection_target
falsepositives:
    - Legitimate PHP deployment scripts reading environment configuration
level: high
tags:
    - attack.t1555
    - attack.t1552.001
    - attack.t1195.002
---
title: Git Force Push or History Rewrite on Protected Repository
id: 9f2c1a7e-polin-0002-0002-000000000002
status: experimental
description: Detects git history rewriting operations (force push, reset --hard followed by push) commonly used by PolinRider operators to conceal malicious commits after compromising maintainer accounts.
author: Security Arsenal Threat Intel
date: 2026/10/18
logsource:
    category: process_creation
    product: windows
    definition: linux
 detection_placeholder: null
detection:
    selection_img:
        Image|endswith:
            - '\git.exe'
            - '/git'
    selection_cmd:
        CommandLine|contains:
            - 'push --force'
            - 'push -f'
            - 'reset --hard'
            - 'commit --amend'
            - 'filter-branch'
            - 'rebase'
    condition: selection_img and selection_cmd
falsepositives:
    - Developer workflow on feature branches; correlate with pushes to main/release branches via git server audit logs
level: medium
tags:
    - attack.t1195.002
    - attack.t1078
---
title: Infostealer Browser Credential Store Access
id: 9f2c1a7e-polin-0003-0003-000000000003
status: experimental
description: Detects non-browser processes accessing Chromium/Firefox credential databases, consistent with PolinRider infostealer payload execution on developer workstations.
author: Security Arsenal Threat Intel
date: 2026/10/18
logsource:
    category: file_event
    product: windows
    definition: sysmon
 detection_placeholder: null
detection:
    selection_file:
        TargetFilename|contains:
            - '\Google\Chrome\User Data\'
            - '\Microsoft\Edge\User Data\'
            - '\BraveSoftware\'
            - '\Mozilla\Firefox\Profiles\'
        TargetFilename|endswith:
            - 'Login Data'
            - 'Cookies'
            - 'Web Data'
            - 'logins.json'
            - 'key4.db'
    filter_browser:
        Image|endswith:
            - '\chrome.exe'
            - '\msedge.exe'
            - '\firefox.exe'
            - '\brave.exe'
    condition: selection_file and not filter_browser
falsepositives:
    - Backup software, enterprise password managers, forensic tooling
level: high
tags:
    - attack.t1555.003
    - attack.t1539
KQL — Microsoft Sentinel / Defender
// PolinRider supply chain hunt — poisoned package execution + credential theft + known payload hashes
// Microsoft Sentinel / Defender XDR
let PolinRiderHashes = dynamic([
    "7d47c430e6e404dc2fa8b4837678d1cbdb4d0aeacec9b405655cab79d54a2ad9",
    "b7ede935d4979146b55f12b9eec7c83b61962b478f5dc9b8db251e539ec2abd3",
    "ccb187dc9de0cc7477c9817ae53365d273e121407c0305f863e2ab67c35d6395",
    "139ea03dcddf4aa810d55740be3cf6c92ce7a9f3cbcbbb35440e25b769a87683",
    "515a53291d25d229e1f9fa72e66407e1cfd7e77c91478400b24d5185af68531a"
]);
// Leg 1: file hits for known PolinRider payload hashes
let HashHits = DeviceFileEvents
    | where TimeGenerated > ago(14d)
    | where SHA256 in (PolinRiderHashes)
    | project HashHitTime=TimeGenerated, DeviceName, DeviceId, FileName, FolderPath, SHA256, InitiatingProcessFileName;
// Leg 2: package manager install hooks spawning credential-accessing children
let SuspiciousInstallExec = DeviceProcessEvents
    | where TimeGenerated > ago(14d)
    | where InitiatingProcessFileName in~ ("php.exe", "composer.exe", "composer.phar", "node.exe", "npm.cmd", "pip.exe", "python.exe")
    | where ProcessCommandLine has_any ("Login Data", "Cookies", ".ssh", "id_rsa", "id_ed25519", ".git-credentials", ".aws", ".azure", ".env")
    | project InstallExecTime=TimeGenerated, DeviceName, DeviceId, FileName, ProcessCommandLine, InitiatingProcessFileName, InitiatingProcessCommandLine;
// Leg 3: git history rewriting on developer endpoints
let GitRewrite = DeviceProcessEvents
    | where TimeGenerated > ago(14d)
    | where FileName =~ "git.exe"
    | where ProcessCommandLine has_any ("push --force", "push -f", "filter-branch", "reset --hard", "commit --amend")
    | project GitTime=TimeGenerated, DeviceName, DeviceId, ProcessCommandLine, AccountName;
union HashHits, SuspiciousInstallExec, GitRewrite
| summarize by DeviceName, DeviceId
| join kind=leftouter (HashHits) on DeviceId
| join kind=leftouter (SuspiciousInstallExec) on DeviceId
| join kind=leftouter (GitRewrite) on DeviceId
| project DeviceName, HashHitTime, FolderPath, SHA256, InstallExecTime, ProcessCommandLine, GitTime
| sort by HashHitTime desc
PowerShell
# PolinRider Supply Chain IOC Hunt — Security Arsenal
# Sweep developer workstations & build servers for poisoned package artifacts and credential-theft staging
$ErrorActionPreference = 'SilentlyContinue'

$PolinRiderHashes = @(
    '7d47c430e6e404dc2fa8b4837678d1cbdb4d0aeacec9b405655cab79d54a2ad9',
    'b7ede935d4979146b55f12b9eec7c83b61962b478f5dc9b8db251e539ec2abd3',
    'ccb187dc9de0cc7477c9817ae53365d273e121407c0305f863e2ab67c35d6395',
    '139ea03dcddf4aa810d55740be3cf6c92ce7a9f3cbcbbb35440e25b769a87683',
    '515a53291d25d229e1f9fa72e66407e1cfd7e77c91478400b24d5185af68531a'
)

Write-Host '[*] === PolinRider IOC Hunt Started ===' -ForegroundColor Cyan

# 1. Scan Composer vendor dirs and build caches for known-bad hashes
$ScanRoots = @("$env:USERPROFILE\vendor", "$env:USERPROFILE\source", "$env:USERPROFILE\Projects", 'C:\builds', 'C:\workspace')
foreach ($root in $ScanRoots) {
    if (Test-Path $root) {
        Write-Host "[*] Hashing files under $root ..."
        Get-ChildItem -Path $root -Recurse -File | ForEach-Object {
            $h = (Get-FileHash -Path $_.FullName -Algorithm SHA256).Hash.ToLower()
            if ($PolinRiderHashes -contains $h) {
                Write-Host "[!] POLINRIDER PAYLOAD MATCH: $($_.FullName) [$h]" -ForegroundColor Red
            }
        }
    }
}

# 2. Identify installs of the compromised package
Write-Host '[*] Checking composer.lock files for visanduma/nova-two-factor ...'
Get-ChildItem -Path $env:USERPROFILE -Recurse -Filter 'composer.lock' | ForEach-Object {
    $content = Get-Content $_.FullName -Raw
    if ($content -match 'visanduma/nova-two-factor') {
        Write-Host "[WARNING] Compromised package present in: $($_.FullName)" -ForegroundColor Yellow
    }
}

# 3. Check for git history rewriting artifacts in reflogs
Write-Host '[*] Auditing local git reflogs for force-push / history rewrite traces ...'
Get-ChildItem -Path $env:USERPROFILE -Recurse -Directory -Filter '.git' | ForEach-Object {
    $repo = $_.Parent.FullName
    Push-Location $repo
    $reflog = git reflog --all 2>$null | Select-String -Pattern 'reset|rebase|amend|filter-branch'
    if ($reflog) { Write-Host "[WARNING] History rewrite activity in $repo" -ForegroundColor Yellow; $reflog | ForEach-Object { Write-Host "    $_" } }
    Pop-Location
}

# 4. Hunt persistence artifacts (scheduled tasks spawned near install windows)
Write-Host '[*] Reviewing non-Microsoft scheduled tasks ...'
Get-ScheduledTask | Where-Object { $_.TaskPath -notlike '\Microsoft*' } | ForEach-Object {
    $action = $_.Actions[0].Execute
    if ($action -match 'php|composer|powershell|cmd|wscript|node') {
        Write-Host "[WARNING] Suspicious task: $($_.TaskName) -> $action" -ForegroundColor Yellow
    }
}

# 5. Flag recent outbound connections from PHP/Composer processes (exfil check)
Write-Host '[*] Checking network connections from php/composer/node processes ...'
Get-NetTCPConnection -State Established | ForEach-Object {
    $proc = Get-Process -Id $_.OwningProcess
    if ($proc.Name -match 'php|composer|node') {
        Write-Host "[WARNING] $($proc.Name) (PID $($_.OwningProcess)) -> $($_.RemoteAddress):$($_.RemotePort)" -ForegroundColor Yellow
    }
}

Write-Host '[*] === Hunt Complete ===' -ForegroundColor Cyan

Response Priorities

Immediate (0-4 hours):

  • Block all five SHA256 indicators in EDR and email/web gateways; sweep endpoints, build servers, and artifact repositories for matches.
  • Inventory every codebase, container image, and CI pipeline consuming visanduma/nova-two-factor — pin to a known-good release or remove pending validation.
  • Freeze pulls of development (dev-*) branches of the affected package across all projects.
  • Audit GitHub organization audit logs for force-pushes, unexpected maintainer logins, new deploy keys, and OAuth app authorizations.

24 hours:

  • Treat any host that executed the poisoned package as fully credential-compromised: rotate browser-stored passwords, SSH keypairs, cloud CLI tokens, GitHub PATs, npm/Packagist tokens, and any secrets present in .env files on the affected machine.
  • Enforce phishing-resistant MFA (hardware keys) re-enrollment for all maintainer accounts; revoke all active sessions on GitHub, Packagist, npm, and PyPI.
  • Review authentication logs for the two-factor package's downstream applications — the malicious code sat inside an auth component and may have intercepted credentials in transit.
  • Hunt for downstream lateral movement using stolen developer credentials (VPN, SSO, CI systems).

1 week:

  • Implement dependency pinning with signed commits and lock-file integrity verification in CI/CD; block unsigned or history-rewritten commits from merging to release branches.
  • Deploy a software composition analysis (SCA) gate that alerts on maintainer account changes, sudden version bumps from new committers, and packages with rewritten Git history.
  • Require Sigstore/cosign or equivalent artifact signing for internally built packages; enable GitHub's required signed commits for critical repos.
  • Conduct tabletop exercise: maintainer account takeover → package poisoning scenario, and update IR playbooks accordingly.

Related Resources

Security Arsenal Incident Response

Managed SOC & MDR Services

AlertMonitor Threat Detection

From The Dark Side Intel Hub

Is your security operations ready?

Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.