Cremit
/incidentsfield log
탐지캠페인유출지패턴LLM사고 사례방법론
↺rss↗cremit.io

incidents.cremit.io

실제 발생한 비인간 식별자(NHI) 크리덴셜 유출 사고를 정리한 인덱스. 운영: Cremit

둘러보기

  • 전체 사고
  • npm 공급망
  • CI/CD 침해
  • 방법론

구독

  • RSS 피드
  • @cremit_io
  • GitHub
// 상태
모니터 가동중
// 빌드
2026-05-20
// 출처
cremit · 서울, 대한민국
// 라이선스
CC BY 4.0

© 2026 Cremit. 출처 표시 시 자유롭게 재사용 가능.

홈/사고/rc-coa-coordinated-takeover-2021
CRITICAL8.7·confirmed·공개 Nov 4, 2021·5분 분량

rc and coa Coordinated npm Account Takeover (2021)

Two long-unmaintained npm packages — rc and coa, with combined weekly downloads in the tens of millions — were hijacked the same day and shipped credential-harvesting payloads matching ua-parser-js.

Summary

On November 4, 2021 — roughly two weeks after the ua-parser-js compromise — two more long-dormant npm packages were hijacked in rapid succession: coa (a command-line option parser used as a transitive dependency by the Angular and React CLI ecosystems) and rc (a configuration loader used in roughly 14 million weekly downloads). Both received malicious patch versions carrying a credential-stealing payload nearly identical to the ua-parser-js attack. The two takeovers happened within hours of each other and used the same payload infrastructure, indicating a single coordinated operator.

Timeline

  • 2021-11-04 ~14:00 UTC — coa@2.0.3, 2.0.4, and 2.1.x malicious versions begin landing.
  • 2021-11-04 ~16:00 UTC — Public discovery via failing CI builds across the React ecosystem (the legitimate coa had been at 2.0.2 for years; new patches broke installs).
  • 2021-11-04 ~17:00 UTC — rc@1.2.9, 1.3.9, and 2.3.9 malicious versions discovered with similar characteristics.
  • 2021-11-04 ~19:00 UTC — npm removes all malicious versions; clean replacements re-published.
  • 2021-11-04 ~22:00 UTC — GitHub Security Advisories published for both packages.

Attack Vector

Both packages were essentially unmaintained at the time of takeover. The legitimate coa had not received a release in three years; rc had been stable for similar duration. Both compromises followed the same pattern as ua-parser-js:

  1. Maintainer npm account credentials compromised via credential reuse / credential stuffing.
  2. Attacker published version bumps that looked like routine maintenance releases (2.0.3 → 2.0.4, etc.) rather than dramatic version jumps.
  3. preinstall script in each malicious version downloaded a platform-specific payload.
  4. Linux install: cryptominer + minimal credential collection.
  5. Windows install: cryptominer + DanaBot-family credential stealer (same payload family observed in ua-parser-js).

The coordination signal — both packages hijacked the same day, both using the same payload infrastructure — strongly suggests a single operator working through a list of dormant-but-popular npm accounts harvested from a credential breach corpus.

Tokens & Credentials Exposed

Identical scope to ua-parser-js because the payload was the same family:

  • Browser-stored credentials (Chrome, Edge, Firefox password and cookie stores).
  • OS-level credentials (Windows Credential Manager, FTP client stored credentials).
  • Cryptocurrency wallet files (wallet.dat, MetaMask local storage, hardware-wallet companion data).
  • Session tokens for any post-2FA session active in the affected browser.

For the rc install footprint specifically, the practical exposure was enormous: rc is a transitive dependency of huge swaths of the Node.js tooling ecosystem (everything from npm itself in some configurations, to test runners, to CLI tools). Any developer workstation or CI runner that ran npm install during the exposure window potentially pulled the malicious version.

Confirmed Impact

  • Both packages quickly removed by npm; window was ~2–5 hours each.
  • GitHub Security Advisories issued classifying installs of affected versions as fully compromised.
  • DanaBot operator continuity confirmed: malware analysts tied the C2 infrastructure to the same operation as ua-parser-js, suggesting a deliberate campaign rather than independent incidents.
  • No specific organization disclosures, but Fortune-500 IR activations were widely reported in industry discussion channels.

