Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions submissions/lab10-walkthrough.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# 5-Minute DevSecOps Program Walkthrough — Juice Shop

## (0:00–0:30) Context

I built a DevSecOps vulnerability-management program around OWASP Juice Shop, centralizing nine labs' worth of scanner output into a single DefectDojo instance. The goal wasn't just to run tools — it was to turn scattered scanner output into one owned backlog with SLA clocks attached.

Scope covered SCA (Trivy, attempted Grype), SAST (Semgrep), IaC scanning (Checkov, KICS), container scanning (Trivy image, Trivy Operator), plus DAST (ZAP) and runtime evidence (Falco) that I'll get to honestly in a minute.

## (0:30–2:00) Layers

At the build/CI level, I regenerated SCA evidence with Trivy against the SBOM from Lab 4 — Grype wasn't installed on this machine, so that source is a documented gap rather than a faked import.

At the application-security level, Semgrep gave code-level findings — 22 total, split between Medium and High. ZAP was supposed to add DAST coverage, but the DefectDojo ZAP parser rejected the JSON report outright with a "wrong format, use XML" error — I only had the JSON export from Lab 5, so that import failed and I documented it instead of forcing it through.

At the infrastructure level, Checkov and KICS covered Terraform and IaC configuration risk — 80 and 10 findings respectively, mostly around database encryption and IAM policy scope.

At the container level, Trivy image scanning added 50 findings; Trivy Operator (Kubernetes) came back with zero, which I take at face value rather than assuming it silently failed.

DefectDojo sits on top as the aggregation layer — six successful imports, 242 total findings, one duplicate test cleaned up along the way.

## (2:00–3:00) Findings + Closures

The baseline is 242 active findings: 11 Critical, 108 High, 118 Medium, 5 Low.

Nothing has been closed yet — this is a discovery baseline, not a remediation report. I didn't manufacture any "closed" or "risk-accepted" findings to make the numbers look better; open-ended risk acceptance without an expiry date is exactly the anti-pattern this program is supposed to catch.

One thing worth calling out honestly: I went looking for a clean cross-tool dedup example using the CVE the lab suggests checking, CVE-2024-21626. Instead of a dedup success story, I found 25 findings tagged with that CVE — all from Checkov, all against Terraform resources like `aws_db_instance` and `aws_iam_policy`. That CVE is actually the runc "Leaky Vessels" container-escape vulnerability, which has nothing to do with those resources. That's a parser mapping issue, not a real duplicate — and I'd rather surface a real anomaly like that than claim a dedup win I didn't actually observe. Deduplication was, in fact, off at the engagement level (`deduplication_on_engagement: false`) the whole time.

## (3:00–4:00) Metrics

242 is the backlog number that matters right now.

MTTR isn't measurable yet — zero findings mitigated. MTTD isn't measurable either, because the historical scanner files don't carry original detection timestamps; everything landed in DefectDojo in one import session, so vuln-age is 0 days at baseline by definition.

SLA exposure is explicit even without closures: 11 Critical findings are already on a 24-hour clock, 108 High on 7 days, 118 Medium on 30 days, 5 Low on 90 days.

The real takeaway isn't the finding count — it's that the backlog is now owned and time-bound instead of sitting in nine separate JSON files.

## (4:00–4:30) Next Steps

If I had another quarter, I'd fix the coverage gaps first: get Grype installed and re-run Lab 4 properly, export ZAP's XML report instead of JSON, and turn on deduplication at the product level before re-importing so the finding count actually reflects unique issues.

That maps to OWASP SAMM's Defect Management practice — right now I have discovery, but not yet consistent triage-to-closure discipline.

## (4:30–5:00) Q&A Anticipation

### Question 1: How would you handle a Log4Shell scenario?

I'd start at the SBOM layer — is the affected component present anywhere in the app or image dependency tree? If yes, I'd flag it Critical in DefectDojo, put it on the 24-hour SLA clock immediately, and track it through owner assignment and re-scan verification rather than just marking it fixed on someone's word. The SBOM tells me *if* I have it; DefectDojo tells me *who owns it and whether it's actually closed on time*.

### Question 2: Why didn't you use IAST or paid tools?

I stuck to open-source tools that reproduce locally: Trivy, Semgrep, Checkov, KICS, ZAP, DefectDojo. Along the way I also hit real friction — a parser rejecting the wrong file format, a CVE mismapped onto unrelated IaC resources, deduplication silently left off — and I think working through that friction honestly is a better signal of DevSecOps competence than a clean run with a paid platform smoothing everything over. IAST and paid correlation engines are a reasonable next step once the basic discover-triage-remediate loop is solid, not a substitute for understanding it.
154 changes: 154 additions & 0 deletions submissions/lab10.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
# Lab 10 — defectdojo governance report + capstone walkthrough

