Contagious Interview Fake-Recruiter and Front-Company Infrastructure
WindowsmacOSNetwork
TTP Hunt medium Contagious InterviewDeceptiveDevelopmentDPRK IT Worker Fraud
Catches the interview lure itself: a candidate's workstation cloning and running an unvetted take-home repository, and traffic toward the front companies DPRK operators register to look like employers.
What this hunt looks for
Operators tracked under the Contagious Interview and DeceptiveDevelopment clusters pose as recruiters on LinkedIn and job boards, sometimes standing up United States registered front companies before pushing a candidate to a coding-assessment repository that delivers BeaverTail and InvisibleFerret. Silent Push documented BlockNovas LLC, Angeloper Agency and SoftGlide LLC; the FBI seized the BlockNovas and SoftGlide domains in April 2025.
This hunt targets the moment a candidate's workstation clones and executes an unvetted take-home assignment repository, and traffic toward reported front-company infrastructure, so the lure can be caught before or during initial access rather than only after malware runs.
- Technique
- Initial access through social-engineering job-interview lures (MITRE ATT&CK T1566, T1204.002) fronted by DPRK-controlled shell companies and recruiter personas (Group G1052, Contagious Interview).
- Data sources
- EDR process telemetry, DNS or proxy logs
- Last updated
- 2026-10-04
Indicators
The atomic values this hunt matches on, listed separately from the queries so they can be lifted into tooling that speaks none of the query languages below. Every value here is reported by one of the sources cited at the foot of this page.
| Type | Value | Note |
|---|---|---|
| Domain | blocknovas.com |
BlockNovas front-company domain, with subdomains such as gitlab and apply, documented by Silent Push; seized by the FBI in April 2025. |
| Domain | apply-blocknovas.site |
Second BlockNovas application domain documented by Silent Push. |
| Domain | angeloper.com |
Angeloper Agency front-company domain documented by Silent Push. |
| Domain | angeloperonline.online |
Angeloper Agency domain documented by Silent Push. |
| Domain | softglide.co |
SoftGlide front-company domain documented by Silent Push; seized by the FBI in April 2025. |
Logic
Every query below implements these steps, so the same hunt returns the same result in each product.
- Collect: DNS lookups and web connections on Windows and macOS endpoints, plus process starts for the sequence
- Match: name is, or is a subdomain of, a reported front-company domain (BlockNovas, Angeloper, SoftGlide)
- Match: or git clone then node, npm, python or pip within 10 minutes (lower fidelity; KQL, SPL and Sigma only)
- Report: devices with the signals hit, newest first
Queries
Defender / Sentinel KQL
Written for this site, from indicators reported by Silent Push, Unit 42A device with a front-company domain hit is the strongest result; a clone-then-run hit alone needs recruiting context before escalating.
union
// optional: lower fidelity, git clone then a developer tool that names the cloned folder; delete this line and the branch below it
(DeviceProcessEvents
| where Timestamp > ago(1d) and FileName in~ ("node.exe", "node", "npm.cmd", "npm", "python.exe", "python", "python3", "pip.exe", "pip", "pip3")
| join kind=inner (
DeviceProcessEvents
| where Timestamp > ago(1d) and FileName in~ ("git.exe", "git") and ProcessCommandLine has "clone"
| extend RepoFolder = extract(@"([^/\\\s]+?)(?:\.git)?[\s""']*$", 1, ProcessCommandLine)
| where isnotempty(RepoFolder)
| project DeviceId, CloneTime = Timestamp, CloneCommand = ProcessCommandLine, RepoFolder
) on DeviceId
| where Timestamp between (CloneTime .. (CloneTime + 10m))
| where ProcessCommandLine has RepoFolder or InitiatingProcessCommandLine has RepoFolder or FolderPath has RepoFolder
| project Timestamp, DeviceId, DeviceName, Signal = "clone then run", Detail = strcat(CloneCommand, " -> ", ProcessCommandLine)),
(DeviceNetworkEvents
| where Timestamp > ago(30d)
| where RemoteUrl has_any ("blocknovas.com", "apply-blocknovas.site", "angeloper.com", "angeloperonline.online", "softglide.co")
| project Timestamp, DeviceId, DeviceName, Signal = "front-company domain", Detail = RemoteUrl)
| summarize Hits = count(), Signals = make_set(Signal), FirstSeen = min(Timestamp), LastSeen = max(Timestamp), Details = make_set(Detail, 5) by DeviceId, DeviceName
| order by array_length(Signals) desc, LastSeen desc
Lower-fidelity parts (2)
- the BlockNovas and SoftGlide domains — the FBI seized them in April 2025 and the infrastructure rotates, so they are of historical value and any entry may be stale. Remove: delete those entries from the has_any list
- the git clone then developer-tool sequence — legitimate technical interviews and ordinary developer work clone and run unfamiliar repositories. Remove: delete the // optional: comment line and the whole (DeviceProcessEvents ... ) branch beneath it, up to the line ending in Detail = strcat(...)),
Splunk SPL
Written for this site, from indicators reported by Silent Push, Unit 42The same two signals, with the domain branch over DNS data and the sequence branch over process starts joined to the cloned folder.
```Placeholders: Network_Resolution carries DNS lookups (for proxy data use the host your proxy extracts); Endpoint.Processes carries Windows and macOS process starts.```
| tstats count max(_time) AS _time FROM datamodel=Network_Resolution.DNS WHERE earliest=-30d DNS.query IN ("blocknovas.com","*.blocknovas.com","apply-blocknovas.site","*.apply-blocknovas.site","angeloper.com","*.angeloper.com","angeloperonline.online","*.angeloperonline.online","softglide.co","*.softglide.co") BY DNS.src, DNS.query
| rename DNS.src AS host, DNS.query AS detail
| eval signal="front-company domain"
```optional: lower fidelity, git clone then a developer tool that names the cloned folder; delete this line and the append block below it```
| append
[| tstats count FROM datamodel=Endpoint.Processes WHERE earliest=-1d ((Processes.process_name IN ("git","git.exe") AND Processes.process="*clone*") OR Processes.process_name IN ("node","node.exe","npm","npm.cmd","python","python3","python.exe","pip","pip3","pip.exe")) BY _time span=1s, Processes.dest, Processes.process_name, Processes.process
| rename Processes.* AS *
| sort 0 dest _time
| eval is_clone=if(match(process_name, "^git"), 1, 0)
| eval clone_time=if(is_clone=1, _time, null()), clone_cmd=if(is_clone=1, process, null())
| streamstats current=f last(clone_time) AS prev_clone_time last(clone_cmd) AS prev_clone_cmd BY dest
| where is_clone=0 AND _time-prev_clone_time<=600
| rex field=prev_clone_cmd "(?<repo>[^/\s]+?)(?:\.git)?\s*$"
| where like(process, "%".repo."%")
| eval host=dest, detail=prev_clone_cmd." -> ".process, signal="clone then run"
| fields _time, host, detail, signal]
| stats count AS hits min(_time) AS first_seen max(_time) AS last_seen values(signal) AS signals values(detail) AS details BY host
| convert ctime(first_seen) ctime(last_seen)
| sort - last_seen
Lower-fidelity parts (2)
- the BlockNovas and SoftGlide domains — the FBI seized them in April 2025 and the infrastructure rotates, so they are of historical value and any entry may be stale. Remove: delete those names and their *.name twins from the IN list
- the git clone then developer-tool sequence — legitimate technical interviews and ordinary developer work clone and run unfamiliar repositories. Remove: delete the optional comment line and the whole append block beneath it
Sigma
Written for this site, from indicators reported by Silent Push, Unit 42The domain rule applies to Windows and macOS DNS telemetry, and the correlation below the marker converts to a single-host temporal search.
title: DNS Lookup of a Contagious Interview Front-Company Domain
id: 5f0c2f0e-3c55-5a77-9a40-5d7c9d0e2b11
status: experimental
description: >
Detects lookups of the BlockNovas, Angeloper and SoftGlide front-company
domains documented by Silent Push, on Windows and macOS DNS telemetry.
references:
- https://www.silentpush.com/blog/contagious-interview-front-companies/
logsource:
category: dns_query
detection:
selection_exact:
QueryName:
- 'blocknovas.com'
- 'apply-blocknovas.site'
- 'angeloper.com'
- 'angeloperonline.online'
- 'softglide.co'
selection_sub:
QueryName|endswith:
- '.blocknovas.com'
- '.apply-blocknovas.site'
- '.angeloper.com'
- '.angeloperonline.online'
- '.softglide.co'
condition: 1 of selection_*
falsepositives:
- Researchers and defenders opening the reported domains
level: high
---
# optional: lower fidelity, git clone then a developer tool; delete this line and every document below it
title: Git Clone Executed on an Endpoint
name: dprk_git_clone
id: 0ab700d2-d8a1-5287-816c-7da7ac1ab319
description: >
A repository being cloned. Meaningless alone; it is the first half of the
correlation rule below.
references:
- https://www.silentpush.com/blog/contagious-interview-front-companies/
- https://unit42.paloaltonetworks.com/two-campaigns-by-north-korea-bad-actors-target-job-hunters/
logsource:
category: process_creation
detection:
clone:
Image|endswith:
- '\git.exe'
- '/git'
CommandLine|contains: 'clone'
condition: clone
---
title: Package Manager or Interpreter Executed on an Endpoint
name: dprk_dev_tooling_exec
id: 0d4e6d4d-8a59-5124-985b-e62b2082a482
description: >
A package manager or interpreter running. Meaningless alone; it is the second
half of the correlation rule below.
logsource:
category: process_creation
detection:
install:
Image|endswith:
- '\node.exe'
- '\npm.cmd'
- '\python.exe'
- '\pip.exe'
- '/node'
- '/npm'
- '/python3'
- '/pip3'
condition: install
---
title: Developer Tooling Executes a Freshly Cloned Repository During an Interview-Style Session
id: 61470ffb-d857-5d4e-a58b-aa9198d04911
status: experimental
description: >
Detects a git clone followed within ten minutes by a package manager or
interpreter on the same host, consistent with a candidate running a malicious
take-home assignment repository during a fake interview. A Sigma temporal
correlation does not enforce order or compare the cloned folder.
correlation:
type: temporal
rules:
- dprk_git_clone
- dprk_dev_tooling_exec
group-by:
- ComputerName
timespan: 10m
falsepositives:
- Legitimate technical interviews and normal developer workflows also clone
and run unfamiliar repositories
level: low
Lower-fidelity parts (2)
- the BlockNovas and SoftGlide domains — the FBI seized them in April 2025 and the infrastructure rotates, so they are of historical value and any entry may be stale. Remove: delete those names from both selection lists
- the git clone then developer-tool sequence — legitimate technical interviews and ordinary developer work clone and run unfamiliar repositories. Remove: delete the # optional: comment line and every document below it
CrowdStrike LogScale
Written for this site, from indicators reported by Silent Push, Unit 42The domain signal over Falcon DnsRequest events on Windows and macOS.
#event_simpleName=DnsRequest
| lower(DomainName, as=DomainName)
| regex("(?<parent>[^.]+\\.[^.]+)\\.?$", field=DomainName)
| in(parent, values=["blocknovas.com", "apply-blocknovas.site", "angeloper.com", "angeloperonline.online", "softglide.co"])
| groupBy([aid, ComputerName], function=[count(as=Lookups), min(@timestamp, as=FirstSeen), max(@timestamp, as=LastSeen), collect([DomainName])])
| sort(LastSeen, order=desc)
Lower-fidelity parts (1)
- the BlockNovas and SoftGlide domains — the FBI seized them in April 2025 and the infrastructure rotates, so they are of historical value and any entry may be stale. Remove: delete those names from the values list
Elastic
Written for this site, from indicators reported by Silent Push, Unit 42The domain signal over ECS DNS and network events.
FROM logs-*
| EVAL name = TO_LOWER(COALESCE(dns.question.name, destination.domain))
| WHERE name RLIKE "(.*\\.)?(blocknovas\\.com|apply-blocknovas\\.site|angeloper\\.com|angeloperonline\\.online|softglide\\.co)\\.?"
| STATS lookups = COUNT(*), names = VALUES(name), first_seen = MIN(@timestamp), last_seen = MAX(@timestamp) BY host.name
| SORT last_seen DESC
Lower-fidelity parts (1)
- the BlockNovas and SoftGlide domains — the FBI seized them in April 2025 and the infrastructure rotates, so they are of historical value and any entry may be stale. Remove: delete those names and their pipes from the RLIKE pattern
Cortex XQL
Written for this site, from indicators reported by Silent Push, Unit 42The domain signal over Cortex network events carrying a DNS name.
dataset = xdr_data
| filter event_type = ENUM.NETWORK and (dns_query_name != null or action_external_hostname != null)
| alter host = lowercase(coalesce(dns_query_name, action_external_hostname))
| alter parent = arrayindex(regextract(host, "([^.]+[.][^.]+)[.]?$"), 0)
| filter parent in ("blocknovas.com", "apply-blocknovas.site", "angeloper.com", "angeloperonline.online", "softglide.co")
| comp count() as lookups, values(host) as names, max(_time) as last_seen by agent_hostname
| sort desc last_seen
Lower-fidelity parts (1)
- the BlockNovas and SoftGlide domains — the FBI seized them in April 2025 and the infrastructure rotates, so they are of historical value and any entry may be stale. Remove: delete those names from the in list
False positives and tuning
Legitimate technical interviews routinely involve cloning a take-home repository and installing its dependencies, so on a developer's machine the sequence is normal. Correlate with recruiting context, contractor or bring-your-own-device status and domain reputation before escalating.
The domain match needs a current list of campaign domains, since this infrastructure rotates and the seized domains are of historical value only.
Sources
- Contagious Interview (DPRK) Launches a New Campaign Creating Three Front Companies to Deliver a Trio of Malware: BeaverTail, InvisibleFerret, and OtterCookie — Silent Push, 2025-04-24
- Hacking Employers and Seeking Employment: Two Job-Related Campaigns Bear Hallmarks of North Korean Threat Actors — Unit 42 (Palo Alto Networks), 2023-11-21
- Contagious Interview, DeceptiveDevelopment, Gwisin Gang, Tenacious Pungsan, DEV#POPPER, PurpleBravo, TAG-121, Group G1052 — The MITRE Corporation (MITRE ATT&CK), 2026-07-31