Module 5 · Supply Chain Security
Module 5 · Part 2 of 2
Hardening & SLSA
Docker, Kubernetes, and Jenkins deep dives. The SLSA framework for measuring your supply chain maturity. Specific tools, configurations, and a path forward.
Developers — these sections build the infrastructure context you'll need as a Champion. Focus on the risks described rather than memorizing every command.
DOCKER KUBERNETES JENKINS SLSA maturity framework
01 / 22 · Cover
Time to think · Recap from Part 1
Develop
Inventory deps · SBOM
Signed commits · Ownership
Build
Isolate runners · Monitor
Build count = MR count
Deliver
Sign artifacts · Verify sigs
SBOM in delivery

Part 1 covered the what — three attack surfaces with key controls for each. Part 2 covers the how — specific tools, configurations, and a maturity framework.

Did you notice — each surface has its own color? Orange for develop, red for build, blue for deliver. The same scheme continues throughout Part 2.
Time to think and reflect
Act 5 · Container security
Container images: the trust problem
Docker Hub and beyond
Docker Hub is the default source for container images — and that's the problem. Researchers found 17 backdoored images on Docker Hub, including a fake Nginx image that was actually a crypto miner (XMRig). These images were downloaded millions of times before removal.
Docker's layered architecture creates a second risk: running RUN rm secrets.txt in a Dockerfile doesn't actually delete the file — it's still in a previous layer. Anyone who pulls the image can walk backward through the layers and extract it.
CVEAlpine Linux null root password (CVE-2019-5021)
Alpine Linux — the most popular minimal base image — shipped with a null root password for three years. Any container built on Alpine during that period inherited this vulnerability. The root account had no password set, meaning local access to the container granted immediate root.
Pulling an unverified image is trusting a stranger with your infrastructure. The image runs your code, holds your secrets, and connects to your network. Verify it the way you'd verify a new employee with admin access.
03 / 22
Act 5 · Docker runtime
Docker runtime risks
When isolation fails
Privileged containers (--privileged) effectively grant root access to the host. Container escape becomes trivial — Felix Wilhelm's PoC demonstrated breaking out via cgroup notify_on_release in under 10 lines of code.
The Docker API, when exposed on TCP port 2375 without authentication or TLS, gives anyone on the network full control. Researchers found over 8,000 unsecured Redis instances in public clouds — many of them running in containers with exposed management ports.
The --privileged flag grants a container ALL Linux capabilities, disables seccomp and AppArmor profiles, gives full access to all devices on the host, and allows the container to modify kernel parameters. It effectively removes the isolation boundary between the container and the host. There is almost never a legitimate reason to use it in production.
By default, the Docker daemon runs as root. That's not a bug — it's a design choice you need to work around. Every container inherits the daemon's privilege level unless you explicitly restrict it.
04 / 22
Act 5 · Hardening
Docker hardening
Mitigations
Rootless Docker mode runs the entire daemon as a non-root user, eliminating the most dangerous class of container escapes. User namespaces (--userns-remap) map container root to an unprivileged host user — even if an attacker gets root inside the container, they're nobody on the host.
Drop capabilities using the principle of least privilege. A web server doesn't need CAP_SYS_ADMIN. Drop everything and add back only what's required. Never run --privileged in production. Scan images before deployment. Use only trusted and verified base images.
Step 1: Switch to rootless Docker or enable user namespace remapping. Step 2: Audit every running container for --privileged and remove it. Step 3: Add --cap-drop ALL --cap-add only what's needed. Step 4: Ensure no Docker API ports are exposed without TLS + authentication. Step 5: Set up automated image scanning in your CI pipeline. This sequence can be implemented in a single sprint.
Use official images from verified publishers. Prefer minimal images (Alpine, distroless) — fewer packages mean fewer vulnerabilities. Pin image digests, not just tags. nginx:latest can change without notice; nginx@sha256:abc123... is immutable. Rebuild regularly to pick up base image security patches.
05 / 22
Time to think · Container isolation
Host Kernel
Namespaces · Cgroups
Capabilities · seccomp
AppArmor / SELinux
YOUR APP
--privileged removes most layers

