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

CheckGroupCatchesResult
ESLintCode qualityBugs, unused code, complex functionsPASS
PHI guardSecurityPatient data patternsFAIL
Semgrep SASTSecurityXSS, eval, unsafe storageFAIL
GitleaksSecuritySecrets in codePASS
npm auditSecurityVulnerable packagesPASS
Playwright + axeTestsAcceptance criteria, WCAG 2.1 AAPASS

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 found
PASS 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)