You are currently viewing Software Supply Chain Security: Risks in Dependencies, Builds, and Secrets
Supply Chain Security: Risks in Dependencies, Builds & Secrets

Software Supply Chain Security: Risks in Dependencies, Builds, and Secrets

📋 Key Takeaways
  • What Supply Chain Attacks Actually Are
  • Protect Against Supply Chain Security Risks
  • Mastering Supply Chain Security: Dependencies, Builds & Secrets
  • Famous Supply Chain Attacks
  • Dependency Risks
12 min read · 2,239 words
Software supply chain concept showing interconnected code dependencies

What Supply Chain Attacks Actually Are

Protect Against Supply Chain Security Risks

Mastering Supply Chain Security: Dependencies, Builds & Secrets

A supply chain attack targets the dependencies, build processes, or infrastructure that your software relies on — rather than attacking your application directly. The attacker compromises something upstream, and every downstream consumer inherits the compromise. You can write perfectly secure code and still get breached because a transitive dependency you’ve never heard of is malicious.

Taxonomy of Supply Chain Attacks

  • Dependency attacks: Compromising a package, library, or module that your software depends on.
  • Build attacks: Poisoning the CI/CD pipeline, build server, or toolchain to inject malicious code during compilation.
  • Deployment attacks: Compromising the infrastructure where your software runs — container registries, package managers, CDN endpoints.
  • Infrastructure attacks: Targeting the shared services your software depends on — DNS providers, certificate authorities, cloud APIs.

Famous Supply Chain Attacks

SolarWinds (2020)

Russian state actors (APT29/Cozy Bear) compromised the build environment of SolarWinds Orion IT monitoring software. They inserted a backdoor (SUNBURST) into the build process that was included in signed, legitimate updates distributed to approximately 18,000 customers. The backdoor communicated with attacker-controlled infrastructure using DNS tunneling, making it extremely difficult to detect. The breach affected US government agencies, Microsoft, FireEye, and thousands of other organizations.

Codecov (2021)

Attackers modified a Bash script (codecovUploader.sh) used by the Codecov CI/CD integration to export environment variables containing CI tokens, AWS keys, and other secrets to an attacker-controlled server. Since Codecov runs in CI pipelines as part of the build process, it had access to every secret in the environment. The modified script was in production for nearly two months.

Log4Shell (2021)

The log4j library’s JNDI lookup feature allowed remote code execution through a single log message string. Log4j is embedded in virtually every Java application, many of which didn’t know they depended on it through transitive dependencies. The vulnerability (CVE-2021-44228) had a CVSS score of 10.0 and is still being exploited years later in unpatched systems.

3CX (2023)

The 3CX desktop VoIP client was compromised through a supply chain attack on one of its own dependencies — a trojanized trading platform (X_Trader) installed on a 3CX employee’s machine. The attackers used that access to compromise the 3CX build chain and distributed malicious updates to the 3CX desktop app. Over 600,000 customers were affected. This was a supply chain attack within a supply chain attack.

XZ Utils Backdoor (2024)

A social engineering attack on the xz-utils compression library (used by virtually every Linux distribution). An attacker named “Jia Tan” spent two years contributing legitimate commits to build trust, then gained maintainer access and injected a backdoor into the build system. The backdoor modified how SSH authentication worked, potentially allowing remote code execution on affected systems. It was caught by a Microsoft engineer who noticed a 500ms latency increase in SSH connections — likely the closest call in open source history.

Dependency Risks

Typosquatting

Attackers publish packages with names similar to popular ones — lod-ash instead of lodash, reqeusts instead of requests. When developers mistype an install command, they get the malicious package instead. In 2024, researchers found over 200,000 malicious packages across npm, PyPI, and RubyGems using this technique.

Dependency Confusion

When an internal package name matches a public registry name, an attacker can publish a malicious package with the same name and a higher version number to the public registry. Build systems that check public registries will pull the attacker’s package instead of the internal one. Alex Birsan demonstrated this against Apple, Microsoft, and dozens of other companies in 2021.

Maintainer Compromise

The XZ Utils attack is the canonical example, but it happens regularly at smaller scale. Package maintainers get their accounts compromised, or are socially engineered into adding malicious code. The event-stream npm package (2018) and ua-parser-js (2021) are notable cases.

Build Pipeline Attacks

CI/CD systems are high-value targets because they have access to deployment credentials, signing keys, and production infrastructure. Compromising a build pipeline gives the attacker the ability to inject malicious code into every artifact that pipeline produces.

Common vectors include stolen CI tokens from leaked environment variables, poisoned build dependencies (like the Codecov case), and compromised build agents. If your CI runner has access to production AWS credentials, a single compromised build step means game over.

Secret Leakage in Supply Chains

