1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #ifndef nsTreeSanitizer_h_
6 #define nsTreeSanitizer_h_
9 #include "nsHashKeys.h"
10 #include "nsHashtablesFwd.h"
11 #include "nsIPrincipal.h"
13 #include "nsTHashSet.h"
14 #include "mozilla/Maybe.h"
15 #include "mozilla/dom/NameSpaceConstants.h"
16 #include "mozilla/dom/SanitizerBinding.h"
19 class nsIGlobalObject
;
23 class DeclarationBlock
;
25 enum class StyleSanitizationKind
: uint8_t;
26 } // namespace mozilla
28 namespace mozilla::dom
{
29 class DocumentFragment
;
32 class OwningStringOrSanitizerAttributeNamespace
;
33 class OwningStringOrSanitizerElementNamespace
;
34 class OwningStringOrSanitizerElementNamespaceWithAttributes
;
35 } // namespace mozilla::dom
38 * See the documentation of nsIParserUtils::sanitize for documentation
39 * about the default behavior and the configuration options of this sanitizer.
41 class nsTreeSanitizer
{
46 * @param aFlags Flags from nsIParserUtils
48 explicit nsTreeSanitizer(uint32_t aFlags
= 0);
50 static void InitializeStatics();
51 static void ReleaseStatics();
54 * Sanitizes a disconnected DOM fragment freshly obtained from a parser.
55 * The fragment must have just come from a parser so that it can't have
56 * mutation event listeners set on it.
58 void Sanitize(mozilla::dom::DocumentFragment
* aFragment
);
61 * Sanitizes a disconnected (not in a docshell) document freshly obtained
62 * from a parser. The document must not be embedded in a docshell and must
63 * not have had a chance to get mutation event listeners attached to it.
64 * The root element must be <html>.
66 void Sanitize(mozilla::dom::Document
* aDocument
);
69 * Provides additional options for usage from the Web Sanitizer API
70 * which allows modifying the allow-list from above
72 void WithWebSanitizerOptions(nsIGlobalObject
* aGlobal
,
73 const mozilla::dom::SanitizerConfig
& aOptions
,
74 mozilla::ErrorResult
& aRv
);
77 * Removes conditional CSS from this subtree.
79 static void RemoveConditionalCSSFromSubtree(nsINode
* aRoot
);
83 * Whether <style> and style="" are allowed.
88 * Whether comment nodes are allowed.
93 * Whether HTML <font>, <center>, bgcolor="", etc., are dropped.
95 bool mDropNonCSSPresentation
;
98 * Whether to remove forms and form controls (excluding fieldset/legend).
103 * Whether only cid: embeds are allowed.
108 * Whether to drop <img>, <video>, <audio> and <svg>.
113 * Whether we are sanitizing a full document (as opposed to a fragment).
118 * Whether we should notify to the console for anything that's stripped.
122 // WindowID used for logging removals.
123 uint64_t mInnerWindowID
= 0;
126 * We have various tables of static atoms for elements and attributes.
128 class AtomsTable
: public nsTHashSet
<const nsStaticAtom
*> {
130 explicit AtomsTable(uint32_t aLength
)
131 : nsTHashSet
<const nsStaticAtom
*>(aLength
) {}
133 bool Contains(nsAtom
* aAtom
) {
134 // Because this table only contains static atoms, if aAtom isn't
135 // static we can immediately fail.
136 return aAtom
->IsStatic() && GetEntry(aAtom
->AsStatic());
140 // The name of an element combined with its namespace.
141 class NamespaceAtom
: public PLDHashEntryHdr
{
143 using KeyType
= const NamespaceAtom
&;
144 using KeyTypePointer
= const NamespaceAtom
*;
146 explicit NamespaceAtom(KeyTypePointer aKey
)
147 : mNamespaceID(aKey
->mNamespaceID
), mLocalName(aKey
->mLocalName
) {}
148 NamespaceAtom(int32_t aNamespaceID
, RefPtr
<nsAtom
> aLocalName
)
149 : mNamespaceID(aNamespaceID
), mLocalName(std::move(aLocalName
)) {}
150 NamespaceAtom(NamespaceAtom
&&) = default;
151 ~NamespaceAtom() = default;
153 bool KeyEquals(KeyTypePointer aKey
) const {
154 return mNamespaceID
== aKey
->mNamespaceID
&&
155 mLocalName
== aKey
->mLocalName
;
158 static KeyTypePointer
KeyToPointer(KeyType aKey
) { return &aKey
; }
159 static PLDHashNumber
HashKey(KeyTypePointer aKey
) {
164 return mozilla::HashGeneric(aKey
->mNamespaceID
, aKey
->mLocalName
.get());
167 enum { ALLOW_MEMMOVE
= true };
170 int32_t mNamespaceID
= kNameSpaceID_None
;
171 RefPtr
<nsAtom
> mLocalName
;
174 using ElementName
= NamespaceAtom
;
175 using AttributeName
= NamespaceAtom
;
177 using ElementNameSet
= nsTHashSet
<ElementName
>;
178 using AttributeNameSet
= nsTHashSet
<AttributeName
>;
180 class ElementWithAttributes
{
182 mozilla::Maybe
<AttributeNameSet
> mAttributes
;
183 mozilla::Maybe
<AttributeNameSet
> mRemoveAttributes
;
186 using ElementsToAttributesMap
=
187 nsTHashMap
<ElementName
, ElementWithAttributes
>;
189 void SanitizeChildren(nsINode
* aRoot
);
192 * Queries if an element must be replaced with its children.
193 * @param aNamespace the namespace of the element the question is about
194 * @param aLocal the local name of the element the question is about
195 * @return true if the element must be replaced with its children and
196 * false if the element is to be kept
198 bool MustFlatten(int32_t aNamespace
, nsAtom
* aLocal
);
199 bool MustFlattenForSanitizerAPI(int32_t aNamespace
, nsAtom
* aLocal
);
202 * Queries if an element including its children must be removed.
203 * @param aNamespace the namespace of the element the question is about
204 * @param aLocal the local name of the element the question is about
205 * @param aElement the element node itself for inspecting attributes
206 * @return true if the element and its children must be removed and
207 * false if the element is to be kept
209 bool MustPrune(int32_t aNamespace
, nsAtom
* aLocal
,
210 mozilla::dom::Element
* aElement
);
211 bool MustPruneForSanitizerAPI(int32_t aNamespace
, nsAtom
* aLocal
,
212 mozilla::dom::Element
* aElement
);
215 * Checks if a given local name (for an attribute) is on the given list
216 * of URL attribute names.
217 * @param aURLs the list of URL attribute names
218 * @param aLocalName the name to search on the list
219 * @return true if aLocalName is on the aURLs list and false otherwise
221 bool IsURL(const nsStaticAtom
* const* aURLs
, nsAtom
* aLocalName
);
224 * Struct for what attributes and their values are allowed.
226 struct AllowedAttributes
{
227 // The whitelist of permitted local names to use.
228 AtomsTable
* mNames
= nullptr;
229 // The local names of URL-valued attributes for URL checking.
230 const nsStaticAtom
* const* mURLs
= nullptr;
231 // Whether XLink attributes are allowed.
233 // Whether the style attribute is allowed.
235 // Whether to leave the value of the src attribute unsanitized.
236 bool mDangerousSrc
= false;
240 * Removes dangerous attributes from the element. If the style attribute
241 * is allowed, its value is sanitized. The values of URL attributes are
242 * sanitized, except src isn't sanitized when it is allowed to remain
243 * potentially dangerous.
245 * @param aElement the element whose attributes should be sanitized
246 * @param aAllowed options for sanitizing attributes
248 void SanitizeAttributes(mozilla::dom::Element
* aElement
,
249 AllowedAttributes aAllowed
);
250 // Currently only used for the Sanitizer API.
251 bool MustDropAttribute(mozilla::dom::Element
* aElement
,
252 int32_t aAttrNamespace
, nsAtom
* aAttrLocalName
);
253 bool MustDropFunkyAttribute(mozilla::dom::Element
* aElement
,
254 int32_t aAttrNamespace
, nsAtom
* aAttrLocalName
);
257 * Remove the named URL attribute from the element if the URL fails a
260 * @param aElement the element whose attribute to possibly modify
261 * @param aNamespace the namespace of the URL attribute
262 * @param aLocalName the local name of the URL attribute
263 * @param aFragmentsOnly allows same-document references only
264 * @return true if the attribute was removed and false otherwise
266 bool SanitizeURL(mozilla::dom::Element
* aElement
, int32_t aNamespace
,
267 nsAtom
* aLocalName
, bool aFragmentsOnly
= false);
270 * Checks a style rule for the presence of the 'binding' CSS property and
271 * removes that property from the rule.
273 * @param aDeclaration The style declaration to check
274 * @return true if the rule was modified and false otherwise
276 bool SanitizeStyleDeclaration(mozilla::DeclarationBlock
* aDeclaration
);
279 * Sanitizes an inline style element (an HTML or SVG <style>).
281 * Returns whether the style has changed.
283 static bool SanitizeInlineStyle(mozilla::dom::Element
*,
284 mozilla::StyleSanitizationKind
);
287 * Removes all attributes from an element node.
289 static void RemoveAllAttributes(mozilla::dom::Element
* aElement
);
292 * Removes all attributes from the descendants of an element but not from
293 * the element itself.
295 static void RemoveAllAttributesFromDescendants(mozilla::dom::Element
*);
297 static bool MatchesElementName(ElementNameSet
& aNames
, int32_t aNamespace
,
299 static bool MatchesAttributeName(AttributeNameSet
& aNames
, int32_t aNamespace
,
302 static ElementNameSet
ConvertElements(
303 const nsTArray
<mozilla::dom::OwningStringOrSanitizerElementNamespace
>&
305 mozilla::ErrorResult
& aRv
);
307 static ElementsToAttributesMap
ConvertElementsWithAttributes(
309 mozilla::dom::OwningStringOrSanitizerElementNamespaceWithAttributes
>&
311 mozilla::ErrorResult
& aRv
);
313 static AttributeNameSet
ConvertAttributes(
314 const nsTArray
<mozilla::dom::OwningStringOrSanitizerAttributeNamespace
>&
316 mozilla::ErrorResult
& aRv
);
319 * Log a Console Service message to indicate we removed something.
320 * If you pass an element and/or attribute, their information will
321 * be appended to the message.
323 * @param aMessage the basic message to log.
324 * @param aDocument the base document we're modifying
325 * (used for the error message)
326 * @param aElement optional, the element being removed or modified.
327 * @param aAttribute optional, the attribute being removed or modified.
329 void LogMessage(const char* aMessage
, mozilla::dom::Document
* aDoc
,
330 mozilla::dom::Element
* aElement
= nullptr,
331 nsAtom
* aAttr
= nullptr);
334 * The whitelist of HTML elements.
336 static AtomsTable
* sElementsHTML
;
339 * The whitelist of non-presentational HTML attributes.
341 static AtomsTable
* sAttributesHTML
;
344 * The whitelist of presentational HTML attributes.
346 static AtomsTable
* sPresAttributesHTML
;
349 * The whitelist of SVG elements.
351 static AtomsTable
* sElementsSVG
;
354 * The whitelist of SVG attributes.
356 static AtomsTable
* sAttributesSVG
;
359 * The whitelist of SVG elements.
361 static AtomsTable
* sElementsMathML
;
364 * The whitelist of MathML attributes.
366 static AtomsTable
* sAttributesMathML
;
369 * The built-in baseline attribute allow list used by the Sanitizer API.
371 static AtomsTable
* sBaselineAttributeAllowlist
;
374 * The built-in baseline element allow list used by the Sanitizer API.
376 static AtomsTable
* sBaselineElementAllowlist
;
379 * The default configuration's attribute allow list used by the Sanitizer API.
381 static AtomsTable
* sDefaultConfigurationAttributeAllowlist
;
384 * The default configuration's element allow list used by the Sanitizer API.
386 static AtomsTable
* sDefaultConfigurationElementAllowlist
;
389 * Reusable null principal for URL checks.
391 static nsIPrincipal
* sNullPrincipal
;
393 // === Variables used to implement HTML Sanitizer API. ==
395 // This nsTreeSanitizer instance should behave like the Sanitizer API.
396 bool mIsForSanitizerAPI
= false;
398 bool mAllowCustomElements
= false;
399 bool mAllowUnknownMarkup
= false;
401 // An allow-list of elements to keep, with potentially associated lists of
402 // attributes to keep/remove.
403 mozilla::Maybe
<ElementsToAttributesMap
> mElements
;
405 // A deny-list of elements to remove. (aka prune)
406 mozilla::Maybe
<ElementNameSet
> mRemoveElements
;
408 // A deny-list of elements to replace with children. (aka flatten)
409 mozilla::Maybe
<ElementNameSet
> mReplaceWithChildrenElements
;
411 // An allow-list of attributes to keep.
412 mozilla::Maybe
<AttributeNameSet
> mAttributes
;
414 // A deny-list of attributes to remove.
415 mozilla::Maybe
<AttributeNameSet
> mRemoveAttributes
;
418 #endif // nsTreeSanitizer_h_