-
Notifications
You must be signed in to change notification settings - Fork 2
Closed
Description
Thanks for this package. I built a very similar project in TypeScript a few years ago, having completions and types makes a big difference.
I've been trying the package and noticed that there's no escapeing of attributes keys or values. On some scenarios you might need to take user input and present it as attribute keys or values.
For example:
>>> # this is ok
>>> user_input = "red"
>>> div({"class": user_input})
<div class="red"></div>
>>> # this is xss
>>> user_input = '" onmouseenter="alert(1)" noop="'
>>> div({"class": user_input})
<div class="" onmouseenter="alert(1)" noop=""></div>
>>> # this is xss
>>> user_input = 'onmouseenter="alert(1)" noop'
>>> div({user_input: "1"})
<div onmouseenter="alert(1)" noop="1"></div>I suggest escapeing both attribute keys and values to prevent this. On my testing I've tried the following which has successfully prevented the issue.
>>> # this is ok
>>> user_input = '" onmouseenter="alert(1)" noop="'
>>> div({"class": escape(user_input)})
<div class="" onmouseenter="alert(1)" noop=""></div>On the key side of attributes simple escapeing works at least on my basic tests but I would throw a few additional replacements that I've seen on other libraries to be on the safe side.
>>> # this is ok
>>> user_input = 'onmousenter="alert(1)" noop'
>>> div({escape(user_input): "1"})
<div onmousenter="alert(1)" noop="1"></div>>>> # this is more ok?
>>> def escape_attr_key(key: str) -> str:
return (
escape(key)
.replace("=", "=")
.replace("\\", "\")
.replace("`", "`")
)
>>> user_input = 'onmousenter="alert(1)" noop'
>>> div({escape_attr_key(user_input): "1"})
<div onmousenter="alert(1)" noop="1"></div>What do you think?
Metadata
Metadata
Assignees
Labels
No labels