Reflected Cross-Site Scripting (XSS) error

Hi,

I am deploying a Streamlit app for a client and in that process it has undergone a security review. They raised the following issue:

A request to the streamlit server on the /component/ endpoint there is an XSS error

http://localhost:8501/component/<img/src=x%20on%20error=alert(document.domain)>

where localhost:8501 is in reality a domain controlled by the client.

My question is whether its possible to configure in Streamlit to avoid this security concern or if I should set up some kind of reverse proxy and restrict access to /components to avoid such XSS errors?

Best,
Peter

Hi Peter -

In a release build, components are served directly by the Streamlit process itself, from the same host that the rest of Streamlit is served from, so this shouldn’t be an issue.

Can you verify that you’re using components.declare_component with the path param (as opposed to the url param, which should generally only be used when serving a development build of a component from a devserver)?

# When we're distributing a production version of the component, we'll
# replace the `url` param with `path`, and point it to to the component's
# build directory:
parent_dir = os.path.dirname(os.path.abspath(__file__))
build_dir = os.path.join(parent_dir, "frontend/build")
_component_func = components.declare_component("my_component", path=build_dir)

Also, the URL you pasted looks strange - it has less-than/greater-than characters enclosing the text after “component/”, and it looks like it contains an escaped HTML string. Where is this request coming from, do you know?

http://localhost:8501/component/<img/src=x%20on%20error=alert(document.domain)>

Hi Tim,

Thank you for getting back to me so quickly!

Actually, I am not declaring any components, and the problem appears without even with a minimal example such as

import streamlit as st

st.write("Hello world")

on several versions, e.g. 0.75.0 and 0.80.0.

I think the request is illustrating that the site is somewhat open to a malicious attack (the actual code is harmless, so try it out with any streamlit app and see what happens), though my limited security knowledge hinders me from knowing exactly how this can be used maliciously.

I also noticed that visiting <base_url>/component/ gives a different not found message than other e.g. <base_url>/example/

Best,
Peter

Strange! Streamlit shouldn’t be making that request on its own (and I’m not able to reproduce it locally). Do you have any modifications to Streamlit code? How are you deploying the app - is it via Streamlit sharing, or an external host, or just locally?

I don’t think this indicates anything about the site being open to a malicious attack - the error you’re seeing is just about a malformed request failing. But I’m curious where that request is coming from!

Any more details you can share? Does this happen locally for you, or just for the client? Do you have dependencies beyond Streamlit in your project’s Python environment?

It’s not that Streamlit is making the request on its own. The request is being made on purpose IT security guys when checking for security holes.

Ideally, the request should just show “404 not found” and no content on the page when opening a browser. Instead, it actually running Javascript code in form of an alert. Like this:

It is both locally and on EC2 server and I tested it in a a fresh PipEnv after installing only Streamlit. Also tested in a few other of my environments, and its the same everywhere…

NB: Just noticed a small error in the URL i pasted above, try with this one
http://localhost:8501/component/<img/src=x%20onerror=alert(document.domain)>

Ah, thanks for the extra details. I understand now, and can reproduce what you’re seeing. I’ll run this up the flagpole and we’ll get back to you with an answer soon.

2 Likes

@PeterT - this is a good catch. What’s happening is that Streamlit is returning a 404 with an error string saying “{path} not found”, where {path} in this case is your valid HTML. Then the browser is rendering that string as a 404 page.

We’ve just removed this behavior: in the next Streamlit release, component requests will simply 404 with a static error string.

Thanks for the heads up!

2 Likes

Awesome Tim - thanks a lot for your prompt and as always very helpful response!

1 Like