From an information security perspective, 2022 can be called “The Year of Software Supply Chain Attacks.” Malicious actors have shifted their focus to new landscapes. Ten or 20 years ago, malware was piled up and served through services providing pirated content and email spam. Today’s malware has evolved to target the supply chain, and it is getting served through open source software distribution points.
Developers have become one of the key targets for malicious actors. Reports about malicious campaigns targeting developers via popular open source repositories can be seen on a weekly basis. The more popular the package repository is, the more malicious content gets discovered in it, with npm and PyPI taking the top spots on the list. But this doesn’t mean that less popular open source repositories are clean of malware.
A few weeks ago, Aqua Security provided a report describing how malicious actors can manipulate Visual Studio Code (VS Code) Extensions Marketplace to increase the chances for developers to install malicious extensions into their Integrated Development Environment (IDE).
Here's how malicious code can get into the VS Code IDE — and how it can traverse between various development ecosystems.
VS Code extensions vs. npm packages
VS Code extensions are developed in Node.js, and that is why their structure is similar to npm packages, with an added wrapping layer used to interconnect them with VS Code API’s. Since they are developed in Node.js the developers have all the npm modules at their disposal so they could quickly include a required functionality without needing to implement it themselves. This also means that all of those malicious npm packages seen in so many different threat reports can get included into VS Code extensions with the same ease as the legitimate functionalities.
ReversingLabs makes continuous efforts to improve the security of open source package repositories. One of our efforts included the analysis of VS Code extensions published to the official Visual Studio marketplace. Most often when malicious extensions get published to the marketplace, the malicious actor tries to make them look as similar as possible to legitimate extensions in order to lure their targets into installing them. Display names and descriptions often get duplicated as part of that effort. Implementing the functionalities of the original extension often gets skipped and created extensions end up containing only malicious functionality. Such packages are the most usual type of malicious packages seen in open source repositories.
But another type of malicious package seen in the VS Code marketplace looked more interesting. Several VS Code extensions were previously removed by the Microsoft team from the marketplace. Why these extensions are interesting is because they showcase how quickly malicious compromises can proliferate from the npm user community, to the unrelated community of VS Code users. The entire incident started when the maintainer of the quite popular event-stream npm package, with allegedly millions of weekly installs, decided to stop working on the project and transferred the maintenance rights to another developer which volunteered to replace him on that duty.
The new maintainer behind the nickname "right9ctrl" modified the codebase by adding a dependency to a package called "flatmap-stream". On September 9th 2018, when it was included in the event-stream package, the flatmap-stream project had a low download rate and only one commit. On September 16th the code was rewritten and the dependency was removed from the event-stream package. But the changes were published as a semver-major version, which means that packages using default version naming won’t apply this update automatically, leaving all users of 3.x.x versions vulnerable to compromise of the flatmap-stream package.
On October 5th, a new version 0.1.1 of the flatmap-stream package, empowered with crypto-stealing capabilities, got published to the npm repository. Since it is a patch version, from this moment on, new installations of the vulnerable event-stream versions would include this malicious version of flatmap-stream dependency. The issue was discovered on November 19th 2018 and by November 26th the threats were investigated in detail and removed from the npm repository.
Malicious packages in open source repositories aren’t something revolutionary, and everybody has heard of at least one software supply chain attack which was caused by inclusion of a bad dependency into the codebase. The developer community is well aware of this type of threat and verifying third-party software packages before using them in a software project is becoming a part of security hygiene.
But security assessment of npm derivatives such as VS Code extensions is rarely performed. They are not perceived as a potential source of compromise. The thinking is likely “I’m installing a plugin for my IDE, I’m not adding anything to my code base, there is no need to worry about it”. Such a mindset can get you into trouble before you know it.
Figure 1: Propagation of malicious dependency
Figure 1 visualizes the propagation of malicious dependency published on npm through the compromised npm module into the VS Code ecosystem. The automated propagation of the malicious package throughout the npm ecosystem was a byproduct of automated CI/CD workflows. The malicious actor took advantage of npm’s version numbering system, which is designed to support automation of CI/CD workflows, to perform inclusion of malicious code into a popular project and its dependents.
The npm packages define their dependencies in the package.json file. When a dependency is installed it gets an entry in the package.json file containing the name of the dependency and its version number prefixed with a rule symbol. The rule symbol defines how a dependency should be updated based on version number changes. This way, CI/CD systems can read package.json files and decide if a new release of a dependency should be included into a project or not.
By default, npm package manager prefixes a caret sign (^) before the version number of an installed dependency instructing it to include future patch releases and minor version releases, but not apply major version releases which would introduce breaking changes. When a project gets built during CI/CD release, the package.json files get parsed and acceptable updates get included into the release artifact. Since the same mechanism is used in VS Code extensions, the malicious package got propagated to this ecosystem in the same way.
Additional infections within the VS Code ecosystem may occur due to the way VS Code IDE handles updating of the extensions installed on the developers machine. The default option in VS Code IDE is set to perform automatic update of installed extensions. This results in automated propagation of compromised extensions to their users during the next startup of VS Code.
Mechanisms in npm used to support CI/CD workflows were used to include malicious package dependency into release artifacts of legitimate packages. Additionally, the default VS Code extension update settings caused an automated installation of compromised extensions in the developer’s VS Code IDE.
Figure 2: Default auto-update settings explained in VS Code documentation
What can be done about the VS Code hack
Complexity and numerous extension possibilities of various IDEs makes them an attractive target for malicious actors. Compromise of IDE inevitably leads to an insecure local development environment and a landing point for further compromise of the development infrastructure used throughout the enterprise.
To ensure the integrity of the development process, all IDEs and their associated plugins used within a developer environment must be pre-approved, validated by scanning for supply chain attacks and vulnerabilities before being cleared for usage. IDEs have become a security boundary and need to be included into risk management and security assessment of the development process.
General guidelines and best practices for security hygiene should be adopted on all levels of software development. This includes typical role management actions used to control users' permission levels and to restrict excessive access rights.
Continuous education needs to be conducted to increase the general security awareness of all stakeholders in the software development lifecycle. Don’t forget — the (software supply) chain is as strong as its weakest link. Even though automatic updating of software dependencies has its advantages, it can also be abused by malicious actors to achieve their goals.
Even though automatic updating of software dependencies has its advantages, it can also be abused by malicious actors to achieve their goals.
General pre-deployment advice for software users
Always perform a security assessment of the software you intend to use before it gets deployed. Some threats can be detected by common sense. To detect more advanced threats, specialized security tools will be needed - an SCA will do very little to detect software supply chain attacks.
If you wish to test some piece of software, always test it in a safe and isolated environment before deploying it into the working environment. Employ security policies in a restrictive manner, and adopt a zero-trust mentality across the organization. In order to protect the integrity of the development environment, prepare a list of tools for which security assessment has been performed and that can be safely installed on a local development machine. Any additional software and its accompanying plugins and extensions should perform the same type of security evaluation before being cleared for usage.
Remember that the most recent headline-grabbing security incidents have started by attacking developers and other personas in the organization who have high access privileges.
The collective consciousness about software supply chain attacks has improved significantly throughout the last two years. Security companies are putting continuous efforts to detect malicious packages in open source repositories and the developer community is becoming more aware of the risks associated with the inclusion of unverified third-party dependencies into their code base. But the threat landscape is always expanding. The forever increasing software complexity is making it harder to secure the overall software supply chain.
It is very important that all stakeholders in software development understand that any type of software that gets installed may contain malicious functionalities. It is not only typical Windows executables that can represent danger for your environment. Any type of software that gets executed should go through security assessment before installation, especially open source software. Even though the advantage of open source projects is that anyone can take a look at the project's source code and detect threats and vulnerabilities, it doesn’t mean that anyone has really made that effort.
Trust, but verify.