Company Source Code Pushed to Personal Repositories from an Employee Endpoint
WindowsmacOS
Behavioral Hunt low DPRK IT Worker Fraud
Git pushes, remote changes and mirror clones aimed at accounts outside the organisation on public hosting services: the precursor to the data-extortion the FBI now attributes to discovered DPRK IT workers.
What this hunt looks for
The FBI's January 2025 announcement records a change in what happens when a DPRK IT worker is caught. Alongside the fraud, workers have copied company code repositories such as GitHub to their own user profiles and, after termination, held the stolen code and proprietary data for ransom.
The copying leaves two kinds of evidence. Where the source-control audit log records clones and archive downloads, an employee pulling tens of repositories they have no work in, especially in their first weeks, stands out. On the endpoint, a git push, remote add or mirror clone whose target is an account outside the organisation is the act itself.
This hunt covers the endpoint side, which any EDR can see; the audit-log side needs the source-control audit stream and is read there. It complements the credential-notes hunt, which looks at what the same employee keeps rather than what they take.
- Technique
- Data from information repositories and code repositories (MITRE ATT&CK T1213.003), exfiltration to a code repository or web service (T1567.001, T1567) by a fraudulently hired insider (T1078), preceding financial extortion.
- Data sources
- EDR process telemetry
- Last updated
- 2026-10-04
Logic
Every query below implements these steps, so the same hunt returns the same result in each product.
- Collect: git process starts on Windows and macOS endpoints, last 30 days
- Match: command line is a remote add, remote set-url, clone --mirror or push
- Match: command line names a public hosting service (github.com, gitlab.com, bitbucket.org, gitee.com)
- Exclude: the organisation's own paths on those services (your-org placeholder)
- Report: each command with device, account, command line and parent, newest first
Queries
Defender / Sentinel KQL
Written for this sitegit commands that change a remote, mirror-clone or push to a public hosting service outside the organisation's own paths.
// Replace your-org with the organisation's own paths on the hosting services.
let OrgPaths = @"(?i)(github\.com|gitlab\.com|bitbucket\.org)[/:]your-org/";
DeviceProcessEvents
| where Timestamp > ago(30d)
| where FileName in~ ("git.exe", "git")
| where ProcessCommandLine matches regex @"(?i)(remote add|remote set-url|clone --mirror)"
// optional: every push to a public service, including legitimate open-source work
or ProcessCommandLine contains " push "
| where ProcessCommandLine matches regex @"(?i)(github\.com|gitlab\.com|bitbucket\.org|gitee\.com)"
| where not(ProcessCommandLine matches regex OrgPaths)
| project Timestamp, DeviceName, AccountName, ProcessCommandLine, InitiatingProcessFileName, InitiatingProcessCommandLine
| sort by Timestamp desc
Lower-fidelity parts (1)
- the push verb — it matches every push to a public hosting service, including ordinary open-source contributions, where remote add, remote set-url and clone --mirror are the stronger signs of a copy. Remove: Delete the line beginning // optional: and the or line after it.
Splunk SPL
Written for this sitegit commands that change a remote, mirror-clone or push to a public hosting service outside the organisation's own paths.
```sourcetype placeholders: index=endpoint with Sysmon or EDR process events (process_name, process, parent_process_name, host, user)```
```replace your-org with the organisation's own paths on the hosting services```
```optional: the OR match for push covers every push to a public service, including legitimate open-source work```
index=endpoint earliest=-30d process_name IN ("git.exe", "git")
| where match(process, "(?i)(remote add|remote set-url|clone --mirror)") OR match(process, "(?i) push ")
| where match(process, "(?i)(github\.com|gitlab\.com|bitbucket\.org|gitee\.com)")
| where NOT match(process, "(?i)(github\.com|gitlab\.com|bitbucket\.org)[/:]your-org/")
| table _time, host, user, process, parent_process_name
| sort 0 - _time
Lower-fidelity parts (1)
- the push verb — it matches every push to a public hosting service, including ordinary open-source contributions, where remote add, remote set-url and clone --mirror are the stronger signs of a copy. Remove: Delete OR match(process, "(?i) push ") from the first where line.
Sigma
Written for this siteA single git command that changes a remote, mirror-clones or pushes to a public hosting service outside the organisation's own paths.
title: Git Remote Change or Push Targeting a Public Hosting Service
id: 7c1f9d28-b4a3-4e60-85d7-0a3e6f12c9b5
status: experimental
description: >
Detects git adding or re-pointing a remote, mirror-cloning, or pushing to a
public code-hosting service from an employee endpoint on Windows or macOS.
Replace the your-org paths with the organisation's own paths on those
services; the residue is code leaving the company, which the FBI documents
as the precursor to extortion by DPRK IT workers.
references:
- https://www.ic3.gov/PSA/2025/PSA250123
logsource:
category: process_creation
detection:
selection_image:
Image|endswith:
- '\git.exe'
- '/git'
selection_verb:
CommandLine|contains:
- 'remote add'
- 'remote set-url'
- 'clone --mirror'
# optional: every push to a public service, including legitimate open-source work
selection_push:
CommandLine|contains: ' push '
selection_host:
CommandLine|contains:
- 'github.com'
- 'gitlab.com'
- 'bitbucket.org'
- 'gitee.com'
filter_org:
CommandLine|contains:
- 'github.com/your-org/'
- 'github.com:your-org/'
- 'gitlab.com/your-org/'
- 'gitlab.com:your-org/'
- 'bitbucket.org/your-org/'
- 'bitbucket.org:your-org/'
condition: selection_image and (selection_verb or selection_push) and selection_host and not filter_org
falsepositives:
- Developers contributing to open-source projects from a work machine
level: low
Lower-fidelity parts (1)
- the push verb — it matches every push to a public hosting service, including ordinary open-source contributions, where remote add, remote set-url and clone --mirror are the stronger signs of a copy. Remove: Delete the # optional: line and selection_push, and change the condition to selection_image and selection_verb and selection_host and not filter_org.
Elastic
Written for this sitegit commands that change a remote, mirror-clone or push to a public hosting service outside the organisation's own paths.
FROM logs-endpoint.events.process-*
| WHERE @timestamp > NOW() - 30 days AND event.action IN ("start", "exec") AND TO_LOWER(process.name) IN ("git.exe", "git")
| EVAL cmd = TO_LOWER(process.command_line)
| WHERE cmd RLIKE ".*(remote add|remote set-url|clone --mirror).*" OR cmd RLIKE ".* push .*"
| WHERE cmd RLIKE ".*(github\\.com|gitlab\\.com|bitbucket\\.org|gitee\\.com).*"
| WHERE NOT cmd RLIKE ".*(github\\.com|gitlab\\.com|bitbucket\\.org)[/:]your-org/.*"
| KEEP @timestamp, host.name, user.name, process.command_line, process.parent.name
| SORT @timestamp DESC
| LIMIT 200
Lower-fidelity parts (1)
- the push verb — it matches every push to a public hosting service, including ordinary open-source contributions, where remote add, remote set-url and clone --mirror are the stronger signs of a copy. Remove: Delete OR cmd RLIKE ".* push .*" from the third WHERE line.
CrowdStrike LogScale
Written for this sitegit commands that change a remote, mirror-clone or push to a public hosting service outside the organisation's own paths.
// Replace your-org with the organisation's own paths on the hosting services.
#event_simpleName=ProcessRollup2
| in(field=FileName, values=["git.exe", "git"], ignoreCase=true)
| CommandLine=/(remote add|remote set-url|clone --mirror)/i
// optional: every push to a public service, including legitimate open-source work
or CommandLine=/ push /i
| CommandLine=/(github\.com|gitlab\.com|bitbucket\.org|gitee\.com)/i
| not CommandLine=/(github\.com|gitlab\.com|bitbucket\.org)[:\/]your-org\//i
| table([@timestamp, ComputerName, UserName, CommandLine, ParentBaseFileName])
| sort(@timestamp, order=desc)
Lower-fidelity parts (1)
- the push verb — it matches every push to a public hosting service, including ordinary open-source contributions, where remote add, remote set-url and clone --mirror are the stronger signs of a copy. Remove: Delete the line beginning // optional: and the or line after it.
Cortex XQL
Written for this sitegit commands that change a remote, mirror-clone or push to a public hosting service outside the organisation's own paths.
// Replace your-org with the organisation's own paths on the hosting services.
dataset = xdr_data
| filter event_type = ENUM.PROCESS and lowercase(action_process_image_name) in ("git.exe", "git")
| filter action_process_image_command_line ~= "(?i)(remote add|remote set-url|clone --mirror)"
// optional: every push to a public service, including legitimate open-source work
or action_process_image_command_line ~= "(?i) push "
| filter action_process_image_command_line ~= "(?i)(github\.com|gitlab\.com|bitbucket\.org|gitee\.com)"
| filter not (action_process_image_command_line ~= "(?i)(github\.com|gitlab\.com|bitbucket\.org)[:/]your-org/")
| fields _time, agent_hostname, actor_effective_username, action_process_image_command_line, actor_process_image_name
| sort desc _time
Lower-fidelity parts (1)
- the push verb — it matches every push to a public hosting service, including ordinary open-source contributions, where remote add, remote set-url and clone --mirror are the stronger signs of a copy. Remove: Delete the line beginning // optional: and the or line after it.
False positives and tuning
Engineers contribute to open-source projects from work machines and mirror repositories for legitimate migrations, so a hit is not an alert on its own.
Replace the your-org placeholder with the organisation's own paths first, and exclude service accounts and CI runners.
The endpoint queries miss git run through an IDE that hides the remote URL and see nothing on a device without an agent, as contractor laptops often are.
Both are strongest as evidence gathered after another hunt has raised the question, and as the record to preserve before a termination conversation.
Sources
- North Korean IT Workers Conducting Data Extortion — FBI Internet Crime Complaint Center, 2025-01-23