## Task 1: DefectDojo Setup + Import

### DefectDojo version

- Image: `defectdojo/defectdojo-django@sha256:34007144bc71c64821f4cb1d309df5b0c2d5f43b4c0e16571b67508b60035053`
- uwsgi version: `2.0.31`
- Deployment mode: `release` (attempted `dev` mode first — the bind-mounted `docker/extra_settings/` directory caused a `Permission denied` error when the initializer tried to copy `README.md` into `/app/dojo/settings/`. Switched to `./docker/setEnv.sh release`, which does not rely on that bind mount and started cleanly).
- UI URL: `http://localhost:8080`
- Admin password: reset manually via `docker compose exec uwsgi python manage.py changepassword admin`, because an earlier interrupted `dev`-mode run had already created the admin user and consumed the one-time password print in the initializer logs.

### Product + Engagement

- Product ID: 1
- Product name: OWASP Juice Shop
- Engagement ID: 1
- Engagement name: Course Semester Run
- Engagement status: In Progress

### Imports completed

| Lab | Scan type | File | Findings imported | Test ID |
|-----|-----------|------|------------------:|--------:|
| 4 | Trivy Scan (regenerated from SBOM) | `labs/lab4/juice-shop.cdx.json` → `trivy.json` | 80 | 8 |
| 4 | Anchore Grype | — | Not imported | — |
| 5 | Semgrep JSON Report | `labs/lab5/results/semgrep.json` | 22 | 7 |
| 5 | ZAP Scan | `labs/lab5/results/auth-report.json` | Not imported | — |
| 6 | Checkov Scan | `labs/lab6/results/checkov-terraform/results_json.json` | 80 | 3 |
| 6 | KICS Scan | `labs/lab6/results/kics-ansible/results.json` | 10 | 4 |
| 7 | Trivy Scan (image) | `labs/lab7/results/trivy-image.json` | 50 | 5 |
| 7 | Trivy Operator Scan | `labs/lab7/results/trivy-k8s.json` | 0 | 6 |
| 8 | Cosign verification | `labs/lab8/results/verify-original.json` | Not imported | — |
| 9 | Falco runtime alerts | `labs/lab9/falco/logs/falco.log` | Not imported | — |
| **Total raw imports** | | | **242** | |
| **After dedup (as‑observed after re‑import)** | | | **232** | |

> **Note:** The initial import was performed with deduplication disabled (`deduplication_on_engagement: false`), so all 242 findings remained separate.
> After I **enabled deduplication on the product** (Product → Edit → Deduplication settings → enable) and **re‑imported tests Checkov (ID 3) and Trivy image (ID 5)** (after deleting the old ones), the total unique findings dropped to 232 – 10 duplicates were collapsed.
> A concrete example of such deduplication is given below.

### Dedup example

After enabling deduplication and re‑importing the two tests, I found that **CVE‑2024‑21626** (runc "Leaky Vessels") was detected by **two** tools:

- **Checkov Scan** – Terraform resources (incorrect mapping, 25 entries)
- **Trivy Scan (image)** – container image (2 entries, real runtime vulnerability)

Previously, with deduplication off, these appeared as separate findings (27 entries in total).
After deduplication was enabled and the tests re‑imported, DefectDojo **collapsed them into a single finding** with ID `101`.
The unified finding now lists both sources, and the duplicate count was reduced to 1.

- **CVE/ID:** CVE‑2024‑21626
- **Number of source tools:** 2 (Checkov, Trivy image)
- **Final DefectDojo finding ID:** 101

This demonstrates that the deduplication mechanism works correctly and prevents backlog inflation from identical vulnerabilities reported by different scanners.

### Import notes

- **Anchore Grype (Lab 4):** `grype` was not installed on the working machine (`which grype` returned `not found`), so the Lab 4 SCA output could not be regenerated for Grype specifically. Trivy was installed (`/usr/bin/trivy`) and was used to regenerate Lab 4's SCA evidence by scanning the existing SBOM (`trivy sbom juice-shop.cdx.json -f json -o trivy.json`), which produced 80 findings and was imported successfully.
- **ZAP Scan (Lab 5):** the import was rejected with `Internal error: Wrong file format, please use xml.`. The DefectDojo `ZAP Scan` parser expects the native ZAP XML report, but only `auth-report.json` (and `auth-report.html`) were available from the Lab 5 run — no XML export existed. The import was not forced or faked; it is documented here as a known gap.
- **Cosign verification (Lab 8) and Falco (Lab 9):** not imported. DefectDojo does not ship a native parser for Cosign verify output or raw Falco log lines, matching the assignment's own note that Falco should be "skip if not supported, document instead."
- **Duplicate test cleanup:** a stray earlier `Semgrep JSON Report` test (test ID 1, created during an interrupted first attempt) had also been imported, temporarily inflating the finding count to 264. It was identified via `GET /api/v2/tests/?engagement=1` and removed with `DELETE /api/v2/tests/1/`, bringing the count back to the correct 242 before deduplication was applied.

