Summary
A hackbrowser crawl crashed the whole worker (exit code 1) mid-run when a page element's id contained a character that is invalid in a CSS selector. The worker builds a label lookup as `label[for="${id}"]` without escaping the interpolated value, so an id like content" produced label[for="content""] — an invalid selector — and document.querySelector threw a SyntaxError inside page.evaluate. The throw was uncaught, so the entire crawl died after ~20 BFS pages instead of skipping the one bad element.
error: evaluate: SyntaxError: Failed to execute 'querySelector' on 'Document':
'label[for="content""]' is not a valid selector.
Impact
- One malformed attribute value on a single page kills the whole multi-page crawl. This became visible now that crawls run to depth (they previously died early for an unrelated reason).
Locations
packages/hackbrowser/src/scanner.ts:129 — document.querySelector(\label[for="${id}"]`)`
packages/hackbrowser/src/capture.ts:46 — same pattern
Fix
- Escape the interpolated value with
CSS.escape(id) so the selector is always valid.
- Wrap the lookup in try/catch so a bad selector (here or from any DOM quirk) degrades to "no label found" instead of crashing the worker — one page's DOM should never abort the crawl.
Follow-up (optional)
Audit other interpolated selectors in scanner.ts for the same class of issue; consider a shared safe-query helper.
Summary
A hackbrowser crawl crashed the whole worker (exit code 1) mid-run when a page element's
idcontained a character that is invalid in a CSS selector. The worker builds a label lookup as`label[for="${id}"]`without escaping the interpolated value, so anidlikecontent"producedlabel[for="content""]— an invalid selector — anddocument.querySelectorthrew aSyntaxErrorinsidepage.evaluate. The throw was uncaught, so the entire crawl died after ~20 BFS pages instead of skipping the one bad element.Impact
Locations
packages/hackbrowser/src/scanner.ts:129—document.querySelector(\label[for="${id}"]`)`packages/hackbrowser/src/capture.ts:46— same patternFix
CSS.escape(id)so the selector is always valid.Follow-up (optional)
Audit other interpolated selectors in scanner.ts for the same class of issue; consider a shared safe-query helper.