Skip to content

Commit e26a465

Browse files
afshinSteven Silvester
authored and
Steven Silvester
committed
Merge pull request from GHSA-hwvq-6gjx-j797
* sanitizer fix * Pass sanitizer options explicitly
1 parent 7aa0b1b commit e26a465

File tree

6 files changed

+45
-123
lines changed

6 files changed

+45
-123
lines changed

bower.json

-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
"create-react-class": "https://cdn.jsdelivr.net/npm/[email protected]/create-react-class.min.js",
1010
"es6-promise": "~1.0",
1111
"font-awesome": "components/font-awesome#~4.7.0",
12-
"google-caja": "5669",
1312
"jed": "~1.1.1",
1413
"jquery": "components/jquery#~3.4.1",
1514
"jquery-typeahead": "~2.0.0",

notebook/static/base/js/namespace.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ define(function(){
3232
// expose modules
3333

3434
jprop('utils','base/js/utils')
35-
35+
3636
//Jupyter.load_extensions = Jupyter.utils.load_extensions;
3737
//
3838
jprop('security','base/js/security');

notebook/static/base/js/security.js

+11-112
Original file line numberDiff line numberDiff line change
@@ -3,124 +3,24 @@
33

44
define([
55
'jquery',
6-
'components/google-caja/html-css-sanitizer-minified',
7-
], function($, sanitize) {
6+
'components/sanitizer/index',
7+
], function($, sanitizer) {
88
"use strict";
9-
9+
1010
var noop = function (x) { return x; };
11-
12-
var caja;
13-
if (window && window.html) {
14-
caja = window.html;
15-
caja.html4 = window.html4;
16-
caja.sanitizeStylesheet = window.sanitizeStylesheet;
17-
}
18-
19-
var sanitizeAttribs = function (tagName, attribs, opt_naiveUriRewriter, opt_nmTokenPolicy, opt_logger) {
20-
/**
21-
* add trusting data-attributes to the default sanitizeAttribs from caja
22-
* this function is mostly copied from the caja source
23-
*/
24-
var ATTRIBS = caja.html4.ATTRIBS;
25-
for (var i = 0; i < attribs.length; i += 2) {
26-
var attribName = attribs[i];
27-
if (attribName.substr(0,5) == 'data-') {
28-
var attribKey = '*::' + attribName;
29-
if (!ATTRIBS.hasOwnProperty(attribKey)) {
30-
ATTRIBS[attribKey] = 0;
31-
}
32-
}
33-
}
34-
// Caja doesn't allow data uri for img::src, see
35-
// https://github.com/google/caja/issues/1558
36-
// This is not a security issue for browser post ie6 though, so we
37-
// disable the check
38-
// https://www.owasp.org/index.php/Script_in_IMG_tags
39-
ATTRIBS['img::src'] = 0;
40-
return caja.sanitizeAttribs(tagName, attribs, opt_naiveUriRewriter, opt_nmTokenPolicy, opt_logger);
41-
};
42-
43-
var sanitize_css = function (css, tagPolicy) {
44-
/**
45-
* sanitize CSS
46-
* like sanitize_html, but for CSS
47-
* called by sanitize_stylesheets
48-
*/
49-
return caja.sanitizeStylesheet(
50-
window.location.pathname,
51-
css,
52-
{
53-
containerClass: null,
54-
idSuffix: '',
55-
tagPolicy: tagPolicy,
56-
virtualizeAttrName: noop
57-
},
58-
noop
59-
);
60-
};
61-
62-
var sanitize_stylesheets = function (html, tagPolicy) {
63-
/**
64-
* sanitize just the css in style tags in a block of html
65-
* called by sanitize_html, if allow_css is true
66-
*/
67-
var h = $("<div/>").append(html);
68-
var style_tags = h.find("style");
69-
if (!style_tags.length) {
70-
// no style tags to sanitize
71-
return html;
72-
}
73-
style_tags.each(function(i, style) {
74-
style.innerHTML = sanitize_css(style.innerHTML, tagPolicy);
75-
});
76-
return h.html();
77-
};
78-
11+
var defaultSanitizer = sanitizer.defaultSanitizer;
12+
7913
var sanitize_html = function (html, allow_css) {
8014
/**
8115
* sanitize HTML
8216
* if allow_css is true (default: false), CSS is sanitized as well.
8317
* otherwise, CSS elements and attributes are simply removed.
8418
*/
85-
var html4 = caja.html4;
86-
87-
if (allow_css) {
88-
// allow sanitization of style tags,
89-
// not just scrubbing
90-
html4.ELEMENTS.style &= ~html4.eflags.UNSAFE;
91-
html4.ATTRIBS.style = html4.atype.STYLE;
92-
} else {
93-
// scrub all CSS
94-
html4.ELEMENTS.style |= html4.eflags.UNSAFE;
95-
html4.ATTRIBS.style = html4.atype.SCRIPT;
96-
}
97-
98-
var record_messages = function (msg, opts) {
99-
console.log("HTML Sanitizer", msg, opts);
100-
};
101-
102-
var policy = function (tagName, attribs) {
103-
if (!(html4.ELEMENTS[tagName] & html4.eflags.UNSAFE)) {
104-
return {
105-
'attribs': sanitizeAttribs(tagName, attribs,
106-
noop, noop, record_messages)
107-
};
108-
} else {
109-
record_messages(tagName + " removed", {
110-
change: "removed",
111-
tagName: tagName
112-
});
113-
}
114-
};
115-
116-
var sanitized = caja.sanitizeWithPolicy(html, policy);
117-
118-
if (allow_css) {
119-
// sanitize style tags as stylesheets
120-
sanitized = sanitize_stylesheets(sanitized, policy);
121-
}
122-
123-
return sanitized;
19+
const options = {};
20+
if (!allow_css) {
21+
options.allowedStyles = {};
22+
}
23+
return defaultSanitizer.sanitize(html, options);
12424
};
12525

12626
var sanitize_html_and_parse = function (html, allow_css) {
@@ -141,9 +41,8 @@ define([
14141
$.htmlPrefilter = prev_htmlPrefilter; // Set it back again
14242
}
14343
};
144-
44+
14545
var security = {
146-
caja: caja,
14746
sanitize_html_and_parse: sanitize_html_and_parse,
14847
sanitize_html: sanitize_html
14948
};

package.json

+11-6
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,18 @@
1111
"scripts": {
1212
"bower": "bower install",
1313
"build": "python setup.py js css",
14-
"build:watch": "set -e; while true; do npm run build; sleep 3; done"
14+
"build:webpack": "webpack --mode development",
15+
"build:watch": "npm run watch",
16+
"watch": "onchange 'notebook/static/**/!(*.min).js' 'notebook/static/**/*.less' 'bower.json' -- npm run build"
1517
},
1618
"devDependencies": {
17-
"bower": "*",
19+
"@jupyterlab/apputils": "^3.1.3",
20+
"bower": "^1.8.8",
1821
"less": "~2",
19-
"requirejs": "^2.1.17",
20-
"po2json": "^0.4.5"
21-
},
22-
"dependencies": {}
22+
"onchange": "^6.0.0",
23+
"po2json": "^0.4.5",
24+
"requirejs": "^2.3.6",
25+
"webpack": "^5.46.0",
26+
"webpack-cli": "^4.7.2"
27+
}
2328
}

setupbase.py

+12-3
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,6 @@ def find_package_data():
140140
pjoin(components, "font-awesome", "css", "*.css"),
141141
pjoin(components, "es6-promise", "*.js"),
142142
pjoin(components, "font-awesome", "fonts", "*.*"),
143-
pjoin(components, "google-caja", "html-css-sanitizer-minified.js"),
144143
pjoin(components, "jed", "jed.js"),
145144
pjoin(components, "jquery", "jquery.min.js"),
146145
pjoin(components, "jquery-typeahead", "dist", "jquery.typeahead.min.js"),
@@ -153,6 +152,7 @@ def find_package_data():
153152
pjoin(components, "requirejs", "require.js"),
154153
pjoin(components, "requirejs-plugins", "src", "json.js"),
155154
pjoin(components, "requirejs-text", "text.js"),
155+
pjoin(components, "sanitizer", "index.js"),
156156
pjoin(components, "underscore", "underscore-min.js"),
157157
pjoin(components, "moment", "moment.js"),
158158
pjoin(components, "moment", "min", "*.js"),
@@ -376,14 +376,21 @@ def finalize_options(self):
376376

377377
bower_dir = pjoin(static, 'components')
378378
node_modules = pjoin(repo_root, 'node_modules')
379+
sanitizer_dir = pjoin(bower_dir, 'sanitizer')
379380

380381
def should_run(self):
381382
if self.force:
382383
return True
383384
if not os.path.exists(self.bower_dir):
384385
return True
385-
386-
return mtime(self.bower_dir) < mtime(pjoin(repo_root, 'bower.json'))
386+
if not os.path.exists(self.sanitizer_dir):
387+
return True
388+
389+
bower_stale = mtime(self.bower_dir) < mtime(pjoin(repo_root, 'bower.json'))
390+
if bower_stale:
391+
return True
392+
393+
return mtime(self.sanitizer_dir) < mtime(pjoin(repo_root, 'webpack.config.js'))
387394

388395
def should_run_npm(self):
389396
if not which('npm'):
@@ -417,6 +424,8 @@ def run(self):
417424
print("You can install js dependencies with `npm install`", file=sys.stderr)
418425
raise
419426
# self.npm_components()
427+
if not os.path.exists(self.sanitizer_dir):
428+
run(['npm', 'run', 'build:webpack'], cwd=repo_root, env=env)
420429
os.utime(self.bower_dir, None)
421430
# update package data in case this created new files
422431
update_package_data(self.distribution)

webpack.config.js

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
const path = require('path');
2+
3+
module.exports = {
4+
entry: '@jupyterlab/apputils/lib/sanitizer',
5+
output: {
6+
filename: 'index.js',
7+
path: path.resolve(__dirname, 'notebook/static/components/sanitizer'),
8+
libraryTarget: "amd"
9+
}
10+
}

0 commit comments

Comments
 (0)