Blog

UNC4899 Used AirDrop to Breach a Crypto Firm's Cloud and Steal Millions

North Korean hackers tricked a developer into AirDropping a trojanized file to their work laptop, then pivoted through CI/CD tokens and container escapes to drain crypto wallets.

A developer downloads an archive file from what looks like an open-source collaboration project. They transfer it to their corporate laptop over AirDrop because it's faster than cloning from Git. They open it in their AI-assisted IDE, interact with the contents, and unknowingly execute malicious Python that spawns a backdoor disguised as the Kubernetes CLI. Within hours, North Korean state-sponsored hackers have pivoted from that single developer machine into the company's Google Cloud environment, extracted CI/CD service account tokens, escaped from privileged containers, accessed production databases, and drained several million dollars in cryptocurrency.

That's not a hypothetical kill chain. That's the UNC4899 incident documented in Google Cloud's H1 2026 Threat Horizons Report, published this week. The threat actor - also tracked as Jade Sleet, Slow Pisces, and TraderTraitor - is a North Korean group that Mandiant attributes with moderate confidence to this breach. And the attack chain reads like a masterclass in exploiting the gap between personal device convenience and enterprise cloud security.

I've been covering related attack patterns for weeks now: MFA bypass phishing services that render authentication controls useless, secrets management failures that leave credentials exposed in environment variables and CI/CD logs, and AI agent vulnerabilities that turn developer tools into attack vectors. UNC4899 ties all three threads together in a single, devastating campaign.

The Attack Chain, Step by Step

The initial access was social engineering. UNC4899 posed as a collaborator on a legitimate-looking open-source project and convinced a developer to download an archive file. Nothing unusual there - developers evaluate code samples, libraries, and project contributions constantly.

What made this attack different was the pivot vector. The developer transferred the archive to their corporate workstation using AirDrop, Apple's peer-to-peer file transfer mechanism. This is a common workflow - developers routinely AirDrop files between personal phones, tablets, and work machines. It feels safe because it's local, direct, and doesn't touch the internet.

Once on the corporate machine, the developer opened the archive contents in an AI-assisted IDE. The interaction with the code - whether through code exploration, running tests, or following embedded instructions - triggered malicious Python that spawned a binary masquerading as kubectl, the Kubernetes command-line tool. That binary established a backdoor connection to an attacker-controlled domain.

From there, the attackers had a foothold on a developer machine with authenticated sessions and cached cloud credentials. The rest of the attack unfolded through what Google Cloud calls "Living-off-the-Cloud" (LotC) techniques - using legitimate cloud tools and services to avoid detection:

Phase Action Technique
Reconnaissance Mapped cloud services and projects Standard GCP API calls
Lateral movement Discovered and accessed bastion host Authenticated sessions from developer machine
Persistence Modified MFA policy attributes Cloud IAM manipulation
Privilege escalation Altered Kubernetes deployments to inject bash commands Container orchestration abuse
Credential theft Modified CI/CD resources to dump service account tokens to logs Pipeline manipulation
Container escape Used high-privileged tokens to access pods running in privileged mode Kubernetes privilege escalation
Data access Extracted static DB credentials from pod environment variables Environment variable harvesting
Database access Connected to production DB via Cloud SQL Auth Proxy Legitimate tooling
Account takeover Reset passwords and MFA seeds for high-value accounts Direct database modification
Theft Withdrew several million dollars in digital assets Cryptocurrency transaction

Every step after the initial backdoor used legitimate cloud infrastructure. No zero-days. No custom exploits against cloud services. Just methodical abuse of permissions, misconfigurations, and secrets left in the wrong places.

Why AirDrop Is the New USB Drive

The AirDrop vector deserves special attention because it exploits a blind spot in most security programs.

Enterprise security teams have spent years building controls around email attachments, web downloads, and USB devices. Email gets scanned by secure email gateways. Web downloads go through proxy inspection. USB ports are disabled or monitored on managed devices. But AirDrop? Most organizations haven't even thought about it.

AirDrop operates over Bluetooth and Wi-Fi Direct. It doesn't touch your corporate network, which means your network monitoring sees nothing. It doesn't go through your email gateway, so your attachment scanning never triggers. It's a direct peer-to-peer transfer between two Apple devices that happens to bypass every network-based security control you've implemented.

