What an independent security and UX audit found that our own review did not
We ran two audits against this site — one offensive, one about content and interaction — and then tried to break our own findings. Three of them are worth publishing because each one is a class of mistake, not a one-off bug.
1. Stored XSS through JSON-LD
Structured data is JSON, and `JSON.stringify` does not escape the `<` character. A CMS field containing `</script>` therefore closed the script tag early and everything after it executed as markup. Our own review had looked at the CMS validation and the rendered HTML — both fine — and missed the serializer. The fix is one function: escape `<`, `>` and `&` when serialising JSON-LD. If you render structured data from any user-editable field, check this today.
2. A rate limit defeated by rotating one header
Our login limiter keyed on the client IP, which it read from `x-forwarded-for`. Rotating that header gave the attacker a fresh bucket per request — seven attempts, never a 429. The fix is two parts: only trust proxy headers when a trusted proxy is declared, and add an IP-independent ceiling that no single caller can dodge.
3. A 404 that answered HTTP 200
Unknown service URLs returned the not-found page with a 200 status, which teaches search engines that the page exists. The cause was not the routing: a route-level `loading.tsx` streamed the response shell, committing the status before `notFound()` could run. `dynamicParams = false` and a `generateMetadata` guard both failed to fix it; removing the streaming boundary did.
What we changed about our process
- **Check the serializer, not just the input.** Validation and escaping are different jobs.
- **Any limit keyed on a client-supplied value is not a limit.**
- **Test status codes, not just page content.** A page that renders the right thing with the wrong status is still broken.
- **An audit that only confirms your own review was not an audit.** The value is in the findings you argued with.
Share this content
Mayank Batra
Avartana Labs Editorial Team



