Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
seleniumhq
GitHub Repository: seleniumhq/selenium
Path: blob/trunk/third_party/closure/goog/html/sanitizer/unsafe_test.js
2868 views
1
// Copyright 2016 The Closure Library Authors. All Rights Reserved.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
// http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS-IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
/**
16
* @fileoverview Unit Test for the unsafe API of the HTML Sanitizer.
17
*/
18
19
goog.setTestOnly();
20
21
goog.require('goog.html.SafeHtml');
22
goog.require('goog.html.sanitizer.HtmlSanitizer');
23
goog.require('goog.html.sanitizer.TagBlacklist');
24
goog.require('goog.html.sanitizer.unsafe');
25
26
goog.require('goog.string.Const');
27
goog.require('goog.testing.dom');
28
goog.require('goog.testing.jsunit');
29
goog.require('goog.userAgent');
30
31
/**
32
* @return {boolean} Whether the browser is IE8 or below.
33
*/
34
function isIE8() {
35
return goog.userAgent.IE && !goog.userAgent.isVersionOrHigher(9);
36
}
37
38
39
/**
40
* @return {boolean} Whether the browser is IE9.
41
*/
42
function isIE9() {
43
return goog.userAgent.IE && !goog.userAgent.isVersionOrHigher(10) && !isIE8();
44
}
45
46
47
var just = goog.string.Const.from('test');
48
49
50
/**
51
* Sanitizes the original HTML and asserts that it is the same as the expected
52
* HTML. Supports adding tags and attributes through the unsafe API.
53
* @param {string} originalHtml
54
* @param {string} expectedHtml
55
* @param {?Array<string>=} opt_tags
56
* @param {?Array<(string|!goog.html.sanitizer.HtmlSanitizerAttributePolicy)>=}
57
* opt_attrs
58
* @param {?goog.html.sanitizer.HtmlSanitizer.Builder=} opt_builder
59
*/
60
function assertSanitizedHtml(
61
originalHtml, expectedHtml, opt_tags, opt_attrs, opt_builder) {
62
var builder = opt_builder || new goog.html.sanitizer.HtmlSanitizer.Builder();
63
if (opt_tags)
64
builder = goog.html.sanitizer.unsafe.alsoAllowTags(just, builder, opt_tags);
65
if (opt_attrs)
66
builder = goog.html.sanitizer.unsafe.alsoAllowAttributes(
67
just, builder, opt_attrs);
68
var sanitizer = builder.build();
69
try {
70
var sanitized = sanitizer.sanitize(originalHtml);
71
if (isIE9()) {
72
assertEquals('', goog.html.SafeHtml.unwrap(sanitized));
73
return;
74
}
75
goog.testing.dom.assertHtmlMatches(
76
expectedHtml, goog.html.SafeHtml.unwrap(sanitized),
77
true /* opt_strictAttributes */);
78
} catch (err) {
79
if (!isIE8()) {
80
throw err;
81
}
82
}
83
}
84
85
86
function testAllowEmptyTagList() {
87
var input = '<sdf><aaa></aaa></sdf><b></b>';
88
var expected = '<span><span></span></span><b></b>';
89
assertSanitizedHtml(input, expected, []);
90
}
91
92
93
function testAllowBlacklistedTag() {
94
var input = '<div><script>aaa</script></div>';
95
var expected = '<div></div>';
96
assertSanitizedHtml(input, expected, ['SCriPT']);
97
}
98
99
100
function testAllowUnknownTags() {
101
var input = '<hello><bye>aaa</bye></hello><zzz></zzz>';
102
var expected = '<hello><span>aaa</span></hello><zzz></zzz>';
103
assertSanitizedHtml(input, expected, ['HElLO', 'zZZ']);
104
}
105
106
107
function testAllowAlreadyWhiteListedTag() {
108
var input = '<hello><p><zzz></zzz></p></hello>';
109
var expected = '<span><p><zzz></zzz></p></span>';
110
assertSanitizedHtml(input, expected, ['p', 'ZZZ']);
111
}
112
113
114
function testAllowEmptyAttrList() {
115
var input = '<a href="#" qwe="nope">b</a>';
116
var expected = '<a href="#">b</a>';
117
assertSanitizedHtml(input, expected, null, []);
118
}
119
120
121
function testAllowUnknownAttributeSimple() {
122
var input = '<qqq zzz="3" nnn="no"></qqq>';
123
var expected = '<span zzz="3"></span>';
124
assertSanitizedHtml(input, expected, null, ['Zzz']);
125
}
126
127
128
function testAllowUnknownAttributeWildCard() {
129
var input = '<div ab="yes" bb="no"><img ab="yep" bb="no" /></div>';
130
var expected = '<div ab="yes"><img ab="yep" /></div>';
131
assertSanitizedHtml(
132
input, expected, null, [{tagName: '*', attributeName: 'aB'}]);
133
}
134
135
136
function testAllowUnknownAttributeOnSpecificTag() {
137
var input = '<a www="3" zzz="4">fff</a><img www="3" />';
138
var expected = '<a www="3">fff</a><img />';
139
assertSanitizedHtml(
140
input, expected, null, [{tagName: 'a', attributeName: 'WwW'}]);
141
}
142
143
144
function testAllowUnknownAttributePolicy() {
145
var input = '<img ab="yes" /><img ab="no" />';
146
var expected = '<img ab="yes" /><img />';
147
assertSanitizedHtml(input, expected, null, [{
148
tagName: '*',
149
attributeName: 'aB',
150
policy: function(value, hints) {
151
assertEquals(hints.attributeName, 'ab');
152
return value === 'yes' ? value : null;
153
}
154
}]);
155
}
156
157
158
function testAllowOverwriteAttrPolicy() {
159
var input = '<a href="yes"></a><a href="no"></a>';
160
var expected = '<a href="yes"></a><a></a>';
161
assertSanitizedHtml(
162
input, expected, null, [{
163
tagName: 'a',
164
attributeName: 'href',
165
policy: function(value) { return value === 'yes' ? value : null; }
166
}]);
167
}
168
169
170
function testWhitelistAliasing() {
171
var builder = new goog.html.sanitizer.HtmlSanitizer.Builder();
172
goog.html.sanitizer.unsafe.alsoAllowTags(just, builder, ['QqQ']);
173
goog.html.sanitizer.unsafe.alsoAllowAttributes(just, builder, ['QqQ']);
174
builder.build();
175
assertUndefined(goog.html.sanitizer.TagWhitelist['QQQ']);
176
assertUndefined(goog.html.sanitizer.TagWhitelist['QqQ']);
177
assertUndefined(goog.html.sanitizer.TagWhitelist['qqq']);
178
assertUndefined(goog.html.sanitizer.AttributeWhitelist['* QQQ']);
179
assertUndefined(goog.html.sanitizer.AttributeWhitelist['* QqQ']);
180
assertUndefined(goog.html.sanitizer.AttributeWhitelist['* qqq']);
181
}
182
183
184
function testTemplateUnsanitized() {
185
if (!goog.html.sanitizer.HTML_SANITIZER_TEMPLATE_SUPPORTED) {
186
return;
187
}
188
var input = '<template><div>a</div><script>qqq</script>' +
189
'<template>a</template></template>';
190
// TODO(pelizzi): use unblockTag once it's available
191
delete goog.html.sanitizer.TagBlacklist['TEMPLATE'];
192
var builder = new goog.html.sanitizer.HtmlSanitizer.Builder();
193
goog.html.sanitizer.unsafe.keepUnsanitizedTemplateContents(just, builder);
194
assertSanitizedHtml(input, input, ['TEMPLATE'], null, builder);
195
goog.html.sanitizer.TagBlacklist['TEMPLATE'] = true;
196
}
197
198
199
function testTemplateSanitizedUnsanitizedXSS() {
200
if (!goog.html.sanitizer.HTML_SANITIZER_TEMPLATE_SUPPORTED) {
201
return;
202
}
203
var input = '<template><p>a</p><script>aaaa;</script></template>';
204
var expected = '<span><p>a</p></span>';
205
delete goog.html.sanitizer.TagBlacklist['TEMPLATE'];
206
var builder = new goog.html.sanitizer.HtmlSanitizer.Builder();
207
goog.html.sanitizer.unsafe.keepUnsanitizedTemplateContents(just, builder);
208
assertSanitizedHtml(input, expected, null, null, builder);
209
goog.html.sanitizer.TagBlacklist['TEMPLATE'] = true;
210
}
211
212
213
function testTemplateUnsanitizedThrowsIE() {
214
if (goog.html.sanitizer.HTML_SANITIZER_TEMPLATE_SUPPORTED) {
215
return;
216
}
217
var builder = new goog.html.sanitizer.HtmlSanitizer.Builder();
218
assertThrows(function() {
219
goog.html.sanitizer.unsafe.keepUnsanitizedTemplateContents(just, builder);
220
});
221
}
222
223
224
function testAllowRelaxExistingAttributePolicyWildcard() {
225
var input = '<a href="javascript:alert(1)"></a>';
226
// define a tag-specific one, takes precedence
227
assertSanitizedHtml(
228
input, input, null,
229
[{tagName: 'a', attributeName: 'href', policy: goog.functions.identity}]);
230
// overwrite the global one
231
assertSanitizedHtml(
232
input, input, null,
233
[{tagName: '*', attributeName: 'href', policy: goog.functions.identity}]);
234
}
235
236
237
function testAllowRelaxExistingAttributePolicySpecific() {
238
var input = '<a target="foo"></a>';
239
var expected = '<a></a>';
240
// overwrite the global one, the specific one still has precedence
241
assertSanitizedHtml(input, expected, null, [
242
{tagName: '*', attributeName: 'target', policy: goog.functions.identity}
243
]);
244
// overwrite the tag-specific one, this one should take precedence
245
assertSanitizedHtml(input, input, null, [
246
{tagName: 'a', attributeName: 'target', policy: goog.functions.identity}
247
]);
248
}
249
250