Background
Since late 2025, Lazarus-linked DPRK operators have been routing command-and-control traffic through GitHub repositories and the pCloud cloud storage API. The technique is a variant of T1102.001 (Web Service: Dead Drop Resolver): the implant fetches an initial “dead-drop” from a GitHub gist or repository blob that contains the real C2 IP or domain encoded in a comment or README field, then pivots to communicate with actual infrastructure.
Because outbound HTTPS traffic to github.com, api.github.com, and api.pcloud.com passes through most enterprise proxy allowlists without inspection, network-level detection fires on zero sessions. Traditional perimeter controls are blind. The detection challenge moves entirely into behavioral telemetry on endpoints and cloud egress anomaly analysis.
Fortinet’s threat research team documented this pattern in April 2026 against South Korean targets, and it has since been observed in campaigns targeting financial and defense-adjacent supply chain firms.
How the Chain Works
- Initial access: Spearphish or trojanised npm/PyPI package delivers a first-stage loader
- Dead-drop resolution: Loader contacts a public GitHub gist or repository file (e.g.,
raw.githubusercontent.com/[victim-acct]/[repo]/main/config.md) and parses embedded C2 IP from HTML comment or Base64 blob - C2 establishment: Secondary implant beacons to the resolved IP via a custom binary protocol over HTTPS/443 or WebSocket
- Exfiltration: Data staged to
api.pcloud.comupload endpoints using a stolen or actor-controlled API key - Clean-up: Dead-drop gist is deleted post-delivery; the GitHub account often has a plausible history (star counts, prior commits) to appear legitimate
Sigma Rules
Rule 1 — Process Making Suspicious GitHub Raw Content Requests
title: Suspicious Process Fetching GitHub Raw Content
id: a3f17e82-2b44-4d91-8c59-f2b1e6a04dc3
status: experimental
description: Detects non-browser processes making HTTPS requests to raw.githubusercontent.com,
which is characteristic of dead-drop resolver C2 patterns used by DPRK-linked actors.
references:
- https://www.fortinet.com/blog/threat-research/dprk-related-campaigns-with-lnk-and-github-c2
author: SOC Analyst Hub
date: 2026-07-03
tags:
- attack.command_and_control
- attack.t1102.001
- attack.t1105
- detection.emerging_threat
logsource:
category: network_connection
product: windows
detection:
selection:
DestinationHostname|contains:
- 'raw.githubusercontent.com'
- 'gist.githubusercontent.com'
- 'api.github.com'
Initiated: 'true'
filter_legit_browsers:
Image|endswith:
- '\chrome.exe'
- '\msedge.exe'
- '\firefox.exe'
- '\safari.exe'
- '\opera.exe'
- '\brave.exe'
- '\iexplore.exe'
filter_legit_dev:
Image|endswith:
- '\git.exe'
- '\gh.exe'
- '\node.exe'
- '\Code.exe'
- '\devenv.exe'
- '\rider64.exe'
- '\idea64.exe'
filter_system:
Image|startswith:
- 'C:\Windows\System32\'
- 'C:\Windows\SysWOW64\'
Image|endswith:
- '\svchost.exe'
- '\MicrosoftEdgeUpdate.exe'
condition: selection and not filter_legit_browsers and not filter_legit_dev and not filter_system
falsepositives:
- Developer tools, CI/CD agents, package managers (pip, npm, cargo)
- Security tools pulling threat intel from GitHub
level: medium
Rule 2 — pCloud Upload by Non-User Process
title: Non-Interactive Process Uploading to pCloud API
id: b8c22d13-9e55-4b07-af3c-71d4e0ab7612
status: experimental
description: Detects processes connecting to pCloud upload API endpoints. Legitimate pCloud
usage is typically via the desktop client, not arbitrary executables. DPRK actors use
pCloud as an exfiltration staging platform.
references:
- https://www.fortinet.com/blog/threat-research/dprk-related-campaigns-with-lnk-and-github-c2
author: SOC Analyst Hub
date: 2026-07-03
tags:
- attack.exfiltration
- attack.t1567.002
- attack.command_and_control
- attack.t1102
logsource:
category: network_connection
product: windows
detection:
selection_host:
DestinationHostname|contains:
- 'api.pcloud.com'
- 'eapi.pcloud.com'
- 'binapi.pcloud.com'
selection_method:
DestinationPort: 443
filter_pcloud_client:
Image|endswith:
- '\pCloud.exe'
- '\pcloud.exe'
- '\PCLoud.exe'
condition: (selection_host and selection_method) and not filter_pcloud_client
falsepositives:
- Custom pCloud integrations and scripts with business justification
- Developer test environments
level: high
Rule 3 — Encoded Payload Parsed from Remote File Content
title: Script Process Fetching and Decoding Remote File Content
id: c1d48f96-5a11-4e22-b827-0f93cc8d1a4f
status: experimental
description: Detects PowerShell or script interpreters fetching content from known
cloud platforms and immediately invoking decoders (Base64, Inflate, XOR), consistent
with dead-drop resolver resolution.
author: SOC Analyst Hub
date: 2026-07-03
tags:
- attack.command_and_control
- attack.t1102.001
- attack.t1059.001
logsource:
category: process_creation
product: windows
detection:
selection_ps:
CommandLine|contains|all:
- 'githubusercontent.com'
- 'FromBase64String'
selection_iwr_decode:
CommandLine|contains|all:
- 'Invoke-WebRequest'
- 'githubusercontent.com'
CommandLine|contains:
- 'Decompress'
- 'MemoryStream'
- 'Load('
condition: selection_ps or selection_iwr_decode
falsepositives:
- Legitimate PowerShell deployment scripts fetching from GitHub
level: high
KQL (Microsoft Sentinel / Defender XDR)
Anomalous GitHub Connections by Untrusted Binaries
// Identify processes connecting to GitHub raw content endpoints that aren't expected tooling
let LegitProcesses = dynamic([
"chrome.exe", "msedge.exe", "firefox.exe", "git.exe", "gh.exe",
"node.exe", "Code.exe", "devenv.exe", "python.exe", "pip.exe",
"npm.exe", "cargo.exe", "curl.exe", "wget.exe"
]);
DeviceNetworkEvents
| where TimeGenerated > ago(7d)
| where RemoteUrl has_any("raw.githubusercontent.com", "gist.githubusercontent.com")
| extend ProcessName = tostring(split(InitiatingProcessFileName, "\\")[-1])
| where ProcessName !in~ (LegitProcesses)
| where InitiatingProcessFileName !startswith "C:\\Windows\\System32\\"
| summarize
ConnectionCount = count(),
RemoteUrls = make_set(RemoteUrl, 20),
FirstSeen = min(TimeGenerated),
LastSeen = max(TimeGenerated)
by DeviceName, InitiatingProcessFileName, ProcessName
| where ConnectionCount < 10 // Low volume typical of dead-drop resolver (one-time fetch)
| order by FirstSeen desc
pCloud Exfiltration Pattern
// Hunt for pCloud API connections from non-pCloud processes with data upload characteristics
DeviceNetworkEvents
| where TimeGenerated > ago(7d)
| where RemoteUrl has_any("api.pcloud.com", "eapi.pcloud.com", "binapi.pcloud.com")
| where InitiatingProcessFileName !endswith "pCloud.exe"
| project TimeGenerated, DeviceName, InitiatingProcessFileName,
InitiatingProcessCommandLine, RemoteUrl, RemotePort,
BytesSent, BytesReceived
| order by BytesSent desc
GitHub to pCloud Hop Sequence (Correlated)
// Detect the full dead-drop pattern: GitHub fetch followed by pCloud upload from same process
let GitHubFetches = DeviceNetworkEvents
| where TimeGenerated > ago(1d)
| where RemoteUrl has_any("raw.githubusercontent.com", "gist.githubusercontent.com")
| project TimeGenerated, DeviceName, ProcessId = InitiatingProcessId,
InitiatingProcessFileName, GitHubTime = TimeGenerated;
let pCloudUploads = DeviceNetworkEvents
| where TimeGenerated > ago(1d)
| where RemoteUrl has "pcloud.com"
| where BytesSent > 10000
| project DeviceName, ProcessId = InitiatingProcessId,
pCloudTime = TimeGenerated, BytesSent;
GitHubFetches
| join kind=inner pCloudUploads
on DeviceName, ProcessId
| where pCloudTime > GitHubTime
| where (pCloudTime - GitHubTime) < 1h
| project DeviceName, InitiatingProcessFileName, GitHubTime, pCloudTime, BytesSent
| order by GitHubTime desc
Hunting Guidance
Network Proxy / DNS Telemetry
Query your DNS or web proxy logs for raw.githubusercontent.com requests, then filter by the process or user agent making the request. Legitimate CI/CD tooling and developer environments will create background noise; focus on:
- Requests from endpoints that are not developer workstations (servers, KIOSK machines, OT jump hosts)
- First-time connections to specific gist URLs (a raw gist URL is functionally unique)
- Short session duration with small response body (typical of config blob retrieval)
Threat Intelligence Enrichment
Cross-reference GitHub usernames in observed raw.githubusercontent.com paths against:
- VirusTotal URL analysis for the specific path
- GitHub account creation date (actor accounts often < 30 days old)
- Number of repositories and star count (legitimacy proxies)
False Positive Reduction
The biggest source of FPs is legitimate DevOps automation. Create a suppression list of known CI/CD service accounts and their expected GitHub org namespaces. Anything accessing content from personal accounts (github.com/<username>/ patterns) deserves scrutiny even from otherwise-allowed processes.
MITRE ATT&CK Mapping
| Technique | ID | Notes |
|---|---|---|
| Web Service: Dead Drop Resolver | T1102.001 | GitHub gist/repo used for IP resolution |
| Exfiltration to Cloud Storage | T1567.002 | pCloud as staging platform |
| Command and Control via Web Service | T1102 | Primary C2 channel |
| Ingress Tool Transfer | T1105 | Secondary payload fetch post-resolution |
| Obfuscated Files or Information | T1027 | Base64 encoded C2 config in README |