Exercise 2: Detection Guardrails
Exercise 2: Detection Guardrails (~12 min)
Goal: Experience 3 distinct GHAS detection mechanisms operating at different points in the workflow.
📝 Open
docs/detection-worksheet.md— record your observations for each detection mechanism as you complete the steps below.
Push time PR review time Merge time
│ │ │
▼ ▼ ▼
┌──────────┐ ┌───────────────┐ ┌──────────────────┐
│ Push │ │ CodeQL + │ │ Required status │
│Protection│ │ Dependency │ │ checks block │
│ blocks │ │ Review │ │ merge │
│ secrets │ │ find issues │ │ │
└──────────┘ └───────────────┘ └──────────────────┘
2a. Push Protection — Blocks Secrets at Push Time
- Open
vulnerable-samples/secret-leak.jsand review the hardcoded API key - Attempt to push the file:
git add vulnerable-samples/secret-leak.js
git commit -m "Add API integration module"
git push origin workshop/secure-by-design
- Observe: The push is BLOCKED by push protection
remote: error: GH013: Repository rule violations found for refs/heads/workshop/secure-by-design.
remote:
remote: - GITHUB PUSH PROTECTION
remote: —————————————————————————————————————————
remote: Resolve the following violations before pushing again
remote:
remote: — Push cannot contain secrets
- Note: This happened BEFORE the code entered the repository. The secret never reached GitHub.
To proceed with the remaining exercises, remove the secret from the file or use
git resetto undo the commit. In a real workflow, you would rotate the credential immediately.
2b. Code Scanning — CodeQL Finds Insecure Patterns in PR
- Push
vulnerable-samples/sql-injection.jsto the feature branch (this push will succeed — no secrets):
git add vulnerable-samples/sql-injection.js
git commit -m "Add database query module"
git push origin workshop/secure-by-design
- Open a Pull Request from
workshop/secure-by-design→main - Wait for the CodeQL analysis to complete (1–3 minutes)
-
Observe: CodeQL findings appear on the PR:
- Alert: SQL injection vulnerability
- Severity: High / Error
- Location:
sql-injection.js, line with string concatenation in SQL query
-
Trace the Data Flow Path — Click the CodeQL alert → click “Show paths”:
SOURCE: req.query.username ← Untrusted user input from HTTP request ↓ FLOW: const query = "..." + username + "..." ← Tainted data concatenated into SQL string ↓ SINK: pool.query(query) ← SQL execution with tainted dataCodeQL didn’t just find “string concatenation near SQL” — it tracked the data flow from the HTTP request parameter all the way to the database query execution. This is semantic analysis, not pattern matching.
-
Why did CodeQL catch ALL 3 patterns? Our
sql-injection.jscontains 3 different SQL injection techniques:# Pattern Code Grep Catches? CodeQL Catches? 1 String concatenation "..." + username + "..."✅ (regex for +)✅ 2 Template literal `...${category}...`❌ (different syntax) ✅ 3 DELETE with param "DELETE ... " + userId⚠️ (maybe) ✅ A simple
grepor regex scanner would miss pattern 2 (template literals use${}, not+). CodeQL catches ALL 3 because it uses semantic data flow analysis — it understands thatreq.query.*andreq.params.*are sources of untrusted input, regardless of the string construction method. - Note: These vulnerabilities were caught AFTER push but BEFORE merge. The vulnerable code is in the repository but cannot reach
mainbecause the required status check (CodeQL) blocks the merge.
[!NOTE] CodeQL Query Suites and Threat Coverage
Suite Coverage Threat Rows False Positives Default High-precision security queries Rows 1-2 Few Extended Default + lower-confidence security Rows 1-2 + edge cases Moderate Security-and-Quality Extended + code quality/maintainability Rows 1-2, 8, 9 More For this workshop, we use the Default suite. For regulated production environments, consider Extended to broaden threat coverage.
2c. Dependency Review — Flags Vulnerable Dependencies in PR
- Push
vulnerable-samples/package.jsonto the feature branch:
git add vulnerable-samples/package.json
git commit -m "Add project dependencies"
git push origin workshop/secure-by-design
- Open (or update) the Pull Request
- Observe: The dependency review surfaces:
- Vulnerable package:
lodash@3.10.1 - CVEs: Multiple known vulnerabilities (e.g., Prototype Pollution)
- Fix version: Upgrade to
lodash@4.17.21
- Vulnerable package:
- Note: This was caught in the PR review, with CVE details and the specific fix version.
Update the Threat Model
After completing all three detection scenarios, update THREAT-MODEL.md — fill in the first 3 rows of the attack vectors table:
| # | Attack Vector | Current Control | Gap? |
|---|---|---|---|
| 1 | Secret leaked in commit | ✅ Push protection | Covered |
| 2 | Insecure code pattern (e.g., SQL injection) | ✅ CodeQL code scanning | Covered |
| 3 | Vulnerable dependency in supply chain | ✅ Dependency review | Covered |
Key Insight
Push protection stops secrets BEFORE they enter the repository. Code scanning and dependency review stop vulnerabilities BEFORE they reach
main. Each operates at a different point in the workflow — together, they form a layered defense.
[!TIP] Run
scripts/verify-exercise2.shto validate your Exercise 2 completion.