mirror of
https://github.com/apache/superset.git
synced 2024-09-17 11:09:47 -04:00
[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:
parent
bd4a4c2753
commit
0c5db55d55
@ -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:
|
||||
|
@ -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)}
|
||||
|
@ -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>`.
|
||||
|
@ -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%;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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):
|
||||
|
Loading…
Reference in New Issue
Block a user