Skip to content

Consider escapeing argument keys and values to prevent XSS in some scenarios #7

@gcollazo

Description

@gcollazo

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="&quot; onmouseenter=&quot;alert(1)&quot; noop=&quot;"></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=&quot;alert(1)&quot; noop="1"></div>
>>> # this is more ok?
>>> def escape_attr_key(key: str) -> str:
    return (
        escape(key)
        .replace("=", "&#x3D;")
        .replace("\\", "&#x5C;")
        .replace("`", "&#x60;")
    )
>>> user_input = 'onmousenter="alert(1)" noop'
>>> div({escape_attr_key(user_input): "1"})
<div onmousenter&#x3D;&quot;alert(1)&quot; noop="1"></div>

What do you think?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions