GET /xrpc/app.bsky.actor.searchActorsTypeahead typeahead.waow.tech
16
fork

Configure Feed

Select the types of activity you want to include in your feed.

escape dynamic html in server-rendered messages to prevent xss

the /request-indexing endpoint interpolated user input and slingshot
response data directly into html. added escHtml() for entity encoding.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

+6 -2
+6 -2
src/index.ts
··· 19 19 return request.headers.get("CF-Connecting-IP") || "unknown"; 20 20 } 21 21 22 + function escHtml(s: string): string { 23 + return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;"); 24 + } 25 + 22 26 function json(data: unknown, status = 200): Response { 23 27 return Response.json(data, { status, headers: CORS_HEADERS }); 24 28 } ··· 286 290 `${SLINGSHOT_URL}?identifier=${encodeURIComponent(identifier)}` 287 291 ); 288 292 if (!res.ok) { 289 - return html(indexPage(`could not resolve "${identifier}". check that it's a valid handle or DID.`)); 293 + return html(indexPage(`could not resolve "${escHtml(identifier)}". check that it's a valid handle or DID.`)); 290 294 } 291 295 292 296 const identity: SlingshotResponse = await res.json(); ··· 320 324 .run(); 321 325 322 326 return html( 323 - indexPage(`indexed <strong>@${identity.handle}</strong> (${identity.did})`) 327 + indexPage(`indexed <strong>@${escHtml(identity.handle)}</strong> (${escHtml(identity.did)})`) 324 328 ); 325 329 } 326 330