`SLUG_RE` in `lib/blog.ts` (added in #61) is the central guard against an entire class of stored-XSS bugs — the sitemap comment in `app/sitemap-pages.xml/route.ts` explicitly notes that raw interpolation is safe only because of this regex.
The PR tightened the regex to forbid empty strings, leading/trailing hyphens, and consecutive hyphens. None of those tighter constraints are protected against regression — a future contributor could loosen the regex and the only signal would be a CodeQL re-flag (if that scanner is still in place) or someone manually noticing.
Fix
Add a small test file exercising `parseSlug` boundary cases:
- accepts: `"a"`, `"a-b"`, `"a-b-c"`, `"abc123"`, `"a1-b2"`
- rejects: `""`, `"-a"`, `"a-"`, `"a--b"`, `"A"`, `"a_b"`, `"a b"`, `"a.b"`, `"<script>"`, `42` (non-string)
Scope note
This will be the first test in the repo, so wiring up the runner is part of the scope. Vitest is the natural choice given the Next 16 + React 19 + ESM stack.
Found during PR review of #61.
`SLUG_RE` in `lib/blog.ts` (added in #61) is the central guard against an entire class of stored-XSS bugs — the sitemap comment in `app/sitemap-pages.xml/route.ts` explicitly notes that raw interpolation is safe only because of this regex.
The PR tightened the regex to forbid empty strings, leading/trailing hyphens, and consecutive hyphens. None of those tighter constraints are protected against regression — a future contributor could loosen the regex and the only signal would be a CodeQL re-flag (if that scanner is still in place) or someone manually noticing.
Fix
Add a small test file exercising `parseSlug` boundary cases:
Scope note
This will be the first test in the repo, so wiring up the runner is part of the scope. Vitest is the natural choice given the Next 16 + React 19 + ESM stack.
Found during PR review of #61.