Module 5 · Supply Chain Security
Module 5 · Part 1 of 2
Supply Chain Security
Your code is only as secure as the pipeline that builds it. Three attack surfaces, three real cases, and the controls that matter at every stage.
DEVELOP BUILD DELIVER
01 / 31 · Cover
Your journey · Program map
Your journey so far
RoleProcessRisksFindM5SupplySecretsConfigRespondMobile
9 modules. One toolkit. You are at Module 5.
Context
Your toolkit · So far
What you already have
Modules 1–4
M1–2
Champion role, sprint workflow, business-language skills
You can frame security as value, not overhead
M3
Ten risk categories, five lenses
OWASP Top 10 isn't a checklist — it's a way of seeing
M4
Threat model workflow: STRIDE → DREAD → tickets
Your primary production skill — threats become shippable tickets
Context
Module 5 · What you didn't write
What you didn't write
DEVBUILDSHIP
You can model threats in your own code. But how much of "your code" did you actually write?
A typical project has 200–1,500 transitive dependencies. Most of what ships was written by someone else.
This module gives you the controls for all three:
1
Three attack surfaces
Development, build, and delivery — where supply chain attacks happen
2
SBOM + SLSA
Verify what your pipeline ships with a measurable maturity score
3
Connected block: M5 → M6 → M7
Supply chain (this), secrets (next), configuration (after) — the three layers of production
Context
Time to think · The SDLC pipeline
DEV
BUILD
TEST
DELIVER
OPERATE
your sdlc — every stage is an attack surface

Data packets circle the pipeline. Threats pulse at every stage. You test. You review. But supply chain risk keeps rising — because attackers target the pipeline itself.

Did you notice — the warning signs flash at different stages? No single checkpoint catches them all.
Time to think and reflect
Act 1 · Why supply chain matters
The scale problem
Dependencies you chose vs. dependencies you inherited
Your app has 20 direct dependencies. Those pull in 200 transitive ones. You chose 20. You inherited 200.
Each transitive dependency is code you didn't audit, written by someone you don't know, updated on a schedule you don't control. A vulnerability in any one of them is your vulnerability — in your container, serving your customers.
A dependency of a dependency of a dependency. When you install express, you also get body-parser, which pulls in raw-body, which pulls in iconv-lite. You never asked for iconv-lite. But a vulnerability in it is your problem. Run npm ls --all and count the lines — that's your real dependency surface.
Consider the question honestly: how many dependencies does your project have right now? 10? 15? 50? The real answer, once you count transitive deps, is almost always hundreds. We are not C developers anymore. We compose — and the cost of composition is supply chain risk.
06 / 31
Act 1 · Why supply chain matters
Assume Breach
The paradigm shift
There is no environment that is 100% safe. Even with high-protection standards, there is always internal risk. The concept of a fully "secure environment" contradicts the Assume Breach paradigm.
Assume Breach means designing your systems as if an attacker already has a foothold somewhere. A disgruntled employee, a compromised VPN, a stolen laptop, a supply chain dependency with a backdoor — the breach vector is secondary. What matters is how your architecture limits the blast radius.
If you assume your environment is secure, you stop looking for indicators of compromise inside it. You trust internal traffic. You grant wide access to build systems. You don't monitor east-west network movement. Assume Breach flips that — every zone is potentially compromised, and controls exist at every boundary.
Threat scenarios to hold in mind: a disgruntled employee with legitimate access, a compromised VPN credential sold on a dark web marketplace, or an insider threat that passes every background check because they weren't a threat when they were hired.
07 / 31
Module 5 · Core principle
"
Supply Chain Principle
You cannot secure what you do not inventory. You cannot monitor what you do not own.
Every control in this module traces back to two things: visibility and ownership.
"
08 / 31
Time to think · Three attack surfaces
① DEVELOP
code + deps
MR review · signed commits
② BUILD
CI/CD + containers
isolated builds · monitoring
③ DELIVER
signing + dist
signed artifacts · SBOM

Packages move through three zones. Each zone lights up when it's under attack — attackers strike at every stage.

Did you notice — the lightning bolts hit from above? Attacks target the pipeline, not just your code.
Time to think and reflect
Knowledge check · pipeline basics
Which stage?
Think about the attack vector
An airport receives new HP network printers. Three days later, SIEM detects malicious traffic from the printers' IP addresses. Which supply chain stage was compromised?
D — Delivery. The printers were compromised during physical delivery — between the manufacturer and the airport. The firmware was legitimate when it left the factory. Somewhere in the logistics chain, it was tampered with. Not a code problem. Not a build problem. A delivery problem.
10 / 31
Time to think · Supply chain attacks
2016
Airport printers
Deliver
2017
NotPetya / MEDOC
Develop + Build
2018
17 Docker Hub images
Build
2019
GitLab runner exploit
Build

