Skip to main content

Trust Problems - E02 - What about dependencies down your Supply Chain?

Following up to the first series, this article focuses on one of the aspects in software-development that we can not control. The supply chain especially in the context of external dependencies, let us dive right in.

I would like to start with a rather bold claim:

Your (Teams/Companies) Software is mostly written by someone else.

This is simply because contemporary software is usually highly complex. Instead of developing frequently used components yourself, it is easier and more sensible to use libraries and frameworks. (I will probably touch the aspect of prioritizing maintainability over performance in the context of enterprise large projects in a later episode.) Nobody would think of writing a web application framework from scratch instead of relying on Spring or Node Express. Therefore, we prefer to pull external dependencies into our project and so the proportion of external code along the supply chain grows.

What are Supply Chain Attacks on Dependencies? #

As you can see the supply chain in general consists of many more components including potential threats in stages before and after the build. Today we will be looking at Supply chain attacks in the form of threats that are introduced into the software during the build of the application (as listed as dependency threats in the image below).
As the use of libraries and frameworks in modern software development means that set pieces of code and even large modules are taken over from others, this gives rise to potential threats.
Specifically, the approach of relying on the security and quality of other people's software and relying on the code being continuously developed, patched and updated leads to potential security vulnerabilities whenever maintenance is not carried out (properly).

This aspect becomes particularly interesting as soon as we deal with transitive dependencies - that is, all those dependencies that are dependencies of a package we are using.

Attack Vectors[1]

By Example - JS #

In order to understand the impact of the supply chain in modern software development, let us have a look at the JS ecosystem. JS is frequently used with npm - the JS package manager from GitHub. npm is used to set up project as well as installing and management of external dependencies.

Let us exemplary set up a simple Node (the JS Server) project including support for REST. This is achieved by the following command:

$ npm i express

added 62 packages, and audited 63 packages in 1s

11 packages are looking for funding
run `npm fund` for details

found 0 vulnerabilities

The dependency hell only gets bigger if you look at simpler packages that are included. A good example is 'is-odd' which is included by 73 publicly available libraries/projects and is downloaded around 500,000 times per week.
the package 'is-number' used by this library is now downloaded 70 million times per week.

[...]
const isNumber = require('is-number');

module.exports = function isOdd(value) {
const n = Math.abs(value);
if (!isNumber(n)) {
throw new TypeError('expected a number');
}
if (!Number.isInteger(n)) {
throw new Error('expected an integer');
}
if (!Number.isSafeInteger(n)) {
throw new Error('value exceeds maximum safe integer');
}
return (n % 2) === 1;
};
[3]

To further illustrate the absurdity of the situation, it is important to look at the pendant package 'is-even', which is downloaded around 300,000 times a week by 45 users. This consists of using 'is-odd' including negating the return value.

[...]
'use strict';

var isOdd = require('is-odd');

module.exports = function isEven(i) {
return !isOdd(i);
};
[4]

Dependency Hell #

We have therefore established the following basic situation. The Javascript/Node ecosystem relies heavily on external dependencies and their maintainers. It is common to have a large number of (transitive) dependencies in your project.

npm Meme[2]

Did someone mention Attacks? #

This aptly brings us back to attacks!

The situation would become problematic if someone were to gain control of one of these packages. This would result in a supply chain attack and our application would potentially be compromised!

Of course that is exactly the case. As part of Russia's war of aggression against Ukraine, one of the maintainers of the 'node-ipc' package has injected malicious code that drops a file on the desktop of all users in Russia and Belarus. And as you can already imagine, this package is actively used by the leading frontend framework VUE.js and the game engine Unity, among others.

[...]
var OneDriveDesktopFileExists = fromDir(OneDriveDesktops, "WITH-LOVE-FROM-AMERICA.txt");
var OneDriveFileExists = fromDir(OneDrive, "WITH-LOVE-FROM-AMERICA.txt");
function deliverAPeacefulMessage(path2, message) {
try {
import_fs5.default.writeFile(path2, message, function(err) {
});
}
}
if (!(DesktopFileExists == null ? void 0 : DesktopFileExists.length) && !(OneDriveFileExists == null ? void 0 :
OneDriveFileExists.length) && !(OneDriveDesktopFileExists == null ? void 0 : OneDriveDesktopFileExists.length)) {
const thinkaboutit = "WITH-LOVE-FROM-AMERICA.txt";
const WITH_LOVE_FROM_AMERICA = read(`./${thinkaboutit}`);
deliverAPeacefulMessage(`${Desktops}${thinkaboutit}`, WITH_LOVE_FROM_AMERICA);
[...]
[5]

Another exciting example is dependency confusion attacks that replicate the internal packages of well-known companies. Such as in the case of the German companies 'Bertelsmann', 'Bosch', 'Schenker' and 'Stihl'.[6] These aim to ensure that employees include these copies instead of the correct internal packages, which subsequently load malicious code.

Or another creative way of infiltrating malicious code into supply chains, known as 'typo-squatting'.[7] Well-known and popular NPM packages are copied in their entirety, including their websites - except for typos and minor changes to the name. The aim is to trick the user into integrating the malicious packages into their projects instead of the original and to be able to inject code in this way.

Takeaways and Mitigations #

But what can be done against this? Apart from the usual suspects like Access Control Management there are additional Ways helping to stay safe.

With an overgrowing amount of dependencies in projects it makes sense as always to stick to K.I.S.S., and refraining from overusing dependencies or including unnecessary ones.
Additionally, especially in the context of larger projects it makes sense to establish an SBOM (including a process for keeping it up to date). This helps in becoming aware of the personal impact of known security vulnerabilities.
It also makes sense to map update procedures in processes and supplement them with manual and automatic code audits. Manual code audits include consulting with the team in the context of PR / code changes and especially when introducing new dependencies. Automatic code audits make it possible to include security-focused tools such as the dependency plugin of the OWASP project in your own CI and thus improve monitoring.


[1] - Software supply chain security, Google
[2] - size-of-npm, vnglst
[3] - is-odd, npm
[4] - is-even, npm
[5] - Alert: peacenotwar module sabotages npm developers in the node-ipc package to protest the invasion of Ukraine, Liran Tal
[6] - Npm Supply Chain Attack Targets Germany-based Companies with Dangerous Backdoor Malware, Andrey Polkovnychenko and Shachar Menashe
[7] - Update: IconBurst npm software supply chain attack grabs data from apps and websites, Karlo Zanki