---
title: "Tenacious Pungsan: A DPRK threat actor linked to Contagious Interview"
description: "Analysis of three npm packages containing malware linked to Democratic People's Republic of Korea and Contagious Interview"
author: "Ian Kretz, Sebastian Obregoso, Datadog"
date: 2024-10-24
category: "emerging threats and vulnerabilities"
tags: ["software supply-chain security", "threat research"]
url: "https://securitylabs.datadoghq.com/articles/tenacious-pungsan-dprk-threat-actor-contagious-interview/"
---

## Key points and observations

- In September 2024, Datadog Security Research discovered three malicious npm packages: `passports-js`, `bcrypts-js`, and `blockscan-api`.  
- These packages had a combined 323 downloads and contained samples of [BeaverTail](https://unit42.paloaltonetworks.com/two-campaigns-by-north-korea-bad-actors-target-job-hunters/) malware, a family of JavaScript infostealers and downloaders used by threat actors associated with Democratic People’s Republic of Korea (DPRK, also referred to as North Korea).  
- [Reporting from Palo Alto Networks Unit 42](https://unit42.paloaltonetworks.com/north-korean-threat-actors-lure-tech-job-seekers-as-fake-recruiters/) has associated BeaverTail with an ongoing campaign named Contagious Interview, which targets job-seekers in the US tech industry. Victims are encouraged to participate in a fictitious job interview, during which the BeaverTail malware is delivered as part of an interview task.  
- Datadog Security Research has linked the samples presented in this blog to Contagious Interview and attributes them to a single threat actor which we designate “Tenacious Pungsan.” (We align nation-state threat actor clusters with their national breeds, and the Pungsan is a dog native to North Korea.)

## Background

In recent years, the open source software supply chain has become a focus of increasing concern as an effective attack vector for malicious actors to compromise downstream targets. Attackers may seek to compromise existing, often broadly used packages, or they may publish new packages containing malicious code. Attacks of this second kind usually involve some form of namesquatting, in which the name of the malicious package is very similar to a targeted legitimate package in hopes that developers will confuse the former for the latter. We have observed significant attacks of [both](https://securitylabs.datadoghq.com/articles/stressed-pungsan-dprk-aligned-threat-actor-leverages-npm-for-initial-access.md) [kinds](https://securitylabs.datadoghq.com/articles/xz-backdoor-cve-2024-3094.md) in 2024 alone.

Datadog Security Research continuously monitors both npm and PyPI for new and ongoing software supply chain attacks. We do so using [GuardDog](https://securitylabs.datadoghq.com/articles/guarddog-2-0-release.md), a command-line scanner for identifying malicious open source packages via code behaviors and package metadata. With the assistance of GuardDog, we have cataloged more than 1,700 (and counting) malicious PyPI and npm packages over the past two years, which we publish in a [public dataset](https://github.com/DataDog/malicious-software-packages-dataset).

## The timeline

On September 11, 2024, versions 0.7.0 and 0.7.1 of the npm package `passports-js` were automatically flagged for manual triage by a security researcher as part of our continuous monitoring of npm. GuardDog’s scans reported that both versions of `passports-js` contained the same very long line of obfuscated JavaScript code in an otherwise unobfuscated source file, giving cause for suspicion.

Code obfuscation is the practice of obscuring the text or behaviors of a unit of code so that they are difficult for humans or automated analyzers to discern. Naturally, it is a routinely deployed tactic in open source malware. Common forms of obfuscation include using random identifiers instead of meaningful ones, removing code formatting, adding useless operations to complicate the code’s structure, and concealing code behind nonstandard text encodings or encryption. The obfuscated line found in `passports-js`, shown in the following image, uses all but the last of these techniques.

![Obfuscated code in passports-js](https://securitylabs.dd-static.net/img/tenacious-pungsan-dprk-threat-actor-contagious-interview/passports-obfuscated.png?auto=format)
*Obfuscated JavaScript found in an otherwise obfuscated passports-js source file (click to enlarge)*

After closer investigation, we found that the `passports-js` package was in fact a backdoored copy of `passport`, a legitimate npm package providing a highly popular authentication framework for Express applications. The additional obfuscated line appeared to be the only difference between the two packages. Given this, it would appear that the uploader of `passports-js` was using a namesquatting attack to target would-be `passport` users who misremembered the latter’s name.

![The npm page for passports-js](https://securitylabs.dd-static.net/img/tenacious-pungsan-dprk-threat-actor-contagious-interview/passports-npm.png?auto=format)
*The npm page for passports-js (click to enlarge)*

At the time of this discovery, the uploading user, `superdev727`, had published only one other package to npm: `bcrypts-js`. We determined that `bcrypts-js` was also namesquatting another legitimate npm package, `bcryptjs`, a bcrypt library with 2.1M weekly average downloads at time of writing.

![The npm page for bcrypts-js](https://securitylabs.dd-static.net/img/tenacious-pungsan-dprk-threat-actor-contagious-interview/bcrypts-npm.png?auto=format)
*The npm page for bcrypts-js (click to enlarge)*

As with `passports-js` and `passport`, the only difference between `bcrypts-js` and `bcryptjs` appeared to be a long, obfuscated line inserted into an unobfuscated source file. We found the obfuscated lines from `passports-js` and `bcrypts-js` to be identical.

As the final entry in this saga, two days later, on September 13, 2024, GuardDog flagged version 1.3.1 of the package `blockscan-api` for review with similar findings. This time, the single obfuscated line was contained in its own source file instead of being wedged in among unobfuscated code.

![Obfuscated code in blockscan-api](https://securitylabs.dd-static.net/img/tenacious-pungsan-dprk-threat-actor-contagious-interview/blockscan-obfuscated.png?auto=format)
*Obfuscated JavaScript found in a standalone blockscan-api source file (click to enlarge)*

We found that `blockscan-api`, like `passports-js` and `bcrypts-js`, is a backdoored copy of another package, `etherscan-api`, which provides an interface to the Etherscan API. The obfuscated line found in `blockscan-api` differed from that in the other two packages. However, we were able to confirm that the two samples are highly similar after deobfuscation, though not without some interesting differences that we describe below.

It is worth noting that `blockscan-api` was published to npm by a different user account, `intelliman`, and also appears to be primarily targeting blockchain developers. At time of discovery, the `intelliman` account had no other published packages.

![The npm page for blockscan-api](https://securitylabs.dd-static.net/img/tenacious-pungsan-dprk-threat-actor-contagious-interview/blockscan-npm.png?auto=format)
*The npm page for blockscan-api (click to enlarge)*

The `passports-js` and `bcrypts-js` packages and the `superdev727` account were removed from npm just after 11pm UTC on September 11, around 12 hours after our initial discovery. Meanwhile, `blockscan-api` and the `intelliman` account remained live for nearly a month, being removed on October 9, 2024 after our report on October 3\. GitHub Security Advisories have been released for [all](https://github.com/advisories/GHSA-q99j-q5f8-qcc8) [three](https://github.com/advisories/GHSA-h6cw-hrwc-f4wm) [packages](https://github.com/advisories/GHSA-xvv2-hxxf-4phq). Over their respective lifetimes, `passports-js` was downloaded 118 times, `bcrypts-js` 81 times, and `blockscan-api` at least 124 times, for a total of 323 downloads.

## Obfuscated BeaverTail malware

In the npm ecosystem, use of a particular JavaScript obfuscator (available [here](https://obfuscator.io/)) is surprisingly common, even among totally benign packages. We found that the two malware samples discovered in `passports-js`/`bcrypts-js` and `blockscan-api` were obfuscated using this common obfuscator. This particular kind of obfuscation can be partially undone easily using [free automated tools](https://obf-io.deobfuscate.io/), allowing us to statically analyze both recovered samples.

What we found was that both obfuscated samples conceal a recent variant of a malware family known as BeaverTail. [First identified in late 2023](https://unit42.paloaltonetworks.com/two-campaigns-by-north-korea-bad-actors-target-job-hunters/) by researchers at Palo Alto Networks Unit 42, BeaverTail is a JavaScript infostealer and downloader malware prominently used by threat actors connected to the DPRK, in particular as part of the Contagious Interview campaign that targeted developer job applicants.

BeaverTail targets cryptocurrency wallets as well as credit card information stored in browser caches and login keychains on Unix and Windows systems. It then exfiltrates those data to attacker-controlled C2 servers. As [described](https://unit42.paloaltonetworks.com/two-campaigns-by-north-korea-bad-actors-target-job-hunters/) in detail by Unit 42, it also contains logic to download and persistently run a second-stage Python backdoor known as InvisibleFerret from these servers. We observe all characteristic behaviors of BeaverTail in both deobfuscated samples, illustrated via the following images.

![BeaverTail samples comparison](https://securitylabs.dd-static.net/img/tenacious-pungsan-dprk-threat-actor-contagious-interview/beavertail-browsers.png?auto=format)
*Side-by-side comparison of the passports-js/bcrypts-js and blockscan-api BeaverTail samples showing hardcoded paths for Brave, Google Chrome, and Opera data directories and services as well as IDs for several cryptocurrency wallet browser extensions (click to enlarge)*

![BeaverTail samples comparison](https://securitylabs.dd-static.net/img/tenacious-pungsan-dprk-threat-actor-contagious-interview/beavertail-keychain.png?auto=format)
*Side-by-side comparison of the passports-js/bcrypts-js and blockscan-api BeaverTail samples showing exfiltration of data from the Login Keychain (click to enlarge)*

![BeaverTail samples comparison](https://securitylabs.dd-static.net/img/tenacious-pungsan-dprk-threat-actor-contagious-interview/beavertail-brave.png?auto=format)
*Side-by-side comparison of the passports-js/bcrypts-js and blockscan-api BeaverTail samples exfiltration of data from Brave browser caches (click to enlarge)*

There are some interesting differences between the two BeaverTail variants. Most notably, they appear to be associated with different threat actor–specified campaign IDs. These IDs are discernable in the URLs shown in the following side-by-side comparison, both of which have the form `http://<C2 server>:1224/client/3/<campaign ID>`. In particular, this is the URL from which BeaverTail sources the first stage of InvisibleFerret to run on the victim's system.

![BeaverTail samples comparison](https://securitylabs.dd-static.net/img/tenacious-pungsan-dprk-threat-actor-contagious-interview/beavertail-campaigns.png?auto=format)
*Side-by-side comparison of the passports-js/bcrypts-js and blockscan-api BeaverTail samples showing the presence of different campaign IDs (click to enlarge)*

As seen here, the `passports-js`/`bcrypts-js` sample (left) uses campaign ID `726` while the `blockscan-api` sample uses ID `525`. This raises the possibility that different InvisibleFerret variants are being used, with each matched to particular targeted groups.

The campaign ID `525` was [recently observed](https://stacklok.com/blog/dependency-hijacking-dissecting-north-koreas-new-wave-of-defi-themed-open-source-attacks-targeting-developers) by Stacklok in a new wave of a Contagious Interview–like campaigns targeting blockchain-related developer job applicants. However, it appears that `726` is a previously unseen campaign ID from this threat actor, indicating the possibility of a new effort to target new segments of Node.js developers.

There may also be a certain amount of refactoring that differentiates the two BeaverTail samples, with two functions in the `passports-js`/`bcrypts-js` sample being slightly more structured than their analogues in the `blockscan-api` sample. These code segments deal with debugging and Firefox data collection, with side-by-side comparisons in the images that follow. It should be noted that these differences may simply be deobfuscation artifacts.

![BeaverTail samples comparison](https://securitylabs.dd-static.net/img/tenacious-pungsan-dprk-threat-actor-contagious-interview/beavertail-refactoring-1.png?auto=format)
*Side-by-side comparison of the passports-js/bcrypts-js and blockscan-api BeaverTail samples showing differences possibly due to refactoring (click to enlarge)*

![BeaverTail samples comparison](https://securitylabs.dd-static.net/img/tenacious-pungsan-dprk-threat-actor-contagious-interview/beavertail-refactoring-2.png?auto=format)
*Side-by-side comparison of the passports-js/bcrypts-js and blockscan-api BeaverTail samples showing differences possibly due to refactoring (click to enlarge)*

As for the second-stage InvisibleFerret payloads, we were unable to obtain either sample before the C2 infrastructure was taken down.

## Links to Contagious Interview

The samples of BeaverTail contained in these packages have several tactics, techniques, and procedures (TTPs) that overlap with those described in public reporting of the Contagious Interview campaign. We have already noted similarities in the distribution method (hosting on npm) and obfuscation of the samples themselves. However, there are some additional observations that allow us to link this activity to Contagious Interview.

Tenacious Pungsan tend to reuse infrastructure for their campaigns. The BeaverTail samples described in this blog all communicate with a web server hosted at the IP address `95.164.17[.]24` on port 1224\. In October 2024, this IP was linked to Contagious Interview in a [blog](https://unit42.paloaltonetworks.com/north-korean-threat-actors-lure-tech-job-seekers-as-fake-recruiters/) that described a new, Qt GUI variant of BeaverTail. Prior to October 2024, [two](https://www.group-ib.com/blog/apt-lazarus-python-scripts/) [other](https://blog.phylum.io/north-korea-still-attacking-developers-via-npm/) vendors had linked this IP to DPRK activities.

In addition to the IP address, Tenacious Pungsan also reuse the same web directory structure for their C2 server. Exfiltrated files are sent to the URL endpoint `/uploads`, the Python installation is hosted at `/pdown`, and InvisibleFerret is hosted at `/client/<integer>/<3 digit campaign ID>`. This is consistent with the reports linked above.

The infostealer component of BeaverTail targets a specific set of browser extensions associated with cryptocurrency and web3 technologies. This list is consistent across our BeaverTail samples, the Qt GUI variant Unit42 reported on, and the original nodeJS variant also covered by Unit42. Similarly, these samples all attempt to extract the macOS Login Keychain.

The above points allow us to assess with high confidence that these samples are indeed BeaverTail and are being distributed as part of the Contagious Interview campaign.

## How Datadog can help

Datadog [Software Composition Analysis (SCA)](https://www.datadoghq.com/blog/datadog-software-composition-analysis/) customers can verify whether any of these packages are currently installed in their infrastructure by running [this query](https://app.datadoghq.com/security/appsec/vm/library-risk?query=library_name%3A%28passports-js%20OR%20bcrypts-js%20OR%20blockscan-api%29%20status%3AOpen) in the Library Risks explorer: `library_name:(passports-js OR bcrypts-js OR blockscan-api) Status:Open`. If your system is impacted, it is important to take immediate measures such as rotating credentials, isolating the application, and investigating potential spread.

![SCA finding](https://securitylabs.dd-static.net/img/tenacious-pungsan-dprk-threat-actor-contagious-interview/sca-finding.png?auto=format)
*Datadog SCA identifying a malicious dependency (click to enlarge)*

In order to enable further research, we have published all affected versions of `passports-js`, `bcrypts-js,` and `blockscan-api` to our public [malicious package dataset](https://github.com/DataDog/malicious-software-packages-dataset).

## Conclusion

Copying and backdooring legitimate npm packages [continues](https://securitylabs.datadoghq.com/articles/stressed-pungsan-dprk-aligned-threat-actor-leverages-npm-for-initial-access.md) to be a common tactic of threat actors in this ecosystem. These campaigns, along with Contagious Interview more broadly, highlight that individual developers remain valuable targets for these DPRK-linked threat actors.

## Indicators of compromise

| Package                                                                                                                                            | Purpose         |
| -------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- |
| [passports-js-v0.7.0.zip](https://github.com/DataDog/malicious-software-packages-dataset/blob/main/samples/npm/passports-js/0.7.0/2024-09-09-passports-js-v0.7.0.zip)   | Initial payload |
| [passports-js-v0.7.1.zip](https://github.com/DataDog/malicious-software-packages-dataset/blob/main/samples/npm/passports-js/0.7.1/2024-09-10-passports-js-v0.7.1.zip)   | Initial payload |
| [bcrypts-js-v2.4.4.zip](https://github.com/DataDog/malicious-software-packages-dataset/blob/main/samples/npm/bcrypts-js/2.4.4/2024-09-11-bcrypts-js-v2.4.4.zip) | Initial payload |
| [blockscan-api-v1.3.1.zip](https://github.com/DataDog/malicious-software-packages-dataset/blob/main/samples/npm/blockscan-api/1.3.1/2024-09-13-blockscan-api-v1.3.1.zip) | Initial payload |

|  **IP addresses**  |          **Purpose**          |         **Note**         |
| :----------------: | :---------------------------: | :-----------------------:|
| ` 95.164.17[.]24` | Data exfiltration, InvisibleFerret download | Reused from previous campaign [documented by Unit42](https://unit42.paloaltonetworks.com/north-korean-threat-actors-lure-tech-job-seekers-as-fake-recruiters/) |

|  **NPM authors** |    **Email**    |  **Packages published** |
|:----------------:|:---------------:|:------------------------:|
| `superdev727`    | `austin27ahn@outlook.com` | `passports-js`, `bcrypts-js` |
| `intelliman`     | `g65492036@gmail.com` | `blockscan-api`|