Google Cloud's remediation guidance was explicit: organizations should "enforce policies to disable AirDrop and Bluetooth file sharing" and "restrict mounting of unmanaged external media on corporate devices." This puts AirDrop in the same category as USB drives - a data transfer mechanism that needs to be controlled at the endpoint level because network controls can't see it.

For startups and growing companies, the practical question is whether your MDM (Mobile Device Management) configuration addresses this. If you're using Jamf, Kandji, Mosyle, or another macOS management tool, check whether AirDrop receiving is restricted on corporate machines. If you don't have MDM at all, this incident is another data point in the argument for implementing it before your next SOC 2 audit asks about endpoint controls.

The CI/CD Token Problem

The most technically interesting part of this attack was how UNC4899 escalated from a developer machine to full cloud compromise. The pivot point was CI/CD service account tokens.

The attackers modified CI/CD platform resources to inject commands that displayed service account tokens in pipeline logs. This is a pattern I covered in detail in my secrets management post - the tendency to treat CI/CD environments as trusted contexts where secrets can flow freely. Pipeline logs are often accessible to anyone with developer access to the repository, and service account tokens in those logs become credentials that bypass every human-facing authentication control.

Here's what went wrong in sequence:

  1. Service accounts with excessive privileges. The CI/CD service account tokens had enough permissions to access privileged Kubernetes pods. In most organizations, CI/CD service accounts are over-provisioned because restricting them requires understanding the exact minimum permissions needed for each pipeline, and that analysis rarely happens.

  2. Privileged container mode enabled. Some pods were running in privileged mode, which gives containers full access to the host kernel. Container escape from a privileged pod is trivial - it's not even an exploit, it's just using the elevated permissions as designed. Privileged mode exists for legitimate use cases (system-level monitoring, hardware access), but it should never be enabled on pods that handle application workloads or that service accounts can reach.

  3. Static credentials in environment variables. The production database credentials were stored as environment variables in pod configurations. Once the attackers escaped the container, those credentials were immediately available. This is the exact anti-pattern that every secrets management guide warns against - including Google Cloud's own documentation.

  4. No segmentation between CI/CD and production databases. The stolen service account tokens eventually led to production database access. There was no network segmentation or additional authentication barrier between the CI/CD execution environment and the production data plane.

Each of these is a known problem with a known solution. Together, they created a path from "developer ran suspicious code" to "attackers have production database access."

The MFA Manipulation That Enabled the Heist

After gaining database access, UNC4899 didn't just exfiltrate data. They modified it. Specifically, they performed password resets and MFA seed updates for several high-value accounts directly through the database.

This is a critical detail because it highlights a gap in how most companies think about MFA. Your MFA controls might be robust at the application layer - phishing-resistant authentication, hardware keys, the works. But if an attacker can reach the database where those MFA configurations are stored and directly modify the records, the application-layer controls become irrelevant. They don't need to bypass your MFA. They rewrite it.

This attack pattern demands that MFA seed storage gets the same security treatment as credential storage:

  • MFA seeds should be encrypted at rest with keys managed outside the database
  • Direct database modifications to authentication-related tables should trigger alerts
  • MFA resets should require out-of-band verification, not just a database write
  • Authentication tables should have separate access controls from application data tables

What Your Organization Should Do

Immediate actions (this week)

Disable AirDrop on corporate devices. If you're using Jamf or another MDM, push a configuration profile that restricts AirDrop to "contacts only" or disables it entirely. If you're not using MDM, add this to the device hardening checklist for new employee machines.

Audit CI/CD service account permissions. List every service account used by your CI/CD platform. For each one, document what it can access. Apply least-privilege: build pipelines should not have access to production Kubernetes clusters. Deployment pipelines should not have access to modify other pipelines.

Check for privileged containers. Run kubectl get pods -o json | jq '.items[] | select(.spec.containers[].securityContext.privileged==true) | .metadata.name' across every cluster. If any application workload pods are running in privileged mode, fix it. Use Pod Security Standards to enforce this going forward.

Search for secrets in environment variables. Audit your Kubernetes deployments and CI/CD configurations for static credentials stored as environment variables. Migrate them to a proper secrets manager - Google Cloud Secret Manager, HashiCorp Vault, or whatever your stack supports.

