Change record · class-waitlist-demo
CSD-3 · show phone and date of birth on the roster
What changed and where
- Result
- 2 check(s) failed: PHI guard, Semgrep SAST
- Jira
- CSD-3
- Pull request
- None (push build)
- Branch
demo-security-issue- Commit
25a095f- CI run
- Local run
- Tests
- 11 of 11 passed
- Built
- Nov 9, 2026, 12:10 AM ET
Checks
| Check | Group | Catches | Result |
|---|---|---|---|
| ESLint | Code quality | Bugs, unused code, complex functions | PASS |
| PHI guard | Security | Patient data patterns | FAIL |
| Semgrep SAST | Security | XSS, eval, unsafe storage | FAIL |
| Gitleaks | Security | Secrets in code | PASS |
| npm audit | Security | Vulnerable packages | PASS |
| Playwright + axe | Tests | Acceptance criteria, WCAG 2.1 AA | PASS |
Open the full Playwright report (every test, every step, screenshots of failures)
Tool output
PASS Code quality: ESLint
(no output)
FAIL Security: PHI guard
PHI guard: 4 problem(s) found.
public/data.js:17 [phone] Phone number pattern
{ name: 'Alex Rivera', email: 'alex.rivera@example.com', status: 'confirmed', phone: '616-555-0142', dob: '1990-04-12' }
public/data.js:17 [phi-field] Patient data field (phone, dob, ssn, mrn, diagnosis, insurance)
{ name: 'Alex Rivera', email: 'alex.rivera@example.com', status: 'confirmed', phone: '616-555-0142', dob: '1990-04-12' }
public/data.js:18 [phone] Phone number pattern
{ name: 'Sam Lee', email: 'sam.lee@example.com', status: 'confirmed', phone: '616-555-0187', dob: '1985-11-02' },
public/data.js:18 [phi-field] Patient data field (phone, dob, ssn, mrn, diagnosis, insurance)
{ name: 'Sam Lee', email: 'sam.lee@example.com', status: 'confirmed', phone: '616-555-0187', dob: '1985-11-02' },
Remove the data, or use fictional test data that does not look like PHI.FAIL Security: Semgrep SAST
┌─────────────┐
│ Scan Status │
└─────────────┘
Scanning 64 files tracked by git with 3 Code rules:
Scanning 12 files with 3 js rules.
┌────────────────┐
│ 1 Code Finding │
└────────────────┘
public/app.js
❯❯❱ dom-xss-innerhtml-concat
HTML is built from a variable. If the value comes from a user (for example a name), a script can run
in the browser (XSS). Use textContent or createElement instead.
158┆ contact.innerHTML = '<small>' + (s.phone || '') + ' · ' + (s.dob || '') + '</small>';
┌──────────────┐
│ Scan Summary │
└──────────────┘
Some files were skipped or only partially analyzed.
Scan was limited to files tracked by git.
Ran 3 rules on 12 files: 1 finding.PASS Security: Gitleaks
○
│╲
│ ○
○ ░
░ gitleaks
12:09AM INF scan completed in 264ms
12:09AM INF no leaks foundPASS Security: npm audit
found 0 vulnerabilities
PASS Tests: Playwright + axe
Running 11 tests using 1 worker ✓ 1 [chromium] › tests/accessibility.spec.js:14:3 › Accessibility › A11Y: class page has no WCAG 2.1 AA violations (1.5s) ✓ 2 [chromium] › tests/accessibility.spec.js:20:3 › Accessibility › A11Y: messages and roster have no WCAG 2.1 AA violations (1.6s) ✓ 3 [chromium] › tests/registration.spec.js:6:3 › Registration (baseline) › a person can register for a class with open seats (741ms) ✓ 4 [chromium] › tests/registration.spec.js:15:3 › Registration (baseline) › name and a valid email are required (693ms) ✓ 5 [chromium] › tests/waitlist.spec.js:23:3 › CSD-1 Class waitlist › AC1: a full class puts a new person on the waitlist (932ms) ✓ 6 [chromium] › tests/waitlist.spec.js:33:3 › CSD-1 Class waitlist › AC2: the waitlist keeps the order people joined (1.2s) ✓ 7 [chromium] › tests/waitlist.spec.js:44:3 › CSD-1 Class waitlist › AC3: the same email cannot register twice (seat or waitlist) (1.1s) ✓ 8 [chromium] › tests/waitlist.spec.js:54:3 › CSD-1 Class waitlist › AC4: when a person cancels, the FIRST waitlist person gets a seat offer (1.2s) ✓ 9 [chromium] › tests/waitlist.spec.js:71:3 › CSD-1 Class waitlist › AC5: a person can accept the offer inside the hold window (1.2s) ✓ 10 [chromium] › tests/waitlist.spec.js:83:3 › CSD-1 Class waitlist › AC6: an offer expires after 24 hours and the next person gets it (1.2s) ✓ 11 [chromium] › tests/waitlist.spec.js:100:3 › CSD-1 Class waitlist › AC7: confirmed plus offered seats never go above capacity (1.3s) 11 passed (13.9s)
Approvals
The PR approvals on GitHub are the system of record. Use this space if a printed copy is needed.
Product owner (spec approved)
Developer reviewer
Dev lead (High risk only)