Incidents drop onto the timeline — every year, a different stage. The question is not if — it's which stage is weakest in your pipeline.

Did you notice — the shockwave ripples after the last event? Each incident amplifies the next.
Time to think and reflect
Act 2
Attack Surface ①
Development & Dependencies
The code you write — and the code you import.
YOUR CODE
12 / 31
Act 2 · Dependencies
Third-party dependency risk
Two problems from the field
The first problem is sheer volume — a big amount of uncontrolled and potentially vulnerable dependencies that you never explicitly chose. The second is invisibility: transitive dependencies don't show up in your project file. They exist deep in the tree.
Scanners like Trivy and Aqua find known CVEs — but they also find non-exploitable vulnerabilities buried in transitive deps. This creates alert fatigue: your team sees 400 findings, 380 of which are noise, and starts ignoring the list entirely.
When every scan produces hundreds of findings, the team triages less carefully. Real vulnerabilities — the ones actually exploitable in your context — get buried in the noise. Alert fatigue is not laziness. It's a structural consequence of scanning without context. The fix isn't "pay more attention" — it's filtering by reachability: is this vulnerable code path actually called by your application?
13 / 31
Case · NotPetya (2017)
NotPetya
2017 · $10B+ damages
Real CaseNotPetya via MEDOC (2017)
Adversaries accessed the update servers of MEDOC — a legitimate Ukrainian accounting software used by virtually every business in the country. They injected malicious code into a routine software update. The update was signed, distributed through official channels, and installed automatically by trusting customers. The result: a global wiper disguised as ransomware that spread through corporate networks for months. $10B+ in global damages
This wasn't a dependency attack. This was a trusted vendor's code, compromised at the source. Both the development process and the build pipeline were breached. No customer had any reason to suspect the update — it came from the official source, through the official channel.
The lesson: trusting a vendor is not a security strategy. Verification is. If MEDOC's update had included integrity hashes verified by an independent mechanism, the tampered payload would have failed validation on client side.
TRUSTEDM.E.DocPOISONEDupdateNotPetya$10B damageworldwide
Pattern
NotPetya spread via a trusted update channel. The lesson: your update mechanism is an attack surface. If you auto-update dependencies, you're trusting every maintainer in the chain.
14 / 31
Time to think · NotPetya failure chain
🏢
Trusted Vendor
MEDOC
accounting
💀
Compromised
Update server
backdoored
💉
Malicious Code
Injected into
routine update
📦
Distributed
Legitimate
update channel
🌍
GLOBAL SPREAD
$10B+
damages
⚠ No integrity verification at any step

Dominoes fall — trusted vendor to global catastrophe in five steps. One compromised update server. $10 billion in damages.