Mitigation & Lessons

The Mitigation playbook is identical to ua-parser-js:

  • Treat any host that pulled a malicious version as fully compromised; reformat workstations and rebuild CI runners.
  • Rotate every credential reachable from the affected host — browser-stored, OS-stored, cloud, source control, third-party SaaS.
  • Audit for DanaBot-family persistence (scheduled tasks, registry run keys).

The structural lessons that this pair of incidents added to the field:

  • Coordinated takeovers are a deliberate operating model. A single attacker with a credential corpus can hit multiple dormant-but-popular packages within hours. The defender response cost scales with the number of packages compromised, not with the technical complexity of each compromise.
  • "Unmaintained" is a security state, not a maintenance state. A package that has not received a release in three years is not safe by virtue of stability — it is dangerous because the security posture of its publishing credentials has not been reviewed in three years.
  • Detection by ecosystem-wide CI failure is the wrong end of the funnel. Both coa and rc were detected because their version bumps broke downstream installs, not because npm or any monitoring vendor flagged the publish event itself.

Cremit Analysis

This pair is the cleanest ghost-key + drifted-key combination in the index.

Ghost Key: both maintainer credentials were long-lived static identities held by individuals whose engagement with the package had ended years earlier. There was no operational signal — no team, no review, no rotation calendar — to detect that the credential was now in someone else's hands.

Drifted Key: both packages had drifted from small utilities to load-bearing transitive dependencies in the JavaScript ecosystem. rc in particular ended up underneath a substantial fraction of all Node.js tooling. The trust model that worked for a small utility was inadequate for the blast radius the package had accumulated.

The NHI Severity Index score of 8.7 reflects ecosystem-wide reach (especially rc at ~14M weekly downloads), production reachability (the credentials harvested were live OS and browser credentials), and variable privilege levels.

What this pair adds beyond ua-parser-js is the demonstration that the technique scales. Once an attacker has the playbook — credential corpus, dormant-package list, copy-paste DanaBot payload — additional takeovers cost the attacker close to nothing. The defender side has no equivalent leverage. Each incident requires individual investigation, individual customer contact, individual credential rotation. The asymmetry is structural and is exactly what credential-leak detection platforms like Argus are built to flatten by surfacing exfiltrated credentials in the public ecosystem before downstream re-use.


참고 자료

  1. [1]
    GitHub Security Advisory GHSA-3jfq-g458-7qm9 (coa)
    primary·2021-11-04·github.com
  2. [2]
    GitHub Security Advisory GHSA-g2q5-5433-rhrf (rc)
    primary·2021-11-04·github.com
  3. [3]
    Popular 'coa' NPM library hijacked to steal user passwords
    reporting·2021-11-04·bleepingcomputer.com
  4. [4]
    Hackers update 'rc' npm library with malware mimicking the ua-parser-js attack
    reporting·2021-11-04·bleepingcomputer.com

관련 사고

2021-10-22·CRITICAL
ua-parser-js npm Account Compromise (2021)
2018-07-12·HIGH
eslint-scope npm Publish Token Theft (2018)
2018-11-26·HIGH
event-stream / flatmap-stream Backdoor (2018)
2026-04-22·CRITICAL
Bitwarden CLI Supply Chain Compromise (2026)
최종 검토 / 2026-05-04검토자 / ben라이선스 / CC BY 4.0
// 사고 메타데이터
심각도
CRITICAL8.7
상태
confirmed
공개
2021-11-04
발생
2021-11-04 → 2021-11-04
벡터
npm supply chain
플랫폼
npm
토큰
API Key (generic)Environment VariableDatabase CredentialSigning Key
nhi severity index
점수8.7 / 10blast radiusecosystem-widereachabilityproduction권한variable
nhi kill chain
Ghost Key↗Drifted Key↗
지표
노출 기간1일