Secure SDLC, Tooling & Fuzzing
Software Security · Nutthakorn Chalaemwongwan
Today
- Security across the SDLC ("shift left")
- SAST · DAST · SCA · secret scanning · fuzzing
- Triaging findings by CWE
- 🏁 Game: Bug Triage Race + a Fuzzing Race
Recap — Week 1
- Threat modeling finds design flaws (before code)
- This week: find implementation flaws — automatically, at scale
- Same goal: catch it early, cheap to fix
Security across the SDLC
Requirements → Design → Code → Build → Test → Deploy → Operate
- Each phase has security activities
- Shift left: find issues early — cheaper to fix
- DevSecOps = security automated into the pipeline
The tooling families
SAST vs DAST in one line
- SAST — reads the code, finds bug patterns (no running). Many false positives.
- DAST — attacks the live app from outside. Fewer FPs, misses source-level issues.
Use both — they find different things.
Worked example: what each tool catches
@app.route("/user")
def user():
name = request.args.get("name")
q = "SELECT * FROM users WHERE name='%s'" % name # SAST → CWE-89
return db.execute(q).fetchall()
AWS_SECRET_ACCESS_KEY = "hK8pQ2mN5vX9wZ3rT6yU1sA4bC7dE0fG2hJ5kL8" # Gitleaks → CWE-798
- Semgrep (SAST): flags the string-built SQL query (CWE-89)
- Gitleaks (secret scan): flags the hardcoded key — must be a real-looking secret; the AWS-docs example key (
wJalr...EXAMPLEKEY) is a known public string and won't fire any rule - DAST/fuzzer: would catch a crash/SQLi by hitting
/user, not reading it - Same file also plants command injection, a weak
md5hash, anddebug=True— Task 1 grades all five
Fuzzing — how real CVEs are found
- Feed random/mutated inputs, watch for crashes
- Coverage-guided (libFuzzer/AFL++) explores new code paths
- Pair with sanitizers (ASan) to pinpoint the bug
# run inside labs/toolbox — Apple clang has no libFuzzer runtime
clang -g -fsanitize=address,fuzzer harness.c -o fuzz
mkdir -p corpus && printf 'FUZ' > corpus/seed && ./fuzz corpus
How fuzzing finds it
![A coverage-guided fuzzer reaches a bug a static analyzer misses: the harness has four nested byte checks (F, U, Z, Z) and the fourth reads data[3] with no size>3 guard, so the input 'FUZ' reads one byte out of bounds. SAST reads the code and stays silent; the fuzzer mutates inputs and is rewarded for each new branch reached, climbing random -> F -> FU -> FUZ until the unguarded read crashes under AddressSanitizer, which writes a reproducer file. SAST and fuzzing are complements, not substitutes.](img/fuzzing-finds-it.svg)
Try it — what actually crashes this harness
Type bytes, or pick a preset. Each cell is one if in the real source.
Triage: not every finding is a bug
- True positive vs false positive
- Map each to a CWE + severity
- Prioritize by exploitability × impact
- Noise kills trust in tools — triage well
Try it — which bug is this, really?
Seven raw findings from a real scan. Map each back to the one bug underneath.
Tools you'll meet
- Trivy — the SCA scanner you'll actually run this lab (dependency scan today; image + IaC scanning return in W12/13)
- SonarQube, GitHub Advanced Security (GHAS) — quality-gate/SAST-in-the-repo tools you'll see in industry/internships, not used in this lab
- Address technical debt early — cheaper than re-work later
🏁 Game — Bug Triage Race
- Run Semgrep + Gitleaks on the flawed repo
- Score = true positives − misclassified · live scoreboard
docker run --rm -v "$PWD/vulnerable-repo:/src" semgrep/semgrep \
semgrep --config p/default --config p/owasp-top-ten /src
docker run --rm -v "$PWD/vulnerable-repo:/repo" zricethezav/gitleaks:latest \
detect -s /repo -v --no-git
🐝 Mini-game — Fuzzing Race
- First team to make the provided target crash wins
- One crash → one root-cause note
- Full fuzz→exploit lab returns in Week 11
Lab 2 — deliverable
📋 Worksheet 2 —
labs/week02-sdlc-tooling/worksheet.md(Part 3) · kickoff:bash scan.sh(Semgrep ×2 rulesets + Gitleaks--no-giton./vulnerable-repo)
- A findings triage table: tool, CWE, severity, TP/FP, fix idea (3 TP + 1 FP, justified)
- 1 fuzzing crash with a one-line root cause
- Trivy SCA scan of the NoteVault project target
- A security CI gate built from Week 15's
security-ci.yml - One SAST blind spot you found by hand
- Defend/fix: remediate all 5 planted flaws, before/after diff — this alone is 25 of 100 rubric points
- + Audit the AI and EiPE / Prompt Problem (see worksheet)
Key takeaways
- No single tool finds everything — layer SAST/DAST/SCA/fuzzing
- Triage by CWE + severity; kill the noise
- Fuzzing is the highest-yield bug finder — automate it
Questions?
Next week: Cryptography used correctly