Hardcoded API keys, database credentials, and tokens in source code are a supply chain problem. When you commit secrets to a Git repository, they persist in history even after you delete them. Automated Tools scan public repositories for leaked secrets within minutes of a push.

The most common sources of secret leakage: .env files committed to public repos, secrets in CI configuration files, API keys in client-side JavaScript, and credentials hardcoded in Docker images.

Hardening Strategies

  • SBOM (Software Bill of Materials): Maintain a complete list of every dependency in your software. Tools like syft, Trivy, and cdxgen generate SBOMs in CycloneDX or SPDX format.
  • SLSA Framework: Supply-chain Levels for Software Artifacts provides a framework for ensuring the integrity of your build pipeline.
    See also: SLSA Supply Chain Security Framework. SLSA Level 3 requires hermetic builds and provenance attestation.
  • sigstore/cosign: Sign your container images and build artifacts. Cosign provides keyless signing using Fulcio certificates, making it possible to verify who built an artifact and when.
  • Dependency pinning: Always use lockfiles (package-lock.json, Cargo.lock, Pipfile.lock). Never use version ranges like ^1.0.0 in production without a lockfile.
  • Secret scanning: Run truffleHog and gitleaks against your repositories to find leaked credentials.

Practical Audit Commands

# Generate an SBOM for a Node.js project
syft packages dir:./ -o cyclonedx-json > sbom.json

# Scan for known vulnerabilities in dependencies
trivy fs ./ --severity HIGH,CRITICAL

# Find leaked secrets in git history
trufflehog git file://. --only-verified

# Check for typosquatted packages in npm
npx npm-audit --audit-level=high

# Verify container image signature
cosign verify --key cosign.pub registry.example.com/app:v1.2.0

# List all transitive dependencies
npm ls --all 2>/dev/null | head -50

Package Manager Security: Trusting the Ecosystem

Every language ecosystem centres on a package registry — npm for JavaScript, PyPI for Python, Maven Central for Java, and crates.io for Rust. These registries are designed for convenience: a single command pulls someone else’s code into your project. That convenience is also the attack surface.

How Registries Work — and Where They Fail

Most registries operate on a first-come, first-served namespace model. On npm, anyone can publish a package under an unclaimed name. Typosquatting exploits this: an attacker publishes lod4j instead of log4j, or cross-env with a zero instead of an ‘o’. PyPI has seen the same pattern with packages mimicking popular libraries like requests or urllib3. The npm @scope namespace (e.g., @babel/core) adds a layer of organisational control — scoped packages require an organisation account, making impersonation harder — but it doesn’t eliminate the risk of a compromised organisation account.

Provenance and Publisher Identity

Package provenance links a published artefact back to the source repository and build pipeline that produced it. npm supports provenance attestations via Sigstore, and PyPI has begun rolling out similar features. When a package includes a provenance record, you can verify that the published tarball was actually built from the claimed source at a specific commit.

Enabling two-factor authentication (2FA) on your publisher account is non-negotiable. npm and PyPI both support mandatory 2FA for publishing. If your registry account is compromised, every package you maintain becomes a potential attack vector.

Verifying Integrity with Checksums and Lockfiles

Lockfiles (package-lock.json, Pipfile.lock, Cargo.lock) pin exact dependency versions and, in some ecosystems, integrity hashes. Always commit your lockfile to version control and audit changes during code review:

# npm: verify integrity hashes in the lockfile
npm audit

# Python: generate a requirements file with hashes
pip-compile --generate-hashes requirements.in

# Cargo: check lockfile consistency
cargo verify-project

Without lockfiles, a fresh npm install could pull a different minor version of a dependency — one that an attacker has since compromised. This is the “left-pad” lesson: registries are mutable, and your builds must be reproducible.

Container Image Security: The Invisible Foundation

Containers have become the default deployment unit, but every container starts with a base image — and base images are a supply chain attack vector that many teams overlook.

Base Image Risks

Popular Docker Hub images like node:18 or python:3.12 are downloaded billions of times, making them high-value targets. Risks include image phishing (attackers publishing lookalike images with slightly different tags), stale images that bundle known CVEs, and hidden malware injected into compromised maintainer accounts. In 2024, researchers discovered cryptominers embedded in Docker images that had been pulled millions of times.

Minimal Images and Multi-Stage Builds

The most effective mitigation is reducing your attack surface. Distroless images (Google’s container images that include only your application and its runtime dependencies, no shell or package manager) and scratch images (completely empty) remove entire categories of attack:

# Dockerfile: multi-stage build with distroless
FROM golang:1.22 AS builder
WORKDIR /app
COPY . .
RUN CGO_ENABLED=0 go build -o server .

# Distroless — no shell, no package manager
FROM gcr.io/distroless/static-debian12
COPY --from=builder /app/server /server
ENTRYPOINT ["/server"]

