Source code

Revision control

Other Tools

1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
* License, v. 2.0. If a copy of the MPL was not distributed with this
5
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "nsTreeSanitizer.h"
8
9
#include "mozilla/ArrayUtils.h"
10
#include "mozilla/BindingStyleRule.h"
11
#include "mozilla/DeclarationBlock.h"
12
#include "mozilla/StyleSheetInlines.h"
13
#include "mozilla/css/Rule.h"
14
#include "mozilla/dom/CSSRuleList.h"
15
#include "mozilla/dom/DocumentFragment.h"
16
#include "mozilla/dom/SRIMetadata.h"
17
#include "mozilla/NullPrincipal.h"
18
#include "nsCSSPropertyID.h"
19
#include "nsUnicharInputStream.h"
20
#include "nsAttrName.h"
21
#include "nsIScriptError.h"
22
#include "nsIScriptSecurityManager.h"
23
#include "nsNetUtil.h"
24
#include "nsComponentManagerUtils.h"
25
#include "nsContentUtils.h"
26
#include "nsIParserUtils.h"
27
#include "mozilla/dom/Document.h"
28
#include "nsQueryObject.h"
29
30
using namespace mozilla;
31
using namespace mozilla::dom;
32
33
//
34
// Thanks to Mark Pilgrim and Sam Ruby for the initial whitelist
35
//
36
const nsStaticAtom* const kElementsHTML[] = {
37
// clang-format off
38
nsGkAtoms::a,
39
nsGkAtoms::abbr,
40
nsGkAtoms::acronym,
41
nsGkAtoms::address,
42
nsGkAtoms::area,
43
nsGkAtoms::article,
44
nsGkAtoms::aside,
45
nsGkAtoms::audio,
46
nsGkAtoms::b,
47
nsGkAtoms::bdi,
48
nsGkAtoms::bdo,
49
nsGkAtoms::big,
50
nsGkAtoms::blockquote,
51
// body checked specially
52
nsGkAtoms::br,
53
nsGkAtoms::button,
54
nsGkAtoms::canvas,
55
nsGkAtoms::caption,
56
nsGkAtoms::center,
57
nsGkAtoms::cite,
58
nsGkAtoms::code,
59
nsGkAtoms::col,
60
nsGkAtoms::colgroup,
61
nsGkAtoms::datalist,
62
nsGkAtoms::dd,
63
nsGkAtoms::del,
64
nsGkAtoms::details,
65
nsGkAtoms::dfn,
66
nsGkAtoms::dir,
67
nsGkAtoms::div,
68
nsGkAtoms::dl,
69
nsGkAtoms::dt,
70
nsGkAtoms::em,
71
nsGkAtoms::fieldset,
72
nsGkAtoms::figcaption,
73
nsGkAtoms::figure,
74
nsGkAtoms::font,
75
nsGkAtoms::footer,
76
nsGkAtoms::form,
77
nsGkAtoms::h1,
78
nsGkAtoms::h2,
79
nsGkAtoms::h3,
80
nsGkAtoms::h4,
81
nsGkAtoms::h5,
82
nsGkAtoms::h6,
83
// head checked specially
84
nsGkAtoms::header,
85
nsGkAtoms::hgroup,
86
nsGkAtoms::hr,
87
// html checked specially
88
nsGkAtoms::i,
89
nsGkAtoms::img,
90
nsGkAtoms::input,
91
nsGkAtoms::ins,
92
nsGkAtoms::kbd,
93
nsGkAtoms::keygen,
94
nsGkAtoms::label,
95
nsGkAtoms::legend,
96
nsGkAtoms::li,
97
nsGkAtoms::link,
98
nsGkAtoms::listing,
99
nsGkAtoms::map,
100
nsGkAtoms::mark,
101
nsGkAtoms::menu,
102
nsGkAtoms::meta,
103
nsGkAtoms::meter,
104
nsGkAtoms::nav,
105
nsGkAtoms::nobr,
106
nsGkAtoms::noscript,
107
nsGkAtoms::ol,
108
nsGkAtoms::optgroup,
109
nsGkAtoms::option,
110
nsGkAtoms::output,
111
nsGkAtoms::p,
112
nsGkAtoms::pre,
113
nsGkAtoms::progress,
114
nsGkAtoms::q,
115
nsGkAtoms::rb,
116
nsGkAtoms::rp,
117
nsGkAtoms::rt,
118
nsGkAtoms::rtc,
119
nsGkAtoms::ruby,
120
nsGkAtoms::s,
121
nsGkAtoms::samp,
122
nsGkAtoms::section,
123
nsGkAtoms::select,
124
nsGkAtoms::small,
125
nsGkAtoms::source,
126
nsGkAtoms::span,
127
nsGkAtoms::strike,
128
nsGkAtoms::strong,
129
nsGkAtoms::sub,
130
nsGkAtoms::summary,
131
nsGkAtoms::sup,
132
// style checked specially
133
nsGkAtoms::table,
134
nsGkAtoms::tbody,
135
nsGkAtoms::td,
136
nsGkAtoms::textarea,
137
nsGkAtoms::tfoot,
138
nsGkAtoms::th,
139
nsGkAtoms::thead,
140
nsGkAtoms::time,
141
// title checked specially
142
nsGkAtoms::tr,
143
nsGkAtoms::track,
144
nsGkAtoms::tt,
145
nsGkAtoms::u,
146
nsGkAtoms::ul,
147
nsGkAtoms::var,
148
nsGkAtoms::video,
149
nsGkAtoms::wbr,
150
nullptr
151
// clang-format on
152
};
153
154
const nsStaticAtom* const kAttributesHTML[] = {
155
// clang-format off
156
nsGkAtoms::abbr,
157
nsGkAtoms::accept,
158
nsGkAtoms::acceptcharset,
159
nsGkAtoms::accesskey,
160
nsGkAtoms::action,
161
nsGkAtoms::alt,
162
nsGkAtoms::as,
163
nsGkAtoms::autocomplete,
164
nsGkAtoms::autofocus,
165
nsGkAtoms::autoplay,
166
nsGkAtoms::axis,
167
nsGkAtoms::_char,
168
nsGkAtoms::charoff,
169
nsGkAtoms::charset,
170
nsGkAtoms::checked,
171
nsGkAtoms::cite,
172
nsGkAtoms::_class,
173
nsGkAtoms::cols,
174
nsGkAtoms::colspan,
175
nsGkAtoms::content,
176
nsGkAtoms::contenteditable,
177
nsGkAtoms::contextmenu,
178
nsGkAtoms::controls,
179
nsGkAtoms::coords,
180
nsGkAtoms::crossorigin,
181
nsGkAtoms::datetime,
182
nsGkAtoms::dir,
183
nsGkAtoms::disabled,
184
nsGkAtoms::draggable,
185
nsGkAtoms::enctype,
186
nsGkAtoms::face,
187
nsGkAtoms::_for,
188
nsGkAtoms::frame,
189
nsGkAtoms::headers,
190
nsGkAtoms::height,
191
nsGkAtoms::hidden,
192
nsGkAtoms::high,
193
nsGkAtoms::href,
194
nsGkAtoms::hreflang,
195
nsGkAtoms::icon,
196
nsGkAtoms::id,
197
nsGkAtoms::integrity,
198
nsGkAtoms::ismap,
199
nsGkAtoms::itemid,
200
nsGkAtoms::itemprop,
201
nsGkAtoms::itemref,
202
nsGkAtoms::itemscope,
203
nsGkAtoms::itemtype,
204
nsGkAtoms::kind,
205
nsGkAtoms::label,
206
nsGkAtoms::lang,
207
nsGkAtoms::list_,
208
nsGkAtoms::longdesc,
209
nsGkAtoms::loop,
210
nsGkAtoms::low,
211
nsGkAtoms::max,
212
nsGkAtoms::maxlength,
213
nsGkAtoms::media,
214
nsGkAtoms::method,
215
nsGkAtoms::min,
216
nsGkAtoms::minlength,
217
nsGkAtoms::multiple,
218
nsGkAtoms::muted,
219
nsGkAtoms::name,
220
nsGkAtoms::nohref,
221
nsGkAtoms::novalidate,
222
nsGkAtoms::nowrap,
223
nsGkAtoms::open,
224
nsGkAtoms::optimum,
225
nsGkAtoms::pattern,
226
nsGkAtoms::placeholder,
227
nsGkAtoms::playbackrate,
228
nsGkAtoms::poster,
229
nsGkAtoms::preload,
230
nsGkAtoms::prompt,
231
nsGkAtoms::pubdate,
232
nsGkAtoms::radiogroup,
233
nsGkAtoms::readonly,
234
nsGkAtoms::rel,
235
nsGkAtoms::required,
236
nsGkAtoms::rev,
237
nsGkAtoms::reversed,
238
nsGkAtoms::role,
239
nsGkAtoms::rows,
240
nsGkAtoms::rowspan,
241
nsGkAtoms::rules,
242
nsGkAtoms::scoped,
243
nsGkAtoms::scope,
244
nsGkAtoms::selected,
245
nsGkAtoms::shape,
246
nsGkAtoms::span,
247
nsGkAtoms::spellcheck,
248
nsGkAtoms::src,
249
nsGkAtoms::srclang,
250
nsGkAtoms::start,
251
nsGkAtoms::summary,
252
nsGkAtoms::tabindex,
253
nsGkAtoms::target,
254
nsGkAtoms::title,
255
nsGkAtoms::type,
256
nsGkAtoms::usemap,
257
nsGkAtoms::value,
258
nsGkAtoms::width,
259
nsGkAtoms::wrap,
260
nullptr
261
// clang-format on
262
};
263
264
const nsStaticAtom* const kPresAttributesHTML[] = {
265
// clang-format off
266
nsGkAtoms::align,
267
nsGkAtoms::background,
268
nsGkAtoms::bgcolor,
269
nsGkAtoms::border,
270
nsGkAtoms::cellpadding,
271
nsGkAtoms::cellspacing,
272
nsGkAtoms::color,
273
nsGkAtoms::compact,
274
nsGkAtoms::clear,
275
nsGkAtoms::hspace,
276
nsGkAtoms::noshade,
277
nsGkAtoms::pointSize,
278
nsGkAtoms::size,
279
nsGkAtoms::valign,
280
nsGkAtoms::vspace,
281
nullptr
282
// clang-format on
283
};
284
285
const nsStaticAtom* const kURLAttributesHTML[] = {
286
// clang-format off
287
nsGkAtoms::action,
288
nsGkAtoms::href,
289
nsGkAtoms::src,
290
nsGkAtoms::longdesc,
291
nsGkAtoms::cite,
292
nsGkAtoms::background,
293
nullptr
294
// clang-format on
295
};
296
297
const nsStaticAtom* const kElementsSVG[] = {
298
nsGkAtoms::a, // a
299
nsGkAtoms::circle, // circle
300
nsGkAtoms::clipPath, // clipPath
301
nsGkAtoms::colorProfile, // color-profile
302
nsGkAtoms::cursor, // cursor
303
nsGkAtoms::defs, // defs
304
nsGkAtoms::desc, // desc
305
nsGkAtoms::ellipse, // ellipse
306
nsGkAtoms::elevation, // elevation
307
nsGkAtoms::erode, // erode
308
nsGkAtoms::ex, // ex
309
nsGkAtoms::exact, // exact
310
nsGkAtoms::exponent, // exponent
311
nsGkAtoms::feBlend, // feBlend
312
nsGkAtoms::feColorMatrix, // feColorMatrix
313
nsGkAtoms::feComponentTransfer, // feComponentTransfer
314
nsGkAtoms::feComposite, // feComposite
315
nsGkAtoms::feConvolveMatrix, // feConvolveMatrix
316
nsGkAtoms::feDiffuseLighting, // feDiffuseLighting
317
nsGkAtoms::feDisplacementMap, // feDisplacementMap
318
nsGkAtoms::feDistantLight, // feDistantLight
319
nsGkAtoms::feDropShadow, // feDropShadow
320
nsGkAtoms::feFlood, // feFlood
321
nsGkAtoms::feFuncA, // feFuncA
322
nsGkAtoms::feFuncB, // feFuncB
323
nsGkAtoms::feFuncG, // feFuncG
324
nsGkAtoms::feFuncR, // feFuncR
325
nsGkAtoms::feGaussianBlur, // feGaussianBlur
326
nsGkAtoms::feImage, // feImage
327
nsGkAtoms::feMerge, // feMerge
328
nsGkAtoms::feMergeNode, // feMergeNode
329
nsGkAtoms::feMorphology, // feMorphology
330
nsGkAtoms::feOffset, // feOffset
331
nsGkAtoms::fePointLight, // fePointLight
332
nsGkAtoms::feSpecularLighting, // feSpecularLighting
333
nsGkAtoms::feSpotLight, // feSpotLight
334
nsGkAtoms::feTile, // feTile
335
nsGkAtoms::feTurbulence, // feTurbulence
336
nsGkAtoms::filter, // filter
337
nsGkAtoms::font, // font
338
nsGkAtoms::font_face, // font-face
339
nsGkAtoms::font_face_format, // font-face-format
340
nsGkAtoms::font_face_name, // font-face-name
341
nsGkAtoms::font_face_src, // font-face-src
342
nsGkAtoms::font_face_uri, // font-face-uri
343
nsGkAtoms::foreignObject, // foreignObject
344
nsGkAtoms::g, // g
345
// glyph
346
nsGkAtoms::glyphRef, // glyphRef
347
// hkern
348
nsGkAtoms::image, // image
349
nsGkAtoms::line, // line
350
nsGkAtoms::linearGradient, // linearGradient
351
nsGkAtoms::marker, // marker
352
nsGkAtoms::mask, // mask
353
nsGkAtoms::metadata, // metadata
354
nsGkAtoms::missingGlyph, // missingGlyph
355
nsGkAtoms::mpath, // mpath
356
nsGkAtoms::path, // path
357
nsGkAtoms::pattern, // pattern
358
nsGkAtoms::polygon, // polygon
359
nsGkAtoms::polyline, // polyline
360
nsGkAtoms::radialGradient, // radialGradient
361
nsGkAtoms::rect, // rect
362
nsGkAtoms::stop, // stop
363
nsGkAtoms::svg, // svg
364
nsGkAtoms::svgSwitch, // switch
365
nsGkAtoms::symbol, // symbol
366
nsGkAtoms::text, // text
367
nsGkAtoms::textPath, // textPath
368
nsGkAtoms::title, // title
369
nsGkAtoms::tref, // tref
370
nsGkAtoms::tspan, // tspan
371
nsGkAtoms::use, // use
372
nsGkAtoms::view, // view
373
// vkern
374
nullptr};
375
376
const nsStaticAtom* const kAttributesSVG[] = {
377
// accent-height
378
nsGkAtoms::accumulate, // accumulate
379
nsGkAtoms::additive, // additive
380
nsGkAtoms::alignment_baseline, // alignment-baseline
381
// alphabetic
382
nsGkAtoms::amplitude, // amplitude
383
// arabic-form
384
// ascent
385
nsGkAtoms::attributeName, // attributeName
386
nsGkAtoms::attributeType, // attributeType
387
nsGkAtoms::azimuth, // azimuth
388
nsGkAtoms::baseFrequency, // baseFrequency
389
nsGkAtoms::baseline_shift, // baseline-shift
390
// baseProfile
391
// bbox
392
nsGkAtoms::begin, // begin
393
nsGkAtoms::bias, // bias
394
nsGkAtoms::by, // by
395
nsGkAtoms::calcMode, // calcMode
396
// cap-height
397
nsGkAtoms::_class, // class
398
nsGkAtoms::clip_path, // clip-path
399
nsGkAtoms::clip_rule, // clip-rule
400
nsGkAtoms::clipPathUnits, // clipPathUnits
401
nsGkAtoms::color, // color
402
nsGkAtoms::colorInterpolation, // color-interpolation
403
nsGkAtoms::colorInterpolationFilters, // color-interpolation-filters
404
nsGkAtoms::cursor, // cursor
405
nsGkAtoms::cx, // cx
406
nsGkAtoms::cy, // cy
407
nsGkAtoms::d, // d
408
// descent
409
nsGkAtoms::diffuseConstant, // diffuseConstant
410
nsGkAtoms::direction, // direction
411
nsGkAtoms::display, // display
412
nsGkAtoms::divisor, // divisor
413
nsGkAtoms::dominant_baseline, // dominant-baseline
414
nsGkAtoms::dur, // dur
415
nsGkAtoms::dx, // dx
416
nsGkAtoms::dy, // dy
417
nsGkAtoms::edgeMode, // edgeMode
418
nsGkAtoms::elevation, // elevation
419
// enable-background
420
nsGkAtoms::end, // end
421
nsGkAtoms::fill, // fill
422
nsGkAtoms::fill_opacity, // fill-opacity
423
nsGkAtoms::fill_rule, // fill-rule
424
nsGkAtoms::filter, // filter
425
nsGkAtoms::filterUnits, // filterUnits
426
nsGkAtoms::flood_color, // flood-color
427
nsGkAtoms::flood_opacity, // flood-opacity
428
// XXX focusable
429
nsGkAtoms::font, // font
430
nsGkAtoms::font_family, // font-family
431
nsGkAtoms::font_size, // font-size
432
nsGkAtoms::font_size_adjust, // font-size-adjust
433
nsGkAtoms::font_stretch, // font-stretch
434
nsGkAtoms::font_style, // font-style
435
nsGkAtoms::font_variant, // font-variant
436
nsGkAtoms::fontWeight, // font-weight
437
nsGkAtoms::format, // format
438
nsGkAtoms::from, // from
439
nsGkAtoms::fx, // fx
440
nsGkAtoms::fy, // fy
441
// g1
442
// g2
443
// glyph-name
444
// glyphRef
445
// glyph-orientation-horizontal
446
// glyph-orientation-vertical
447
nsGkAtoms::gradientTransform, // gradientTransform
448
nsGkAtoms::gradientUnits, // gradientUnits
449
nsGkAtoms::height, // height
450
// horiz-adv-x
451
// horiz-origin-x
452
// horiz-origin-y
453
nsGkAtoms::id, // id
454
// ideographic
455
nsGkAtoms::image_rendering, // image-rendering
456
nsGkAtoms::in, // in
457
nsGkAtoms::in2, // in2
458
nsGkAtoms::intercept, // intercept
459
// k
460
nsGkAtoms::k1, // k1
461
nsGkAtoms::k2, // k2
462
nsGkAtoms::k3, // k3
463
nsGkAtoms::k4, // k4
464
// kerning
465
nsGkAtoms::kernelMatrix, // kernelMatrix
466
nsGkAtoms::kernelUnitLength, // kernelUnitLength
467
nsGkAtoms::keyPoints, // keyPoints
468
nsGkAtoms::keySplines, // keySplines
469
nsGkAtoms::keyTimes, // keyTimes
470
nsGkAtoms::lang, // lang
471
// lengthAdjust
472
nsGkAtoms::letter_spacing, // letter-spacing
473
nsGkAtoms::lighting_color, // lighting-color
474
nsGkAtoms::limitingConeAngle, // limitingConeAngle
475
// local
476
nsGkAtoms::marker, // marker
477
nsGkAtoms::marker_end, // marker-end
478
nsGkAtoms::marker_mid, // marker-mid
479
nsGkAtoms::marker_start, // marker-start
480
nsGkAtoms::markerHeight, // markerHeight
481
nsGkAtoms::markerUnits, // markerUnits
482
nsGkAtoms::markerWidth, // markerWidth
483
nsGkAtoms::mask, // mask
484
nsGkAtoms::maskContentUnits, // maskContentUnits
485
nsGkAtoms::maskUnits, // maskUnits
486
// mathematical
487
nsGkAtoms::max, // max
488
nsGkAtoms::media, // media
489
nsGkAtoms::method, // method
490
nsGkAtoms::min, // min
491
nsGkAtoms::mode, // mode
492
nsGkAtoms::name, // name
493
nsGkAtoms::numOctaves, // numOctaves
494
nsGkAtoms::offset, // offset
495
nsGkAtoms::opacity, // opacity
496
nsGkAtoms::_operator, // operator
497
nsGkAtoms::order, // order
498
nsGkAtoms::orient, // orient
499
nsGkAtoms::orientation, // orientation
500
// origin
501
// overline-position
502
// overline-thickness
503
nsGkAtoms::overflow, // overflow
504
// panose-1
505
nsGkAtoms::path, // path
506
nsGkAtoms::pathLength, // pathLength
507
nsGkAtoms::patternContentUnits, // patternContentUnits
508
nsGkAtoms::patternTransform, // patternTransform
509
nsGkAtoms::patternUnits, // patternUnits
510
nsGkAtoms::pointer_events, // pointer-events XXX is this safe?
511
nsGkAtoms::points, // points
512
nsGkAtoms::pointsAtX, // pointsAtX
513
nsGkAtoms::pointsAtY, // pointsAtY
514
nsGkAtoms::pointsAtZ, // pointsAtZ
515
nsGkAtoms::preserveAlpha, // preserveAlpha
516
nsGkAtoms::preserveAspectRatio, // preserveAspectRatio
517
nsGkAtoms::primitiveUnits, // primitiveUnits
518
nsGkAtoms::r, // r
519
nsGkAtoms::radius, // radius
520
nsGkAtoms::refX, // refX
521
nsGkAtoms::refY, // refY
522
nsGkAtoms::repeatCount, // repeatCount
523
nsGkAtoms::repeatDur, // repeatDur
524
nsGkAtoms::requiredExtensions, // requiredExtensions
525
nsGkAtoms::requiredFeatures, // requiredFeatures
526
nsGkAtoms::restart, // restart
527
nsGkAtoms::result, // result
528
nsGkAtoms::rotate, // rotate
529
nsGkAtoms::rx, // rx
530
nsGkAtoms::ry, // ry
531
nsGkAtoms::scale, // scale
532
nsGkAtoms::seed, // seed
533
nsGkAtoms::shape_rendering, // shape-rendering
534
nsGkAtoms::slope, // slope
535
nsGkAtoms::spacing, // spacing
536
nsGkAtoms::specularConstant, // specularConstant
537
nsGkAtoms::specularExponent, // specularExponent
538
nsGkAtoms::spreadMethod, // spreadMethod
539
nsGkAtoms::startOffset, // startOffset
540
nsGkAtoms::stdDeviation, // stdDeviation
541
// stemh
542
// stemv
543
nsGkAtoms::stitchTiles, // stitchTiles
544
nsGkAtoms::stop_color, // stop-color
545
nsGkAtoms::stop_opacity, // stop-opacity
546
// strikethrough-position
547
// strikethrough-thickness
548
nsGkAtoms::string, // string
549
nsGkAtoms::stroke, // stroke
550
nsGkAtoms::stroke_dasharray, // stroke-dasharray
551
nsGkAtoms::stroke_dashoffset, // stroke-dashoffset
552
nsGkAtoms::stroke_linecap, // stroke-linecap
553
nsGkAtoms::stroke_linejoin, // stroke-linejoin
554
nsGkAtoms::stroke_miterlimit, // stroke-miterlimit
555
nsGkAtoms::stroke_opacity, // stroke-opacity
556
nsGkAtoms::stroke_width, // stroke-width
557
nsGkAtoms::surfaceScale, // surfaceScale
558
nsGkAtoms::systemLanguage, // systemLanguage
559
nsGkAtoms::tableValues, // tableValues
560
nsGkAtoms::target, // target
561
nsGkAtoms::targetX, // targetX
562
nsGkAtoms::targetY, // targetY
563
nsGkAtoms::text_anchor, // text-anchor
564
nsGkAtoms::text_decoration, // text-decoration
565
// textLength
566
nsGkAtoms::text_rendering, // text-rendering
567
nsGkAtoms::title, // title
568
nsGkAtoms::to, // to
569
nsGkAtoms::transform, // transform
570
nsGkAtoms::type, // type
571
// u1
572
// u2
573
// underline-position
574
// underline-thickness
575
// unicode
576
nsGkAtoms::unicode_bidi, // unicode-bidi
577
// unicode-range
578
// units-per-em
579
// v-alphabetic
580
// v-hanging
581
// v-ideographic
582
// v-mathematical
583
nsGkAtoms::values, // values
584
nsGkAtoms::vector_effect, // vector-effect
585
// vert-adv-y
586
// vert-origin-x
587
// vert-origin-y
588
nsGkAtoms::viewBox, // viewBox
589
nsGkAtoms::viewTarget, // viewTarget
590
nsGkAtoms::visibility, // visibility
591
nsGkAtoms::width, // width
592
// widths
593
nsGkAtoms::word_spacing, // word-spacing
594
nsGkAtoms::writing_mode, // writing-mode
595
nsGkAtoms::x, // x
596
// x-height
597
nsGkAtoms::x1, // x1
598
nsGkAtoms::x2, // x2
599
nsGkAtoms::xChannelSelector, // xChannelSelector
600
nsGkAtoms::y, // y
601
nsGkAtoms::y1, // y1
602
nsGkAtoms::y2, // y2
603
nsGkAtoms::yChannelSelector, // yChannelSelector
604
nsGkAtoms::z, // z
605
nsGkAtoms::zoomAndPan, // zoomAndPan
606
nullptr};
607
608
const nsStaticAtom* const kURLAttributesSVG[] = {nsGkAtoms::href, nullptr};
609
610
const nsStaticAtom* const kElementsMathML[] = {
611
nsGkAtoms::abs_, // abs
612
nsGkAtoms::_and, // and
613
nsGkAtoms::annotation_, // annotation
614
nsGkAtoms::annotation_xml_, // annotation-xml
615
nsGkAtoms::apply_, // apply
616
nsGkAtoms::approx_, // approx
617
nsGkAtoms::arccos_, // arccos
618
nsGkAtoms::arccosh_, // arccosh
619
nsGkAtoms::arccot_, // arccot
620
nsGkAtoms::arccoth_, // arccoth
621
nsGkAtoms::arccsc_, // arccsc
622
nsGkAtoms::arccsch_, // arccsch
623
nsGkAtoms::arcsec_, // arcsec
624
nsGkAtoms::arcsech_, // arcsech
625
nsGkAtoms::arcsin_, // arcsin
626
nsGkAtoms::arcsinh_, // arcsinh
627
nsGkAtoms::arctan_, // arctan
628
nsGkAtoms::arctanh_, // arctanh
629
nsGkAtoms::arg_, // arg
630
nsGkAtoms::bind_, // bind
631
nsGkAtoms::bvar_, // bvar
632
nsGkAtoms::card_, // card
633
nsGkAtoms::cartesianproduct_, // cartesianproduct
634
nsGkAtoms::cbytes_, // cbytes
635
nsGkAtoms::ceiling, // ceiling
636
nsGkAtoms::cerror_, // cerror
637
nsGkAtoms::ci_, // ci
638
nsGkAtoms::cn_, // cn
639
nsGkAtoms::codomain_, // codomain
640
nsGkAtoms::complexes_, // complexes
641
nsGkAtoms::compose_, // compose
642
nsGkAtoms::condition_, // condition
643
nsGkAtoms::conjugate_, // conjugate
644
nsGkAtoms::cos_, // cos
645
nsGkAtoms::cosh_, // cosh
646
nsGkAtoms::cot_, // cot
647
nsGkAtoms::coth_, // coth
648
nsGkAtoms::cs_, // cs
649
nsGkAtoms::csc_, // csc
650
nsGkAtoms::csch_, // csch
651
nsGkAtoms::csymbol_, // csymbol
652
nsGkAtoms::curl_, // curl
653
nsGkAtoms::declare, // declare
654
nsGkAtoms::degree_, // degree
655
nsGkAtoms::determinant_, // determinant
656
nsGkAtoms::diff_, // diff
657
nsGkAtoms::divergence_, // divergence
658
nsGkAtoms::divide_, // divide
659
nsGkAtoms::domain_, // domain
660
nsGkAtoms::domainofapplication_, // domainofapplication
661
nsGkAtoms::el, // el
662
nsGkAtoms::emptyset_, // emptyset
663
nsGkAtoms::eq_, // eq
664
nsGkAtoms::equivalent_, // equivalent
665
nsGkAtoms::eulergamma_, // eulergamma
666
nsGkAtoms::exists_, // exists
667
nsGkAtoms::exp_, // exp
668
nsGkAtoms::exponentiale_, // exponentiale
669
nsGkAtoms::factorial_, // factorial
670
nsGkAtoms::factorof_, // factorof
671
nsGkAtoms::_false, // false
672
nsGkAtoms::floor, // floor
673
nsGkAtoms::fn_, // fn
674
nsGkAtoms::forall_, // forall
675
nsGkAtoms::gcd_, // gcd
676
nsGkAtoms::geq_, // geq
677
nsGkAtoms::grad, // grad
678
nsGkAtoms::gt_, // gt
679
nsGkAtoms::ident_, // ident
680
nsGkAtoms::image, // image
681
nsGkAtoms::imaginary_, // imaginary
682
nsGkAtoms::imaginaryi_, // imaginaryi
683
nsGkAtoms::implies_, // implies
684
nsGkAtoms::in, // in
685
nsGkAtoms::infinity, // infinity
686
nsGkAtoms::int_, // int
687
nsGkAtoms::integers_, // integers
688
nsGkAtoms::intersect_, // intersect
689
nsGkAtoms::interval_, // interval
690
nsGkAtoms::inverse_, // inverse
691
nsGkAtoms::lambda_, // lambda
692
nsGkAtoms::laplacian_, // laplacian
693
nsGkAtoms::lcm_, // lcm
694
nsGkAtoms::leq_, // leq
695
nsGkAtoms::limit_, // limit
696
nsGkAtoms::list_, // list
697
nsGkAtoms::ln_, // ln
698
nsGkAtoms::log_, // log
699
nsGkAtoms::logbase_, // logbase
700
nsGkAtoms::lowlimit_, // lowlimit
701
nsGkAtoms::lt_, // lt
702
nsGkAtoms::maction_, // maction
703
nsGkAtoms::maligngroup_, // maligngroup
704
nsGkAtoms::malignmark_, // malignmark
705
nsGkAtoms::math, // math
706
nsGkAtoms::matrix, // matrix
707
nsGkAtoms::matrixrow_, // matrixrow
708
nsGkAtoms::max, // max
709
nsGkAtoms::mean_, // mean
710
nsGkAtoms::median_, // median
711
nsGkAtoms::menclose_, // menclose
712
nsGkAtoms::merror_, // merror
713
nsGkAtoms::mfenced_, // mfenced
714
nsGkAtoms::mfrac_, // mfrac
715
nsGkAtoms::mglyph_, // mglyph
716
nsGkAtoms::mi_, // mi
717
nsGkAtoms::min, // min
718
nsGkAtoms::minus_, // minus
719
nsGkAtoms::mlabeledtr_, // mlabeledtr
720
nsGkAtoms::mlongdiv_, // mlongdiv
721
nsGkAtoms::mmultiscripts_, // mmultiscripts
722
nsGkAtoms::mn_, // mn
723
nsGkAtoms::mo_, // mo
724
nsGkAtoms::mode, // mode
725
nsGkAtoms::moment_, // moment
726
nsGkAtoms::momentabout_, // momentabout
727
nsGkAtoms::mover_, // mover
728
nsGkAtoms::mpadded_, // mpadded
729
nsGkAtoms::mphantom_, // mphantom
730
nsGkAtoms::mprescripts_, // mprescripts
731
nsGkAtoms::mroot_, // mroot
732
nsGkAtoms::mrow_, // mrow
733
nsGkAtoms::ms_, // ms
734
nsGkAtoms::mscarries_, // mscarries
735
nsGkAtoms::mscarry_, // mscarry
736
nsGkAtoms::msgroup_, // msgroup
737
nsGkAtoms::msline_, // msline
738
nsGkAtoms::mspace_, // mspace
739
nsGkAtoms::msqrt_, // msqrt
740
nsGkAtoms::msrow_, // msrow
741
nsGkAtoms::mstack_, // mstack
742
nsGkAtoms::mstyle_, // mstyle
743
nsGkAtoms::msub_, // msub
744
nsGkAtoms::msubsup_, // msubsup
745
nsGkAtoms::msup_, // msup
746
nsGkAtoms::mtable_, // mtable
747
nsGkAtoms::mtd_, // mtd
748
nsGkAtoms::mtext_, // mtext
749
nsGkAtoms::mtr_, // mtr
750
nsGkAtoms::munder_, // munder
751
nsGkAtoms::munderover_, // munderover
752
nsGkAtoms::naturalnumbers_, // naturalnumbers
753
nsGkAtoms::neq_, // neq
754
nsGkAtoms::none, // none
755
nsGkAtoms::_not, // not
756
nsGkAtoms::notanumber_, // notanumber
757
nsGkAtoms::note_, // note
758
nsGkAtoms::notin_, // notin
759
nsGkAtoms::notprsubset_, // notprsubset
760
nsGkAtoms::notsubset_, // notsubset
761
nsGkAtoms::_or, // or
762
nsGkAtoms::otherwise, // otherwise
763
nsGkAtoms::outerproduct_, // outerproduct
764
nsGkAtoms::partialdiff_, // partialdiff
765
nsGkAtoms::pi_, // pi
766
nsGkAtoms::piece_, // piece
767
nsGkAtoms::piecewise_, // piecewise
768
nsGkAtoms::plus_, // plus
769
nsGkAtoms::power_, // power
770
nsGkAtoms::primes_, // primes
771
nsGkAtoms::product_, // product
772
nsGkAtoms::prsubset_, // prsubset
773
nsGkAtoms::quotient_, // quotient
774
nsGkAtoms::rationals_, // rationals
775
nsGkAtoms::real_, // real
776
nsGkAtoms::reals_, // reals
777
nsGkAtoms::reln_, // reln
778
nsGkAtoms::rem, // rem
779
nsGkAtoms::root_, // root
780
nsGkAtoms::scalarproduct_, // scalarproduct
781
nsGkAtoms::sdev_, // sdev
782
nsGkAtoms::sec_, // sec
783
nsGkAtoms::sech_, // sech
784
nsGkAtoms::selector_, // selector
785
nsGkAtoms::semantics_, // semantics
786
nsGkAtoms::sep_, // sep
787
nsGkAtoms::set, // set
788
nsGkAtoms::setdiff_, // setdiff
789
nsGkAtoms::share_, // share
790
nsGkAtoms::sin_, // sin
791
nsGkAtoms::sinh_, // sinh
792
nsGkAtoms::subset_, // subset
793
nsGkAtoms::sum, // sum
794
nsGkAtoms::tan_, // tan
795
nsGkAtoms::tanh_, // tanh
796
nsGkAtoms::tendsto_, // tendsto
797
nsGkAtoms::times_, // times
798
nsGkAtoms::transpose_, // transpose
799
nsGkAtoms::_true, // true
800
nsGkAtoms::union_, // union
801
nsGkAtoms::uplimit_, // uplimit
802
nsGkAtoms::variance_, // variance
803
nsGkAtoms::vector_, // vector
804
nsGkAtoms::vectorproduct_, // vectorproduct
805
nsGkAtoms::xor_, // xor
806
nullptr};
807
808
const nsStaticAtom* const kAttributesMathML[] = {
809
nsGkAtoms::accent_, // accent
810
nsGkAtoms::accentunder_, // accentunder
811
nsGkAtoms::actiontype_, // actiontype
812
nsGkAtoms::align, // align
813
nsGkAtoms::alignmentscope_, // alignmentscope
814
nsGkAtoms::alt, // alt
815
nsGkAtoms::altimg_, // altimg
816
nsGkAtoms::altimg_height_, // altimg-height
817
nsGkAtoms::altimg_valign_, // altimg-valign
818
nsGkAtoms::altimg_width_, // altimg-width
819
nsGkAtoms::background, // background
820
nsGkAtoms::base, // base
821
nsGkAtoms::bevelled_, // bevelled
822
nsGkAtoms::cd_, // cd
823
nsGkAtoms::cdgroup_, // cdgroup
824
nsGkAtoms::charalign_, // charalign
825
nsGkAtoms::close, // close
826
nsGkAtoms::closure_, // closure
827
nsGkAtoms::color, // color
828
nsGkAtoms::columnalign_, // columnalign
829
nsGkAtoms::columnalignment_, // columnalignment
830
nsGkAtoms::columnlines_, // columnlines
831
nsGkAtoms::columnspacing_, // columnspacing
832
nsGkAtoms::columnspan_, // columnspan
833
nsGkAtoms::columnwidth_, // columnwidth
834
nsGkAtoms::crossout_, // crossout
835
nsGkAtoms::decimalpoint_, // decimalpoint
836
nsGkAtoms::definitionURL_, // definitionURL
837
nsGkAtoms::denomalign_, // denomalign
838
nsGkAtoms::depth_, // depth
839
nsGkAtoms::dir, // dir
840
nsGkAtoms::display, // display
841
nsGkAtoms::displaystyle_, // displaystyle
842
nsGkAtoms::edge_, // edge
843
nsGkAtoms::encoding, // encoding
844
nsGkAtoms::equalcolumns_, // equalcolumns
845
nsGkAtoms::equalrows_, // equalrows
846
nsGkAtoms::fence_, // fence
847
nsGkAtoms::fontfamily_, // fontfamily
848
nsGkAtoms::fontsize_, // fontsize
849
nsGkAtoms::fontstyle_, // fontstyle
850
nsGkAtoms::fontweight_, // fontweight
851
nsGkAtoms::form, // form
852
nsGkAtoms::frame, // frame
853
nsGkAtoms::framespacing_, // framespacing
854
nsGkAtoms::groupalign_, // groupalign
855
nsGkAtoms::height, // height
856
nsGkAtoms::href, // href
857
nsGkAtoms::id, // id
858
nsGkAtoms::indentalign_, // indentalign
859
nsGkAtoms::indentalignfirst_, // indentalignfirst
860
nsGkAtoms::indentalignlast_, // indentalignlast
861
nsGkAtoms::indentshift_, // indentshift
862
nsGkAtoms::indentshiftfirst_, // indentshiftfirst
863
nsGkAtoms::indenttarget_, // indenttarget
864
nsGkAtoms::index, // index
865
nsGkAtoms::integer, // integer
866
nsGkAtoms::largeop_, // largeop
867
nsGkAtoms::length, // length
868
nsGkAtoms::linebreak_, // linebreak
869
nsGkAtoms::linebreakmultchar_, // linebreakmultchar
870
nsGkAtoms::linebreakstyle_, // linebreakstyle
871
nsGkAtoms::linethickness_, // linethickness
872
nsGkAtoms::location_, // location
873
nsGkAtoms::longdivstyle_, // longdivstyle
874
nsGkAtoms::lquote_, // lquote
875
nsGkAtoms::lspace_, // lspace
876
nsGkAtoms::ltr, // ltr
877
nsGkAtoms::mathbackground_, // mathbackground
878
nsGkAtoms::mathcolor_, // mathcolor
879
nsGkAtoms::mathsize_, // mathsize
880
nsGkAtoms::mathvariant_, // mathvariant
881
nsGkAtoms::maxsize_, // maxsize
882
nsGkAtoms::minlabelspacing_, // minlabelspacing
883
nsGkAtoms::minsize_, // minsize
884
nsGkAtoms::movablelimits_, // movablelimits
885
nsGkAtoms::msgroup_, // msgroup
886
nsGkAtoms::name, // name
887
nsGkAtoms::newline, // newline
888
nsGkAtoms::notation_, // notation
889
nsGkAtoms::numalign_, // numalign
890
nsGkAtoms::number, // number
891
nsGkAtoms::open, // open
892
nsGkAtoms::order, // order
893
nsGkAtoms::other, // other
894
nsGkAtoms::overflow, // overflow
895
nsGkAtoms::position, // position
896
nsGkAtoms::role, // role
897
nsGkAtoms::rowalign_, // rowalign
898
nsGkAtoms::rowlines_, // rowlines
899
nsGkAtoms::rowspacing_, // rowspacing
900
nsGkAtoms::rowspan, // rowspan
901
nsGkAtoms::rquote_, // rquote
902
nsGkAtoms::rspace_, // rspace
903
nsGkAtoms::schemaLocation_, // schemaLocation
904
nsGkAtoms::scriptlevel_, // scriptlevel
905
nsGkAtoms::scriptminsize_, // scriptminsize
906
nsGkAtoms::scriptsize_, // scriptsize
907
nsGkAtoms::scriptsizemultiplier_, // scriptsizemultiplier
908
nsGkAtoms::selection_, // selection
909
nsGkAtoms::separator_, // separator
910
nsGkAtoms::separators_, // separators
911
nsGkAtoms::shift_, // shift
912
nsGkAtoms::side_, // side
913
nsGkAtoms::src, // src
914
nsGkAtoms::stackalign_, // stackalign
915
nsGkAtoms::stretchy_, // stretchy
916
nsGkAtoms::subscriptshift_, // subscriptshift
917
nsGkAtoms::superscriptshift_, // superscriptshift
918
nsGkAtoms::symmetric_, // symmetric
919
nsGkAtoms::type, // type
920
nsGkAtoms::voffset_, // voffset
921
nsGkAtoms::width, // width
922
nsGkAtoms::xref_, // xref
923
nullptr};
924
925
const nsStaticAtom* const kURLAttributesMathML[] = {
926
// clang-format off
927
nsGkAtoms::href,
928
nsGkAtoms::src,
929
nsGkAtoms::cdgroup_,
930
nsGkAtoms::altimg_,
931
nsGkAtoms::definitionURL_,
932
nullptr
933
// clang-format on
934
};
935
936
nsTreeSanitizer::AtomsTable* nsTreeSanitizer::sElementsHTML = nullptr;
937
nsTreeSanitizer::AtomsTable* nsTreeSanitizer::sAttributesHTML = nullptr;
938
nsTreeSanitizer::AtomsTable* nsTreeSanitizer::sPresAttributesHTML = nullptr;
939
nsTreeSanitizer::AtomsTable* nsTreeSanitizer::sElementsSVG = nullptr;
940
nsTreeSanitizer::AtomsTable* nsTreeSanitizer::sAttributesSVG = nullptr;
941
nsTreeSanitizer::AtomsTable* nsTreeSanitizer::sElementsMathML = nullptr;
942
nsTreeSanitizer::AtomsTable* nsTreeSanitizer::sAttributesMathML = nullptr;
943
nsIPrincipal* nsTreeSanitizer::sNullPrincipal = nullptr;
944
945
nsTreeSanitizer::nsTreeSanitizer(uint32_t aFlags)
946
: mAllowStyles(aFlags & nsIParserUtils::SanitizerAllowStyle),
947
mAllowComments(aFlags & nsIParserUtils::SanitizerAllowComments),
948
mDropNonCSSPresentation(aFlags &
949
nsIParserUtils::SanitizerDropNonCSSPresentation),
950
mDropForms(aFlags & nsIParserUtils::SanitizerDropForms),
951
mCidEmbedsOnly(aFlags & nsIParserUtils::SanitizerCidEmbedsOnly),
952
mDropMedia(aFlags & nsIParserUtils::SanitizerDropMedia),
953
mFullDocument(false),
954
mLogRemovals(aFlags & nsIParserUtils::SanitizerLogRemovals),
955
mOnlyConditionalCSS(aFlags &
956
nsIParserUtils::SanitizerRemoveOnlyConditionalCSS) {
957
if (mCidEmbedsOnly) {
958
// Sanitizing styles for external references is not supported.
959
mAllowStyles = false;
960
}
961
if (!sElementsHTML) {
962
// Initialize lazily to avoid having to initialize at all if the user
963
// doesn't paste HTML or load feeds.
964
InitializeStatics();
965
}
966
/* Ensure SanitizerRemoveOnlyConditionalCSS isn't combined with any
967
* flags, except SanitizerLogRemovals. */
968
MOZ_ASSERT(!mOnlyConditionalCSS ||
969
0 ==
970
(aFlags & ~(nsIParserUtils::SanitizerRemoveOnlyConditionalCSS |
971
nsIParserUtils::SanitizerLogRemovals)));
972
}
973
974
bool nsTreeSanitizer::MustFlatten(int32_t aNamespace, nsAtom* aLocal) {
975
if (aNamespace == kNameSpaceID_XHTML) {
976
if (mDropNonCSSPresentation &&
977
(nsGkAtoms::font == aLocal || nsGkAtoms::center == aLocal)) {
978
return true;
979
}
980
if (mDropForms &&
981
(nsGkAtoms::form == aLocal || nsGkAtoms::input == aLocal ||
982
nsGkAtoms::option == aLocal || nsGkAtoms::optgroup == aLocal)) {
983
return true;
984
}
985
if (mFullDocument &&
986
(nsGkAtoms::title == aLocal || nsGkAtoms::html == aLocal ||
987
nsGkAtoms::head == aLocal || nsGkAtoms::body == aLocal)) {
988
return false;
989
}
990
return !sElementsHTML->Contains(aLocal);
991
}
992
if (aNamespace == kNameSpaceID_SVG) {
993
if (mCidEmbedsOnly || mDropMedia) {
994
// Sanitizing CSS-based URL references inside SVG presentational
995
// attributes is not supported, so flattening for cid: embed case.
996
return true;
997
}
998
return !sElementsSVG->Contains(aLocal);
999
}
1000
if (aNamespace == kNameSpaceID_MathML) {
1001
return !sElementsMathML->Contains(aLocal);
1002
}
1003
return true;
1004
}
1005
1006
bool nsTreeSanitizer::IsURL(const nsStaticAtom* const* aURLs,
1007
nsAtom* aLocalName) {
1008
const nsStaticAtom* atom;
1009
while ((atom = *aURLs)) {
1010
if (atom == aLocalName) {
1011
return true;
1012
}
1013
++aURLs;
1014
}
1015
return false;
1016
}
1017
1018
bool nsTreeSanitizer::MustPrune(int32_t aNamespace, nsAtom* aLocal,
1019
mozilla::dom::Element* aElement) {
1020
// To avoid attacks where a MathML script becomes something that gets
1021
// serialized in a way that it parses back as an HTML script, let's just
1022
// drop elements with the local name 'script' regardless of namespace.
1023
if (nsGkAtoms::script == aLocal) {
1024
return true;
1025
}
1026
if (aNamespace == kNameSpaceID_XHTML) {
1027
if (nsGkAtoms::title == aLocal && !mFullDocument) {
1028
// emulate the quirks of the old parser
1029
return true;
1030
}
1031
if (mDropForms &&
1032
(nsGkAtoms::select == aLocal || nsGkAtoms::button == aLocal ||
1033
nsGkAtoms::datalist == aLocal)) {
1034
return true;
1035
}
1036
if (mDropMedia &&
1037
(nsGkAtoms::img == aLocal || nsGkAtoms::video == aLocal ||
1038
nsGkAtoms::audio == aLocal || nsGkAtoms::source == aLocal)) {
1039
return true;
1040
}
1041
if (nsGkAtoms::meta == aLocal &&
1042
(aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::charset) ||
1043
aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::httpEquiv))) {
1044
// Throw away charset declarations even if they also have microdata
1045
// which they can't validly have.
1046
return true;
1047
}
1048
if (((!mFullDocument && nsGkAtoms::meta == aLocal) ||
1049
nsGkAtoms::link == aLocal) &&
1050
!(aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::itemprop) ||
1051
aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::itemscope))) {
1052
// emulate old behavior for non-Microdata <meta> and <link> presumably
1053
// in <head>. <meta> and <link> are whitelisted in order to avoid
1054
// corrupting Microdata when they appear in <body>. Note that
1055
// SanitizeAttributes() will remove the rel attribute from <link> and
1056
// the name attribute from <meta>.
1057
return true;
1058
}
1059
}
1060
if (mAllowStyles) {
1061
if (nsGkAtoms::style == aLocal &&
1062
!(aNamespace == kNameSpaceID_XHTML || aNamespace == kNameSpaceID_SVG)) {
1063
return true;
1064
}
1065
return false;
1066
}
1067
if (nsGkAtoms::style == aLocal) {
1068
return true;
1069
}
1070
return false;
1071
}
1072
1073
bool nsTreeSanitizer::SanitizeStyleSheet(const nsAString& aOriginal,
1074
nsAString& aSanitized,
1075
Document* aDocument,
1076
nsIURI* aBaseURI) {
1077
nsresult rv = NS_OK;
1078
aSanitized.Truncate();
1079
// aSanitized will hold the permitted CSS text.
1080
// -moz-binding is blacklisted.
1081
bool didSanitize = false;
1082
// Create a sheet to hold the parsed CSS
1083
RefPtr<StyleSheet> sheet = new StyleSheet(mozilla::css::eAuthorSheetFeatures,
1084
CORS_NONE, SRIMetadata());
1085
sheet->SetURIs(aDocument->GetDocumentURI(), nullptr, aBaseURI);
1086
sheet->SetPrincipal(aDocument->NodePrincipal());
1087
sheet->ParseSheetSync(aDocument->CSSLoader(),
1088
NS_ConvertUTF16toUTF8(aOriginal),
1089
/* aLoadData = */ nullptr,
1090
/* aLineNumber = */ 0);
1091
NS_ENSURE_SUCCESS(rv, true);
1092
// Mark the sheet as complete.
1093
MOZ_ASSERT(!sheet->HasForcedUniqueInner(),
1094
"should not get a forced unique inner during parsing");
1095
1096
// This should be an inline stylesheet
1097
nsCOMPtr<nsIReferrerInfo> referrerInfo =
1098
ReferrerInfo::CreateForInternalCSSResources(aDocument);
1099
sheet->SetReferrerInfo(referrerInfo);
1100
sheet->SetComplete();
1101
// Loop through all the rules found in the CSS text
1102
ErrorResult err;
1103
RefPtr<dom::CSSRuleList> rules =
1104
sheet->GetCssRules(*nsContentUtils::GetSystemPrincipal(), err);
1105
err.SuppressException();
1106
if (!rules) {
1107
return true;
1108
}
1109
uint32_t ruleCount = rules->Length();
1110
for (uint32_t i = 0; i < ruleCount; ++i) {
1111
mozilla::css::Rule* rule = rules->Item(i);
1112
if (!rule) continue;
1113
if (!mOnlyConditionalCSS) {
1114
switch (rule->Type()) {
1115
default:
1116
didSanitize = true;
1117
// Ignore these rule types.
1118
break;
1119
case CSSRule_Binding::STYLE_RULE:
1120
case CSSRule_Binding::NAMESPACE_RULE:
1121
case CSSRule_Binding::FONT_FACE_RULE: {
1122
// Append style, @namespace and @font-face rules verbatim.
1123
nsAutoString cssText;
1124
rule->GetCssText(cssText);
1125
aSanitized.Append(cssText);
1126
break;
1127
}
1128
}
1129
} else {
1130
switch (rule->Type()) {
1131
case CSSRule_Binding::MEDIA_RULE:
1132
case CSSRule_Binding::SUPPORTS_RULE:
1133
case CSSRule_Binding::DOCUMENT_RULE:
1134
didSanitize = true;
1135
// Ignore (remove) these rule types.
1136
break;
1137
default: {
1138
// Append other rules verbatim.
1139
nsAutoString cssText;
1140
rule->GetCssText(cssText);
1141
aSanitized.Append(cssText);
1142
break;
1143
}
1144
}
1145
}
1146
}
1147
if (didSanitize && mLogRemovals) {
1148
LogMessage("Removed some rules and/or properties from stylesheet.",
1149
aDocument);
1150
}
1151
return didSanitize;
1152
}
1153
1154
template <size_t Len>
1155
static bool UTF16StringStartsWith(const char16_t* aStr, uint32_t aLength,
1156
const char16_t (&aNeedle)[Len]) {
1157
MOZ_ASSERT(aNeedle[Len - 1] == '\0',
1158
"needle should be a UTF-16 encoded string literal");
1159
1160
if (aLength < Len - 1) {
1161
return false;
1162
}
1163
for (size_t i = 0; i < Len - 1; i++) {
1164
if (aStr[i] != aNeedle[i]) {
1165
return false;
1166
}
1167
}
1168
return true;
1169
}
1170
1171
void nsTreeSanitizer::SanitizeAttributes(mozilla::dom::Element* aElement,
1172
AllowedAttributes aAllowed) {
1173
uint32_t ac = aElement->GetAttrCount();
1174
1175
for (int32_t i = ac - 1; i >= 0; --i) {
1176
const nsAttrName* attrName = aElement->GetAttrNameAt(i);
1177
int32_t attrNs = attrName->NamespaceID();
1178
RefPtr<nsAtom> attrLocal = attrName->LocalName();
1179
1180
if (kNameSpaceID_None == attrNs) {
1181
if (aAllowed.mStyle && nsGkAtoms::style == attrLocal) {
1182
continue;
1183
}
1184
if (aAllowed.mDangerousSrc && nsGkAtoms::src == attrLocal) {
1185
continue;
1186
}
1187
if (IsURL(aAllowed.mURLs, attrLocal)) {
1188
if (SanitizeURL(aElement, attrNs, attrLocal)) {
1189
// in case the attribute removal shuffled the attribute order, start
1190
// the loop again.
1191
--ac;
1192
i = ac; // i will be decremented immediately thanks to the for loop
1193
continue;
1194
}
1195
// else fall through to see if there's another reason to drop this
1196
// attribute (in particular if the attribute is background="" on an
1197
// HTML element)
1198
}
1199
if (!mDropNonCSSPresentation &&
1200
(aAllowed.mNames == sAttributesHTML) && // element is HTML
1201
sPresAttributesHTML->Contains(attrLocal)) {
1202
continue;
1203
}
1204
if (aAllowed.mNames->Contains(attrLocal) &&
1205
!((attrLocal == nsGkAtoms::rel &&
1206
aElement->IsHTMLElement(nsGkAtoms::link)) ||
1207
(!mFullDocument && attrLocal == nsGkAtoms::name &&
1208
aElement->IsHTMLElement(nsGkAtoms::meta)))) {
1209
// name="" and rel="" are whitelisted, but treat them as blacklisted
1210
// for <meta name> (fragment case) and <link rel> (all cases) to avoid
1211
// document-wide metadata or styling overrides with non-conforming
1212
// <meta name itemprop> or
1213
// <link rel itemprop>
1214
continue;
1215
}
1216
const char16_t* localStr = attrLocal->GetUTF16String();
1217
uint32_t localLen = attrLocal->GetLength();
1218
// Allow underscore to cater to the MCE editor library.
1219
// Allow data-* on SVG and MathML, too, as a forward-compat measure.
1220
// Allow aria-* on all for simplicity.
1221
if (UTF16StringStartsWith(localStr, localLen, u"_") ||
1222
UTF16StringStartsWith(localStr, localLen, u"data-") ||
1223
UTF16StringStartsWith(localStr, localLen, u"aria-")) {
1224
continue;
1225
}
1226
// else not allowed
1227
} else if (kNameSpaceID_XML == attrNs) {
1228
if (nsGkAtoms::lang == attrLocal || nsGkAtoms::space == attrLocal) {
1229
continue;
1230
}
1231
// else not allowed
1232
} else if (aAllowed.mXLink && kNameSpaceID_XLink == attrNs) {
1233
if (nsGkAtoms::href == attrLocal) {
1234
if (SanitizeURL(aElement, attrNs, attrLocal)) {
1235
// in case the attribute removal shuffled the attribute order, start
1236
// the loop again.
1237
--ac;
1238
i = ac; // i will be decremented immediately thanks to the for loop
1239
}
1240
continue;
1241
}
1242
if (nsGkAtoms::type == attrLocal || nsGkAtoms::title == attrLocal ||
1243
nsGkAtoms::show == attrLocal || nsGkAtoms::actuate == attrLocal) {
1244
continue;
1245
}
1246
// else not allowed
1247
}
1248
aElement->UnsetAttr(kNameSpaceID_None, attrLocal, false);
1249
if (mLogRemovals) {
1250
LogMessage("Removed unsafe attribute.", aElement->OwnerDoc(), aElement,
1251
attrLocal);
1252
}
1253
// in case the attribute removal shuffled the attribute order, start the
1254
// loop again.
1255
--ac;
1256
i = ac; // i will be decremented immediately thanks to the for loop
1257
}
1258
1259
// If we've got HTML audio or video, add the controls attribute, because
1260
// otherwise the content is unplayable with scripts removed.
1261
if (aElement->IsAnyOfHTMLElements(nsGkAtoms::video, nsGkAtoms::audio)) {
1262
aElement->SetAttr(kNameSpaceID_None, nsGkAtoms::controls, EmptyString(),
1263
false);
1264
}
1265
}
1266
1267
bool nsTreeSanitizer::SanitizeURL(mozilla::dom::Element* aElement,
1268
int32_t aNamespace, nsAtom* aLocalName) {
1269
nsAutoString value;
1270
aElement->GetAttr(aNamespace, aLocalName, value);
1271
1272
// Get value and remove mandatory quotes
1273
static const char* kWhitespace = "\n\r\t\b";
1274
const nsAString& v = nsContentUtils::TrimCharsInSet(kWhitespace, value);
1275
// Fragment-only url cannot be harmful.
1276
if (!v.IsEmpty() && v.First() == u'#') {
1277
return false;
1278
}
1279
1280
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
1281
uint32_t flags = nsIScriptSecurityManager::DISALLOW_INHERIT_PRINCIPAL;
1282
1283
nsCOMPtr<nsIURI> attrURI;
1284
nsresult rv =
1285
NS_NewURI(getter_AddRefs(attrURI), v, nullptr, aElement->GetBaseURI());
1286
if (NS_SUCCEEDED(rv)) {
1287
if (mCidEmbedsOnly && kNameSpaceID_None == aNamespace) {
1288
if (nsGkAtoms::src == aLocalName || nsGkAtoms::background == aLocalName) {
1289
// comm-central uses a hack that makes nsIURIs created with cid: specs
1290
// actually have an about:blank spec. Therefore, nsIURI facilities are
1291
// useless for cid: when comm-central code is participating.
1292
if (!(v.Length() > 4 && (v[0] == 'c' || v[0] == 'C') &&
1293
(v[1] == 'i' || v[1] == 'I') && (v[2] == 'd' || v[2] == 'D') &&
1294
v[3] == ':')) {
1295
rv = NS_ERROR_FAILURE;
1296
}
1297
} else if (nsGkAtoms::cdgroup_ == aLocalName ||
1298
nsGkAtoms::altimg_ == aLocalName ||
1299
nsGkAtoms::definitionURL_ == aLocalName) {
1300
// Gecko doesn't fetch these now and shouldn't in the future, but
1301
// in case someone goofs with these in the future, let's drop them.
1302
rv = NS_ERROR_FAILURE;
1303
} else {
1304
rv = secMan->CheckLoadURIWithPrincipal(sNullPrincipal, attrURI, flags);
1305
}
1306
} else {
1307
rv = secMan->CheckLoadURIWithPrincipal(sNullPrincipal, attrURI, flags);
1308
}
1309
}
1310
if (NS_FAILED(rv)) {
1311
aElement->UnsetAttr(aNamespace, aLocalName, false);
1312
if (mLogRemovals) {
1313
LogMessage("Removed unsafe URI from element attribute.",
1314
aElement->OwnerDoc(), aElement, aLocalName);
1315
}
1316
return true;
1317
}
1318
return false;
1319
}
1320
1321
void nsTreeSanitizer::Sanitize(DocumentFragment* aFragment) {
1322
// If you want to relax these preconditions, be sure to check the code in
1323
// here that notifies / does not notify or that fires mutation events if
1324
// in tree.
1325
MOZ_ASSERT(!aFragment->IsInUncomposedDoc(), "The fragment is in doc?");
1326
1327
mFullDocument = false;
1328
SanitizeChildren(aFragment);
1329
}
1330
1331
void nsTreeSanitizer::Sanitize(Document* aDocument) {
1332
// If you want to relax these preconditions, be sure to check the code in
1333
// here that notifies / does not notify or that fires mutation events if
1334
// in tree.
1335
#ifdef DEBUG
1336
MOZ_ASSERT(!aDocument->GetContainer(), "The document is in a shell.");
1337
RefPtr<mozilla::dom::Element> root = aDocument->GetRootElement();
1338
MOZ_ASSERT(root->IsHTMLElement(nsGkAtoms::html), "Not HTML root.");
1339
#endif
1340
1341
mFullDocument = true;
1342
SanitizeChildren(aDocument);
1343
}
1344
1345
void nsTreeSanitizer::SanitizeChildren(nsINode* aRoot) {
1346
nsIContent* node = aRoot->GetFirstChild();
1347
while (node) {
1348
if (node->IsElement()) {
1349
mozilla::dom::Element* elt = node->AsElement();
1350
mozilla::dom::NodeInfo* nodeInfo = node->NodeInfo();
1351
nsAtom* localName = nodeInfo->NameAtom();
1352
int32_t ns = nodeInfo->NamespaceID();
1353
1354
if (!mOnlyConditionalCSS && MustPrune(ns, localName, elt)) {
1355
if (mLogRemovals) {
1356
LogMessage("Removing unsafe node.", elt->OwnerDoc(), elt);
1357
}
1358
RemoveAllAttributes(elt);
1359
nsIContent* descendant = node;
1360
while ((descendant = descendant->GetNextNode(node))) {
1361
if (descendant->IsElement()) {
1362
RemoveAllAttributes(descendant->AsElement());
1363
}
1364
}
1365
nsIContent* next = node->GetNextNonChildNode(aRoot);
1366
node->RemoveFromParent();
1367
node = next;
1368
continue;
1369
}
1370
if (nsGkAtoms::style == localName) {
1371
// If !mOnlyConditionalCSS check the following condition:
1372
// If styles aren't allowed, style elements got pruned above. Even
1373
// if styles are allowed, non-HTML, non-SVG style elements got pruned
1374
// above.
1375
NS_ASSERTION((ns == kNameSpaceID_XHTML || ns == kNameSpaceID_SVG) ||
1376
mOnlyConditionalCSS,
1377
"Should have only HTML or SVG here!");
1378
nsAutoString styleText;
1379
nsContentUtils::GetNodeTextContent(node, false, styleText);
1380
1381
nsAutoString sanitizedStyle;
1382
if (SanitizeStyleSheet(styleText, sanitizedStyle, aRoot->OwnerDoc(),
1383
node->GetBaseURI())) {
1384
nsContentUtils::SetNodeTextContent(node, sanitizedStyle, true);
1385
} else {
1386
// If the node had non-text child nodes, this operation zaps those.
1387
// XXXgijs: if we're logging, we should theoretically report about
1388
// this, but this way of removing those items doesn't allow for that
1389
// to happen. Seems less likely to be a problem for actual chrome
1390
// consumers though.
1391
nsContentUtils::SetNodeTextContent(node, styleText, true);
1392
}
1393
if (!mOnlyConditionalCSS) {
1394
AllowedAttributes allowed;
1395
allowed.mStyle = mAllowStyles;
1396
if (ns == kNameSpaceID_XHTML) {
1397
allowed.mNames = sAttributesHTML;
1398
allowed.mURLs = kURLAttributesHTML;
1399
SanitizeAttributes(elt, allowed);
1400
} else {
1401
allowed.mNames = sAttributesSVG;
1402
allowed.mURLs = kURLAttributesSVG;
1403
allowed.mXLink = true;
1404
SanitizeAttributes(elt, allowed);
1405
}
1406
}
1407
node = node->GetNextNonChildNode(aRoot);
1408
continue;
1409
}
1410
if (!mOnlyConditionalCSS && MustFlatten(ns, localName)) {
1411
if (mLogRemovals) {
1412
LogMessage("Flattening unsafe node (descendants are preserved).",
1413
elt->OwnerDoc(), elt);
1414
}
1415
RemoveAllAttributes(elt);
1416
nsCOMPtr<nsIContent> next = node->GetNextNode(aRoot);
1417
nsCOMPtr<nsIContent> parent = node->GetParent();
1418
nsCOMPtr<nsIContent> child; // Must keep the child alive during move
1419
ErrorResult rv;
1420
while ((child = node->GetFirstChild())) {
1421
nsCOMPtr<nsINode> refNode = node;
1422
parent->InsertBefore(*child, refNode, rv);
1423
if (rv.Failed()) {
1424
break;
1425
}
1426
}
1427
node->RemoveFromParent();
1428
node = next;
1429
continue;
1430
}
1431
if (!mOnlyConditionalCSS) {
1432
NS_ASSERTION(ns == kNameSpaceID_XHTML || ns == kNameSpaceID_SVG ||
1433
ns == kNameSpaceID_MathML,
1434
"Should have only HTML, MathML or SVG here!");
1435
AllowedAttributes allowed;
1436
if (ns == kNameSpaceID_XHTML) {
1437
allowed.mNames = sAttributesHTML;
1438
allowed.mURLs = kURLAttributesHTML;
1439
allowed.mStyle = mAllowStyles;
1440
allowed.mDangerousSrc =
1441
nsGkAtoms::img == localName && !mCidEmbedsOnly;
1442
SanitizeAttributes(elt, allowed);
1443
} else if (ns == kNameSpaceID_SVG) {
1444
allowed.mNames = sAttributesSVG;
1445
allowed.mURLs = kURLAttributesSVG;
1446
allowed.mXLink = true;
1447
allowed.mStyle = mAllowStyles;
1448
SanitizeAttributes(elt, allowed);
1449
} else {
1450
allowed.mNames = sAttributesMathML;
1451
allowed.mURLs = kURLAttributesMathML;
1452
allowed.mXLink = true;
1453
SanitizeAttributes(elt, allowed);
1454
}
1455
}
1456
node = node->GetNextNode(aRoot);
1457
continue;
1458
}
1459
NS_ASSERTION(!node->GetFirstChild(), "How come non-element node had kids?");
1460
nsIContent* next = node->GetNextNonChildNode(aRoot);
1461
if (!mOnlyConditionalCSS && (!mAllowComments && node->IsComment())) {
1462
node->RemoveFromParent();
1463
}
1464
node = next;
1465
}
1466
}
1467
1468
void nsTreeSanitizer::RemoveAllAttributes(Element* aElement) {
1469
const nsAttrName* attrName;
1470
while ((attrName = aElement->GetAttrNameAt(0))) {
1471
int32_t attrNs = attrName->NamespaceID();
1472
RefPtr<nsAtom> attrLocal = attrName->LocalName();
1473
aElement->UnsetAttr(attrNs, attrLocal, false);
1474
}
1475
}
1476
1477
void nsTreeSanitizer::LogMessage(const char* aMessage, Document* aDoc,
1478
Element* aElement, nsAtom* aAttr) {
1479
if (mLogRemovals) {
1480
nsAutoString msg;
1481
msg.Assign(NS_ConvertASCIItoUTF16(aMessage));
1482
if (aElement) {
1483
msg.Append(NS_LITERAL_STRING(" Element: ") + aElement->LocalName() +
1484
NS_LITERAL_STRING("."));
1485
}
1486
if (aAttr) {
1487
msg.Append(NS_LITERAL_STRING(" Attribute: ") +
1488
nsDependentAtomString(aAttr) + NS_LITERAL_STRING("."));
1489
}
1490
1491
nsContentUtils::ReportToConsoleNonLocalized(
1492
msg, nsIScriptError::warningFlag, NS_LITERAL_CSTRING("DOM"), aDoc);
1493
}
1494
}
1495
1496
void nsTreeSanitizer::InitializeStatics() {
1497
MOZ_ASSERT(!sElementsHTML, "Initializing a second time.");
1498
1499
sElementsHTML = new AtomsTable(ArrayLength(kElementsHTML));
1500
for (uint32_t i = 0; kElementsHTML[i]; i++) {
1501
sElementsHTML->PutEntry(kElementsHTML[i]);
1502
}
1503
1504
sAttributesHTML = new AtomsTable(ArrayLength(kAttributesHTML));
1505
for (uint32_t i = 0; kAttributesHTML[i]; i++) {
1506
sAttributesHTML->PutEntry(kAttributesHTML[i]);
1507
}
1508
1509
sPresAttributesHTML = new AtomsTable(ArrayLength(kPresAttributesHTML));
1510
for (uint32_t i = 0; kPresAttributesHTML[i]; i++) {
1511
sPresAttributesHTML->PutEntry(kPresAttributesHTML[i]);
1512
}
1513
1514
sElementsSVG = new AtomsTable(ArrayLength(kElementsSVG));
1515
for (uint32_t i = 0; kElementsSVG[i]; i++) {
1516
sElementsSVG->PutEntry(kElementsSVG[i]);
1517
}
1518
1519
sAttributesSVG = new AtomsTable(ArrayLength(kAttributesSVG));
1520
for (uint32_t i = 0; kAttributesSVG[i]; i++) {
1521
sAttributesSVG->PutEntry(kAttributesSVG[i]);
1522
}
1523
1524
sElementsMathML = new AtomsTable(ArrayLength(kElementsMathML));
1525
for (uint32_t i = 0; kElementsMathML[i]; i++) {
1526
sElementsMathML->PutEntry(kElementsMathML[i]);
1527
}
1528
1529
sAttributesMathML = new AtomsTable(ArrayLength(kAttributesMathML));
1530
for (uint32_t i = 0; kAttributesMathML[i]; i++) {
1531
sAttributesMathML->PutEntry(kAttributesMathML[i]);
1532
}
1533
1534
nsCOMPtr<nsIPrincipal> principal =
1535
NullPrincipal::CreateWithoutOriginAttributes();
1536
principal.forget(&sNullPrincipal);
1537
}
1538
1539
void nsTreeSanitizer::ReleaseStatics() {
1540
delete sElementsHTML;
1541
sElementsHTML = nullptr;
1542
1543
delete sAttributesHTML;
1544
sAttributesHTML = nullptr;
1545
1546
delete sPresAttributesHTML;
1547
sPresAttributesHTML = nullptr;
1548
1549
delete sElementsSVG;
1550
sElementsSVG = nullptr;
1551
1552
delete sAttributesSVG;
1553
sAttributesSVG = nullptr;
1554
1555
delete sElementsMathML;
1556
sElementsMathML = nullptr;
1557
1558
delete sAttributesMathML;
1559
sAttributesMathML = nullptr;
1560
1561
NS_IF_RELEASE(sNullPrincipal);
1562
}