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

[security] prevent XSS markup viz #3211

Merged
merged 2 commits into from
Aug 11, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 20 additions & 7 deletions superset/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,22 +32,35 @@
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:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)}
Expand Down
2 changes: 1 addition & 1 deletion superset/assets/stylesheets/less/cosmo/variables.less
Original file line number Diff line number Diff line change
Expand Up @@ -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>`.
Expand Down
12 changes: 5 additions & 7 deletions superset/assets/stylesheets/superset.less
Original file line number Diff line number Diff line change
@@ -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;
}
Expand Down Expand Up @@ -255,4 +249,8 @@ div.widget .slice_container {
.panel .table-responsive{
width: 98%;
}
}
}
iframe {
border: none;
width: 100%;
}
22 changes: 20 additions & 2 deletions superset/assets/visualizations/markup.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
4 changes: 2 additions & 2 deletions superset/viz.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
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
Expand Down Expand Up @@ -439,7 +439,7 @@ def get_data(self, df):
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):
Expand Down