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

feat: serve static files similar to the notebook #361

Merged

Conversation

maartenbreddels
Copy link
Member

but limited by whitelist and blacklist rules.

Issue

When using the following in a Jupyter notebook:

import ipywidgets
html = ipywidgets.HTML(value='<img src="./quantstack.svg"></img>')
html

The Jupyter notebook server will happily serve the svg file.

However, in voila, we consider this a security risk, since we do not assume the users are trusted (we don't want to give users access to our files). However, in voila, we'd like this to work as well.

Solution

This PR solves this by having whitelist and blacklist regexes that protect the content that is served. Each request for a file needs to match at least one whitelist regex and NO blacklist regex

E.g. to serve all files, except those starting with private, or notebook files:

voila mynotebook.ipynb --VoilaConfiguration.file_whitelist="['.*']" --VoilaConfiguration.file_blacklist="['private.*', '.*\.(ipynb)']"

To serve only images:

voila tests/ --VoilaConfiguration.file_whitelist=ile_whitelist="['.*\.(png|jpg|gif|svg)']"

Uncertain

I think that we should not always redirect in the handler.py, since it tells users that a file exists (this gives an attacker information which files exists). I think we should check the rules in two places.

Should the default be as it is now (images, and notebooks/py files always blacklisted)?

TODO:

  • tests
  • docs

@SylvainCorlay
Copy link
Member

Thanks for this @maartenbreddels this is not what I had in mind with the inlining but I think that it is a good solution at least for now. Happy to merge this.

@SylvainCorlay SylvainCorlay merged commit 336ecaf into voila-dashboards:master Aug 21, 2019

def get_absolute_path(self, root, path):
# StaticFileHandler.get always calls this method first, so we use this as the
# place to check the path. Note that now the path seperator is os dependent (\\ on windows)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

separator

whitelisted = any(re.fullmatch(pattern, path) for pattern in self.whitelist)
blacklisted = any(re.fullmatch(pattern, path) for pattern in self.blacklist)
if not whitelisted:
raise tornado.web.HTTPError(403, 'File not whitelisted')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these probably should be 404s to be indistinguishable from the file not existing. If you decide on 403s, though, perhaps a more generic message is better, like the default 403 message, or just now message.

@jasongrout
Copy link
Member

I think that we should not always redirect in the handler.py, since it tells users that a file exists (this gives an attacker information which files exists). I think we should check the rules in two places.

I think it is fine to unconditionally redirect, since that gives no more information.

Should the default be as it is now (images, and notebooks/py files always blacklisted)?

I think the default should be secure, i.e., no files served.

@jtpio jtpio mentioned this pull request Oct 2, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants