/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsTreeSanitizer.h" #include "mozilla/ArrayUtils.h" #include "mozilla/BindingStyleRule.h" #include "mozilla/DeclarationBlock.h" #include "mozilla/StyleSheetInlines.h" #include "mozilla/css/Rule.h" #include "mozilla/dom/CSSRuleList.h" #include "mozilla/dom/DocumentFragment.h" #include "mozilla/dom/SRIMetadata.h" #include "mozilla/NullPrincipal.h" #include "nsCSSPropertyID.h" #include "nsUnicharInputStream.h" #include "nsAttrName.h" #include "nsIScriptError.h" #include "nsIScriptSecurityManager.h" #include "nsNetUtil.h" #include "nsComponentManagerUtils.h" #include "nsContentUtils.h" #include "nsIParserUtils.h" #include "mozilla/dom/Document.h" #include "nsQueryObject.h" using namespace mozilla; using namespace mozilla::dom; // // Thanks to Mark Pilgrim and Sam Ruby for the initial whitelist // const nsStaticAtom* const kElementsHTML[] = { // clang-format off nsGkAtoms::a, nsGkAtoms::abbr, nsGkAtoms::acronym, nsGkAtoms::address, nsGkAtoms::area, nsGkAtoms::article, nsGkAtoms::aside, nsGkAtoms::audio, nsGkAtoms::b, nsGkAtoms::bdi, nsGkAtoms::bdo, nsGkAtoms::big, nsGkAtoms::blockquote, // body checked specially nsGkAtoms::br, nsGkAtoms::button, nsGkAtoms::canvas, nsGkAtoms::caption, nsGkAtoms::center, nsGkAtoms::cite, nsGkAtoms::code, nsGkAtoms::col, nsGkAtoms::colgroup, nsGkAtoms::datalist, nsGkAtoms::dd, nsGkAtoms::del, nsGkAtoms::details, nsGkAtoms::dfn, nsGkAtoms::dir, nsGkAtoms::div, nsGkAtoms::dl, nsGkAtoms::dt, nsGkAtoms::em, nsGkAtoms::fieldset, nsGkAtoms::figcaption, nsGkAtoms::figure, nsGkAtoms::font, nsGkAtoms::footer, nsGkAtoms::form, nsGkAtoms::h1, nsGkAtoms::h2, nsGkAtoms::h3, nsGkAtoms::h4, nsGkAtoms::h5, nsGkAtoms::h6, // head checked specially nsGkAtoms::header, nsGkAtoms::hgroup, nsGkAtoms::hr, // html checked specially nsGkAtoms::i, nsGkAtoms::img, nsGkAtoms::input, nsGkAtoms::ins, nsGkAtoms::kbd, nsGkAtoms::keygen, nsGkAtoms::label, nsGkAtoms::legend, nsGkAtoms::li, nsGkAtoms::link, nsGkAtoms::listing, nsGkAtoms::map, nsGkAtoms::mark, nsGkAtoms::menu, nsGkAtoms::meta, nsGkAtoms::meter, nsGkAtoms::nav, nsGkAtoms::nobr, nsGkAtoms::noscript, nsGkAtoms::ol, nsGkAtoms::optgroup, nsGkAtoms::option, nsGkAtoms::output, nsGkAtoms::p, nsGkAtoms::pre, nsGkAtoms::progress, nsGkAtoms::q, nsGkAtoms::rb, nsGkAtoms::rp, nsGkAtoms::rt, nsGkAtoms::rtc, nsGkAtoms::ruby, nsGkAtoms::s, nsGkAtoms::samp, nsGkAtoms::section, nsGkAtoms::select, nsGkAtoms::small, nsGkAtoms::source, nsGkAtoms::span, nsGkAtoms::strike, nsGkAtoms::strong, nsGkAtoms::sub, nsGkAtoms::summary, nsGkAtoms::sup, // style checked specially nsGkAtoms::table, nsGkAtoms::tbody, nsGkAtoms::td, nsGkAtoms::textarea, nsGkAtoms::tfoot, nsGkAtoms::th, nsGkAtoms::thead, nsGkAtoms::time, // title checked specially nsGkAtoms::tr, nsGkAtoms::track, nsGkAtoms::tt, nsGkAtoms::u, nsGkAtoms::ul, nsGkAtoms::var, nsGkAtoms::video, nsGkAtoms::wbr, nullptr // clang-format on }; const nsStaticAtom* const kAttributesHTML[] = { // clang-format off nsGkAtoms::abbr, nsGkAtoms::accept, nsGkAtoms::acceptcharset, nsGkAtoms::accesskey, nsGkAtoms::action, nsGkAtoms::alt, nsGkAtoms::as, nsGkAtoms::autocomplete, nsGkAtoms::autofocus, nsGkAtoms::autoplay, nsGkAtoms::axis, nsGkAtoms::_char, nsGkAtoms::charoff, nsGkAtoms::charset, nsGkAtoms::checked, nsGkAtoms::cite, nsGkAtoms::_class, nsGkAtoms::cols, nsGkAtoms::colspan, nsGkAtoms::content, nsGkAtoms::contenteditable, nsGkAtoms::contextmenu, nsGkAtoms::controls, nsGkAtoms::coords, nsGkAtoms::crossorigin, nsGkAtoms::datetime, nsGkAtoms::dir, nsGkAtoms::disabled, nsGkAtoms::draggable, nsGkAtoms::enctype, nsGkAtoms::face, nsGkAtoms::_for, nsGkAtoms::frame, nsGkAtoms::headers, nsGkAtoms::height, nsGkAtoms::hidden, nsGkAtoms::high, nsGkAtoms::href, nsGkAtoms::hreflang, nsGkAtoms::icon, nsGkAtoms::id, nsGkAtoms::integrity, nsGkAtoms::ismap, nsGkAtoms::itemid, nsGkAtoms::itemprop, nsGkAtoms::itemref, nsGkAtoms::itemscope, nsGkAtoms::itemtype, nsGkAtoms::kind, nsGkAtoms::label, nsGkAtoms::lang, nsGkAtoms::list_, nsGkAtoms::longdesc, nsGkAtoms::loop, nsGkAtoms::low, nsGkAtoms::max, nsGkAtoms::maxlength, nsGkAtoms::media, nsGkAtoms::method, nsGkAtoms::min, nsGkAtoms::minlength, nsGkAtoms::multiple, nsGkAtoms::muted, nsGkAtoms::name, nsGkAtoms::nohref, nsGkAtoms::novalidate, nsGkAtoms::nowrap, nsGkAtoms::open, nsGkAtoms::optimum, nsGkAtoms::pattern, nsGkAtoms::placeholder, nsGkAtoms::playbackrate, nsGkAtoms::poster, nsGkAtoms::preload, nsGkAtoms::prompt, nsGkAtoms::pubdate, nsGkAtoms::radiogroup, nsGkAtoms::readonly, nsGkAtoms::rel, nsGkAtoms::required, nsGkAtoms::rev, nsGkAtoms::reversed, nsGkAtoms::role, nsGkAtoms::rows, nsGkAtoms::rowspan, nsGkAtoms::rules, nsGkAtoms::scoped, nsGkAtoms::scope, nsGkAtoms::selected, nsGkAtoms::shape, nsGkAtoms::span, nsGkAtoms::spellcheck, nsGkAtoms::src, nsGkAtoms::srclang, nsGkAtoms::start, nsGkAtoms::summary, nsGkAtoms::tabindex, nsGkAtoms::target, nsGkAtoms::title, nsGkAtoms::type, nsGkAtoms::usemap, nsGkAtoms::value, nsGkAtoms::width, nsGkAtoms::wrap, nullptr // clang-format on }; const nsStaticAtom* const kPresAttributesHTML[] = { // clang-format off nsGkAtoms::align, nsGkAtoms::background, nsGkAtoms::bgcolor, nsGkAtoms::border, nsGkAtoms::cellpadding, nsGkAtoms::cellspacing, nsGkAtoms::color, nsGkAtoms::compact, nsGkAtoms::clear, nsGkAtoms::hspace, nsGkAtoms::noshade, nsGkAtoms::pointSize, nsGkAtoms::size, nsGkAtoms::valign, nsGkAtoms::vspace, nullptr // clang-format on }; const nsStaticAtom* const kURLAttributesHTML[] = { // clang-format off nsGkAtoms::action, nsGkAtoms::href, nsGkAtoms::src, nsGkAtoms::longdesc, nsGkAtoms::cite, nsGkAtoms::background, nullptr // clang-format on }; const nsStaticAtom* const kElementsSVG[] = { nsGkAtoms::a, // a nsGkAtoms::circle, // circle nsGkAtoms::clipPath, // clipPath nsGkAtoms::colorProfile, // color-profile nsGkAtoms::cursor, // cursor nsGkAtoms::defs, // defs nsGkAtoms::desc, // desc nsGkAtoms::ellipse, // ellipse nsGkAtoms::elevation, // elevation nsGkAtoms::erode, // erode nsGkAtoms::ex, // ex nsGkAtoms::exact, // exact nsGkAtoms::exponent, // exponent nsGkAtoms::feBlend, // feBlend nsGkAtoms::feColorMatrix, // feColorMatrix nsGkAtoms::feComponentTransfer, // feComponentTransfer nsGkAtoms::feComposite, // feComposite nsGkAtoms::feConvolveMatrix, // feConvolveMatrix nsGkAtoms::feDiffuseLighting, // feDiffuseLighting nsGkAtoms::feDisplacementMap, // feDisplacementMap nsGkAtoms::feDistantLight, // feDistantLight nsGkAtoms::feDropShadow, // feDropShadow nsGkAtoms::feFlood, // feFlood nsGkAtoms::feFuncA, // feFuncA nsGkAtoms::feFuncB, // feFuncB nsGkAtoms::feFuncG, // feFuncG nsGkAtoms::feFuncR, // feFuncR nsGkAtoms::feGaussianBlur, // feGaussianBlur nsGkAtoms::feImage, // feImage nsGkAtoms::feMerge, // feMerge nsGkAtoms::feMergeNode, // feMergeNode nsGkAtoms::feMorphology, // feMorphology nsGkAtoms::feOffset, // feOffset nsGkAtoms::fePointLight, // fePointLight nsGkAtoms::feSpecularLighting, // feSpecularLighting nsGkAtoms::feSpotLight, // feSpotLight nsGkAtoms::feTile, // feTile nsGkAtoms::feTurbulence, // feTurbulence nsGkAtoms::filter, // filter nsGkAtoms::font, // font nsGkAtoms::font_face, // font-face nsGkAtoms::font_face_format, // font-face-format nsGkAtoms::font_face_name, // font-face-name nsGkAtoms::font_face_src, // font-face-src nsGkAtoms::font_face_uri, // font-face-uri nsGkAtoms::foreignObject, // foreignObject nsGkAtoms::g, // g // glyph nsGkAtoms::glyphRef, // glyphRef // hkern nsGkAtoms::image, // image nsGkAtoms::line, // line nsGkAtoms::linearGradient, // linearGradient nsGkAtoms::marker, // marker nsGkAtoms::mask, // mask nsGkAtoms::metadata, // metadata nsGkAtoms::missingGlyph, // missingGlyph nsGkAtoms::mpath, // mpath nsGkAtoms::path, // path nsGkAtoms::pattern, // pattern nsGkAtoms::polygon, // polygon nsGkAtoms::polyline, // polyline nsGkAtoms::radialGradient, // radialGradient nsGkAtoms::rect, // rect nsGkAtoms::stop, // stop nsGkAtoms::svg, // svg nsGkAtoms::svgSwitch, // switch nsGkAtoms::symbol, // symbol nsGkAtoms::text, // text nsGkAtoms::textPath, // textPath nsGkAtoms::title, // title nsGkAtoms::tref, // tref nsGkAtoms::tspan, // tspan nsGkAtoms::use, // use nsGkAtoms::view, // view // vkern nullptr}; const nsStaticAtom* const kAttributesSVG[] = { // accent-height nsGkAtoms::accumulate, // accumulate nsGkAtoms::additive, // additive nsGkAtoms::alignment_baseline, // alignment-baseline // alphabetic nsGkAtoms::amplitude, // amplitude // arabic-form // ascent nsGkAtoms::attributeName, // attributeName nsGkAtoms::attributeType, // attributeType nsGkAtoms::azimuth, // azimuth nsGkAtoms::baseFrequency, // baseFrequency nsGkAtoms::baseline_shift, // baseline-shift // baseProfile // bbox nsGkAtoms::begin, // begin nsGkAtoms::bias, // bias nsGkAtoms::by, // by nsGkAtoms::calcMode, // calcMode // cap-height nsGkAtoms::_class, // class nsGkAtoms::clip_path, // clip-path nsGkAtoms::clip_rule, // clip-rule nsGkAtoms::clipPathUnits, // clipPathUnits nsGkAtoms::color, // color nsGkAtoms::colorInterpolation, // color-interpolation nsGkAtoms::colorInterpolationFilters, // color-interpolation-filters nsGkAtoms::cursor, // cursor nsGkAtoms::cx, // cx nsGkAtoms::cy, // cy nsGkAtoms::d, // d // descent nsGkAtoms::diffuseConstant, // diffuseConstant nsGkAtoms::direction, // direction nsGkAtoms::display, // display nsGkAtoms::divisor, // divisor nsGkAtoms::dominant_baseline, // dominant-baseline nsGkAtoms::dur, // dur nsGkAtoms::dx, // dx nsGkAtoms::dy, // dy nsGkAtoms::edgeMode, // edgeMode nsGkAtoms::elevation, // elevation // enable-background nsGkAtoms::end, // end nsGkAtoms::fill, // fill nsGkAtoms::fill_opacity, // fill-opacity nsGkAtoms::fill_rule, // fill-rule nsGkAtoms::filter, // filter nsGkAtoms::filterUnits, // filterUnits nsGkAtoms::flood_color, // flood-color nsGkAtoms::flood_opacity, // flood-opacity // XXX focusable nsGkAtoms::font, // font nsGkAtoms::font_family, // font-family nsGkAtoms::font_size, // font-size nsGkAtoms::font_size_adjust, // font-size-adjust nsGkAtoms::font_stretch, // font-stretch nsGkAtoms::font_style, // font-style nsGkAtoms::font_variant, // font-variant nsGkAtoms::fontWeight, // font-weight nsGkAtoms::format, // format nsGkAtoms::from, // from nsGkAtoms::fx, // fx nsGkAtoms::fy, // fy // g1 // g2 // glyph-name // glyphRef // glyph-orientation-horizontal // glyph-orientation-vertical nsGkAtoms::gradientTransform, // gradientTransform nsGkAtoms::gradientUnits, // gradientUnits nsGkAtoms::height, // height // horiz-adv-x // horiz-origin-x // horiz-origin-y nsGkAtoms::id, // id // ideographic nsGkAtoms::image_rendering, // image-rendering nsGkAtoms::in, // in nsGkAtoms::in2, // in2 nsGkAtoms::intercept, // intercept // k nsGkAtoms::k1, // k1 nsGkAtoms::k2, // k2 nsGkAtoms::k3, // k3 nsGkAtoms::k4, // k4 // kerning nsGkAtoms::kernelMatrix, // kernelMatrix nsGkAtoms::kernelUnitLength, // kernelUnitLength nsGkAtoms::keyPoints, // keyPoints nsGkAtoms::keySplines, // keySplines nsGkAtoms::keyTimes, // keyTimes nsGkAtoms::lang, // lang // lengthAdjust nsGkAtoms::letter_spacing, // letter-spacing nsGkAtoms::lighting_color, // lighting-color nsGkAtoms::limitingConeAngle, // limitingConeAngle // local nsGkAtoms::marker, // marker nsGkAtoms::marker_end, // marker-end nsGkAtoms::marker_mid, // marker-mid nsGkAtoms::marker_start, // marker-start nsGkAtoms::markerHeight, // markerHeight nsGkAtoms::markerUnits, // markerUnits nsGkAtoms::markerWidth, // markerWidth nsGkAtoms::mask, // mask nsGkAtoms::maskContentUnits, // maskContentUnits nsGkAtoms::maskUnits, // maskUnits // mathematical nsGkAtoms::max, // max nsGkAtoms::media, // media nsGkAtoms::method, // method nsGkAtoms::min, // min nsGkAtoms::mode, // mode nsGkAtoms::name, // name nsGkAtoms::numOctaves, // numOctaves nsGkAtoms::offset, // offset nsGkAtoms::opacity, // opacity nsGkAtoms::_operator, // operator nsGkAtoms::order, // order nsGkAtoms::orient, // orient nsGkAtoms::orientation, // orientation // origin // overline-position // overline-thickness nsGkAtoms::overflow, // overflow // panose-1 nsGkAtoms::path, // path nsGkAtoms::pathLength, // pathLength nsGkAtoms::patternContentUnits, // patternContentUnits nsGkAtoms::patternTransform, // patternTransform nsGkAtoms::patternUnits, // patternUnits nsGkAtoms::pointer_events, // pointer-events XXX is this safe? nsGkAtoms::points, // points nsGkAtoms::pointsAtX, // pointsAtX nsGkAtoms::pointsAtY, // pointsAtY nsGkAtoms::pointsAtZ, // pointsAtZ nsGkAtoms::preserveAlpha, // preserveAlpha nsGkAtoms::preserveAspectRatio, // preserveAspectRatio nsGkAtoms::primitiveUnits, // primitiveUnits nsGkAtoms::r, // r nsGkAtoms::radius, // radius nsGkAtoms::refX, // refX nsGkAtoms::refY, // refY nsGkAtoms::repeatCount, // repeatCount nsGkAtoms::repeatDur, // repeatDur nsGkAtoms::requiredExtensions, // requiredExtensions nsGkAtoms::requiredFeatures, // requiredFeatures nsGkAtoms::restart, // restart nsGkAtoms::result, // result nsGkAtoms::rotate, // rotate nsGkAtoms::rx, // rx nsGkAtoms::ry, // ry nsGkAtoms::scale, // scale nsGkAtoms::seed, // seed nsGkAtoms::shape_rendering, // shape-rendering nsGkAtoms::slope, // slope nsGkAtoms::spacing, // spacing nsGkAtoms::specularConstant, // specularConstant nsGkAtoms::specularExponent, // specularExponent nsGkAtoms::spreadMethod, // spreadMethod nsGkAtoms::startOffset, // startOffset nsGkAtoms::stdDeviation, // stdDeviation // stemh // stemv nsGkAtoms::stitchTiles, // stitchTiles nsGkAtoms::stop_color, // stop-color nsGkAtoms::stop_opacity, // stop-opacity // strikethrough-position // strikethrough-thickness nsGkAtoms::string, // string nsGkAtoms::stroke, // stroke nsGkAtoms::stroke_dasharray, // stroke-dasharray nsGkAtoms::stroke_dashoffset, // stroke-dashoffset nsGkAtoms::stroke_linecap, // stroke-linecap nsGkAtoms::stroke_linejoin, // stroke-linejoin nsGkAtoms::stroke_miterlimit, // stroke-miterlimit nsGkAtoms::stroke_opacity, // stroke-opacity nsGkAtoms::stroke_width, // stroke-width nsGkAtoms::surfaceScale, // surfaceScale nsGkAtoms::systemLanguage, // systemLanguage nsGkAtoms::tableValues, // tableValues nsGkAtoms::target, // target nsGkAtoms::targetX, // targetX nsGkAtoms::targetY, // targetY nsGkAtoms::text_anchor, // text-anchor nsGkAtoms::text_decoration, // text-decoration // textLength nsGkAtoms::text_rendering, // text-rendering nsGkAtoms::title, // title nsGkAtoms::to, // to nsGkAtoms::transform, // transform nsGkAtoms::type, // type // u1 // u2 // underline-position // underline-thickness // unicode nsGkAtoms::unicode_bidi, // unicode-bidi // unicode-range // units-per-em // v-alphabetic // v-hanging // v-ideographic // v-mathematical nsGkAtoms::values, // values nsGkAtoms::vector_effect, // vector-effect // vert-adv-y // vert-origin-x // vert-origin-y nsGkAtoms::viewBox, // viewBox nsGkAtoms::viewTarget, // viewTarget nsGkAtoms::visibility, // visibility nsGkAtoms::width, // width // widths nsGkAtoms::word_spacing, // word-spacing nsGkAtoms::writing_mode, // writing-mode nsGkAtoms::x, // x // x-height nsGkAtoms::x1, // x1 nsGkAtoms::x2, // x2 nsGkAtoms::xChannelSelector, // xChannelSelector nsGkAtoms::y, // y nsGkAtoms::y1, // y1 nsGkAtoms::y2, // y2 nsGkAtoms::yChannelSelector, // yChannelSelector nsGkAtoms::z, // z nsGkAtoms::zoomAndPan, // zoomAndPan nullptr}; const nsStaticAtom* const kURLAttributesSVG[] = {nsGkAtoms::href, nullptr}; const nsStaticAtom* const kElementsMathML[] = { nsGkAtoms::abs_, // abs nsGkAtoms::_and, // and nsGkAtoms::annotation_, // annotation nsGkAtoms::annotation_xml_, // annotation-xml nsGkAtoms::apply_, // apply nsGkAtoms::approx_, // approx nsGkAtoms::arccos_, // arccos nsGkAtoms::arccosh_, // arccosh nsGkAtoms::arccot_, // arccot nsGkAtoms::arccoth_, // arccoth nsGkAtoms::arccsc_, // arccsc nsGkAtoms::arccsch_, // arccsch nsGkAtoms::arcsec_, // arcsec nsGkAtoms::arcsech_, // arcsech nsGkAtoms::arcsin_, // arcsin nsGkAtoms::arcsinh_, // arcsinh nsGkAtoms::arctan_, // arctan nsGkAtoms::arctanh_, // arctanh nsGkAtoms::arg_, // arg nsGkAtoms::bind_, // bind nsGkAtoms::bvar_, // bvar nsGkAtoms::card_, // card nsGkAtoms::cartesianproduct_, // cartesianproduct nsGkAtoms::cbytes_, // cbytes nsGkAtoms::ceiling, // ceiling nsGkAtoms::cerror_, // cerror nsGkAtoms::ci_, // ci nsGkAtoms::cn_, // cn nsGkAtoms::codomain_, // codomain nsGkAtoms::complexes_, // complexes nsGkAtoms::compose_, // compose nsGkAtoms::condition_, // condition nsGkAtoms::conjugate_, // conjugate nsGkAtoms::cos_, // cos nsGkAtoms::cosh_, // cosh nsGkAtoms::cot_, // cot nsGkAtoms::coth_, // coth nsGkAtoms::cs_, // cs nsGkAtoms::csc_, // csc nsGkAtoms::csch_, // csch nsGkAtoms::csymbol_, // csymbol nsGkAtoms::curl_, // curl nsGkAtoms::declare, // declare nsGkAtoms::degree_, // degree nsGkAtoms::determinant_, // determinant nsGkAtoms::diff_, // diff nsGkAtoms::divergence_, // divergence nsGkAtoms::divide_, // divide nsGkAtoms::domain_, // domain nsGkAtoms::domainofapplication_, // domainofapplication nsGkAtoms::el, // el nsGkAtoms::emptyset_, // emptyset nsGkAtoms::eq_, // eq nsGkAtoms::equivalent_, // equivalent nsGkAtoms::eulergamma_, // eulergamma nsGkAtoms::exists_, // exists nsGkAtoms::exp_, // exp nsGkAtoms::exponentiale_, // exponentiale nsGkAtoms::factorial_, // factorial nsGkAtoms::factorof_, // factorof nsGkAtoms::_false, // false nsGkAtoms::floor, // floor nsGkAtoms::fn_, // fn nsGkAtoms::forall_, // forall nsGkAtoms::gcd_, // gcd nsGkAtoms::geq_, // geq nsGkAtoms::grad, // grad nsGkAtoms::gt_, // gt nsGkAtoms::ident_, // ident nsGkAtoms::image, // image nsGkAtoms::imaginary_, // imaginary nsGkAtoms::imaginaryi_, // imaginaryi nsGkAtoms::implies_, // implies nsGkAtoms::in, // in nsGkAtoms::infinity, // infinity nsGkAtoms::int_, // int nsGkAtoms::integers_, // integers nsGkAtoms::intersect_, // intersect nsGkAtoms::interval_, // interval nsGkAtoms::inverse_, // inverse nsGkAtoms::lambda_, // lambda nsGkAtoms::laplacian_, // laplacian nsGkAtoms::lcm_, // lcm nsGkAtoms::leq_, // leq nsGkAtoms::limit_, // limit nsGkAtoms::list_, // list nsGkAtoms::ln_, // ln nsGkAtoms::log_, // log nsGkAtoms::logbase_, // logbase nsGkAtoms::lowlimit_, // lowlimit nsGkAtoms::lt_, // lt nsGkAtoms::maction_, // maction nsGkAtoms::maligngroup_, // maligngroup nsGkAtoms::malignmark_, // malignmark nsGkAtoms::math, // math nsGkAtoms::matrix, // matrix nsGkAtoms::matrixrow_, // matrixrow nsGkAtoms::max, // max nsGkAtoms::mean_, // mean nsGkAtoms::median_, // median nsGkAtoms::menclose_, // menclose nsGkAtoms::merror_, // merror nsGkAtoms::mfenced_, // mfenced nsGkAtoms::mfrac_, // mfrac nsGkAtoms::mglyph_, // mglyph nsGkAtoms::mi_, // mi nsGkAtoms::min, // min nsGkAtoms::minus_, // minus nsGkAtoms::mlabeledtr_, // mlabeledtr nsGkAtoms::mlongdiv_, // mlongdiv nsGkAtoms::mmultiscripts_, // mmultiscripts nsGkAtoms::mn_, // mn nsGkAtoms::mo_, // mo nsGkAtoms::mode, // mode nsGkAtoms::moment_, // moment nsGkAtoms::momentabout_, // momentabout nsGkAtoms::mover_, // mover nsGkAtoms::mpadded_, // mpadded nsGkAtoms::mphantom_, // mphantom nsGkAtoms::mprescripts_, // mprescripts nsGkAtoms::mroot_, // mroot nsGkAtoms::mrow_, // mrow nsGkAtoms::ms_, // ms nsGkAtoms::mscarries_, // mscarries nsGkAtoms::mscarry_, // mscarry nsGkAtoms::msgroup_, // msgroup nsGkAtoms::msline_, // msline nsGkAtoms::mspace_, // mspace nsGkAtoms::msqrt_, // msqrt nsGkAtoms::msrow_, // msrow nsGkAtoms::mstack_, // mstack nsGkAtoms::mstyle_, // mstyle nsGkAtoms::msub_, // msub nsGkAtoms::msubsup_, // msubsup nsGkAtoms::msup_, // msup nsGkAtoms::mtable_, // mtable nsGkAtoms::mtd_, // mtd nsGkAtoms::mtext_, // mtext nsGkAtoms::mtr_, // mtr nsGkAtoms::munder_, // munder nsGkAtoms::munderover_, // munderover nsGkAtoms::naturalnumbers_, // naturalnumbers nsGkAtoms::neq_, // neq nsGkAtoms::none, // none nsGkAtoms::_not, // not nsGkAtoms::notanumber_, // notanumber nsGkAtoms::note_, // note nsGkAtoms::notin_, // notin nsGkAtoms::notprsubset_, // notprsubset nsGkAtoms::notsubset_, // notsubset nsGkAtoms::_or, // or nsGkAtoms::otherwise, // otherwise nsGkAtoms::outerproduct_, // outerproduct nsGkAtoms::partialdiff_, // partialdiff nsGkAtoms::pi_, // pi nsGkAtoms::piece_, // piece nsGkAtoms::piecewise_, // piecewise nsGkAtoms::plus_, // plus nsGkAtoms::power_, // power nsGkAtoms::primes_, // primes nsGkAtoms::product_, // product nsGkAtoms::prsubset_, // prsubset nsGkAtoms::quotient_, // quotient nsGkAtoms::rationals_, // rationals nsGkAtoms::real_, // real nsGkAtoms::reals_, // reals nsGkAtoms::reln_, // reln nsGkAtoms::rem, // rem nsGkAtoms::root_, // root nsGkAtoms::scalarproduct_, // scalarproduct nsGkAtoms::sdev_, // sdev nsGkAtoms::sec_, // sec nsGkAtoms::sech_, // sech nsGkAtoms::selector_, // selector nsGkAtoms::semantics_, // semantics nsGkAtoms::sep_, // sep nsGkAtoms::set, // set nsGkAtoms::setdiff_, // setdiff nsGkAtoms::share_, // share nsGkAtoms::sin_, // sin nsGkAtoms::sinh_, // sinh nsGkAtoms::subset_, // subset nsGkAtoms::sum, // sum nsGkAtoms::tan_, // tan nsGkAtoms::tanh_, // tanh nsGkAtoms::tendsto_, // tendsto nsGkAtoms::times_, // times nsGkAtoms::transpose_, // transpose nsGkAtoms::_true, // true nsGkAtoms::union_, // union nsGkAtoms::uplimit_, // uplimit nsGkAtoms::variance_, // variance nsGkAtoms::vector_, // vector nsGkAtoms::vectorproduct_, // vectorproduct nsGkAtoms::xor_, // xor nullptr}; const nsStaticAtom* const kAttributesMathML[] = { nsGkAtoms::accent_, // accent nsGkAtoms::accentunder_, // accentunder nsGkAtoms::actiontype_, // actiontype nsGkAtoms::align, // align nsGkAtoms::alignmentscope_, // alignmentscope nsGkAtoms::alt, // alt nsGkAtoms::altimg_, // altimg nsGkAtoms::altimg_height_, // altimg-height nsGkAtoms::altimg_valign_, // altimg-valign nsGkAtoms::altimg_width_, // altimg-width nsGkAtoms::background, // background nsGkAtoms::base, // base nsGkAtoms::bevelled_, // bevelled nsGkAtoms::cd_, // cd nsGkAtoms::cdgroup_, // cdgroup nsGkAtoms::charalign_, // charalign nsGkAtoms::close, // close nsGkAtoms::closure_, // closure nsGkAtoms::color, // color nsGkAtoms::columnalign_, // columnalign nsGkAtoms::columnalignment_, // columnalignment nsGkAtoms::columnlines_, // columnlines nsGkAtoms::columnspacing_, // columnspacing nsGkAtoms::columnspan_, // columnspan nsGkAtoms::columnwidth_, // columnwidth nsGkAtoms::crossout_, // crossout nsGkAtoms::decimalpoint_, // decimalpoint nsGkAtoms::definitionURL_, // definitionURL nsGkAtoms::denomalign_, // denomalign nsGkAtoms::depth_, // depth nsGkAtoms::dir, // dir nsGkAtoms::display, // display nsGkAtoms::displaystyle_, // displaystyle nsGkAtoms::edge_, // edge nsGkAtoms::encoding, // encoding nsGkAtoms::equalcolumns_, // equalcolumns nsGkAtoms::equalrows_, // equalrows nsGkAtoms::fence_, // fence nsGkAtoms::fontfamily_, // fontfamily nsGkAtoms::fontsize_, // fontsize nsGkAtoms::fontstyle_, // fontstyle nsGkAtoms::fontweight_, // fontweight nsGkAtoms::form, // form nsGkAtoms::frame, // frame nsGkAtoms::framespacing_, // framespacing nsGkAtoms::groupalign_, // groupalign nsGkAtoms::height, // height nsGkAtoms::href, // href nsGkAtoms::id, // id nsGkAtoms::indentalign_, // indentalign nsGkAtoms::indentalignfirst_, // indentalignfirst nsGkAtoms::indentalignlast_, // indentalignlast nsGkAtoms::indentshift_, // indentshift nsGkAtoms::indentshiftfirst_, // indentshiftfirst nsGkAtoms::indenttarget_, // indenttarget nsGkAtoms::index, // index nsGkAtoms::integer, // integer nsGkAtoms::largeop_, // largeop nsGkAtoms::length, // length nsGkAtoms::linebreak_, // linebreak nsGkAtoms::linebreakmultchar_, // linebreakmultchar nsGkAtoms::linebreakstyle_, // linebreakstyle nsGkAtoms::linethickness_, // linethickness nsGkAtoms::location_, // location nsGkAtoms::longdivstyle_, // longdivstyle nsGkAtoms::lquote_, // lquote nsGkAtoms::lspace_, // lspace nsGkAtoms::ltr, // ltr nsGkAtoms::mathbackground_, // mathbackground nsGkAtoms::mathcolor_, // mathcolor nsGkAtoms::mathsize_, // mathsize nsGkAtoms::mathvariant_, // mathvariant nsGkAtoms::maxsize_, // maxsize nsGkAtoms::minlabelspacing_, // minlabelspacing nsGkAtoms::minsize_, // minsize nsGkAtoms::movablelimits_, // movablelimits nsGkAtoms::msgroup_, // msgroup nsGkAtoms::name, // name nsGkAtoms::newline, // newline nsGkAtoms::notation_, // notation nsGkAtoms::numalign_, // numalign nsGkAtoms::number, // number nsGkAtoms::open, // open nsGkAtoms::order, // order nsGkAtoms::other, // other nsGkAtoms::overflow, // overflow nsGkAtoms::position, // position nsGkAtoms::role, // role nsGkAtoms::rowalign_, // rowalign nsGkAtoms::rowlines_, // rowlines nsGkAtoms::rowspacing_, // rowspacing nsGkAtoms::rowspan, // rowspan nsGkAtoms::rquote_, // rquote nsGkAtoms::rspace_, // rspace nsGkAtoms::schemaLocation_, // schemaLocation nsGkAtoms::scriptlevel_, // scriptlevel nsGkAtoms::scriptminsize_, // scriptminsize nsGkAtoms::scriptsize_, // scriptsize nsGkAtoms::scriptsizemultiplier_, // scriptsizemultiplier nsGkAtoms::selection_, // selection nsGkAtoms::separator_, // separator nsGkAtoms::separators_, // separators nsGkAtoms::shift_, // shift nsGkAtoms::side_, // side nsGkAtoms::src, // src nsGkAtoms::stackalign_, // stackalign nsGkAtoms::stretchy_, // stretchy nsGkAtoms::subscriptshift_, // subscriptshift nsGkAtoms::superscriptshift_, // superscriptshift nsGkAtoms::symmetric_, // symmetric nsGkAtoms::type, // type nsGkAtoms::voffset_, // voffset nsGkAtoms::width, // width nsGkAtoms::xref_, // xref nullptr}; const nsStaticAtom* const kURLAttributesMathML[] = { // clang-format off nsGkAtoms::href, nsGkAtoms::src, nsGkAtoms::cdgroup_, nsGkAtoms::altimg_, nsGkAtoms::definitionURL_, nullptr // clang-format on }; nsTreeSanitizer::AtomsTable* nsTreeSanitizer::sElementsHTML = nullptr; nsTreeSanitizer::AtomsTable* nsTreeSanitizer::sAttributesHTML = nullptr; nsTreeSanitizer::AtomsTable* nsTreeSanitizer::sPresAttributesHTML = nullptr; nsTreeSanitizer::AtomsTable* nsTreeSanitizer::sElementsSVG = nullptr; nsTreeSanitizer::AtomsTable* nsTreeSanitizer::sAttributesSVG = nullptr; nsTreeSanitizer::AtomsTable* nsTreeSanitizer::sElementsMathML = nullptr; nsTreeSanitizer::AtomsTable* nsTreeSanitizer::sAttributesMathML = nullptr; nsIPrincipal* nsTreeSanitizer::sNullPrincipal = nullptr; nsTreeSanitizer::nsTreeSanitizer(uint32_t aFlags) : mAllowStyles(aFlags & nsIParserUtils::SanitizerAllowStyle), mAllowComments(aFlags & nsIParserUtils::SanitizerAllowComments), mDropNonCSSPresentation(aFlags & nsIParserUtils::SanitizerDropNonCSSPresentation), mDropForms(aFlags & nsIParserUtils::SanitizerDropForms), mCidEmbedsOnly(aFlags & nsIParserUtils::SanitizerCidEmbedsOnly), mDropMedia(aFlags & nsIParserUtils::SanitizerDropMedia), mFullDocument(false), mLogRemovals(aFlags & nsIParserUtils::SanitizerLogRemovals) { if (mCidEmbedsOnly) { // Sanitizing styles for external references is not supported. mAllowStyles = false; } if (!sElementsHTML) { // Initialize lazily to avoid having to initialize at all if the user // doesn't paste HTML or load feeds. InitializeStatics(); } } bool nsTreeSanitizer::MustFlatten(int32_t aNamespace, nsAtom* aLocal) { if (aNamespace == kNameSpaceID_XHTML) { if (mDropNonCSSPresentation && (nsGkAtoms::font == aLocal || nsGkAtoms::center == aLocal)) { return true; } if (mDropForms && (nsGkAtoms::form == aLocal || nsGkAtoms::input == aLocal || nsGkAtoms::option == aLocal || nsGkAtoms::optgroup == aLocal)) { return true; } if (mFullDocument && (nsGkAtoms::title == aLocal || nsGkAtoms::html == aLocal || nsGkAtoms::head == aLocal || nsGkAtoms::body == aLocal)) { return false; } return !sElementsHTML->Contains(aLocal); } if (aNamespace == kNameSpaceID_SVG) { if (mCidEmbedsOnly || mDropMedia) { // Sanitizing CSS-based URL references inside SVG presentational // attributes is not supported, so flattening for cid: embed case. return true; } return !sElementsSVG->Contains(aLocal); } if (aNamespace == kNameSpaceID_MathML) { return !sElementsMathML->Contains(aLocal); } return true; } bool nsTreeSanitizer::IsURL(const nsStaticAtom* const* aURLs, nsAtom* aLocalName) { const nsStaticAtom* atom; while ((atom = *aURLs)) { if (atom == aLocalName) { return true; } ++aURLs; } return false; } bool nsTreeSanitizer::MustPrune(int32_t aNamespace, nsAtom* aLocal, mozilla::dom::Element* aElement) { // To avoid attacks where a MathML script becomes something that gets // serialized in a way that it parses back as an HTML script, let's just // drop elements with the local name 'script' regardless of namespace. if (nsGkAtoms::script == aLocal) { return true; } if (aNamespace == kNameSpaceID_XHTML) { if (nsGkAtoms::title == aLocal && !mFullDocument) { // emulate the quirks of the old parser return true; } if (mDropForms && (nsGkAtoms::select == aLocal || nsGkAtoms::button == aLocal || nsGkAtoms::datalist == aLocal)) { return true; } if (mDropMedia && (nsGkAtoms::img == aLocal || nsGkAtoms::video == aLocal || nsGkAtoms::audio == aLocal || nsGkAtoms::source == aLocal)) { return true; } if (nsGkAtoms::meta == aLocal && (aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::charset) || aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::httpEquiv))) { // Throw away charset declarations even if they also have microdata // which they can't validly have. return true; } if (((!mFullDocument && nsGkAtoms::meta == aLocal) || nsGkAtoms::link == aLocal) && !(aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::itemprop) || aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::itemscope))) { // emulate old behavior for non-Microdata and presumably // in
. and are whitelisted in order to avoid // corrupting Microdata when they appear in . Note that // SanitizeAttributes() will remove the rel attribute from and // the name attribute from . return true; } } if (mAllowStyles) { if (nsGkAtoms::style == aLocal && !(aNamespace == kNameSpaceID_XHTML || aNamespace == kNameSpaceID_SVG)) { return true; } return false; } if (nsGkAtoms::style == aLocal) { return true; } return false; } bool nsTreeSanitizer::SanitizeStyleDeclaration(DeclarationBlock* aDeclaration) { return aDeclaration->RemovePropertyByID(eCSSProperty__moz_binding); } bool nsTreeSanitizer::SanitizeStyleSheet(const nsAString& aOriginal, nsAString& aSanitized, Document* aDocument, nsIURI* aBaseURI) { nsresult rv = NS_OK; aSanitized.Truncate(); // aSanitized will hold the permitted CSS text. // -moz-binding is blacklisted. bool didSanitize = false; // Create a sheet to hold the parsed CSS RefPtr