Five concentric rings of isolation expand outward from your app. Each ring adds a security boundary. Then --privileged strips most of them away.

Did you notice — the red dashed circle pulses over the layers? That's what --privileged does — it cuts through the rings you built.
Time to think and reflect
Knowledge check · containers
Container scenario
Think about combined risk
Your Docker container runs as root with the --privileged flag. The Docker API is exposed on TCP port 2375 without authentication. What can an attacker do?
B — Full host compromise. An unauthenticated Docker API lets anyone create containers. Combined with --privileged, the attacker can spawn a new container that mounts the host's root filesystem (-v /:/host), then read/write anything on the host — SSH keys, credentials, other containers' data, kernel modules. This is full host takeover, not just container access.
07 / 22
Act 5 · Kubernetes
Kubernetes security
Cluster-level risks
The Kubernetes API server on port 8080 bypasses all authentication and authorization. Access to etcd means reading or modifying any secret, any config, any deployment in the entire cluster.
By default, every pod can talk to every other pod — no network policies exist unless you create them. Pod security settings like runAsNonRoot, readOnlyRootFilesystem, and allowPrivilegeEscalation: false are opt-in, not default.
Managed services (GKE, EKS, AKS) handle control plane security but don't eliminate risk. You still own workload configuration, network policies, RBAC, and secret management.
etcd is the single source of truth for the entire Kubernetes cluster. With read access, an attacker can extract every secret (database passwords, API keys, TLS certificates), every deployment configuration, and every RBAC rule. With write access, they can modify any of these — deploying malicious workloads, escalating privileges, or redirecting traffic. Securing etcd is securing the cluster.
Managed Kubernetes reduces your attack surface — it does not eliminate it. The cloud provider secures the control plane. You secure everything that runs on it.
08 / 22
Act 6 · CI/CD platforms
Jenkins risks
The default is dangerous
Out of the box, Jenkins has no access control — everyone who can reach the instance is admin. Matrix-based security gives a false sense of protection because jobs still execute on the primary node, where they can access configuration files, secrets storage, and source code from all projects.
Groovy sandbox escapes accounted for 12 RCE vulnerabilities in 2019. Plugin vulnerabilities — including plain-text secrets storage — produced 9 CVEs in the same year. Most Jenkins functionality comes from community plugins that you trust implicitly the moment you install them.
Jenkins core is relatively small. Most of what makes Jenkins useful — Git integration, credential management, Docker builds, Slack notifications — comes from community plugins. Each plugin is a third-party dependency with its own update cycle, its own maintainers (sometimes a single person), and its own security posture. Installing a plugin is granting it access to your build environment, your secrets, and your source code. Most teams don't audit plugin source code before installing.
Nine CVEs for plain-text secrets in plugins. Twelve Groovy sandbox escapes. One year. Jenkins' extensibility is its strength and its biggest attack surface.
09 / 22
Act 6 · Hardening checklist
CI/CD hardening
Interactive checklist
Tap each item to check it off. How many does your pipeline meet today?
Disable job execution on primary node
Jobs on primary = access to everything. Use dedicated agents.
Use Authorize Project plugin
Jobs run as the user who triggered them, not as Jenkins admin.
Set shell to /bin/false on primary
Prevents any accidental script execution on the controller.
Enable matrix security + proper ACL
Principle of least privilege for every user and service account.
Audit plugin versions regularly
Outdated plugins = known vulnerabilities. Automate version checks.
MFA for all CI/CD system access
Stolen password alone shouldn't grant pipeline access.
Service account audit
Count them. Check permissions. Rotate credentials. Decommission unused.
Log all pipeline access and changes
Who accessed what, when. Especially config changes and secret reads.
Network-isolate build runners
No arbitrary outbound access. Whitelist only required endpoints.
Monitor: builds = merge requests
If build count exceeds MR count, something triggered outside normal flow.
0 / 10 checked
The same principles apply, different controls. Workflow permissions: set permissions: to least privilege per job — don't leave the default read-write. GITHUB_TOKEN scope: restrict to the minimum needed; contents: read is enough for most build jobs. Third-party actions: pin by commit SHA, not by tag — tags can be rewritten. Fork PRs: never auto-run workflows on PRs from forks without explicit approval; they can inject code that runs with your secrets.
Practical rule
CI/CD hardening starts with one question: who can push to main and trigger a deploy? If the answer is "anyone on the team," your pipeline is your weakest link.
10 / 22
Knowledge check · CI/CD
CI/CD scenario
Think about access boundaries
Your Jenkins instance uses matrix-based security. A junior developer creates a build job that runs on the primary node. What can they access?
C — Everything on the primary node. Matrix-based security controls who can log in and what they see in the Jenkins UI. It does not sandbox job execution. A job running on the primary node has filesystem access to Jenkins home — which contains configuration XML files, the secrets directory, and workspace directories for every project. The fix: never allow job execution on the primary node.
11 / 22
Time to think · Defense in depth
Network Isolation
MFA + Access Control
Signed Commits + SBOM
Build Monitoring + Alerts
Your Artifact

