-
Notifications
You must be signed in to change notification settings - Fork 4k
Fixes issues caused by svg strings passed to st.image() #2003
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
Conversation
3f9c68a to
5a2ff69
Compare
|
I'd forgotten to update the tests for |
5a2ff69 to
1390cc4
Compare
karriebear
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, thanks for taking this on!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So sorry I didn't take a close look earlier but it looks like there's actually some interplay between the frontend so this change doesn't quite work.
The url that gets returned by image_proto works perfectly but we're then running SVG strings through another sanitization with sanitizeSvg from lib/UriUtils.ts. It does another set of encoding + DomPurify.sanitize (to prevent JS from executing) which encodes the % from our previously encoded string.
It would be great if we can consolidate these two so that all the encoding happens in one place while still sanitizing to protect us from any JS included in the svg string.
|
@karriebear Wow, I'd completely missed that. So, I did a little checking and realised that
First Method (removing
|
|
I think most devices at this stage should be able to handle However, it looks like the resulting data url of the encodedUriComponent should work when copied into a new browser window but does not. Not sure if it is some timing thing but if it is something that works with |
|
Hi, makes sense about not being enough computational load for it to matter. However, I am unable to reproduce a case where I'll try and raise a PR by pushing everything to Python |
93f3100 to
a0df895
Compare
|
@karriebear I've pushed the changes such that all the processing is done by quote and the frontend merely displays it. |
|
These tests are failing since DOMPurify is imported but never used, and this was the only file where it was being imported, can I remove it as a dependency? |
a0df895 to
5f9fedb
Compare
|
I actually had the same issue as you when using I didn't find a quick solution to this so it might be something we bring back to our product team to see if this is something we should handle. If you know of a solution for this, that would be great and we can try that out. Otherwise, feel free to put this on hold - sorry to have wasted your time on this |
|
Like the SO answer suggests, one quick fix would be to fetch all linked images and encode them as base64 strings; after which we can encode the whole svg and send it to the front end. If this is something that is acceptable enough of a fix, I could try it out. One caveat being, this would make large SVGs with a lot of links quite slow to load, but then again, a SVG with links to a lot of images beats the point of a SVG |
|
An alternative would be to use a SVG tag instead of a dataURI. Though like you said, a SVG with links to other images does defeat the point of a SVG. I'll review with the team to see what we think about this! |
|
Sure, let me know if there is any work to be done 😁 |
Flyby comment -- We added in DOMPurify as a security measure, to prevent the execution of Javascript inside of the SVG; I believe that just using I could see an argument that we do indeed want to permit JS execution in SVGs (something like: the author of the Streamlit app already has to be trusted), but wanted to make sure this was a deliberate choice. |
|
We just discussed and while this could be an odd use case, this is something we would love to support! Our ideal solution would be to create a SVG tag instead of the fetching/encoding methodology (seems too much of an overkill for us to render an image). However, with SVG, security is a big concern for us so we would definitely want to bring back DOMPurify (or any python alternative). We would probably also want to modify our If this is still something you would like to take on, let me know and happy to provide additional guidance if needed! And if there's a better approach, happy to hear that as well. |
|
Sure I would love to work on this. So, if I understand correctly, what needs to be done is an added support for Since I am still new to the codebase, are there any specific code file(s) that I can start reading to get a better idea of how this is done with other tags? |
|
At this stage, I don't know if we need a Here's some context to help get started: Generally, most of the magic happens in Block.tsx but since In terms of the data being passed into ImageList.tsx, these are proto shapes that are defined in corresponding proto files. In this case it would be Image.proto. When updating proto files, make sure to run I don't think we have another component that does quite this logic so not sure if this would help. The closest approximation I can think of is our upcoming expandable. Here we have a conditional to determine if we should show a regular block or an expandable block. Let me know if this helps or if there's any other context we can provide to point you in the right direction. |
|
@yashshah1 just wanted to check in to see if this is something you would still like to work on? If not, let me know and we'll close the PR and update the issue with our decisions made here. Either way, thanks for your patience as we worked through this! |
|
Hi @karriebear, This is definitely something I want to see through, I've just been caught up a little at work. I should have some decent progress in a day or two. Thank you for your patience! |
|
Hi @karriebear, first off thank you for your patience :) I wanted to run an approach by you, instead of modifying multiple components, we could integrate svg images by just changing In the return part of it, where it maps through const svgString = decodeURIComponent(src.substring(SVG_PREFIX.length))
return (
<div
className="image-container stImage"
key={idx}
style={{ width: containerWidth }}
dangerouslySetInnerHTML={{ __html: svgString }}
></div>
)This shouldn't be a problem as far as I can tell since this is already run through What this solution lacksCurrently, there is also a caption that is added to the bottom of the image, if this solution is accepted, we might have to convert the DOM of the caption part to be a string, add add it above Full code of
|
|
Just an additional thought, if it's okay, we could add |
|
No problems with adding Though, instead of storing the SVG data in This would be nice instead of repurposing Thanks again though for thinking through alternatives! That's always valuable. If it's confusing or you're busy, no worries, we can take it too. Also, didn't mean to rush you. Work and life definitely comes first and we appreciate any time you spare helping us, no matter how big or small! |
5f9fedb to
67d94f8
Compare
|
Got closed since I overwrote my previous work with a force push after a merge from develop. Will push my changes and reopen |
ac5bf43 to
35f6ecf
Compare
|
@karriebear I have done a few changes, which should work in theory, but I am thrown an error that I can't seem to reason out, maybe you can help me out here. This is the debugging output I am given: I've also taken the liberty of converting this PR to a draft. |
|
It looks like something is not happy with your compiled protobuf. The object is coming from a file that gets autogenerated when you set up your development environment and needs to be updated when you update a proto file. Did you run |
|
@karriebear Great, that did work for me, thank you! <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 xlink:href="https://avatars.githubusercontent.com/karriebear" width="50" height="50" clip-path="url(#clipCircle)"/>
</svg>Using the above svg brings up a blank image on the frontend, which is fixed by changing the property name of While trying to reason out why this happens (given that pasting an encoded URI in the browser search bar works perfectly), I came across this, which mentions that the Else, can you try and point me in a direction, because I can't seem to reason out why my browser doesn't show the bear (Given that chrome does still support the tag). One hotfix could be to replace all |
|
Given that it's deprecated, that's more than enough reason for us to not support it. It's recommended to not use anymore so we should support that messaging :) I've updated the test case in the issue to reflect this. Thanks for taking a look into this! If you could also add some tests, that'll be great and then happy to review! |
|
@yashshah1 Hey, since you haven't worked on this in a few months, I'm going to finish it out so we can get it merged in. |
|
Closing now that #2666 is merged. Thanks for the help getting us started on this @yashshah1! |

Before contributing (PLEASE READ!)
This helps make sure (1) two people aren't working on the same thing, (2) this is something Streamlit's maintainers believe should be implemented/fixed, (3) any API, UI, or deeper architectural changes that need to be implemented have been fully thought through by Streamlit's maintainers, and (4) your time is well spent!
More information in our wiki: https://github.com/streamlit/streamlit/wiki/Contributing
Issue: Please include a link to the issue you're addressing. If no issue exists, create one first and then link it here.
Issue: #1957
Description: Describe the changes you made to the code, so it's easier for the reader to navigate your pull request. Usually this is a bullet list.
As discussed:
quotefromurllib.parse(withsafe='')Contribution License Agreement
By submitting this pull request you agree that all contributions to this project are made under the Apache 2.0 license.