Show More
@@ -42,6 +42,7 b' IPython.security = (function (IPython) {' | |||||
42 | if (window && window.html) { |
|
42 | if (window && window.html) { | |
43 | caja = window.html; |
|
43 | caja = window.html; | |
44 | caja.html4 = window.html4; |
|
44 | caja.html4 = window.html4; | |
|
45 | caja.sanitizeStylesheet = window.sanitizeStylesheet; | |||
45 | } |
|
46 | } | |
46 |
|
47 | |||
47 | var sanitizeAttribs = function (tagName, attribs, opt_naiveUriRewriter, opt_nmTokenPolicy, opt_logger) { |
|
48 | var sanitizeAttribs = function (tagName, attribs, opt_naiveUriRewriter, opt_nmTokenPolicy, opt_logger) { | |
@@ -59,8 +60,37 b' IPython.security = (function (IPython) {' | |||||
59 | return caja.sanitizeAttribs(tagName, attribs, opt_naiveUriRewriter, opt_nmTokenPolicy, opt_logger); |
|
60 | return caja.sanitizeAttribs(tagName, attribs, opt_naiveUriRewriter, opt_nmTokenPolicy, opt_logger); | |
60 | }; |
|
61 | }; | |
61 |
|
62 | |||
62 |
var sanitize = function ( |
|
63 | var sanitize_css = function (css, tagPolicy) { | |
|
64 | return caja.sanitizeStylesheet( | |||
|
65 | window.location.pathname, | |||
|
66 | css, | |||
|
67 | { | |||
|
68 | containerClass: null, | |||
|
69 | idSuffix: '', | |||
|
70 | tagPolicy: tagPolicy, | |||
|
71 | virtualizeAttrName: noop | |||
|
72 | }, | |||
|
73 | noop | |||
|
74 | ); | |||
|
75 | }; | |||
|
76 | ||||
|
77 | var sanitize_stylesheets = function (html, tagPolicy) { | |||
|
78 | var h = $("<div/>").append(html); | |||
|
79 | var style_tags = h.find("style"); | |||
|
80 | if (!style_tags.length) { | |||
|
81 | // no style tags to sanitize | |||
|
82 | return html; | |||
|
83 | } | |||
|
84 | style_tags.each(function(i, style) { | |||
|
85 | style.innerHTML = sanitize_css(style.innerHTML, tagPolicy); | |||
|
86 | }); | |||
|
87 | return h.html(); | |||
|
88 | }; | |||
|
89 | ||||
|
90 | var sanitize = function (html, allow_css) { | |||
63 | // sanitize HTML |
|
91 | // sanitize HTML | |
|
92 | // if allow_css is true (default), CSS is sanitized as well. | |||
|
93 | // otherwise, CSS elements and attributes are simply removed. | |||
64 | // returns a struct of |
|
94 | // returns a struct of | |
65 | // { |
|
95 | // { | |
66 | // src: original_html, |
|
96 | // src: original_html, | |
@@ -69,6 +99,20 b' IPython.security = (function (IPython) {' | |||||
69 | // This is an incomplete indication, |
|
99 | // This is an incomplete indication, | |
70 | // only used to indicate whether further verification is necessary. |
|
100 | // only used to indicate whether further verification is necessary. | |
71 | // } |
|
101 | // } | |
|
102 | var html4 = caja.html4; | |||
|
103 | ||||
|
104 | if (allow_css === undefined) allow_css = true; | |||
|
105 | if (allow_css) { | |||
|
106 | // allow sanitization of style tags, | |||
|
107 | // not just scrubbing | |||
|
108 | html4.ELEMENTS.style &= ~html4.eflags.UNSAFE; | |||
|
109 | html4.ATTRIBS.style = html4.atype.STYLE; | |||
|
110 | } else { | |||
|
111 | // scrub all CSS | |||
|
112 | html4.ELEMENTS.style |= html4.eflags.UNSAFE; | |||
|
113 | html4.ATTRIBS.style = html4.atype.SCRIPT; | |||
|
114 | } | |||
|
115 | ||||
72 | var result = { |
|
116 | var result = { | |
73 | src : html, |
|
117 | src : html, | |
74 | _maybe_safe : true |
|
118 | _maybe_safe : true | |
@@ -78,7 +122,6 b' IPython.security = (function (IPython) {' | |||||
78 | result._maybe_safe = false; |
|
122 | result._maybe_safe = false; | |
79 | }; |
|
123 | }; | |
80 |
|
124 | |||
81 | var html4 = caja.html4; |
|
|||
82 | var policy = function (tagName, attribs) { |
|
125 | var policy = function (tagName, attribs) { | |
83 | if (!(html4.ELEMENTS[tagName] & html4.eflags.UNSAFE)) { |
|
126 | if (!(html4.ELEMENTS[tagName] & html4.eflags.UNSAFE)) { | |
84 | return { |
|
127 | return { | |
@@ -94,6 +137,12 b' IPython.security = (function (IPython) {' | |||||
94 | }; |
|
137 | }; | |
95 |
|
138 | |||
96 | result.sanitized = caja.sanitizeWithPolicy(html, policy); |
|
139 | result.sanitized = caja.sanitizeWithPolicy(html, policy); | |
|
140 | ||||
|
141 | if (allow_css) { | |||
|
142 | // sanitize style tags as stylesheets | |||
|
143 | result.sanitized = sanitize_stylesheets(result.sanitized, policy); | |||
|
144 | } | |||
|
145 | ||||
97 | return result; |
|
146 | return result; | |
98 | }; |
|
147 | }; | |
99 |
|
148 | |||
@@ -104,6 +153,7 b' IPython.security = (function (IPython) {' | |||||
104 |
|
153 | |||
105 | var is_safe = function (html) { |
|
154 | var is_safe = function (html) { | |
106 | // just return bool for whether an HTML string is safe |
|
155 | // just return bool for whether an HTML string is safe | |
|
156 | // this is not currently used for anything other than tests. | |||
107 | var result = sanitize(html); |
|
157 | var result = sanitize(html); | |
108 |
|
158 | |||
109 | // caja can strip whole elements without logging, |
|
159 | // caja can strip whole elements without logging, | |
@@ -117,6 +167,7 b' IPython.security = (function (IPython) {' | |||||
117 | }; |
|
167 | }; | |
118 |
|
168 | |||
119 | return { |
|
169 | return { | |
|
170 | caja: caja, | |||
120 | is_safe: is_safe, |
|
171 | is_safe: is_safe, | |
121 | sanitize: sanitize, |
|
172 | sanitize: sanitize, | |
122 | sanitize_html: sanitize_html |
|
173 | sanitize_html: sanitize_html |
@@ -291,7 +291,7 b' class="notebook_app"' | |||||
291 |
|
291 | |||
292 | {{super()}} |
|
292 | {{super()}} | |
293 |
|
293 | |||
294 |
<script src="{{ static_url("components/google-caja/ |
|
294 | <script src="{{ static_url("components/google-caja/html-css-sanitizer-minified.js") }}" charset="utf-8"></script> | |
295 | <script src="{{ static_url("components/codemirror/lib/codemirror.js") }}" charset="utf-8"></script> |
|
295 | <script src="{{ static_url("components/codemirror/lib/codemirror.js") }}" charset="utf-8"></script> | |
296 | <script type="text/javascript"> |
|
296 | <script type="text/javascript"> | |
297 | CodeMirror.modeURL = "{{ static_url("components/codemirror/mode/%N/%N.js", include_version=False) }}"; |
|
297 | CodeMirror.modeURL = "{{ static_url("components/codemirror/mode/%N/%N.js", include_version=False) }}"; |
@@ -3,6 +3,7 b' safe_tests = [' | |||||
3 | '<h1 class="foo">Hi There!</h1>', |
|
3 | '<h1 class="foo">Hi There!</h1>', | |
4 | '<a data-cite="foo">citation</a>', |
|
4 | '<a data-cite="foo">citation</a>', | |
5 | '<div><span>Hi There</span></div>', |
|
5 | '<div><span>Hi There</span></div>', | |
|
6 | '<style>div.foo { background: #ffff; }</style>', | |||
6 | ]; |
|
7 | ]; | |
7 |
|
8 | |||
8 | unsafe_tests = [ |
|
9 | unsafe_tests = [ | |
@@ -17,7 +18,7 b' unsafe_tests = [' | |||||
17 | '<META HTTP-EQUIV="refresh" CONTENT="0; URL=http://;URL=javascript:alert(999);">', |
|
18 | '<META HTTP-EQUIV="refresh" CONTENT="0; URL=http://;URL=javascript:alert(999);">', | |
18 | '<IFRAME SRC="javascript:alert(999);"></IFRAME>', |
|
19 | '<IFRAME SRC="javascript:alert(999);"></IFRAME>', | |
19 | '<IFRAME SRC=# onmouseover="alert(document.cookie)"></IFRAME>', |
|
20 | '<IFRAME SRC=# onmouseover="alert(document.cookie)"></IFRAME>', | |
20 | '<style type="text/css">div.foo { background: #ffff; }</style>', |
|
21 | '<style src="http://untrusted/style.css"></style>', | |
21 | '<EMBED SRC="data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hs aW5rIiB2ZXJzaW9uPSIxLjAiIHg9IjAiIHk9IjAiIHdpZHRoPSIxOTQiIGhlaWdodD0iMjAw IiBpZD0ieHNzIj48c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+YWxlcnQoIlh TUyIpOzwvc2NyaXB0Pjwvc3ZnPg==" type="image/svg+xml" AllowScriptAccess="always"></EMBED>', |
|
22 | '<EMBED SRC="data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hs aW5rIiB2ZXJzaW9uPSIxLjAiIHg9IjAiIHk9IjAiIHdpZHRoPSIxOTQiIGhlaWdodD0iMjAw IiBpZD0ieHNzIj48c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+YWxlcnQoIlh TUyIpOzwvc2NyaXB0Pjwvc3ZnPg==" type="image/svg+xml" AllowScriptAccess="always"></EMBED>', | |
22 | ]; |
|
23 | ]; | |
23 |
|
24 | |||
@@ -26,6 +27,10 b' casper.notebook_test(function () {' | |||||
26 | var is_safe = self.evaluate(function (item) { |
|
27 | var is_safe = self.evaluate(function (item) { | |
27 | return IPython.security.is_safe(item); |
|
28 | return IPython.security.is_safe(item); | |
28 | }, item); |
|
29 | }, item); | |
|
30 | var sanitized = self.evaluate(function (item) { | |||
|
31 | return IPython.security.sanitize_html(item); | |||
|
32 | }, item); | |||
|
33 | ||||
29 | this.test.assert(is_safe, "Safe: " + item); |
|
34 | this.test.assert(is_safe, "Safe: " + item); | |
30 | }); |
|
35 | }); | |
31 | this.each(unsafe_tests, function (self, item) { |
|
36 | this.each(unsafe_tests, function (self, item) { |
General Comments 0
You need to be logged in to leave comments.
Login now