Five concentric layers grow outward from your artifact. No single control is enough. Layers compound — each one catches what the others miss.

Did you notice — the innermost layer is the smallest? Your artifact is tiny. The protection around it needs to be vast.
Time to think and reflect
Act 7 · SLSA framework
What is SLSA?
Supply chain Levels for Software Artifacts
SLSA is a maturity framework — not all-or-nothing. Each level adds specific protections to your supply chain. You don't need to reach Level 4 to get value. Moving from Level 1 to Level 2 is meaningful improvement.
The approach is pragmatic: familiarize yourself with the model, identify what you already do, and add one practice at a time. SLSA gives your team a shared language for discussing supply chain maturity — the same way OWASP Top 10 gives you a shared language for web security risks.
SLSA is to supply chain what OWASP Top 10 is to web security — a shared language for measuring where you stand. It's not a certification. It's a conversation starter and a roadmap.
13 / 22
Time to think · SLSA levels
L1
Build process exists
Generates provenance
L2
Hosted build service
Signed provenance
L3
Hardened platform
Non-falsifiable provenance
L4
Complete deps
Hermetic builds
← lower maturityMost teams are here (L1–L2)higher maturity →

Four ascending steps — each one taller than the last. Most teams sit between Level 1 and 2. Getting to Level 3 is the meaningful jump.

