DEV Community

Cover image for ❄️A Five-Minute UI Feature That Became an XSS Time Bomb

❄️A Five-Minute UI Feature That Became an XSS Time Bomb

Sylwia Laskowska on December 17, 2025

Can a simple script — a trivial visual effect — put your application at risk? Oh yes. And you might not even realize how. What’s more, small, inno...
Collapse
 
pascal_cescato_692b7a8a20 profile image
Pascal CESCATO

Even if you’re describing a fictional case, you’re absolutely right to call out this kind of vulnerability. We’ve seen the exact same pattern play out in real incidents — from the Samy worm on MySpace, to XSS worms on Twitter, and later on at companies like British Airways, GitHub, or Yahoo Mail. In most cases it started with small, seemingly harmless JavaScript that wasn’t designed with untrusted data in mind. So while the story is fictional, the risk it highlights is very real.

Collapse
 
sylwia-lask profile image
Sylwia Laskowska

Exactly! Thanks for calling this out, Pascal.

Those are very well-known cases, and the scary part is that they all started with something small and seemingly harmless. On top of that, there are countless similar incidents at smaller companies that never made the headlines, but still caused real damage.

I’ve seen this pattern many times myself: innerHTML used, safeguards consciously bypassed just to render something “nicely”. Awareness really matters here - these bugs are very real and can seriously hurt a business. The last thing anyone needs is a security incident on production.

Collapse
 
adamthedeveloper profile image
Adam - The Developer

dangerouslySetInnerHTML is basically:
“I acknowledge the risks, waive my rights, and accept XSS into my life.” 🤣

Collapse
 
sylwia-lask profile image
Sylwia Laskowska

I’m literally crying laughing 😂
That name is perfect: “you’ve been warned, this is on you now”.

I mostly work with Angular on a daily basis, and innerHTML is at least sanitized by default. But if you really want to shoot yourself in the foot, you can always inject DomSanitizer and use bypassSecurityTrustHtml 🙃
More annoying to get around, but hey - where there’s a will, there’s a way 😄

Thanks for this, made my day! ❄️

Collapse
 
sloan profile image
Sloan the DEV Moderator

We loved your post so we shared it on social.

Keep up the great work!

Collapse
 
sylwia-lask profile image
Sylwia Laskowska

Aww, thank you so much! ❤️
I swear, writing this post was at least as much fun for me as it seems to be for the people reading it 😄
Really appreciate the love and the share! ❄️

Collapse
 
htho profile image
Hauke T.

Thank you once again.

Yes - innerHtml is nasty.

The point is, that you should only use innerHtml (or insertAdjacentHtml) if you absolutely need it. If you don't need it to be parsed you should prefer innerText (insertAdjacentText). If not for security reasons, then at least for performance reasons.

Collapse
 
sylwia-lask profile image
Sylwia Laskowska

Thanks for the comment - totally agree 👍

InnerText / textContent (or insertAdjacentText) are almost always the better choice - for security and performance reasons.

That’s exactly why I wanted to share this story. Unfortunately, this is still a pretty common mistake, especially among junior developers - often copied straight from random snippets online.

Collapse
 
spo0q profile image
spO0q • Edited

nice!

Always set a robust CSP (content security policy).

Even if it can be a huge pain, it mitigates those untrusted injections.

Collapse
 
sylwia-lask profile image
Sylwia Laskowska

Absolutely agree 👍

A solid CSP is a huge pain sometimes, but it’s also one of the most effective safety nets you can have. It won’t fix bad patterns, but it does dramatically reduce the blast radius when something slips through - and something always does eventually.

Defense in depth for the win 😄
Thanks for calling this out!

Collapse
 
evan-lausier profile image
Evan Lausier

Very nice! Happy Holidays

Collapse
 
sylwia-lask profile image
Sylwia Laskowska

Thank you so much! 😊
Happy Holidays to you too! ❄️🎄

Collapse
 
shemith_mohanan_6361bb8a2 profile image
shemith mohanan

This is a fantastic cautionary story 👏
Love how you show how a harmless UI tweak slowly crosses trust boundaries and turns into real XSS — that progression is very real in production teams. The takeaway about innerHTML patterns, framework false-security, and “small features” skipping review is spot on. Clear, memorable, and genuinely educational.

Collapse
 
sylwia-lask profile image
Sylwia Laskowska

Aww, thank you so much - that really means a lot! 😊

I’m glad the progression resonated with you, because that’s exactly the part I wanted to highlight: how something harmless slowly crosses trust boundaries in very normal, very human ways. If it made the lesson feel clear and memorable, then the post did its job.

Thanks again for the kind words and for taking the time to write such a thoughtful comment! ❄️

Collapse
 
lfariaus profile image
Luis Faria

That was such an interesting post. Curious how such a small change could let doors wide open for scaling trouble!!!!

Collapse
 
sylwia-lask profile image
Sylwia Laskowska

Thank you, I’m really glad you found it interesting! 😊

That’s exactly the scary part - the change itself is tiny, but once it crosses a trust boundary, it can quietly scale into a much bigger problem. Especially in growing teams, those “small” shortcuts tend to get reused, extended, and copied until they’re everywhere.