[security] prevent XSS markup viz (#3211)

* Prevent XSS in Markup viz

We protect the browser by sandboxing the user code inside an iframe

* Helvetica
This commit is contained in:
Maxime Beauchemin 2017-08-10 21:38:33 -07:00 committed by GitHub
parent bd4a4c2753
commit 0c5db55d55
6 changed files with 49 additions and 20 deletions

View File

@ -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:

View File

@ -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)}

View File

@ -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>`.

View File

@ -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%;
}
}
}
iframe {
border: none;
width: 100%;
}

View File

@ -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;

View File

@ -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):