Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove deprecated usage of inline SVG #7183

Merged
merged 24 commits into from Sep 1, 2023
Merged

Conversation

LukasMasuch
Copy link
Collaborator

@LukasMasuch LukasMasuch commented Aug 16, 2023

Describe your changes

Since this PR last year, almost all SVGs used in st.image get rendered by using the img tag instead of injecting the SVG into the HTML DOM. As far as I remember, the only reason we kept markup was to still support xlink functionality for external links. However, xlink has been long deprecated (see here), and usage is not recommended.

Here are a couple more arguments for why we should remove the SVG markup injection:

  • Rendering SVGs in an img tag is considered XSS save (as far as I know). On the other hand, injecting SVG into the HTML DOM is quite problematic from a security perspective, even though we try to sanitize the SVG.
  • SiS clears out the markup field for the stated security concerns, so it will likely never be supported in SiS.
  • We can remove an unmaintained dependency: react-html-parser
  • All images rendered by st.image behave the same by using the img tag, the usage of markup did not correctly adapt to the other st.image parameters (width, use_column_width, and fullscreen mode).

But this change might also break a couple of apps that include external resources within the SVG. For example, this would not work anymore since it requires an external image:

    st.image(
        """<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100" height="100">
        <clipPath id="clipCircle">
            <circle r="25" cx="25" cy="25"/>
        </clipPath>
        <image href="https://avatars.githubusercontent.com/karriebear" width="50" height="50" clip-path="url(#clipCircle)"/>
    </svg>
    """
    )

This PR also removes the xssSanitizeSvg for SVG data URIs. The reason is that this isn't very effective since an attacker could easily circumvent this, e.g., by using base64 or URL-encoding the SVG data URI or by embedding the image via markdown:

# This will be sanitized:

st.image(
    """
<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
<script>alert("BOOOM");</script>
  <circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
</svg>
    """
)

# These two render the same SVGs, but do not get sanitized:

st.image(
"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHNjcmlwdD5hbGVydCgiQk9PT00iKTs8L3NjcmlwdD4KICA8Y2lyY2xlIGN4PSI1MCIgY3k9IjUwIiByPSI0MCIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIzIiBmaWxsPSJyZWQiIC8+Cjwvc3ZnPg=="
)

st.markdown(
    """
![alt text](data:image/svg+xml,%3Csvg%20width%3D%22100%22%20height%3D%22100%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%3Cscript%3Ealert%28%22BOOOM%22%29%3B%3C%2Fscript%3E%0A%20%20%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2240%22%20stroke%3D%22black%22%20stroke-width%3D%223%22%20fill%3D%22red%22%20%2F%3E%0A%3C%2Fsvg%3E)
"""
)

Script in SVG is not executed when used with img tags, so this should be anyways safe without requiring sanitation.

This PR also converts all SVGs to base64 on the backend to prevent encoding issues (e.g. #3882).

GitHub Issue Link (if applicable)

Closes: #3882

Testing Plan

  • This PR doesn't add any new logic, so only some changes in the existing tests.

Contribution License Agreement

By submitting this pull request you agree that all contributions to this project are made under the Apache 2.0 license.

lib/streamlit/elements/image.py Fixed Show fixed Hide fixed
lib/streamlit/elements/image.py Fixed Show fixed Hide fixed
@LukasMasuch LukasMasuch marked this pull request as ready for review August 16, 2023 15:01
@vdonato
Copy link
Collaborator

vdonato commented Aug 19, 2023

This PR also removes the xssSanitizeSvg for SVG data URIs. The reason is that this isn't very effective since an attacker could easily circumvent this, e.g., by using base64 or URL-encoding the SVG data URI or by embedding the image via markdown:
...
Script in SVG is not executed when used with img tags, so this should be anyways safe without requiring sanitation.

This seems fine to me given that scripts embedded in SVG data URIs aren't executed, but I wonder if this is something we might want to run by ProdSec just to be extra-safe

lib/streamlit/elements/widgets/chat.py Outdated Show resolved Hide resolved
@LukasMasuch LukasMasuch merged commit f8ad932 into develop Sep 1, 2023
56 of 57 checks passed
@LukasMasuch LukasMasuch deleted the refactor/remove-svg-markup branch September 1, 2023 16:58
eric-skydio pushed a commit to eric-skydio/streamlit that referenced this pull request Dec 20, 2023
* Remove deprecated usage of inline SVG

* Change pipefile back

* Fix test

* Cleanup

* Add back xssSanitizeSvg

* Fix svg xmlns addition

* Add test

* Remove xss sanitation

* Remove dompurify

* Update notices

* Update unit tests

* Remove unused import

* Remove unneeded test

* Fix e2e test

* Remove print

* Update e2e tests

* Update snapshots

* Update image test

* Fix gif with caption

* Add missing snapshot

* Fix docstring

* Update package.json

* Format
zyxue pushed a commit to zyxue/streamlit that referenced this pull request Mar 22, 2024
* Remove deprecated usage of inline SVG

* Change pipefile back

* Fix test

* Cleanup

* Add back xssSanitizeSvg

* Fix svg xmlns addition

* Add test

* Remove xss sanitation

* Remove dompurify

* Update notices

* Update unit tests

* Remove unused import

* Remove unneeded test

* Fix e2e test

* Remove print

* Update e2e tests

* Update snapshots

* Update image test

* Fix gif with caption

* Add missing snapshot

* Fix docstring

* Update package.json

* Format
zyxue pushed a commit to zyxue/streamlit that referenced this pull request Apr 16, 2024
* Remove deprecated usage of inline SVG

* Change pipefile back

* Fix test

* Cleanup

* Add back xssSanitizeSvg

* Fix svg xmlns addition

* Add test

* Remove xss sanitation

* Remove dompurify

* Update notices

* Update unit tests

* Remove unused import

* Remove unneeded test

* Fix e2e test

* Remove print

* Update e2e tests

* Update snapshots

* Update image test

* Fix gif with caption

* Add missing snapshot

* Fix docstring

* Update package.json

* Format
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Streamlit.image does not accurately display SVGs
3 participants