##// END OF EJS Templates
wrap caja.sanitizeAttribs to trust data-* attributes
MinRK -
Show More
@@ -1,83 +1,120
1 //----------------------------------------------------------------------------
1 //----------------------------------------------------------------------------
2 // Copyright (C) 2014 The IPython Development Team
2 // Copyright (C) 2014 The IPython Development Team
3 //
3 //
4 // Distributed under the terms of the BSD License. The full license is in
4 // Distributed under the terms of the BSD License. The full license is in
5 // the file COPYING, distributed as part of this software.
5 // the file COPYING, distributed as part of this software.
6 //----------------------------------------------------------------------------
6 //----------------------------------------------------------------------------
7
7
8 //============================================================================
8 //============================================================================
9 // Utilities
9 // Utilities
10 //============================================================================
10 //============================================================================
11 IPython.namespace('IPython.security');
11 IPython.namespace('IPython.security');
12
12
13 IPython.security = (function (IPython) {
13 IPython.security = (function (IPython) {
14 "use strict";
14 "use strict";
15
15
16 var utils = IPython.utils;
16 var utils = IPython.utils;
17
17
18 var noop = function (x) { return x; };
18 var noop = function (x) { return x; };
19
19
20 var cmp_tree = function (a, b) {
20 var cmp_tree = function (a, b) {
21 // compare two HTML trees
21 // compare two HTML trees
22 // only checks the tag structure is preserved,
22 // only checks the tag structure is preserved,
23 // not any attributes or contents
23 // not any attributes or contents
24 if (a.length !== b.length) {
24 if (a.length !== b.length) {
25 return false;
25 return false;
26 }
26 }
27
27
28 for (var i = a.length - 1; i >= 0; i--) {
28 for (var i = a.length - 1; i >= 0; i--) {
29 if (a[i].tagName && b[i].tagName && a[i].tagName.toLowerCase() != b[i].tagName.toLowerCase()) {
29 if (a[i].tagName && b[i].tagName && a[i].tagName.toLowerCase() != b[i].tagName.toLowerCase()) {
30 return false;
30 return false;
31 }
31 }
32 }
32 }
33 var ac = a.children();
33 var ac = a.children();
34 var bc = b.children();
34 var bc = b.children();
35 if (ac.length === 0 && bc.length === 0) {
35 if (ac.length === 0 && bc.length === 0) {
36 return true;
36 return true;
37 }
37 }
38 return cmp_tree(ac, bc);
38 return cmp_tree(ac, bc);
39 };
39 };
40
40
41 var caja;
42 if (window && window.html) {
43 caja = window.html;
44 caja.html4 = window.html4;
45 }
46
47 var sanitizeAttribs = function (tagName, attribs, opt_naiveUriRewriter, opt_nmTokenPolicy, opt_logger) {
48 // wrap sanitizeAttribs into trusting data-attributes
49 var ATTRIBS = caja.html4.ATTRIBS;
50 for (var i = 0; i < attribs.length; i += 2) {
51 var attribName = attribs[i];
52 if (attribName.substr(0,5) == 'data-') {
53 var attribKey = '*::' + attribName;
54 if (!ATTRIBS.hasOwnProperty(attribKey)) {
55 ATTRIBS[attribKey] = 0;
56 }
57 }
58 }
59 return caja.sanitizeAttribs(tagName, attribs, opt_naiveUriRewriter, opt_nmTokenPolicy, opt_logger);
60 };
61
41 var sanitize = function (html, log) {
62 var sanitize = function (html, log) {
42 // sanitize HTML
63 // sanitize HTML
43 // returns a struct of
64 // returns a struct of
44 // {
65 // {
45 // src: original_html,
66 // src: original_html,
46 // sanitized: the_sanitized_html,
67 // sanitized: the_sanitized_html,
47 // safe: bool // false if the sanitizer made any changes
68 // safe: bool // false if the sanitizer made any changes
48 // }
69 // }
49 var result = {
70 var result = {
50 src : html,
71 src : html,
51 safe : true
72 safe : true
52 };
73 };
53 var record_messages = function (msg, opts) {
74 var record_messages = function (msg, opts) {
54 console.log("HTML Sanitizer", msg, opts);
75 console.log("HTML Sanitizer", msg, opts);
55 result.safe = false;
76 result.safe = false;
56 };
77 };
57 result.sanitized = window.html_sanitize(html, noop, noop, record_messages);
78
79 var html4 = caja.html4;
80 var policy = function (tagName, attribs) {
81 if (!(html4.ELEMENTS[tagName] & html4.eflags.UNSAFE)) {
82 return {
83 'attribs': sanitizeAttribs(tagName, attribs,
84 noop, noop, record_messages)
85 };
86 } else {
87 record_messages(tagName + " removed", {
88 change: "removed",
89 tagName: tagName
90 });
91 }
92 };
93
94 result.sanitized = caja.sanitizeWithPolicy(html, policy);
58 // caja can strip whole elements without logging,
95 // caja can strip whole elements without logging,
59 // so double-check that node structure didn't change
96 // so double-check that node structure didn't change
60 if (result.safe) {
97 if (result.safe) {
61 result.safe = cmp_tree($(result.sanitized), $(result.src));
98 result.safe = cmp_tree($(result.sanitized), $(result.src));
62 }
99 }
63 return result;
100 return result;
64 };
101 };
65
102
66 var sanitize_html = function (html) {
103 var sanitize_html = function (html) {
67 // shorthand for str-to-str conversion, dropping the struct
104 // shorthand for str-to-str conversion, dropping the struct
68 return sanitize(html).sanitized;
105 return sanitize(html).sanitized;
69 };
106 };
70
107
71 var is_safe = function (html) {
108 var is_safe = function (html) {
72 // just return bool for whether an HTML string is safe
109 // just return bool for whether an HTML string is safe
73 return sanitize(html).safe;
110 return sanitize(html).safe;
74 };
111 };
75
112
76 return {
113 return {
77 is_safe: is_safe,
114 is_safe: is_safe,
78 sanitize: sanitize,
115 sanitize: sanitize,
79 sanitize_html: sanitize_html
116 sanitize_html: sanitize_html
80 };
117 };
81
118
82 }(IPython));
119 }(IPython));
83
120
General Comments 0
You need to be logged in to leave comments. Login now