Structural improvements (this quarter)

Implement network segmentation between CI/CD and production. Your build environment should not have a direct network path to your production database. Use separate VPCs, firewall rules, or service mesh policies to enforce this boundary.

Deploy runtime security monitoring for containers. Tools like Falco, Sysdig Secure, or Google Cloud's Container Threat Detection can alert on container escape attempts, unexpected process execution, and privilege escalation. The UNC4899 attackers used legitimate tools, but the sequence of actions - modifying deployments, dumping tokens to logs, accessing privileged pods - would generate detectable patterns.

Adopt workload identity over static service account keys. Google Cloud Workload Identity Federation, AWS IRSA, or Azure Workload Identity eliminate static service account tokens entirely. The workload proves its identity through the orchestration platform rather than presenting a long-lived credential. No token to steal means no token-based escalation.

Review database access controls for authentication tables. Separate the permissions required to read/write application data from the permissions required to modify authentication records. Implement database audit logging specifically for authentication-related tables.

For AI-assisted development environments

The UNC4899 attack involved malicious code execution through an AI-assisted IDE. This connects directly to the pattern I described in my ClawJacked analysis - AI development tools create new attack surface when they interact with untrusted code.

Sandbox AI code execution. If your IDE or AI coding assistant can execute code, ensure it runs in a sandboxed environment - a container, a VM, or at minimum a restricted user context - that doesn't have access to cloud credentials or production configurations.

Don't cache cloud credentials on developer machines. Use short-lived tokens through gcloud auth login with session duration limits rather than service account key files. If the developer machine is compromised, the attacker gets a session that expires, not a permanent credential.

Establish a policy for evaluating external code. Developers need a safe way to review code from external sources - potential collaborators, open-source contributions, security audit targets. Provide dedicated VMs or cloud workstations for this purpose, isolated from corporate credentials and cloud environments.

The Compliance Angle

If you're SOC 2 certified or pursuing certification, UNC4899 touches several Trust Service Criteria:

CC6.1 (Logical Access Controls): AirDrop as an uncontrolled data transfer mechanism is a gap in logical access controls. Your asset management inventory should include peer-to-peer transfer capabilities on managed devices.

CC6.6 (System Boundaries): The lack of segmentation between CI/CD environments and production databases is a system boundary failure. Auditors will want to see network diagrams that show clear separation between build and production environments.

CC7.1 (Vulnerability Management): Privileged container configurations and static credentials in environment variables are known vulnerability patterns. Your vulnerability management program should include infrastructure-as-code scanning that detects these patterns before deployment.

CC7.2 (Anomaly Detection): The attacker's Living-off-the-Cloud techniques used legitimate tools in abnormal sequences. Your monitoring should detect patterns like CI/CD pipeline modifications followed by service account token access followed by privileged pod access - even if each individual action is technically authorized.

For crypto and fintech companies specifically, this incident will likely appear in regulatory guidance. If you're subject to New York's BitLicense, the EU's MiCA framework, or similar regulations, expect increased scrutiny of cloud security controls and developer environment hardening.

The Bigger Picture

UNC4899 didn't use any zero-day exploits. They didn't compromise a cloud provider. They didn't defeat any cryptographic protections. They convinced a developer to run code, leveraged the gap between personal device convenience and enterprise security controls, and then methodically exploited a series of well-documented misconfigurations to reach the crown jewels.

Every step in this attack chain had a known countermeasure. MDM policies block AirDrop. Least-privilege service accounts limit blast radius. Pod security standards prevent privileged containers. Secrets managers eliminate static credentials. Network segmentation contains lateral movement. Runtime monitoring detects abnormal behavior.

The problem isn't that we don't know how to prevent these attacks. The problem is that implementing all these controls requires systematic effort, and most organizations prioritize shipping features over hardening infrastructure. UNC4899 is a reminder that state-sponsored attackers are patient, methodical, and very good at finding the gaps.

For crypto companies holding millions in digital assets, the calculus is straightforward: the cost of implementing proper cloud security is a rounding error compared to the cost of losing several million dollars in a single incident. For everyone else, the lesson is the same one it's always been - security is a chain, and attackers only need to find one weak link.


Keep reading:

Hardening your cloud infrastructure against state-sponsored threats? Let's talk.