Back to path
IntermediateLedgerline · Project 5 of 12 ~6h· 5 milestones

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.

Semgrep SASTSARIF and GitHub code scanningCustom Semgrep rule authoringDiff aware CI gatingOWASP Top 10 triageLeast privilege GitHub Actions permissionsCI/CD pipeline security

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:

.semgrepignoretext
# 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. 1

    Run Semgrep locally and read real findings

    5 guided steps

    Before 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. 2

    Add a Semgrep job that gates every pull request

    6 guided steps

    Local runs catch what you remember to run. A CI gate catches what nobody remembers to run, on every pull request, before merge.

  3. 3

    Cut the noise with a .semgrepignore and two rules of your own

    6 guided steps

    A 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. 4

    Gate pull requests on new findings, track the backlog separately

    5 guided steps

    If 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. 5

    Make a failing check tell a developer exactly what to fix

    6 guided steps

    A 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

3 starter files, ready to clone
5 guided milestones
5 full reference solutions
8 code blocks explained line-by-line
5 "is it working?" checks
6 interview questions it prepares you for

You'll walk away with

security/semgrep-triage.md documenting every local finding as true or false positive with an OWASP Top 10 mapping
.github/workflows/semgrep.yml running on every pull request, uploading SARIF, and failing on new high severity findings
.semgrepignore with a justified comment on every line
security/semgrep-rules/ containing two custom rules for the SQL injection and IDOR patterns from rungs 2 and 3
Diff aware baseline gating so pull requests fail only on new findings, plus a scheduled workflow tracking the full backlog
A demonstrated fixed versus flagged pull request pair proving the gate is precise, not noisy

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