In this lesson you will
- Describe how each module moves from lessons to a lab to a checkpoint, and how the capstone ties the course together
- Name the tools you will use and what the devsecops-lab repository will contain by the end
- Connect recent real supply-chain attacks to the pipeline control that would have stopped or contained them
How this course is built
The course has six modules. Each one follows the same rhythm:
- Lessons. Short, focused pages, each on one topic, with a Try it block you can run on your own machine.
- A lab. Step-by-step work in your own repository. Each lab adds jobs to a single pipeline and ends with a “Check your work” list. Module 6 has a capstone project in place of a lab.
- A checkpoint. A quiz across the whole module, with questions you have not seen in the lessons.
At the end, a capstone brings every job together and asks you to prove the pipeline works by trying to break it. A final assessment then tests the whole course.
Every page ends with its own questions. Answer them all and check them: get at least 7 in 10 right and the page is passed, and the next one opens. You can try as often as you like, and after three tries the answers and explanations are shown.
Module 1 is open to everyone. To go further, sign in with your email address: there is no password, just a one-time link. Your progress is then saved to your account, so it follows you to any device, and the outline beside each lesson shows what you have passed and what is still locked.
What you will build
One public GitHub repository, devsecops-lab, containing a small Python web
service and a pipeline that grows module by module:
| Module | Job you add | What it stops |
|---|---|---|
| 1 | smoke |
A broken build reaching review (the baseline the others build on) |
| 2 | secrets |
Credentials committed to the repository |
| 3 | sast, deps |
Injection bugs in your code and known-vulnerable libraries |
| 4 | iac |
Open security groups, public buckets, unencrypted storage |
| 5 | image |
Vulnerable base images, unknown contents, unsigned artifacts |
| 6 | test, dast, evidence |
Missing security headers, untested changes, and no proof for an auditor |
The tools are free and open source: Gitleaks, Semgrep, pip-audit, Trivy, Checkov, Conftest, Syft, Cosign and OWASP ZAP, run on GitHub Actions. The ideas carry over to GitLab CI, Bitbucket Pipelines, Jenkins and Azure DevOps.
The threat landscape now
The attacks that matter most to a delivery pipeline in the last few years did not exploit the application. They came in through the build: through dependencies, CI configuration and the tokens pipelines hold. Five incidents show the pattern, and each module in this course answers one of them.
xz-utils: a trusted dependency, backdoored (March 2024)
Malicious code was found in versions 5.6.0 and 5.6.1 of XZ Utils, a compression library shipped in many Linux distributions. It was tracked as CVE-2024-3094 with the maximum severity score. The backdoor was planted by a contributor who had spent a long time gaining maintainer trust, and it lived in release tarballs rather than in the visible source tree. CISA advised downgrading to an uncompromised version.
Lesson: popularity is not proof of safety. You need to know exactly which versions you run (module 3) and what is inside every artifact you ship (module 5).
Ultralytics: a pull request that became a release (December 2024)
An attacker opened a pull request against the Ultralytics repository with a
shell payload in the branch name. A workflow triggered by
pull_request_target, which runs with the base repository’s secrets, passed
that name to a shell. The attacker used the foothold to poison the build
cache, and the project’s own publishing workflow then released versions
8.3.41 and 8.3.42 to PyPI with a cryptominer inside.
Lesson: pipeline configuration is code with privileges.
Threat modelling the pipeline itself
covers pull_request_target and injection through untrusted inputs.
tj-actions/changed-files: a third-party action, repointed (March 2025)
Attackers modified the version tags of the popular tj-actions/changed-files
GitHub Action so that every tag from v1 to v45.0.7 pointed at a malicious
commit. Workflows that referenced the action by tag ran code that dumped
secrets into build logs. CISA tracked it as CVE-2025-30066 and advised
rotating every secret the affected workflows could reach.
Lesson: a tag is not a version you reviewed. The module 3 lab pins every action to a full commit SHA, and Securing the repository covers the organisation policy that can require it.
s1ngularity: a pull request title that stole a publishing token (August 2025)
The Nx build system’s maintainers reported that a workflow using
pull_request_target echoed pull request titles into a shell. An attacker
injected code through a title, used the workflow’s read-and-write token to
trigger the publishing workflow, and stole the npm token. Malicious Nx
versions then harvested developers’ credentials and uploaded them to public
repositories.
Lesson: least-privilege tokens and short-lived publishing credentials (module 2), and short-lived deploy credentials (module 6), shrink what one bug can reach.
Shai-Hulud: a self-replicating npm worm (September 2025)
A worm compromised more than 500 npm packages. Once installed, it searched the machine for GitHub tokens and cloud keys, sent them to the attacker, and used stolen npm credentials to publish infected versions of the victim’s other packages. CISA recommended pinning dependencies to known-good versions, rotating developer credentials and enforcing phishing-resistant MFA. In response, npm moved to short-lived sessions, retired classic tokens in December 2025, and pointed CI publishing at trusted publishing with OIDC.
Lesson: long-lived tokens are the fuel these attacks run on. Module 2 teaches you to keep them out of repositories and, better, to stop needing them at all.
Try it: count your own long-lived tokens
Before you start, take stock of your own exposure. On a machine you use for development, run:
# Tokens and keys that tools commonly store in your home directory
ls -la ~/.npmrc ~/.pypirc ~/.aws/credentials ~/.docker/config.json \
~/.config/gh/hosts.yml 2>/dev/null
# Environment variables that look like credentials (names only, not values)
env | cut -d= -f1 | grep -Ei 'token|secret|key|password' || true
Every file or variable you find is something the Shai-Hulud worm would have gone looking for. You do not need to change anything yet; by module 2 you will know which of them can be replaced with short-lived credentials.
How to get the most out of the course
- Do the labs. The lessons explain; the labs are where the controls become real. Each lab assumes the previous one is finished.
- Break things on purpose. Every lab has a step where you add a vulnerability, a fake key or a misconfiguration and watch the pipeline catch it. A check you have never seen fail is a check you cannot trust.
- Answer before you reveal. Choose an answer to each practice question before opening it. The explanations say why the other answers are wrong, which is where most of the learning is.
Further reading
- CISA: Reported supply chain compromise affecting XZ Utils (CVE-2024-3094)
- PyPI blog: Ultralytics attack analysis
- CISA: Supply chain compromise of tj-actions/changed-files (CVE-2025-30066)
- Nx: s1ngularity postmortem
- CISA: Widespread supply chain compromise impacting npm ecosystem
- GitHub: Our plan for a more secure npm supply chain
- GitHub changelog: npm classic tokens revoked
Key takeaways
- Every module follows the same rhythm: short lessons, one hands-on lab, then a checkpoint quiz.
- You build one repository, devsecops-lab, and each lab adds a job to the same pipeline.
- The recent attacks in this lesson came through pipelines, tokens and dependencies, not through the application's own code.
- Each module closes one of the doors those attacks used: secrets, dependencies, infrastructure, artifacts or deployment.
- Module 1 is open to everyone; sign in to save your progress and unlock each later lesson by passing the one before it.
Lesson questions
Answer all 10, then check them. You need 7 right to pass this lesson and unlock the next one. Try as often as you like; after three tries the answers and explanations are shown. These are our own questions, written for this course.
Courses are taught against the frameworks they name. That is alignment, not certification: no course is certified, approved or endorsed by NIST, the DoD, DISA, FedRAMP, the CMMC program or any other agency or standards body, and completing one does not make a system compliant.