Multi-stage builds separate the build environment (which needs compilers, tools, and build dependencies) from the runtime image (which should contain only what’s necessary to run). This reduces the final image size by 80–95% and eliminates entire classes of vulnerability.

Scanning and Runtime Security

Image scanning tools like Trivy, Grype, and Snyk Container detect known vulnerabilities in OS packages and application dependencies. Integrate scanning into your CI pipeline to block images with critical vulnerabilities:

# Trivy: scan an image and fail on critical CVEs
trivy image --exit-code 1 --severity CRITICAL myapp:latest

# Trivy: scan a Dockerfile during CI
trivy fs --severity HIGH,CRITICAL ./

For runtime security, Falco monitors container behaviour at the kernel level and alerts on suspicious activity (spawning shells inside containers, unexpected network connections, reading sensitive files). OPA Gatekeeper enforces policies on Kubernetes clusters — for example, blocking pods that run as root or use privileged containers.

CI/CD Pipeline Hardening in Practice

Your CI/CD pipeline is the assembly line where source code becomes production artefacts. If the pipeline is compromised, every build it produces is untrustworthy.

GitHub Actions: Pinning, OIDC, and Guardrails

The most common GitHub Actions mistake is referencing third-party actions by tag (actions/checkout@v4) instead of commit SHA. Tags are mutable — a maintainer can push a compromised version to the same tag. Always pin to a specific commit:

# BAD — tag can be reassigned
- uses: actions/checkout@v4

# GOOD — pinned to immutable commit
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683

Use OpenID Connect (OIDC) tokens instead of stored secrets wherever possible. OIDC allows your workflow to authenticate to cloud providers (AWS, GCP, Azure) using short-lived tokens — no long-lived secrets to leak or rotate. Environment protection rules restrict which branches can deploy to production, and required reviewers add a human gate before sensitive workflows run.

Dependency Update Strategies: Automated but Not Blind

Tools like Renovate, Dependabot, and Snyk automate dependency updates by opening pull requests when new versions are available. This is essential for security — vulnerable dependencies don’t fix themselves — but automation introduces its own risks.

The Update Attack Vector

In 2024, security researcher Alex Birsan demonstrated that malicious packages can be pushed to registries with version numbers that satisfy existing version ranges. If your package.json specifies "lodash": "^4.17.0", and a new version 4.17.22 is published containing malware, your next npm install will happily pull it in. Automated updaters can accelerate this — Dependabot opens a PR for the new version, and if reviewers rubber-stamp it without auditing, the compromise lands in production.

Mitigation strategies include lockfile-only updates (update versions in the lockfile without modifying version ranges), reviewing every dependency update PR (yes, actually reading the diff), and monitoring advisory databases before approving updates.

Alert Fatigue and Triage

Large projects can receive hundreds of vulnerability alerts per week. Not every CVE is exploitable in your context. A practical triage strategy: prioritise alerts based on whether the vulnerable code path is actually reachable in your application, whether an exploit requires network access your deployment doesn’t expose, and whether a fix is available. Automate the low-risk updates and reserve manual review for critical or ambiguous alerts.

Software Composition Analysis: Knowing What You Run

Software Composition Analysis (SCA) tools provide visibility into every open-source component in your codebase, including transitive dependencies you never directly chose. Tools like Snyk, Black Duck, and FOSSA work by analysing manifest files (package.json, pom.xml, Cargo.toml) and, in more advanced implementations, parsing the Abstract Syntax Tree (AST) to detect which library functions are actually called.

The CVE-Exploitability Gap

A critical nuance: a CVE does not equal an active exploit. SCA tools report known vulnerabilities, but the gap between “this library has a CVE” and “this CVE is exploitable in your specific context” can be enormous. Treat SCA output as a prioritisation tool, not a binary pass/fail gate. Combine it with reachability analysis (understanding whether the vulnerable code path is actually invoked) and runtime monitoring to focus remediation effort where it matters.

Conclusion

Supply chain attacks exploit trust. Your software trusts its dependencies, its build system, and its infrastructure. An attacker who compromises any link in that chain compromises your software. The defenses — SBOMs, artifact signing, dependency pinning, secret scanning — are well-established but require consistent implementation. You can’t verify what you don’t know about, so start by knowing exactly what’s in your supply chain.

Reference: Open Source Security Foundation

Prabhu Kalyan Samal

Application Security Consultant at TCS. Certifications: CompTIA SecurityX, Burp Suite Certified Practitioner, Azure Security Engineer, Azure AI Engineer, Certified Red Team Operator, eWPTX v3, LPT, CompTIA PenTest+, Professional Cloud Security Engineer, SC-900, SC-200, PSPO I, CEH, Oracle Java SE 8, ISP, Six Sigma Green Belt, DELF, AutoCAD. Writing about ethical hacking, security tutorials, and tech education at Hmmnm.