Did you notice — each level builds on the previous one? You can't skip levels. The height difference represents the effort gap.
Champion's takeaway
SLSA self-assessment isn't pass/fail — it's a maturity ladder. Start at Level 1 (provenance exists) and work up. Most teams are at Level 0 without realizing it.
Time to think and reflect
Act 7 · Self-assessment
SLSA self-assessment
Where does your team stand?
Tap each practice your team currently follows. The counter will show your approximate SLSA level.
Source versioned in VCS
Level 1 · Your code lives in Git (or similar) — not on someone's laptop.
Build process defined and automated
Level 1 · A script or CI config produces the artifact — not a manual process.
Provenance generated
Level 1 · Build outputs include metadata about what was built, when, and from what source.
Build runs on dedicated service
Level 2 · Not a developer laptop. A hosted CI/CD system (Jenkins, GitLab CI, GitHub Actions).
Provenance is signed
Level 2 · Build metadata has a cryptographic signature that can be independently verified.
Build service is hardened / access-controlled
Level 3 · Build environment has MFA, audit logs, restricted network, and monitored access.
Dependencies pinned and complete
Level 3 · Every dependency (direct + transitive) is pinned to an exact version or hash.
SBOM generated and distributed
Level 3 · Software Bill of Materials included with every release.
Hermetic builds (no network during build)
Level 4 · Build environment has no network access. All dependencies pre-fetched and verified.
0 / 9 practices · Approximate level:
15 / 22
Act 7 · Quick wins
Low-hanging fruit
One additional practice decreases risk significantly
Pin all dependencies — direct and transitive. Replace version ranges with exact versions or, better, content hashes. This is an hour of work that eliminates an entire class of supply chain attacks. Run npm shrinkwrap, pip freeze, or go mod vendor and commit the lock file.
Enable SBOM generation in your pipeline. Tools like syft, cyclonedx-cli, or built-in CI features (GitHub Actions has native SBOM) can be added in a single day. Generate on every build, attach to every release.
Audit service accounts in your CI/CD system. One afternoon. Count them, check their permissions, rotate credentials, and decommission any that no one can explain. In most organizations, service accounts outnumber human users 3-to-1.
Don't aim for Level 4. Aim for one level up from where you are now. Each step matters. Perfection is the enemy of improvement — and improvement is what decreases risk.
16 / 22
Knowledge check · SLSA
SLSA scenario
Assess the maturity level
Your team has an automated build on a shared CI server. Builds generate unsigned provenance. Dependencies are listed but not pinned. Where are you on SLSA?
A — Level 1. You have an automated build process that generates provenance — that's Level 1. For Level 2, the provenance would need to be signed and the build would need to run on a dedicated (not shared) service. Unpinned dependencies and unsigned provenance keep you at Level 1. The good news: signing provenance and pinning deps are both achievable in a single sprint.
17 / 22
Practice · Assignment
Your turn
Supply chain posture audit
Audit your project's supply chain posture. Pick one project you work on and walk through these questions. Write your answers down — even rough notes count.
1. Container images: Where do your base images come from? Are they pinned by digest or just by tag? When was the last time someone checked?
2. CI/CD configuration: Can jobs run on the primary node? How many service accounts exist? Who last audited their permissions?
3. SLSA self-assessment: Based on the checklist from this module, what's your current level? What's the single cheapest practice that would move you up one level?
This isn't a graded exercise. It's a mirror. The value is in looking — most teams have never systematically asked these questions about their own pipeline.
Don't manage containers directly? Substitute a dependency tree audit: count transitive deps, check for unpinned versions, and investigate one dependency you've never looked at.
18 / 22
Summary · Part 2
Key takeaways
Six things to remember
1. Container images are code you didn't write. Treat them with the same scrutiny. Pin by digest, scan before deployment, use minimal base images.
2. --privileged is a kill switch for isolation. It removes nearly every security boundary between container and host. Never use it in production.
3. Kubernetes defaults are permissive. No network policies, no pod security, and the API server can bypass all auth. Managed services help but don't eliminate your responsibility.
4. Jenkins primary node is the crown jewel. Jobs running there access everything. Disable execution on primary, audit plugins, enforce MFA.
5. SLSA is a maturity model, not a certification. Know your current level. Aim one level up. Each step meaningfully reduces risk.
6. Low-hanging fruit exists everywhere. Pinning deps, generating SBOMs, and auditing service accounts are each achievable in a single sprint.
19 / 22
Time to think · The full picture
VCS
Source
Signed commits
DEP
Deps
Pinned + SBOM
IMG
Images
Pinned digest
BLD
Build
Isolated runners
SEC
Scan
SAST + SCA
SIG
Sign
Provenance
REG
Registry
Private + verified
K8S
Deploy
Pod security
MON
Monitor
Builds = MRs
SLSA L3 ✓

Nine shields assemble along the pipeline rail. Each one is a control you learned in this module. Together they form a hardened supply chain.

Did you notice — the shields light up in sequence? That's the order of your pipeline: source → deps → images → build → scan → sign → registry → deploy → monitor.
Time to think and reflect
Results
Module complete
Supply Chain Security — Part 2
Total XP
0
Rank
Streak
0
21 / 22
Up next
Coming up
Module 6 — Secret Management
Vaults, rotation, and the art of keeping secrets out of source code. How to manage credentials at scale without losing your mind — or your keys.
22 / 22
Pause & Reflect
Confirm retake
Reset all progress for this module?
Your score, streak, and quiz answers will be cleared. This cannot be undone.