The solution to Secure Code Review Challenge #3: Dice is live!
This one’s a reminder that individually “correct” security controls can still combine into a vulnerability. The app sanitizes user input with DOMPurify — a real, well-regarded XSS sanitizer — and it works exactly as advertised. Strip a <script> tag? Gone. Strip an <img onerror> tag? Gone.
And it still wasn’t enough.
The bug wasn’t in the sanitizer. It was in the order of operations. A Unicode normalization step ran after sanitization instead of before — so fullwidth lookalike characters (< >) sailed through DOMPurify as harmless “text,” then got silently rewritten into real < > characters by the normalizer, resurrecting a live HTML tag downstream. One crafted link, zero clicks needed beyond opening it.
Watch the full walkthrough: https://youtu.be/Wv1kIrZVLbI
Read the write-up: the-secure-code-review-challenge/solutions/003-dice/SOLUTION.md at main · mohamed-osama-aboelkheir/the-secure-code-review-challenge · GitHub
Try Challenge #3 yourself first: the-secure-code-review-challenge/challenges/003-dice at main · mohamed-osama-aboelkheir/the-secure-code-review-challenge · GitHub
Two things before you dive in:
Challenge #4 is already live in the repo: the-secure-code-review-challenge/challenges/004-file-converter at main · mohamed-osama-aboelkheir/the-secure-code-review-challenge · GitHub
Watch → Custom → Releases on the repo to get notified the moment new challenges/solutions drop, instead of checking back manually: Releases · mohamed-osama-aboelkheir/the-secure-code-review-challenge · GitHub