You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by ma...@apache.org on 2017/08/11 04:38:35 UTC
[incubator-superset] branch master updated: [security] prevent XSS
markup viz (#3211)
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 0c5db55 [security] prevent XSS markup viz (#3211)
0c5db55 is described below
commit 0c5db55d55471c1c61c0750733733c157551b2d8
Author: Maxime Beauchemin <ma...@gmail.com>
AuthorDate: Thu Aug 10 21:38:33 2017 -0700
[security] prevent XSS markup viz (#3211)
* Prevent XSS in Markup viz
We protect the browser by sandboxing the user code inside an iframe
* Helvetica
---
superset/__init__.py | 27 ++++++++++++++++------
.../components/controls/TextAreaControl.jsx | 2 +-
.../assets/stylesheets/less/cosmo/variables.less | 2 +-
superset/assets/stylesheets/superset.less | 12 ++++------
superset/assets/visualizations/markup.js | 22 ++++++++++++++++--
superset/viz.py | 4 ++--
6 files changed, 49 insertions(+), 20 deletions(-)
diff --git a/superset/__init__.py b/superset/__init__.py
index 9576458..2e44ebd 100644
--- a/superset/__init__.py
+++ b/superset/__init__.py
@@ -32,22 +32,35 @@ app = Flask(__name__)
app.config.from_object(CONFIG_MODULE)
conf = app.config
+#################################################################
# Handling manifest file logic at app start
+#################################################################
MANIFEST_FILE = APP_DIR + '/static/assets/dist/manifest.json'
-get_manifest_file = lambda x: x
manifest = {}
-try:
- with open(MANIFEST_FILE, 'r') as f:
- manifest = json.load(f)
- get_manifest_file = lambda x: '/static/assets/dist/' + manifest.get(x, '')
-except Exception:
- print("no manifest file found at " + MANIFEST_FILE)
+def parse_manifest_json():
+ global manifest
+ try:
+ with open(MANIFEST_FILE, 'r') as f:
+ manifest = json.load(f)
+ except Exception:
+ print("no manifest file found at " + MANIFEST_FILE)
+
+
+def get_manifest_file(filename):
+ if app.debug:
+ parse_manifest_json()
+ return '/static/assets/dist/' + manifest.get(filename, '')
+
+parse_manifest_json()
+
@app.context_processor
def get_js_manifest():
return dict(js_manifest=get_manifest_file)
+#################################################################
+
for bp in conf.get('BLUEPRINTS'):
try:
diff --git a/superset/assets/javascripts/explore/components/controls/TextAreaControl.jsx b/superset/assets/javascripts/explore/components/controls/TextAreaControl.jsx
index 4fe9b77..31fe2bb 100644
--- a/superset/assets/javascripts/explore/components/controls/TextAreaControl.jsx
+++ b/superset/assets/javascripts/explore/components/controls/TextAreaControl.jsx
@@ -76,7 +76,7 @@ export default class TextAreaControl extends React.Component {
modalTitle={controlHeader}
triggerNode={
<Button bsSize="small" className="m-t-5">
- Edit <b>{this.props.language}</b> in modal
+ Edit <strong>{this.props.language}</strong> in modal
</Button>
}
modalBody={this.renderEditor(true)}
diff --git a/superset/assets/stylesheets/less/cosmo/variables.less b/superset/assets/stylesheets/less/cosmo/variables.less
index ce6b85a..fb2abf6 100644
--- a/superset/assets/stylesheets/less/cosmo/variables.less
+++ b/superset/assets/stylesheets/less/cosmo/variables.less
@@ -41,7 +41,7 @@
//
//## Font, line-height, and color for body text, headings, and more.
-@font-family-sans-serif: "Roboto", "Helvetica Neue", Helvetica, Arial, sans-serif;
+@font-family-sans-serif: Helvetica, Arial;
@font-family-serif: Georgia, "Times New Roman", Times, serif;
//** Default monospace fonts for `<code>`, `<kbd>`, and `<pre>`.
diff --git a/superset/assets/stylesheets/superset.less b/superset/assets/stylesheets/superset.less
index aa5678c..bacc18a 100644
--- a/superset/assets/stylesheets/superset.less
+++ b/superset/assets/stylesheets/superset.less
@@ -1,9 +1,3 @@
-@font-face {
- font-family: "Roboto";
- src: url("./fonts/Roboto-Regular.woff2") format("woff2"),
- url("./fonts/Roboto-Regular.woff") format("woff");
-}
-
body {
margin: 0px !important;
}
@@ -255,4 +249,8 @@ div.widget .slice_container {
.panel .table-responsive{
width: 98%;
}
-}
\ No newline at end of file
+}
+iframe {
+ border: none;
+ width: 100%;
+}
diff --git a/superset/assets/visualizations/markup.js b/superset/assets/visualizations/markup.js
index ba0ad44..379e2ef 100644
--- a/superset/assets/visualizations/markup.js
+++ b/superset/assets/visualizations/markup.js
@@ -4,11 +4,29 @@ require('./markup.css');
function markupWidget(slice, payload) {
$('#code').attr('rows', '15');
- slice.container.css({
+ const jqdiv = slice.container;
+ jqdiv.css({
overflow: 'auto',
height: slice.container.height(),
});
- slice.container.html(payload.data.html);
+
+ const iframeId = `if__${slice.containerId}`;
+ const html = `
+ <html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="${payload.data.theme_css}" />
+ </head>
+ <body style="background-color: transparent;">
+ ${payload.data.html}
+ </body>
+ </html>`;
+ jqdiv.html(`
+ <iframe id="${iframeId}"
+ frameborder="0"
+ height="${slice.height()}"
+ sandbox="allow-scripts">
+ </iframe>`);
+ $('#' + iframeId)[0].srcdoc = html;
}
module.exports = markupWidget;
diff --git a/superset/viz.py b/superset/viz.py
index c2d65e6..100d8bb 100644
--- a/superset/viz.py
+++ b/superset/viz.py
@@ -28,7 +28,7 @@ import simplejson as json
from six import string_types, PY3
from dateutil import relativedelta as rdelta
-from superset import app, utils, cache
+from superset import app, utils, cache, get_manifest_file
from superset.utils import DTTM_ALIAS
config = app.config
@@ -439,7 +439,7 @@ class MarkupViz(BaseViz):
code = self.form_data.get("code", '')
if markup_type == "markdown":
code = markdown(code)
- return dict(html=code)
+ return dict(html=code, theme_css=get_manifest_file('theme.css'))
class SeparatorViz(MarkupViz):
--
To stop receiving notification emails like this one, please contact
['"commits@superset.apache.org" <co...@superset.apache.org>'].