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. 출처 표시 시 자유롭게 재사용 가능.

홈/사고/microsop-apple-dep-confusion-2026
HIGH7.5·confirmed·공개 May 4, 2026·7분 분량

microsop npm Cluster: Dependency-Confusion Campaign Targeting Apple Internal CI/CD (2026)

npm publisher microsop pushed 36 versions across 6 Apple-themed packages between May 4–11, 2026, fingerprinting Apple internal CI and exfiltrating npmrc, env vars, and git origin to 12 rotating webhook.site endpoints.

Summary

Between May 4 and May 11, 2026, the npm publisher account microsop released 36 versions across 6 packages whose names mimic Apple internal tooling (ac-sasskit, apple-mycelium-fix, apple-mycelium-recon-tool, @microsop/apple-mycelium-integrity-check), generic CI utilities (rsflows-pexml), and a PayPal-themed payments package (paypal-payouts-bridge). Every version ships a preinstall or postinstall script that runs at install time, performs targeted reconnaissance against the host, and exfiltrates the result over HTTP to one of 12 distinct webhook.site UUID endpoints. The recon stages observed so far are consistent with dependency confusion against Apple's internal build pipeline, not generic credential theft — the payloads test for Apple-specific DNS, environment variables, and registry configuration before any secondary action.

Timeline

  • 2026-05-04 10:25 UTC — First package published: paypal-payouts-bridge@100.3.3. The version number (100.x.x) is the dependency-confusion tell; the legitimate @paypal/payouts-bridge private package, if it exists internally, would have a far lower version.
  • 2026-05-09 12:56 UTC — Apple-themed cluster begins: @microsop/apple-mycelium-integrity-check@1.0.1778331373, immediately followed by apple-mycelium-fix and apple-mycelium-recon-tool over the next 3 hours.
  • 2026-05-10 14:48 UTC — rsflows-pexml@99.9.9 published, followed by 12 more versions in 2 hours, each carrying a different recon payload to a different webhook endpoint.
  • 2026-05-10 20:15 UTC — ac-sasskit@100.0.0 published. 7 more versions over the next 9 hours.
  • 2026-05-11 05:38 UTC — Most recent observed publish: ac-sasskit@100.1.3. Campaign still active at time of writing.
  • 2026-05-12 — Cremit's live monitor groups all 36 versions under publisher microsop. Incident page published; npm Trust & Safety notified separately.

Attack Vector

The campaign uses dependency confusion: registering public npm packages whose names match (or appear similar to) packages a target organization uses privately, then publishing versions with very high version numbers so npm's resolver prefers the public copy over the private one. Three signals make Apple's internal build farms the most plausible target:

  1. Version numbers are dependency-confusion canonical: 100.0.0, 100.1.3, 99.9.42. No legitimate v1.x package legitimately jumps to v100 in a week.
  2. Package names target specific Apple-internal namespaces:
    • ac-sasskit — described in its package.json as "Critical Security Patch for Apple Internal Sass Toolkit". The ac- prefix and SassKit framing match Apple's internal naming conventions.
    • apple-mycelium-* — mycelium matches an internal Apple distributed-systems / mesh project name.
    • @microsop/apple-mycelium-integrity-check — scoped variant, suggesting the actor probed both unscoped and scoped name resolution.
  3. The install-time payloads explicitly fingerprint Apple infrastructure before doing anything else, indicated by DNS lookups for apple-beta.apple.com, internal.apple.com, and certs.apple.com.

The malicious code lives in preinstall (most versions) or postinstall (some), so it executes during npm install without the developer ever importing or running the package.

Tokens & Credentials Exposed

Across the 36 versions, the install-script payloads collect, in different combinations:

  • .npmrc contents (cat .npmrc ~/.npmrc /root/.npmrc 2>/dev/null | grep -v _password | head -c 150) — includes npm publish auth tokens, private registry URLs, and proxy configuration.
  • Environment variables matching APPLE|BETA|STAGE|TOKEN (env | grep -iE "BETA|STAGE|APPLE" | head -c 100) — captures CI-injected secrets, build environment markers, and target deployment context.
  • SSH private-key paths (read attempt against ~/.ssh/ contents).
  • Git remote origin (git remote -v | head -n 1) — identifies which internal Apple repo, if any, triggered the install.
  • Internal DNS resolution (getent hosts against Apple internal domains) — confirms the host is inside Apple's network perimeter and not, for example, a researcher's workstation.
  • Hostname + npm registry URL — host fingerprinting.

Each version sends a different subset of the above to a different webhook UUID. The pattern is staged reconnaissance: the actor wants to know which version was installed on which class of host before deciding what to do with secondary access. No second-stage payload has been observed in the captured versions.

Confirmed Impact

As of publication, Cremit has direct evidence of:

  • 36 malicious package versions reaching the public npm registry under a single publisher.
  • 12 distinct webhook.site exfiltration endpoints actively receiving HTTP POST traffic (any installation hits one of them).
  • Naming and payload design that only makes operational sense if installed inside Apple's build infrastructure.

What is not yet directly observed:

  • Confirmation that any Apple internal CI actually pulled these packages.
  • Secondary payloads (file theft, lateral movement, code modification). The static payloads end after the first curl to webhook.site.

Apple's internal pipelines using strict private-registry pinning, package-lock.json with npm config set registry, or scoped private namespaces would be unaffected. Pipelines that resolve unscoped names against the public npm registry before falling back to a private one are the primary risk.

