streamlit / streamlit

Streamlit — A faster way to build and share data apps.
https://streamlit.io
Apache License 2.0
35.73k stars 3.1k forks source link

Streamlit removes _xsrf cookie even with 'server.enableXsrfProtection=False' #2517

Closed elephantum closed 11 months ago

elephantum commented 3 years ago

Summary

Our primary use case for streamlit is to run ad-hoc scripts from JupyterHub container. In order to access streamlit tool we're using jupyter-server-proxy. I.e. streamlit app accessed through URL like "{jupyterhub-host-port}/{jupyter-url}/proxy/8501/"

We configure streamlit to disable xsrf and cors protection.

Streamlit is removing _xsrf cookie in its JS code, which breaks JupyterLab functionality.

I believe that offending line is here: https://github.com/streamlit/streamlit/blob/develop/frontend/src/App.tsx#L274

It would be great if streamlit would not touch _xsrf cookie if it was not configured to use it.

nthmost commented 3 years ago

Ah, interesting, @elephantum. I'll have to take this one to Product to discuss whether there are implications for changing this. Thank you for sharing this use case, regardless!

(Also, apologies for the long delay in response while most of us were off for the holidays!)

nthmost commented 3 years ago

@asaini Tagging you to see if a discussion is needed before handling this as a regular bug.

nthmost commented 3 years ago

Hey @elephantum -- we're interested in this issue but it's hard for us to reproduce since we haven't worked in JupyterHub to date (yours is the first request I know of). We're hoping you could provide a step-by-step guide to reproducing the issue so we can get set up more quickly to get our hands dirty in this use case.

I don't know how complex of an ask that is, but I do know it's unlikely we can set aside time for this without such a guide to help us here.

Let me know how to get this one up and running!

elephantum commented 3 years ago

@nthmost reproducing is a bit tricky, but I think I found the easiest way:

I prepared a repo: https://github.com/elephantum/streamlit-issue-2571 (it setups all the dependencies to reproduce the issue)

  1. Navigate to https://mybinder.org/ enter https://github.com/elephantum/streamlit-issue-2571 as github URL, press Launch
  2. Navigate to binder provided URL which looks like https://notebooks.gesis.org/binder/jupyter/user/elephantum-streamlit-issue-2571-o05009km/ (It is a binder instance running the above repo)
  3. Open two tabs: jupyter terminal, notebook Untitled.ipynb
  4. In Untitled.ipynb (sorry for default name), try modifying and saving, check that saving works fine.
  5. In terminal run streamlit run test_streamlit.py
  6. Navigate to url like https://notebooks.gesis.org/binder/jupyter/user/elephantum-streamlit-issue-2571-o05009km/proxy/8501/, /proxy/8501/ is the important part. Observe correct behavior of the streamlit app
  7. Go back to notebook tab (do not reload, pretend that you have unsaved changes), try modifying and saving. Observe "_xsrf argument is missing from POST" error message. Your changes are not saved.
elephantum commented 3 years ago

https://user-images.githubusercontent.com/71321/103665932-0d75ca00-4f85-11eb-8c65-f1a67e7ac53f.mp4

Please find screencast attached

elephantum commented 3 years ago

Also, _xsrf removal can be reproduced locally with access to jupyter via localhost, but in this case jupyter does not check for _xsrf so saving works.

ToucheSir commented 2 years ago

I'm still experiencing this with Jupyterlab 3.0.17 and Streamlit 1.3.1. The removal of _xsrf (which still appears to be present in https://github.com/streamlit/streamlit/blob/c1bfdd153b9f050d3606da0801e31636b2775784/frontend/src/App.tsx#L365) prevents anything Jupyter related from working and essentially converts an entire Jupyterlab instance into a glorified streamlit host proxy :( . These technologies are great and we'd really like to use them together, so has there been any more work on a potential fix?

ToucheSir commented 2 years ago

I was able to work around this by manually changing "_xsrf" to a different name in the minified source so that it wouldn't clobber the Jupyterlab cookie. Could this be renamed to something like "_streamlit_xsrf" instead?

chadaeschliman commented 2 years ago

this is also affecting our system, anytime a user of jupyterhub opens a streamlit dashboard it breaks their jupyterlab instance

raybellwaves commented 2 years ago

I believe this is related to the browser as well. i.e. it may appear for chrome users but not for firefox users

asaini commented 2 years ago

cc: @jrieke

yevgeniy-ds commented 2 years ago

same. Affects us as well. Please fix!

ajbozarth commented 2 years ago

This is still an issue, specifically any tornado instance running on the same domain as a Streamlit instance shares the _xrsf cookie and would break in cases where Streamlit deletes the cookie. Given this a tornado cookie streamlit should not be deleting it directly and should let the tornado API handle it's life cycle.

Kirill888 commented 1 year ago

Same here, using streamlit via jupyterlab/hub. There are really several issues here

  1. Cookies are set at path / on JS side, ignoring --server.baseUrlPath=/some/other/path/
  2. _xsrf cookie is cleared in on JS side, ignoring --server.enableXsrfProtection=false option
  3. Cookies set on JS side lack SameSite=None;Secure options, needed in modern browsers when accessing over https.

Basically scenario where streamlit app is served from behind HTTP reverse proxy under some prefix path over TLS connection is not quite right.

Possible Fixes

In the section below

https://github.com/streamlit/streamlit/blob/f739c18c94a3235ba565d05f8dfdee70bc6dba10/frontend/src/App.tsx#L377-L382

setCookie call needs either a guard like if ( options.enableXsrfProtection ){ ... }*, or just not happen on JS side at all.

in setCookie implementation:

https://github.com/streamlit/streamlit/blob/f739c18c94a3235ba565d05f8dfdee70bc6dba10/frontend/src/lib/utils.ts#L160-L170

path= should be set not to / but to options.baseUrlPath*, and also it should allow specifying SameSite= and Secure options to make things work over https.

Example of warning produced in Firefox when setCookie is called:

Cookie “_xsrf” does not have a proper “SameSite” attribute value. Soon, cookies without the “SameSite” attribute or with an invalid value will be treated as “Lax”. This means that the cookie will no longer be sent in third-party contexts. If your application depends on this cookie being available in such contexts, please add the “SameSite=None“ attribute to it. To know more about the “SameSite“ attribute, read https://developer.mozilla.org/docs/Web/HTTP/Headers/Set-Cookie/SameSite main.951e143b.chunk.js:1:649272

* options object is not a real thing that exists currently as far as I can tell, think of it as JS view of Python app configuration, specifically .baseUrlPath and .enableXsrfProtection parts of the config and also .cookieOptions would be nice to have.

matkozak commented 1 year ago

I am not using Jupyter, but I am running into issues where Streamlit's "_xsrf" cookie is not available after cloud deployment behind SSO. As a result, st.file_uploader returns 403 Forbidden if enableXsrfProtection is true. I suspect @Kirill888 identified the source of my problem as well.

sb-eip commented 1 year ago

We want to deploy something similar to this Ask The Doc AI app in our organization but we ran into this issue. This might currently affect everyone running Streamlit on Azure with AD Authentication. Potential code fixes are documented in https://github.com/streamlit/streamlit/issues/2517#issuecomment-1321281460 as mentioned in the original issue but just thought I want to highlight them again to make it easier to get started.

I can offer to test any potential fix on our infrastructure in case you can share it as a wheel file.