{
	"id": "595ef6ba-bce6-4478-90dd-b1827235798c",
	"created_at": "2026-04-06T00:19:40.108769Z",
	"updated_at": "2026-04-10T13:12:54.763057Z",
	"deleted_at": null,
	"sha1_hash": "c0ae5c1a3573d3ee764bd1247a6ac729d1589c25",
	"title": "Tenacious Pungsan: A DPRK threat actor linked to Contagious Interview | Datadog Security Labs",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 5198347,
	"plain_text": "Tenacious Pungsan: A DPRK threat actor linked to Contagious\r\nInterview | Datadog Security Labs\r\nBy Ian Kretz, Sebastian Obregoso, Datadog Security Research Team\r\nPublished: 2024-10-24 · Archived: 2026-04-05 14:54:15 UTC\r\nKey points and observations\r\nIn September 2024, Datadog Security Research discovered three malicious npm packages: passports-js ,\r\nbcrypts-js , and blockscan-api .\r\nThese packages had a combined 323 downloads and contained samples of BeaverTail malware, a family of\r\nJavaScript infostealers and downloaders used by threat actors associated with Democratic People’s\r\nRepublic of Korea (DPRK, also referred to as North Korea).\r\nReporting from Palo Alto Networks Unit 42 has associated BeaverTail with an ongoing campaign named\r\nContagious Interview, which targets job-seekers in the US tech industry. Victims are encouraged to\r\nparticipate in a fictitious job interview, during which the BeaverTail malware is delivered as part of an\r\ninterview task.\r\nDatadog Security Research has linked the samples presented in this blog to Contagious Interview and\r\nattributes them to a single threat actor which we designate “Tenacious Pungsan.” (We align nation-state\r\nthreat actor clusters with their national breeds, and the Pungsan is a dog native to North Korea.)\r\nBackground\r\nIn recent years, the open source software supply chain has become a focus of increasing concern as an effective\r\nattack vector for malicious actors to compromise downstream targets. Attackers may seek to compromise existing,\r\noften broadly used packages, or they may publish new packages containing malicious code. Attacks of this second\r\nkind usually involve some form of namesquatting, in which the name of the malicious package is very similar to a\r\ntargeted legitimate package in hopes that developers will confuse the former for the latter. We have observed\r\nsignificant attacks of both kinds in 2024 alone.\r\nDatadog Security Research continuously monitors both npm and PyPI for new and ongoing software supply chain\r\nattacks. We do so using GuardDog, a command-line scanner for identifying malicious open source packages via\r\ncode behaviors and package metadata. With the assistance of GuardDog, we have cataloged more than 1,700 (and\r\ncounting) malicious PyPI and npm packages over the past two years, which we publish in a public dataset.\r\nThe timeline\r\nOn September 11, 2024, versions 0.7.0 and 0.7.1 of the npm package passports-js were automatically flagged\r\nfor manual triage by a security researcher as part of our continuous monitoring of npm. GuardDog’s scans\r\nreported that both versions of passports-js contained the same very long line of obfuscated JavaScript code in\r\nan otherwise unobfuscated source file, giving cause for suspicion.\r\nhttps://securitylabs.datadoghq.com/articles/tenacious-pungsan-dprk-threat-actor-contagious-interview/\r\nPage 1 of 12\n\nCode obfuscation is the practice of obscuring the text or behaviors of a unit of code so that they are difficult for\r\nhumans or automated analyzers to discern. Naturally, it is a routinely deployed tactic in open source malware.\r\nCommon forms of obfuscation include using random identifiers instead of meaningful ones, removing code\r\nformatting, adding useless operations to complicate the code’s structure, and concealing code behind nonstandard\r\ntext encodings or encryption. The obfuscated line found in passports-js , shown in the following image, uses all\r\nbut the last of these techniques.\r\nObfuscated JavaScript found in an otherwise obfuscated passports-js source file (click to enlarge)\r\nAfter closer investigation, we found that the passports-js package was in fact a backdoored copy of\r\npassport , a legitimate npm package providing a highly popular authentication framework for Express\r\napplications. The additional obfuscated line appeared to be the only difference between the two packages. Given\r\nthis, it would appear that the uploader of passports-js was using a namesquatting attack to target would-be\r\npassport users who misremembered the latter’s name.\r\nhttps://securitylabs.datadoghq.com/articles/tenacious-pungsan-dprk-threat-actor-contagious-interview/\r\nPage 2 of 12\n\nThe npm page for passports-js (click to enlarge)\r\nAt the time of this discovery, the uploading user, superdev727 , had published only one other package to npm:\r\nbcrypts-js . We determined that bcrypts-js was also namesquatting another legitimate npm package,\r\nbcryptjs , a bcrypt library with 2.1M weekly average downloads at time of writing.\r\nhttps://securitylabs.datadoghq.com/articles/tenacious-pungsan-dprk-threat-actor-contagious-interview/\r\nPage 3 of 12\n\nThe npm page for bcrypts-js (click to enlarge)\r\nAs with passports-js and passport , the only difference between bcrypts-js and bcryptjs appeared to be\r\na long, obfuscated line inserted into an unobfuscated source file. We found the obfuscated lines from passports-js and bcrypts-js to be identical.\r\nAs the final entry in this saga, two days later, on September 13, 2024, GuardDog flagged version 1.3.1 of the\r\npackage blockscan-api for review with similar findings. This time, the single obfuscated line was contained in\r\nits own source file instead of being wedged in among unobfuscated code.\r\nhttps://securitylabs.datadoghq.com/articles/tenacious-pungsan-dprk-threat-actor-contagious-interview/\r\nPage 4 of 12\n\nObfuscated JavaScript found in a standalone blockscan-api source file (click to enlarge)\r\nWe found that blockscan-api , like passports-js and bcrypts-js , is a backdoored copy of another package,\r\netherscan-api , which provides an interface to the Etherscan API. The obfuscated line found in blockscan-api\r\ndiffered from that in the other two packages. However, we were able to confirm that the two samples are highly\r\nsimilar after deobfuscation, though not without some interesting differences that we describe below.\r\nIt is worth noting that blockscan-api was published to npm by a different user account, intelliman , and also\r\nappears to be primarily targeting blockchain developers. At time of discovery, the intelliman account had no\r\nother published packages.\r\nhttps://securitylabs.datadoghq.com/articles/tenacious-pungsan-dprk-threat-actor-contagious-interview/\r\nPage 5 of 12\n\nThe npm page for blockscan-api (click to enlarge)\r\nThe passports-js and bcrypts-js packages and the superdev727 account were removed from npm just after\r\n11pm UTC on September 11, around 12 hours after our initial discovery. Meanwhile, blockscan-api and the\r\nintelliman account remained live for nearly a month, being removed on October 9, 2024 after our report on\r\nOctober 3. GitHub Security Advisories have been released for all three packages. Over their respective lifetimes,\r\npassports-js was downloaded 118 times, bcrypts-js 81 times, and blockscan-api at least 124 times, for a\r\ntotal of 323 downloads.\r\nObfuscated BeaverTail malware\r\nIn the npm ecosystem, use of a particular JavaScript obfuscator (available here) is surprisingly common, even\r\namong 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\r\nbe partially undone easily using free automated tools, allowing us to statically analyze both recovered samples.\r\nWhat we found was that both obfuscated samples conceal a recent variant of a malware family known as\r\nBeaverTail. First identified in late 2023 by researchers at Palo Alto Networks Unit 42, BeaverTail is a JavaScript\r\ninfostealer and downloader malware prominently used by threat actors connected to the DPRK, in particular as\r\npart of the Contagious Interview campaign that targeted developer job applicants.\r\nBeaverTail targets cryptocurrency wallets as well as credit card information stored in browser caches and login\r\nkeychains on Unix and Windows systems. It then exfiltrates those data to attacker-controlled C2 servers. As\r\ndescribed in detail by Unit 42, it also contains logic to download and persistently run a second-stage Python\r\nbackdoor known as InvisibleFerret from these servers. We observe all characteristic behaviors of BeaverTail in\r\nboth deobfuscated samples, illustrated via the following images.\r\nhttps://securitylabs.datadoghq.com/articles/tenacious-pungsan-dprk-threat-actor-contagious-interview/\r\nPage 6 of 12\n\nSide-by-side comparison of the passports-js/bcrypts-js and blockscan-api BeaverTail samples\r\nshowing hardcoded paths for Brave, Google Chrome, and Opera data directories and services as\r\nwell as IDs for several cryptocurrency wallet browser extensions (click to enlarge)\r\nSide-by-side comparison of the passports-js/bcrypts-js and blockscan-api BeaverTail samples\r\nshowing exfiltration of data from the Login Keychain (click to enlarge)\r\nhttps://securitylabs.datadoghq.com/articles/tenacious-pungsan-dprk-threat-actor-contagious-interview/\r\nPage 7 of 12\n\nSide-by-side comparison of the passports-js/bcrypts-js and blockscan-api BeaverTail samples\r\nexfiltration of data from Brave browser caches (click to enlarge)\r\nThere are some interesting differences between the two BeaverTail variants. Most notably, they appear to be\r\nassociated with different threat actor–specified campaign IDs. These IDs are discernable in the URLs shown in the\r\nfollowing side-by-side comparison, both of which have the form http://\u003cC2 server\u003e:1224/client/3/\u003ccampaign\r\nID\u003e . In particular, this is the URL from which BeaverTail sources the first stage of InvisibleFerret to run on the\r\nvictim's system.\r\nSide-by-side comparison of the passports-js/bcrypts-js and blockscan-api BeaverTail samples\r\nshowing the presence of different campaign IDs (click to enlarge)\r\nAs seen here, the passports-js / bcrypts-js sample (left) uses campaign ID 726 while the blockscan-api\r\nsample uses ID 525 . This raises the possibility that different InvisibleFerret variants are being used, with each\r\nmatched to particular targeted groups.\r\nThe campaign ID 525 was recently observed by Stacklok in a new wave of a Contagious Interview–like\r\ncampaigns targeting blockchain-related developer job applicants. However, it appears that 726 is a previously\r\nhttps://securitylabs.datadoghq.com/articles/tenacious-pungsan-dprk-threat-actor-contagious-interview/\r\nPage 8 of 12\n\nunseen campaign ID from this threat actor, indicating the possibility of a new effort to target new segments of\r\nNode.js developers.\r\nThere may also be a certain amount of refactoring that differentiates the two BeaverTail samples, with two\r\nfunctions in the passports-js / bcrypts-js sample being slightly more structured than their analogues in the\r\nblockscan-api sample. These code segments deal with debugging and Firefox data collection, with side-by-side\r\ncomparisons in the images that follow. It should be noted that these differences may simply be deobfuscation\r\nartifacts.\r\nSide-by-side comparison of the passports-js/bcrypts-js and blockscan-api BeaverTail samples\r\nshowing differences possibly due to refactoring (click to enlarge)\r\nSide-by-side comparison of the passports-js/bcrypts-js and blockscan-api BeaverTail samples\r\nshowing differences possibly due to refactoring (click to enlarge)\r\nAs for the second-stage InvisibleFerret payloads, we were unable to obtain either sample before the C2\r\ninfrastructure was taken down.\r\nhttps://securitylabs.datadoghq.com/articles/tenacious-pungsan-dprk-threat-actor-contagious-interview/\r\nPage 9 of 12\n\nLinks to Contagious Interview\r\nThe samples of BeaverTail contained in these packages have several tactics, techniques, and procedures (TTPs)\r\nthat overlap with those described in public reporting of the Contagious Interview campaign. We have already\r\nnoted similarities in the distribution method (hosting on npm) and obfuscation of the samples themselves.\r\nHowever, there are some additional observations that allow us to link this activity to Contagious Interview.\r\nTenacious Pungsan tend to reuse infrastructure for their campaigns. The BeaverTail samples described in this blog\r\nall communicate with a web server hosted at the IP address 95.164.17[.]24 on port 1224. In October 2024, this\r\nIP was linked to Contagious Interview in a blog that described a new, Qt GUI variant of BeaverTail. Prior to\r\nOctober 2024, two other vendors had linked this IP to DPRK activities.\r\nIn addition to the IP address, Tenacious Pungsan also reuse the same web directory structure for their C2 server.\r\nExfiltrated files are sent to the URL endpoint /uploads , the Python installation is hosted at /pdown , and\r\nInvisibleFerret is hosted at /client/\u003cinteger\u003e/\u003c3 digit campaign ID\u003e . This is consistent with the reports\r\nlinked above.\r\nThe infostealer component of BeaverTail targets a specific set of browser extensions associated with\r\ncryptocurrency and web3 technologies. This list is consistent across our BeaverTail samples, the Qt GUI variant\r\nUnit42 reported on, and the original nodeJS variant also covered by Unit42. Similarly, these samples all attempt to\r\nextract the macOS Login Keychain.\r\nThe above points allow us to assess with high confidence that these samples are indeed BeaverTail and are being\r\ndistributed as part of the Contagious Interview campaign.\r\nHow Datadog can help\r\nDatadog Software Composition Analysis (SCA) customers can verify whether any of these packages are currently\r\ninstalled in their infrastructure by running this query in the Library Risks explorer: library_name:(passports-js\r\nOR bcrypts-js OR blockscan-api) Status:Open . If your system is impacted, it is important to take immediate\r\nmeasures such as rotating credentials, isolating the application, and investigating potential spread.\r\nhttps://securitylabs.datadoghq.com/articles/tenacious-pungsan-dprk-threat-actor-contagious-interview/\r\nPage 10 of 12\n\nDatadog SCA identifying a malicious dependency (click to enlarge)\r\nIn order to enable further research, we have published all affected versions of passports-js , bcrypts-js, and\r\nblockscan-api to our public malicious package dataset.\r\nConclusion\r\nCopying and backdooring legitimate npm packages continues to be a common tactic of threat actors in this\r\necosystem. These campaigns, along with Contagious Interview more broadly, highlight that individual developers\r\nremain valuable targets for these DPRK-linked threat actors.\r\nIndicators of compromise\r\nIP addresses Purpose Note\r\n95.164.17[.]24\r\nData exfiltration, InvisibleFerret\r\ndownload\r\nReused from previous campaign documented\r\nby Unit42\r\nNPM authors Email Packages published\r\nsuperdev727 austin27ahn@outlook.com passports-js , bcrypts-js\r\nintelliman g65492036@gmail.com blockscan-api\r\nhttps://securitylabs.datadoghq.com/articles/tenacious-pungsan-dprk-threat-actor-contagious-interview/\r\nPage 11 of 12\n\nSource: https://securitylabs.datadoghq.com/articles/tenacious-pungsan-dprk-threat-actor-contagious-interview/\r\nhttps://securitylabs.datadoghq.com/articles/tenacious-pungsan-dprk-threat-actor-contagious-interview/\r\nPage 12 of 12",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"ETDA",
		"MITRE",
		"Malpedia"
	],
	"origins": [
		"web"
	],
	"references": [
		"https://securitylabs.datadoghq.com/articles/tenacious-pungsan-dprk-threat-actor-contagious-interview/"
	],
	"report_names": [
		"tenacious-pungsan-dprk-threat-actor-contagious-interview"
	],
	"threat_actors": [
		{
			"id": "32e2c6f9-a1f5-42bc-ac1d-5d9dc301cf0e",
			"created_at": "2025-08-07T02:03:25.078429Z",
			"updated_at": "2026-04-10T02:00:03.811418Z",
			"deleted_at": null,
			"main_name": "NICKEL ALLEY",
			"aliases": [
				"CL-STA-0240 ",
				"Purplebravo Recorded Future",
				"Storm-1877 ",
				"Tenacious Pungsan "
			],
			"source_name": "Secureworks:NICKEL ALLEY",
			"tools": [],
			"source_id": "Secureworks",
			"reports": null
		},
		{
			"id": "4fc99d9b-9b66-4516-b0db-520fbef049ed",
			"created_at": "2025-10-29T02:00:51.949631Z",
			"updated_at": "2026-04-10T02:00:05.346203Z",
			"deleted_at": null,
			"main_name": "Contagious Interview",
			"aliases": [
				"Contagious Interview",
				"DeceptiveDevelopment",
				"Gwisin Gang",
				"Tenacious Pungsan",
				"DEV#POPPER",
				"PurpleBravo",
				"TAG-121"
			],
			"source_name": "MITRE:Contagious Interview",
			"tools": [
				"InvisibleFerret",
				"BeaverTail",
				"XORIndex Loader",
				"HexEval Loader"
			],
			"source_id": "MITRE",
			"reports": null
		},
		{
			"id": "ef59a0d9-c556-4448-8553-ed28f315d352",
			"created_at": "2025-06-29T02:01:57.047978Z",
			"updated_at": "2026-04-10T02:00:04.744218Z",
			"deleted_at": null,
			"main_name": "Operation Contagious Interview",
			"aliases": [
				"Jasper Sleet",
				"Nickel Tapestry",
				"Operation Contagious Interview",
				"PurpleBravo",
				"Storm-0287",
				"Tenacious Pungsan",
				"UNC5267",
				"Wagemole",
				"WaterPlum"
			],
			"source_name": "ETDA:Operation Contagious Interview",
			"tools": [
				"BeaverTail",
				"InvisibleFerret",
				"OtterCookie",
				"PylangGhost"
			],
			"source_id": "ETDA",
			"reports": null
		}
	],
	"ts_created_at": 1775434780,
	"ts_updated_at": 1775826774,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/c0ae5c1a3573d3ee764bd1247a6ac729d1589c25.pdf",
		"text": "https://archive.orkl.eu/c0ae5c1a3573d3ee764bd1247a6ac729d1589c25.txt",
		"img": "https://archive.orkl.eu/c0ae5c1a3573d3ee764bd1247a6ac729d1589c25.jpg"
	}
}