Mitigation & Lessons

For organizations that fear they may be in scope:

  1. Audit your private package names against the public npm registry for any name that resolves both privately and publicly. npm view <name> versions will show if a public copy exists.
  2. Force private-only resolution for internal namespaces: use scoped packages (@your-org/foo) with @your-org:registry=https://internal.example.com/ in .npmrc. Unscoped private package names are the surface area dependency confusion exploits.
  3. Block preinstall/postinstall in CI: npm install --ignore-scripts is a hard mitigation against this entire class. If you need scripts, allowlist them per-package.
  4. Egress filtering for webhook.site: legitimate code never POSTs to webhook.site/<uuid> in production. Block at firewall or proxy.
  5. Audit npm publish tokens stored in .npmrc or environment. If any CI runner pulled ac-sasskit, rsflows-pexml, apple-mycelium-*, @microsop/apple-mycelium-integrity-check, or paypal-payouts-bridge since May 4, 2026, rotate every credential reachable from that runner.

The 12 webhook.site UUIDs observed:

10844949-8a75-4998-bb9a-8ed79b681833
4521430f-e618-4d4b-8f13-abd81b74bcf2
49abe75c-2b38-498f-b08f-5f910bbd1f47
4dcec135-8ea0-42dd-bb3a-adef891539a3
53b04b32-06a9-416e-8897-d54dfb7e0373
6e268c68-febc-4f38-9cff-22f9152e9023
9c1e60d7-a1f0-48fd-afaf-ae16b73981b7
cb8d0670-33e0-46e2-8d6f-66a5e2d3df5d
d9ff4a88-0f9f-4f28-a8a0-c283d7e06b44
e442364e-c876-4536-a0c2-4edd3fc75935
f27e815b-2671-4dc3-9785-cc8d36b0ade1
fcd796ad-5e1b-46a6-87e5-e8d6705f23d4

Use these as IOC matches in proxy logs, EDR, or CI artifact scanning.

Cremit Analysis

NHI Severity Index: 7.5 (High)

DimensionValueRationale
Blast radiuscross-platformApple's build pipeline reaches macOS, iOS, watchOS, and tvOS artifacts. If exploited, downstream blast surface is product-wide.
ReachabilityproductionInstall-time execution lands inside the runner that builds production artifacts. There is no staging "safe zone" — npm install is the same code path on every runner.
Privilege levelvariableRecon payloads steal .npmrc publish tokens (high privilege within npm), env vars (variable), and SSH keys (variable). The actor harvests whatever is reachable.

The score sits at 7.5 rather than 9+ because we observed reconnaissance only — no confirmed secondary exfiltration of build artifacts, code signing material, or internal repo content. If a second-stage payload appears, the score moves to critical.

NHI Kill Chain mapping:

  • Ghost Key — npm publish tokens harvested from .npmrc are the textbook ghost-key target: long-lived, broadly-scoped credentials that exist in build environments but rarely show up in any inventory.
  • Drifted Key — environment variables captured by the env | grep payload are drifted-key candidates: secrets injected into CI runners that outlive the build, leak into logs, and sit in CI variable stores months after rotation cycles forgot them.
  • Unattributed Key — the 12 webhook.site endpoints themselves are unattributed: no legitimate organization owns them, no IR process can call the operator, and webhook.site retains POST bodies indefinitely by design. Any data sent here is permanently outside the defender's control.

Why publisher-clustering caught this and per-package scanning would not

Each of the 36 versions individually scores moderately on heuristics (small tarball, single install script, single network call). 11 versions were auto-published by Cremit's heuristic+LLM pipeline; the other 25 sat in low-signal even though the LLM flagged them malicious. What pulled the campaign into focus was the publisher-clustering pass: 36 versions from the same npm account in 7 days, all install-time network egress, all webhook.site. The publisher signal is what survived the noise — individual packages can hide, a sustained publishing pattern from one account cannot.

This is the case Cremit's campaign detector is built for: most npm threat actors operate at the publisher level over weeks, not the single-package level over hours.


참고 자료

  1. [1]
    ac-sasskit on npm (publisher: microsop)
    primary·npmjs.com
  2. [2]
    rsflows-pexml on npm (publisher: microsop)
    primary·npmjs.com
  3. [3]
    paypal-payouts-bridge on npm (publisher: microsop)
    primary·npmjs.com
  4. [4]
    Cremit live monitor — microsop publisher campaign
    analysis·incidents.cremit.io

관련 사고

2021-10-22·CRITICAL
ua-parser-js npm Account Compromise (2021)
2021-11-04·CRITICAL
rc and coa Coordinated npm Account Takeover (2021)
2026-04-22·CRITICAL
Bitwarden CLI Supply Chain Compromise (2026)
최종 검토 / 2026-05-12검토자 / ben라이선스 / CC BY 4.0
// 사고 메타데이터
심각도
HIGH7.5
상태
confirmed
공개
2026-05-04
발생
2026-05-04 → 2026-05-11
벡터
Dependency confusion
플랫폼
npm
토큰
npm Publish TokenEnvironment VariableSSH Private Key
nhi severity index
점수7.5 / 10blast radiuscross-platformreachabilityproduction권한variable
nhi kill chain
Ghost Key↗Drifted Key↗Unattributed Key↗
지표
노출 기간8일