Source-linked AI summary
Backstabber's Knife Collection: A Review of Open Source Software Supply Chain Attacks
Marc Ohm, Henrik Plate, Arnold Sykosch, Michael Meier
TL;DR
Open source supply chain attacks exploit widely reused dependencies and automated package installation to compromise downstream systems. This paper manually analyzes 174 real-world malicious packages and develops two attack trees covering code injection and execution. The dataset identifies recurring techniques, including installation-time triggering, typosquatting, and data exfiltration, while the authors note important dataset biases and unavailable second-stage payloads.
Problem
Open source dependency reuse and automated installation expose downstream projects to deliberately malicious packages that can evade detection.
Method
The paper manually compiles and analyzes real-world malicious packages and derives two attack trees from observed cases, related work, and potential ecosystem weaknesses.
Results
The dataset contains 174 packages, with 62.6% from npm, 16.1% from PyPI, and 21.3% from RubyGems; 56% trigger malicious behavior on installation and 61% use typosquatting.
Takeaways & Limitations
The attack trees expose possible entry points and support further development of preventive and detective safeguards for open source supply chains.
Takeaways & Limitations
The dataset is biased toward JavaScript packages on npm, lacks malicious packages from Maven Central and Packagist, and includes droppers whose second-stage payloads may no longer be available.
Abstract
from arXiv · showhide
A software supply chain attack is characterized by the injection of malicious code into a software package in order to compromise dependent systems further down the chain. Recent years saw a number of supply chain attacks that leverage the increasing use of open source during software development, which is facilitated by dependency managers that automatically resolve, download and install hundreds of open source packages throughout the software life cycle. This paper presents a dataset of 174 malicious software packages that were used in real-world attacks on open source software supply chains, and which were distributed via the popular package repositories npm, PyPI, and RubyGems. Those packages, dating from November 2015 to November 2019, were manually collected and analyzed. The paper also presents two general attack trees to provide a structured overview about techniques to inject malicious code into the dependency tree of downstream users, and to execute such code at different times and under different conditions. This work is meant to facilitate the future development of preventive and detective safeguards by open source and research communities.
1 Introduction
Open source supply chain attacks exploit dependencies and developer trust to distribute malicious code downstream. The paper responds with a curated dataset and attack trees intended to support protective and detective measures.
- Open source projects’ direct and transitive dependencies create attractive targets for attackers abusing trust in package authenticity and automated builds.
- A single package can reach thousands of projects, illustrated by event-stream’s use by 1,600 packages and average weekly downloads of 1.5 million.
- Malicious packages differ from vulnerable packages through deliberate injection and the use of obfuscation or evasion techniques.
- The paper manually analyzes and categorizes 174 malicious packages used in real-world attacks between 2015 and 2019.
- Two attack trees structure techniques for injecting malicious code into dependency trees and executing it under different conditions.
- The paper is organized around related work, methodology, attack trees, package analysis, and conclusions.
2 Related Work
Prior work largely studies accidentally vulnerable packages and specific ecosystems, while this paper examines deliberately malicious packages across multiple ecosystems.
- Malicious packages contain intentionally exploitable flaws, whereas vulnerable packages generally contain accidentally introduced flaws or errors.
- Related work on package reuse and vulnerability propagation also applies to malicious packages because both share ecosystems and software life cycles.
- Dependency-graph studies found that nearly half of npm packages inherited vulnerabilities, with version pinning to vulnerable or outdated packages identified as a main cause.
- Highly popular packages and active developers were identified as single points of failure, motivating developer training and automated code analysis.
- A static-analysis system detected four attack types but lacked real-world examples for evaluation.
- An unsupervised-learning system collected over 700,000 npm packages, reported 539 suspicious updates weekly, and reduced manual inspection by 89%.
- Prediction of vulnerable Python releases was difficult despite good statistical performance, and the studied model did not consider package supply chains.
- Unlike prior work focused mainly on vulnerable packages and individual ecosystems, this study covers malicious packages across several ecosystems.
3 Methodology
The paper combines a systematic distinction between malicious and vulnerable packages with attack-tree construction and manual dataset compilation across major package ecosystems.
- Malicious packages are distinguished from vulnerable packages by attacker intent, although their code may be technically similar or identical.
- Attack trees were developed iteratively from observed malicious packages, potential attacks, and weaknesses described by security researchers and practitioners.
- The dataset contains malicious packages used in real-world attacks whose actual malicious code could be obtained for analysis.
- Compilation occurred from July 2 to August 2, 2019, was updated January 27, 2020, and covered npm, Maven Central, PyPI, Packagist, and RubyGems.
- Security databases, language-specific advisories, and research blogs were reviewed to identify packages and possible attack vectors, while package code was obtained from other sources.
- Libraries.io dated package releases, and advisories and public incident reports dated public disclosure of malicious packages.
4 Threat Analysis and Attack Trees
The threat analysis models open source development as a chain of trust boundaries and uses two attack trees to represent code injection and execution paths.
- Attack-tree framework: Attack trees use an attacker’s top-level goal as the root and alternative ways of achieving it as child nodes.
- Development and build activities: Open source builds resolve direct and transitive dependencies, download them from package repositories, assemble artifacts, and publish them for users or other projects.
- Development and build activities: Multiple dependencies replicate trust boundaries across development environments, expanding the combined attack surface of dependent projects.
- Injection of malicious code: The injection tree models attacks that make malicious code available on a distribution platform and introduce it as a direct or transitive downstream dependency.
- Injection of malicious code: Attackers can submit new packages using typosquatting or trojan-horse promotion, reuse withdrawn identifiers, or infect existing packages.
- Injection of malicious code: Malicious code may enter existing packages through source files, build processes, package repositories, compromised build resources, or repository vulnerabilities.
- Injection of malicious code: Alternative repositories and mirrors can distribute malicious versions, but success depends on victim configuration such as repository query order or mirror use.
- Execution of malicious code: The execution tree models conditional triggering to evade detection or target specific users and systems, including conditions based on application state, build environments, dependency-tree nodes, and operating systems.
5 Description of the Dataset
The dataset contains 174 downloadable malicious packages from real-world attacks, collected across repositories and dated from November 2015 to November 2019. It is concentrated in npm, with additional PyPI and RubyGems coverage, while download success and repository availability varied.
- Download availability: 109/374 (29.14%) npm, 28/44 (63.64%) PyPI, 37/41 (90.24%) RubyGems, and 0/10 (0.00%) Maven Central malicious-package downloads succeeded.All subsequent statements and statistics refer to the downloaded packages.
- Repository composition: 62.6% of the dataset was published on npm, compared with 16.1% on PyPI and 21.3% on RubyGems.The packages correspond to JavaScript, Python, and Ruby ecosystems; no malicious Java package targeting Android developers could be downloaded, and no malicious PHP package was identified.
- Publication timeline: Collected packages range from November 2015 to November 2019, with PyPI packages increasing since 2015, npm packages surging in 2017, and RubyGems packages booming in 2019.Publication dates were identified from package upload times.
- Disclosure timing: Malicious packages remained available for an average of 209 days before public reporting, with values ranging from −1 to 1,216 days.PyPI had the highest average online time, npm showed the greatest variation, and RubyGems tended to detect malicious packages more timely.
5.3 Trigger of Malicious Behavior
Malicious behavior was most often triggered during package installation, while runtime triggers were also common and test-triggered behavior was rare. Trigger mechanisms differed by repository because Ruby lacks install logic.
- Repository-level pattern: Installation was the most-used infection vector because package installation can handle arbitrary code.The trigger analysis separates installation, testing, and runtime interaction points by repository.
- Installation triggers: 56% of malicious packages started their routines during installation.Repository install commands invoke code defined in package metadata such as package.json and setup.py.
- Runtime triggers: 43% of packages exposed malicious behavior during program runtime when invoked from another function.All found RubyGems packages used runtime as their trigger because Ruby does not implement install logic.
- Test triggers: 1% of packages used test routines as their trigger.The npm package ladder-text-js/1.0.0 could execute sudo rm -rf /* when its test routine was invoked.
5.4 Conditional Execution
Conditional execution was used by a substantial minority of malicious packages, with conditions tied to application state, environment, dependencies, domains, or cryptocurrency balances. Repository patterns differed, as npm was nearly balanced while PyPI and RubyGems were mostly unconditional.
- Conditional execution: 41% of malicious packages checked a condition before triggering further execution.Conditions included production mode, domain-name resolvability, and the amount contained in a cryptocurrency wallet.
- Conditional execution: Packages also checked whether another package existed in the dependency tree or whether execution occurred on a particular operating system.These checks provided additional conditions for triggering malicious behavior.
- Repository comparison: Most PyPI and RubyGems packages executed unconditionally, whereas npm showed nearly equal conditional and unconditional execution.The repository comparison is summarized as ratios of conditional and unconditional execution.
- Injection techniques: 61% of malicious packages mimicked existing package names through typosquatting.The average Levenshtein distance to the target was 2.3, with common changes including added or removed hyphens, omitted letters, and exchanged letters.
- Injection techniques: Infection of an existing package was the second most common injection method, although the exact technique often could not be determined retrospectively.Compromised repository credentials were one example of how an existing package could be infected.
- Injection techniques: A trojan horse was a newly created package consisting only of the malicious package, usable standalone or with an infected existing package.The paper reports that these packages had no meaningful typosquatting targets.
5.6 Primary Objective
Most malicious packages target data exfiltration, while droppers, backdoors, denial-of-service attacks, and financial objectives occur less often. Most packages are OS-agnostic, with Unix-like systems appearing more frequently targeted than Windows or macOS.
- Most packages aim at data exfiltration, commonly targeting credentials, environment variables, system information, or Discord tokens.Frequently targeted files include /etc/passwd, ~/.ssh/*, ~/.npmrc, and ~/.bash_history.
- 34% of packages function as droppers that download a second-stage payload.
- 5% open backdoors such as reverse shells, while 3% aim to cause denial of service and 3% pursue financial gain.Financial objectives include cryptomining or direct cryptocurrency theft.
- 53% of packages are OS-agnostic based on their initially visible code.The targeted OS of second-stage payloads remains unknown; Unix-like systems seem more frequently targeted than Windows and macOS.
- Only one known case targets macOS, using denial of service against the McAfee virus scanner by deleting and modifying its files.
5.8 Obfuscation
Obfuscation is used to disguise malicious code from human inspection and program analysis. Packages employ encoding, minification, string sampling, and occasionally encryption, often in combination.
- Nearly half of the packages, 49%, employ some kind of obfuscation.
- Base64 or Hex encoding commonly hides malicious functions or suspicious variables such as domain names.
- Minification can conceal extra unreadable code, while string sampling reconstructs meaningful strings from seemingly random text.
- One package used AES256 encryption with the targeted package’s short description as the decryption key.The malicious behavior was exposed only when the package was used by its target.
5.9 Clusters
The analysis identified clusters of packages sharing malicious code or dependency relationships, indicating repeated campaigns and technique reuse across repositories and programming languages.
- 21 clusters contained at least two packages linked by reused malicious code or dependency relationships.The analysis sought evidence of attack campaigns through code reuse and dependencies.
- 90% of the packages belong to a cluster, with clusters averaging 7.28 packages.Cluster sizes ranged from 2 to 36 packages.
- One cluster contained npm packages and RubyGems/active-support/5.2.0, showing that techniques can flow across package repositories.
- npm/jqeury/3.3.1 and RubyGems/active-support/5.2.0 belonged to the same cluster despite being published on different repositories.The relationship was based on manually assessed code similarity.
6 Conclusions
The paper combines attack trees with a manually curated dataset to characterize real-world malicious open-source packages and their execution techniques. Its findings highlight installation-time execution, typosquatting, data exfiltration, OS agnosticism, obfuscation, and cross-repository code reuse, while the dataset is biased toward npm and lacks Java and PHP cases.
- 6. Conclusions: The paper presents two attack trees describing malicious-package injection and execution techniques.They were derived from observed cases and related work to support systematic description of attacks.
- 6. Conclusions: The dataset contains 174 malicious packages from npm, PyPI, and RubyGems, spanning November 2015 to November 2019.The repository distribution is 62.6% npm, 16.1% PyPI, and 21.3% RubyGems.
- 6.1 Findings: Most packages trigger malicious behavior on installation, while 41% use further conditions to determine whether to run.The conclusions report 56% installation-triggered packages.
- 6.1 Findings: More than half of the packages, 61%, use typosquatting, while data exfiltration is the most common goal.
- 6.1 Findings: The analysis found reused malicious code across packages, including clusters spanning different programming languages and repositories.The dataset is intended to facilitate research on prevention, detection, and mitigation.
- 6.2 Limitation: The dataset is highly biased toward JavaScript packages published on npm and contains no obtained malicious packages for Java or PHP.The authors attribute the npm bias to its enormous size and popularity.