Did you notice — no verification existed between any step? Each domino trusted the one before it.
Time to think and reflect
Act 2 · Controls
Managing dependencies
Three essential controls
Feature-to-dependency mapping. Every dependency references a feature ID and triggers a threat model update. If nobody can say which feature needs this library, it shouldn't be there.
SBOM (Software Bill of Materials). A formal inventory — direct and transitive dependencies, versions, licenses. Generated automatically in the build pipeline, not maintained by hand.
Dependency firewall. A predefined permitted list of approved packages. Everything else is blocked by default. New packages require explicit approval with a documented justification.
When a dependency has a vulnerability, the question isn't just "how bad is the CVE" — it's "which teams and services use this dependency?" Blast radius awareness means mapping dependencies to owners. When lodash gets a prototype pollution CVE, you know in minutes which 14 services need patching — not hours.
16 / 31
Act 2 · Controls
Securing development
Process controls
Code review — real review, not rubber-stamp. The reviewer should understand the business context of the change, not just scan for syntax. Signed commits — every change has a verified author. If a commit isn't signed, it should be flagged.
Ticket-linked changes. Each code change references a ticket or feature. This creates traceability — if code is touched without a corresponding task, that's a signal worth investigating.
Ownership tracking. If someone modifies code they don't normally touch, and there's no ticket for it, that's suspicious. Not necessarily malicious — but worth a conversation.
Be honest with yourself: has merge request approval on your team become a formality? If the answer is yes — that's the risk. A rubber-stamped review is worse than no review, because it creates the illusion of coverage.
The solution design document defines which dependencies are expected. If a merge request introduces a library not in the design — that's a conversation trigger. The design is the contract; the code should implement it, not expand it silently.
17 / 31
Knowledge check · dependencies
Dependency scenario
Think about transitive risk
A developer adds a new npm package. It passes security audit. Two weeks later, one of its 47 transitive dependencies is found to contain a backdoor. What control would have caught this earliest?
C — Transitive dependency scanning + SBOM. The backdoor was in a transitive dependency — invisible without deep scanning. Code review of the main package wouldn't reveal it. Signed commits verify authorship, not content safety. Feature-to-dependency mapping helps with direct deps but wouldn't catch a transitive backdoor. An SBOM that lists all transitive deps, combined with continuous vulnerability scanning, would flag the compromised package.
18 / 31
Act 3
Attack Surface ②
Build Process
Where your code becomes an artifact — and where that artifact can be poisoned.
CI/CD PIPELINE KEY CODE ENV
19 / 31
Act 3 · Build exploits
Build chain exploits
How artifacts get poisoned
Build environments are high-value targets because they have access to everything: source code, secrets, deployment keys, and the ability to produce artifacts that the rest of the pipeline trusts implicitly.
Known attack patterns include spoofing package paths or dependency sources, injecting additional libraries or compiled components into the build output, leaking secrets embedded in build configuration, compromising build tools themselves, and modifying container registry destination paths to exfiltrate code.
A CI/CD runner typically has read access to the source repository, write access to the artifact registry, and access to secrets needed for deployment. Compromise one runner, and you can inject code into production artifacts, steal credentials, and exfiltrate proprietary code — all without triggering alerts that monitor the production environment itself.
20 / 31
Case · GitLab runner exploit
GitLab runner
2019 · One parameter change
Real CaseGitLab Runner Exploit (2019)
Attackers gained access to a GitLab runner. They changed one parameter: the container registry destination path. The build pipeline continued running normally — same code, same tests, same green checkmarks. But the output artifact was now pushed to an attacker-controlled registry. Worse: the source code contained hardcoded credentials in configuration files, which were exfiltrated along with the code.
One parameter change. Full code exfiltration + credential leak. No alerts fired because the build itself succeeded. The monitoring was watching for build failures, not for changes to build configuration.
Champion's takeaway
Your CI runner has more access than most developers. Treat runner configuration as a security-critical asset, not DevOps plumbing.
21 / 31
Act 3 · Hardening
Build hardening
Key controls
Network isolation for the build environment — no arbitrary outbound access. Build count monitoring: the number of builds should equal the number of merge requests. If it doesn't, something triggered a build outside the normal flow.
MFA for development systems. Service accounts — which often outnumber regular users — need auditing. Logging and alerting on all build pipeline access. Exfiltration prevention through security groups, firewalls, and destination whitelisting.
The ideal: re-running the same merge request produces the same artifact, byte for byte. In practice this is hard — timestamps, non-deterministic compilation, and floating dependency versions all break reproducibility. But working toward it gives you a powerful verification tool: if the artifact doesn't match what the source should produce, something changed.
In many organizations, service accounts outnumber human users 3-to-1. They often have broad permissions, rarely rotate credentials, and are the first target for lateral movement. An audit should answer: how many exist, what do they access, when were credentials last rotated, and can any be decommissioned?
22 / 31
Time to think · Secure vs insecure build
insecure build
Open network access
No build monitoring
Shared service accounts
No artifact signing
No config-change alerts
hardened build
Isolated network
Build count = MR count
Dedicated accounts + MFA
Signed output artifacts
Alerts on all access
FAIL
PASS

Same code. Same pipeline. An X-ray scan reveals the difference — the controls are what separate failure from safety.