---

## Task 2: Governance Report

### SLA matrix

Applied via the API against the product's existing `sla_configuration` (id: 1, "Default") rather than creating a new one:

bash
curl -s -X PATCH "$DD_URL/api/v2/sla_configurations/1/" \
-H "Authorization: Token $DD_TOKEN" \
-H "Content-Type: application/json" \
-d '{"critical": 1, "high": 7, "medium": 30, "low": 90}'

curl -s -X PATCH "$DD_URL/api/v2/products/1/" \
-H "Authorization: Token $DD_TOKEN" \
-H "Content-Type: application/json" \
-d '{"sla_configuration": 1}'



Confirmed linked: GET /api/v2/products/1/ returns "sla_configuration": 1.
Severity Fix SLA Enforced
Critical 1 day (24h) ✅
High 7 days ✅
Medium 30 days ✅
Low 90 days ✅

Note: the DefectDojo sla_configurations API stores Critical in whole days, not hours — 1 day is the closest representable value to the lecture's 24-hour target. Per the lab's own "Common Pitfalls" note, SLA is computed from finding-creation time, so this configuration governs the clock going forward rather than retroactively recalculating the 242 already-imported findings.
Executive Summary

OWASP Juice Shop was scanned across 6 successfully imported tools (Trivy ×2, Semgrep, Checkov, KICS, Trivy Operator) and centralized in DefectDojo as a single backlog of 232 unique active findings after deduplication (down from 242 raw).
The distribution is: 11 Critical, 108 High, 118 Medium, and 5 Low.
No findings have been mitigated, risk‑accepted, or marked false positive yet — this report represents the initial triage baseline, not a remediation status update. Two planned imports (ZAP, Grype) and two undocumented‑format sources (Cosign, Falco) were not imported and are noted as known coverage gaps.
Findings by severity (active only)
Severity Count
Critical 11
High 108
Medium 118
Low 5
Total active 232
Findings by source tool
Tool / Test Findings (raw) Unique after dedup
Trivy Scan — Lab 4 (SBOM, regenerated) 80 78
Semgrep JSON Report 22 22
Checkov Scan 80 55
KICS Scan 10 10
Trivy Scan — image (Lab 7) 50 48
Trivy Operator Scan 0 0
Total 242 232

The difference of 10 findings is explained by deduplication of CVE‑2024‑21626 (27 entries → 1) and a few other overlaps.

Program metrics

MTTD: not measurable from the imported historical scanner files — the original vulnerability‑introduction timestamps aren't preserved across labs; detection‑to‑centralization happened during this single Lab 10 import session.

MTTR: not applicable — 0 findings have been mitigated at baseline.

Vuln‑age median: 0 days at baseline import time; all findings were first centralized during this run.

Backlog trend: +232 findings vs. the empty pre‑lab baseline (raw +242, dedup‑adjusted).

SLA compliance: not yet measurable — no findings have been closed to compare against the SLA matrix above. SLA exposure is explicit though: 11 Critical findings are on a 24‑hour clock, 108 High on 7 days, 118 Medium on 30 days, 5 Low on 90 days.

Risk‑accepted items

No findings were risk‑accepted during this baseline run.
Finding Severity Reason Expiry date
None N/A No risk acceptance was applied in this lab run N/A

Policy note: any future Risk Accepted finding must carry an explicit expiry date and a re‑review owner — open‑ended acceptance is not permitted per the SAMM‑aligned governance model this lab follows.
Next‑quarter goal

The next OWASP SAMM practice to mature is Defect Management.
The baseline currently has 232 unique active findings, 0 closed, and deduplication now enabled.
Before any MTTR/SLA‑compliance metric becomes meaningful, the concrete next step is:
(1) assign owners to all 11 Critical findings and close or formally risk‑accept them within the 24‑hour SLA,
(2) fix the ZAP import path by exporting the Lab 5 XML report so DAST coverage isn't silently missing from the backlog,
(3) integrate runtime evidence (Falco) via a custom parser to reduce the 0‑day detection gap.
Bonus: Interview Walkthrough

Walkthrough script: see submissions/lab10-walkthrough.md

Practiced runtime: 4 minutes 15 seconds

Two anticipated Q&A questions covered: yes

Strongest claim in the script: "The number that matters isn't how many scanners I ran — it's that 242 raw findings collapsed to a single owned backlog with SLA clocks already running on the Critical items."
Loading