superset-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From maximebeauche...@apache.org
Subject [incubator-superset] branch master updated: Allowing config flag to turn off javascript controls (#4400)
Date Wed, 21 Feb 2018 16:31:15 GMT
This is an automated email from the ASF dual-hosted git repository.

maximebeauchemin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-superset.git


The following commit(s) were added to refs/heads/master by this push:
     new a373db2  Allowing config flag to turn off javascript controls (#4400)
a373db2 is described below

commit a373db24f044d19fda904331265fae56ee5c28e0
Author: Maxime Beauchemin <maximebeauchemin@gmail.com>
AuthorDate: Wed Feb 21 08:31:07 2018 -0800

    Allowing config flag to turn off javascript controls (#4400)
    
    * Allowing config flag to turn off javascript controls
    
    * lint
    
    * one line, avoiding mutation
    
    * Setting JS fields as readOnly
---
 .../javascripts/explore/components/ControlHeader.jsx       | 14 ++++++++++++++
 .../explore/components/controls/TextAreaControl.jsx        |  4 ++++
 superset/assets/javascripts/explore/stores/controls.jsx    |  5 +++++
 superset/config.py                                         |  6 ++++++
 superset/views/base.py                                     |  5 ++++-
 superset/views/core.py                                     | 13 ++++++++++++-
 6 files changed, 45 insertions(+), 2 deletions(-)

diff --git a/superset/assets/javascripts/explore/components/ControlHeader.jsx b/superset/assets/javascripts/explore/components/ControlHeader.jsx
index bc474a6..ce00a9d 100644
--- a/superset/assets/javascripts/explore/components/ControlHeader.jsx
+++ b/superset/assets/javascripts/explore/components/ControlHeader.jsx
@@ -14,6 +14,7 @@ const propTypes = {
   onClick: PropTypes.func,
   hovered: PropTypes.bool,
   tooltipOnClick: PropTypes.func,
+  warning: PropTypes.string,
 };
 
 const defaultProps = {
@@ -75,6 +76,19 @@ export default class ControlHeader extends React.Component {
               {this.props.label}
             </span>
             {' '}
+            {(this.props.warning) &&
+              <span>
+                <OverlayTrigger
+                  placement="top"
+                  overlay={
+                    <Tooltip id={'error-tooltip'}>{this.props.warning}</Tooltip>
+                  }
+                >
+                  <i className="fa fa-exclamation-circle text-danger" />
+                </OverlayTrigger>
+                {' '}
+              </span>
+            }
             {(this.props.validationErrors.length > 0) &&
               <span>
                 <OverlayTrigger
diff --git a/superset/assets/javascripts/explore/components/controls/TextAreaControl.jsx b/superset/assets/javascripts/explore/components/controls/TextAreaControl.jsx
index 3e96854..11c77a2 100644
--- a/superset/assets/javascripts/explore/components/controls/TextAreaControl.jsx
+++ b/superset/assets/javascripts/explore/components/controls/TextAreaControl.jsx
@@ -25,6 +25,7 @@ const propTypes = {
   offerEditInModal: PropTypes.bool,
   language: PropTypes.oneOf([null, 'json', 'html', 'sql', 'markdown', 'javascript']),
   aboveEditorSection: PropTypes.node,
+  readOnly: PropTypes.bool,
 };
 
 const defaultProps = {
@@ -34,6 +35,7 @@ const defaultProps = {
   minLines: 3,
   maxLines: 10,
   offerEditInModal: true,
+  readOnly: false,
 };
 
 export default class TextAreaControl extends React.Component {
@@ -57,6 +59,7 @@ export default class TextAreaControl extends React.Component {
           editorProps={{ $blockScrolling: true }}
           enableLiveAutocompletion
           value={this.props.value}
+          readOnly={this.props.readOnly}
         />
       );
     }
@@ -67,6 +70,7 @@ export default class TextAreaControl extends React.Component {
           placeholder={t('textarea')}
           onChange={this.onControlChange.bind(this)}
           value={this.props.value}
+          disabled={this.props.readOnly}
           style={{ height: this.props.height }}
         />
       </FormGroup>);
diff --git a/superset/assets/javascripts/explore/stores/controls.jsx b/superset/assets/javascripts/explore/stores/controls.jsx
index 529e51c..22b8b32 100644
--- a/superset/assets/javascripts/explore/stores/controls.jsx
+++ b/superset/assets/javascripts/explore/stores/controls.jsx
@@ -97,6 +97,11 @@ function jsFunctionControl(label, description, extraDescr = null, height
= 100,
         {extraDescr}
       </div>
     ),
+    mapStateToProps: state => ({
+      warning: !state.common.conf.ENABLE_JAVASCRIPT_CONTROLS ?
+        t('This functionality is disabled in your environment for security reasons.') : null,
+      readOnly: !state.common.conf.ENABLE_JAVASCRIPT_CONTROLS,
+    }),
   };
 }
 
diff --git a/superset/config.py b/superset/config.py
index 1ada471..9e84c46 100644
--- a/superset/config.py
+++ b/superset/config.py
@@ -370,6 +370,12 @@ TRACKING_URL_TRANSFORMER = lambda x: x  # noqa: E731
 # Interval between consecutive polls when using Hive Engine
 HIVE_POLL_INTERVAL = 5
 
+# Allow for javascript controls components
+# this enables programmers to customize certain charts (like the
+# geospatial ones) by inputing javascript in controls. This exposes
+# an XSS security vulnerability
+ENABLE_JAVASCRIPT_CONTROLS = False
+
 try:
     if CONFIG_PATH_ENV_VAR in os.environ:
         # Explicitly import config module that is not in pythonpath; useful
diff --git a/superset/views/base.py b/superset/views/base.py
index a909ed0..7e0edc4 100644
--- a/superset/views/base.py
+++ b/superset/views/base.py
@@ -19,7 +19,10 @@ from superset.connectors.connector_registry import ConnectorRegistry
 from superset.connectors.sqla.models import SqlaTable
 from superset.translations.utils import get_language_pack
 
-FRONTEND_CONF_KEYS = ('SUPERSET_WEBSERVER_TIMEOUT',)
+FRONTEND_CONF_KEYS = (
+    'SUPERSET_WEBSERVER_TIMEOUT',
+    'ENABLE_JAVASCRIPT_CONTROLS',
+)
 
 
 def get_error_msg():
diff --git a/superset/views/core.py b/superset/views/core.py
index 46e1650..e5a6bf0 100755
--- a/superset/views/core.py
+++ b/superset/views/core.py
@@ -73,6 +73,14 @@ if perms_instruction_link:
 else:
     DATASOURCE_ACCESS_ERR = __("You don't have access to this datasource")
 
+FORM_DATA_KEY_BLACKLIST = []
+if not config.get('ENABLE_JAVASCRIPT_CONTROLS'):
+    FORM_DATA_KEY_BLACKLIST = [
+        'js_tooltip',
+        'js_onclick_href',
+        'js_data_mutator',
+    ]
+
 
 def get_database_access_error_msg(database_name):
     return __('This view requires the database %(name)s or '
@@ -948,7 +956,10 @@ class Superset(BaseSupersetView):
 
         if request.args.get('viz_type'):
             # Converting old URLs
-            d = cast_form_data(request.args)
+            d = cast_form_data(d)
+
+        d = {k: v for k, v in d.items() if k not in FORM_DATA_KEY_BLACKLIST}
+
         return d
 
     def get_viz(

-- 
To stop receiving notification emails like this one, please contact
maximebeauchemin@apache.org.

Mime
View raw message