March 2023 - Intigriti's XSS Challenge - Author Writeup
Due to time constraints I never delivered a full write-up for my own March 2023 Intigriti challenge, so here are links to the community write-ups plus a short summary of the intended path-traversal and cache-based CSP bypass.

💡 Challenge URL: https://challenge-0323.intigriti.io/
Due to time constraints, I was not able to deliver the write-up for my challenge when it ended, but plenty of people decided to share how they solved it. So, I highly recommend checking their write-ups for a more detailed walkthrough:
- https://ltsirkov.medium.com/intigriti-challenge-0323-solution-1141ef0fda6a
- https://github.com/h43z/writeups/blob/master/0323-intigriti.md
- https://medium.com/@antonio341375/intigriti-challenge-0323-writeup-5ba6a09ee951
- https://mizu.re/post/intigriti-march-2023-xss-challenge
- https://github.com/abishekvashok/writeups/blob/main/intigriti/challenge-0323/WRITE_UP.md
- https://z4ki-blog.vercel.app/blog/intigriti-monthly/challenge-0324
Summary
Goal: Steal the admin’s flag (stored in a note) despite strict CSP and sanitization.
Recon & Source-Code Review
- Notes are created via the
/note/:id?id=<id>endpoint; content is sanitized with DOMPurify. - A special
/debug/<author-ID>/<note-ID>endpoint returns raw note content astext/html, but only when the custom headermode: readis set — otherwise it returns 404.
Client-Side Path Traversal to Reach the Debug Endpoint
- The frontend fetches
/note/<id>(withidcoming from URL parameters) and always includes themode: readheader. - Using directory traversal in the
idparameter (e.g.?id=../debug/<author-ID>/<note-ID>) forces the browser to request the debug path with the correct header, even though the UI makes that impossible normally.
CSP Bypass via 404-Based Script Injection
- A strict CSP blocks inline scripts and untrusted external sources.
- But the custom 404 page reflects paths unsanitized, with the ability to inject
<script src=...>tags into the error message via path-encoding tricks — inserting a crafted path ending in/...;alert(...)causes script execution despite the CSP.
Exploitation via Browser Cache (bfcache / disk cache)
(inspired by ArkArk’s writeup)
- The debug response is fetched as
text/html, which can be stored in the browser’s disk cache. - Navigating (e.g. via
window.open) to the path-traversal note endpoint, then callinghistory.back(), loads the previously fetched debug response without sanitization while the execution context persists — triggering the injected script.
Final Attack Chain
- Submit a note with the payload, or trigger stored content indirectly via path traversal.
- Trigger a fetch to
/debug/...through the traversal path (with forward history), storing the raw HTML response in cache. - Navigate back to the cached view, where the CSP-bypass path injection executes JS — revealing the flag.