Put SAST in the pipeline without drowning in noise
Continues from the last build: Secrets are rotated, purged, and scanned for on every commit.
Gitleaks runs on every commit now, so the next hardcoded key gets caught before it ships.
What you'll build
Every pull request against it now runs Semgrep with the OWASP Top Ten and language rulesets, uploads SARIF results to the repo's Security tab, and fails the check on new high severity findings. A justified .semgrepignore and two custom rules for your own SQL injection and IDOR patterns keep the noise low. Diff aware baselining gates pull requests on new findings only, while the existing backlog is tracked separately on a schedule so turning the scanner on did not stop the world. The CI output points a developer at the exact file, line, and fix, not just a finding count.
See how we teach, before you sign up
You don't just get code dumped on you. Every starter file and every solution is explained line-by-line, in plain English. Here's one real file from this project:
# Generated build artifacts, never hand edited app/dist/ # Vendored client SDK, upstream code we do not own app/src/vendor/stripe-mock/ # Fixture data with intentionally fake but realistic looking secrets app/test/fixtures/*.json
Reading this file
app/dist/Build output is regenerated from source, scanning it duplicates whatever the source scan already found.# Vendored client SDK, upstream code we do not ownYou cannot fix upstream code through this pipeline, and it has its own security process.app/test/fixtures/*.jsonScoped to a specific file pattern in a specific directory, not a blanket test/ exclusion.
Every ignored path carries a comment explaining why it is safe, scoped as narrowly as possible.
That's 1 of 8 explained code blocks in this single project.
The build, milestone by milestone
- 1
Run Semgrep locally and read real findings
5 guided stepsBefore this goes into CI you need to know what a clean local run actually looks like, so you can separate real findings from noise when the pipeline reports them under time pressure.
- 2
Add a Semgrep job that gates every pull request
6 guided stepsLocal runs catch what you remember to run. A CI gate catches what nobody remembers to run, on every pull request, before merge.
- 3
Cut the noise with a .semgrepignore and two rules of your own
6 guided stepsA scanner that cries wolf on test fixtures and migration scripts gets muted within a week. Custom rules encode the specific mistakes your team already made once, which a generic ruleset has no way to know about.
- 4
Gate pull requests on new findings, track the backlog separately
5 guided stepsIf turning on SAST instantly fails every open PR because of pre-existing findings nobody has time to fix today, teams disable the scanner instead of paying down the debt. Diff aware gating lets you adopt SAST without stopping the world.
- 5
Make a failing check tell a developer exactly what to fix
6 guided stepsA scanner nobody can act on is theater. If a developer sees Semgrep failed with no file, line, or suggested fix, they either guess or bypass the check. The gate has to speak the language of go here, do this.
What's inside when you start
You'll walk away with
This is portfolio-grade. Build it free.
Sign up to unlock every milestone step-by-step, the code skeletons, full reference solutions, and checkable tasks, with your progress saved as you build.
Start building