Skip to content
Merged
37 changes: 35 additions & 2 deletions superset/initialization/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@
import os
import sys
from typing import Any, Callable, TYPE_CHECKING
from urllib.parse import urlparse

import wtforms_json
from deprecation import deprecated
from flask import Flask, redirect
from flask import abort, Flask, redirect, request, session
from flask_appbuilder import expose, IndexView
from flask_babel import gettext as __
from flask_appbuilder.api import safe
from flask_babel import gettext as __, refresh
from flask_compress import Compress
from flask_session import Session
from werkzeug.middleware.proxy_fix import ProxyFix
Expand Down Expand Up @@ -701,3 +703,34 @@ class SupersetIndexView(IndexView):
@expose("/")
def index(self) -> FlaskResponse:
return redirect("/superset/welcome/")

@staticmethod
def is_safe_url(target: str) -> bool:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

might belong in superset/utils/urls.py would be surprised if we don't already have a similar method there, grepping for urlparse or next= could point to a similar method.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

otherwise PR LGTM

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thank you @mistercrunch ! I didn't find a similar method anywhere, so 4bb4916 creates superset.utils.urls.is_safe_redirect_url(source_url, target_url).

Does this look ok now?

"""
Is target is a safe URL to redirect to?
"""
ref_url = urlparse(target)
host_url = urlparse(request.host_url)
return ref_url.scheme in ("http", "https") and ref_url.netloc == host_url.netloc

@expose("/lang/<string:locale>")
@safe
def patch_flask_locale(self, locale: str) -> FlaskResponse:
"""
Change user's locale and redirect back to the previous page.

Overrides FAB's babel.views.LocaleView so we can use the request
Referrer as the redirect target, in case our previous page was actually
served by the frontend (and thus not added to the session's page_history
stack).
"""
if locale not in self.appbuilder.bm.languages:
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
abort(404, description="Locale not supported.")
Comment thread
pomegranited marked this conversation as resolved.
session["locale"] = locale
refresh()
self.update_redirect()

redirect_to = request.headers.get("Referer")
if not redirect_to or not self.is_safe_url(redirect_to):
redirect_to = self.get_redirect()
return redirect(redirect_to)
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
1 change: 1 addition & 0 deletions tests/integration_tests/security_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -1543,6 +1543,7 @@ def test_views_are_secured(self):
["SecurityApi", "login"],
["SecurityApi", "refresh"],
["SupersetIndexView", "index"],
["SupersetIndexView", "patch_flask_locale"],
["DatabaseRestApi", "oauth2"],
]
unsecured_views = []
Expand Down