Did you notice — the scan line sweeps both lanes identically? The code is the same. Only the controls differ.
Time to think and reflect
Act 4 · Delivery
Delivery risks
Attack Surface ③
Delivery-stage attacks target what happens after the artifact is built and signed. Violation of the signature process, compromising signing keys, targeting distribution systems (CDN, partner portals), and physical delivery compromise — hardware or firmware tampered with before reaching the customer.
You signed the build. But did anyone verify the signature after delivery? A signed artifact means nothing if the customer's installation process doesn't check the signature. And a compromised CDN can replace the signed artifact with a different one entirely.
It sounds old-fashioned, but physical supply chain attacks are real and growing. Hardware intercepted in shipping, firmware modified before installation, pre-loaded malware on devices — these bypass every software-based security control. The airport printer case from the quiz is a real example: network printers compromised somewhere between the manufacturer and the customer.
24 / 31
Case · Airport printers (2016)
Airport printers
2016 · Physical delivery
Real CaseAirport HP Printers (2016)
An airport received new HP network printers through standard procurement. The IT team installed them, connected them to the internal network. Three days later, the SIEM flagged malicious traffic originating from the printers' IP addresses. Investigation revealed the printers had been compromised during physical delivery — the firmware was tampered with before reaching the airport.
Not a code problem. Not a build problem. A delivery problem. The printers passed every procurement check. They looked right, they functioned correctly, they came from an authorized vendor. The compromise happened in the logistics chain between manufacturer and customer.
📦Package
Tampered in transit
🖨️Hardware
Pre-installed malware
🔌USB
Parking lot drops
Pattern
Physical delivery attacks sound exotic until you remember USB drops in parking lots still work. The supply chain includes the physical path to production.
25 / 31
Act 4 · Controls
Signing & verification
Delivery controls
Digital signatures for packages, updates, and components — signed by the producer, verified by the consumer. Internal registry mirroring — don't pull directly from public repos in production. Mirror what you've verified into an internal registry and pull from there.
SBOM included in delivery, verified by the customer. The vendor signs the artifact and includes a bill of materials. The customer verifies the signature and runs their own independent composition analysis.
The vendor signs the artifact and includes an SBOM listing every component and version. The customer verifies the signature against the vendor's public key, then runs their own composition analysis tool against the delivered artifact. If the scan finds a component not in the SBOM, or a component that differs from what's declared, the delivery is flagged. Trust, but verify — independently.
26 / 31
Knowledge check · delivery
Delivery scenario
Think about post-signing
Your team digitally signs all builds and publishes to a private registry. A customer reports that their installed version contains a component not in your SBOM. What most likely happened?
C — Delivery channel compromise. If the SBOM doesn't match the artifact, something changed after signing. The build was signed with a valid SBOM — but the artifact the customer received is different. That means the modification happened during delivery: a compromised CDN, a man-in-the-middle on the download, or a tampered registry mirror. This is exactly why the customer needs to verify the signature independently, not just trust that the download was clean.
27 / 31
Time to think · End-to-end controls
Signed Commit
verified author
Reviewed MR
approved change
Isolated Build
no net access
Signed Artifact
integrity hash
Verified Delivery
sig + SBOM
Scanned Deploy
runtime scan

Six shields arm one by one as the pipeline hardens. But the blinking gaps between them — those are the opportunities you haven't closed yet.

Did you notice — the question marks blink between stations? Every gap is an adversary's opportunity.
Time to think and reflect
Summary · Part 1
Five takeaways
Part 1 complete
Supply chain risks exist at every SDLC stage — not just in your dependencies. Development, build, and delivery each have distinct attack surfaces and need distinct controls.
Assume Breach — there is no secure environment. Design your architecture to limit blast radius, not to prevent all entry.
Dependencies need inventory, ownership, and a firewall. You cannot secure what you do not know about. SBOM, feature-to-dependency mapping, and a permitted-list approach are the foundation.
Build environments are high-value targets — they have access to source, secrets, and deployment. Isolate them, monitor them, and verify that build count matches merge request count.
Signed builds mean nothing if delivery isn't verified. The customer must independently verify the signature and composition. Signing without verification is a false sense of security.
Your role as a Champion: ensure your team maintains an SBOM and knows what's in the dependency tree. Verify that the build pipeline has integrity controls. Flag when a new dependency enters without a feature justification. You don't audit every package — you ensure the system that audits packages is working.
29 / 31
Part 1 · Your results
Part 1 complete
Attack Surfaces
Your score: calculating...
You covered the three attack surfaces — development, build, and delivery — with real cases and specific controls for each. Part 2 goes deeper: Docker, Kubernetes, Jenkins hardening, and the SLSA maturity framework.
If you missed any quiz, re-read the case study it relates to. The cases in Part 1 are the foundation for the technical deep dives in Part 2 — container security, CI/CD hardening, and SLSA levels all build on the attack surface model introduced here.
30 / 31
Bridge · Part 2
Next
Hardening & SLSA
You now know the three attack surfaces. In Part 2: Docker, Kubernetes, and Jenkins deep dives — plus the SLSA framework for measuring your supply chain maturity.
DOCKER KUBERNETES JENKINS SLSA maturity framework
31 / 31