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/UniquePtr.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
;
31 class OwningStringOrSanitizerElementNameNamespace
;
32 struct SanitizerAttribute
;
33 } // namespace mozilla::dom
36 * See the documentation of nsIParserUtils::sanitize for documentation
37 * about the default behavior and the configuration options of this sanitizer.
39 class nsTreeSanitizer
{
44 * @param aFlags Flags from nsIParserUtils
46 explicit nsTreeSanitizer(uint32_t aFlags
= 0);
48 static void InitializeStatics();
49 static void ReleaseStatics();
52 * Sanitizes a disconnected DOM fragment freshly obtained from a parser.
53 * The fragment must have just come from a parser so that it can't have
54 * mutation event listeners set on it.
56 void Sanitize(mozilla::dom::DocumentFragment
* aFragment
);
59 * Sanitizes a disconnected (not in a docshell) document freshly obtained
60 * from a parser. The document must not be embedded in a docshell and must
61 * not have had a chance to get mutation event listeners attached to it.
62 * The root element must be <html>.
64 void Sanitize(mozilla::dom::Document
* aDocument
);
67 * Provides additional options for usage from the Web Sanitizer API
68 * which allows modifying the allow-list from above
70 void WithWebSanitizerOptions(nsIGlobalObject
* aGlobal
,
71 const mozilla::dom::SanitizerConfig
& aOptions
,
72 mozilla::ErrorResult
& aRv
);
75 * Removes conditional CSS from this subtree.
77 static void RemoveConditionalCSSFromSubtree(nsINode
* aRoot
);
81 * Whether <style> and style="" are allowed.
86 * Whether comment nodes are allowed.
91 * Whether HTML <font>, <center>, bgcolor="", etc., are dropped.
93 bool mDropNonCSSPresentation
;
96 * Whether to remove forms and form controls (excluding fieldset/legend).
101 * Whether only cid: embeds are allowed.
106 * Whether to drop <img>, <video>, <audio> and <svg>.
111 * Whether we are sanitizing a full document (as opposed to a fragment).
116 * Whether we should notify to the console for anything that's stripped.
120 // WindowID used for logging removals.
121 uint64_t mInnerWindowID
= 0;
124 * We have various tables of static atoms for elements and attributes.
126 class AtomsTable
: public nsTHashSet
<const nsStaticAtom
*> {
128 explicit AtomsTable(uint32_t aLength
)
129 : nsTHashSet
<const nsStaticAtom
*>(aLength
) {}
131 bool Contains(nsAtom
* aAtom
) {
132 // Because this table only contains static atoms, if aAtom isn't
133 // static we can immediately fail.
134 return aAtom
->IsStatic() && GetEntry(aAtom
->AsStatic());
138 // The name of an element combined with its namespace.
139 class NamespaceAtom
: public PLDHashEntryHdr
{
141 using KeyType
= const NamespaceAtom
&;
142 using KeyTypePointer
= const NamespaceAtom
*;
144 explicit NamespaceAtom(KeyTypePointer aKey
)
145 : mNamespaceID(aKey
->mNamespaceID
), mLocalName(aKey
->mLocalName
) {}
146 NamespaceAtom(int32_t aNamespaceID
, RefPtr
<nsAtom
> aLocalName
)
147 : mNamespaceID(aNamespaceID
), mLocalName(std::move(aLocalName
)) {}
148 NamespaceAtom(NamespaceAtom
&&) = default;
149 ~NamespaceAtom() = default;
151 bool KeyEquals(KeyTypePointer aKey
) const {
152 return mNamespaceID
== aKey
->mNamespaceID
&&
153 mLocalName
== aKey
->mLocalName
;
156 static KeyTypePointer
KeyToPointer(KeyType aKey
) { return &aKey
; }
157 static PLDHashNumber
HashKey(KeyTypePointer aKey
) {
162 return mozilla::HashGeneric(aKey
->mNamespaceID
, aKey
->mLocalName
.get());
165 enum { ALLOW_MEMMOVE
= true };
168 int32_t mNamespaceID
= kNameSpaceID_None
;
169 RefPtr
<nsAtom
> mLocalName
;
172 using ElementName
= NamespaceAtom
;
173 using AttributeName
= NamespaceAtom
;
175 using ElementNameSet
= nsTHashSet
<ElementName
>;
176 // nullptr value (ElementNameSet) means all elements (*).
177 using AttributesToElementsMap
=
178 nsTHashMap
<AttributeName
, mozilla::UniquePtr
<ElementNameSet
>>;
180 void SanitizeChildren(nsINode
* aRoot
);
183 * Queries if an element must be replaced with its children.
184 * @param aNamespace the namespace of the element the question is about
185 * @param aLocal the local name of the element the question is about
186 * @return true if the element must be replaced with its children and
187 * false if the element is to be kept
189 bool MustFlatten(int32_t aNamespace
, nsAtom
* aLocal
);
190 bool MustFlattenForSanitizerAPI(int32_t aNamespace
, nsAtom
* aLocal
);
193 * Queries if an element including its children must be removed.
194 * @param aNamespace the namespace of the element the question is about
195 * @param aLocal the local name of the element the question is about
196 * @param aElement the element node itself for inspecting attributes
197 * @return true if the element and its children must be removed and
198 * false if the element is to be kept
200 bool MustPrune(int32_t aNamespace
, nsAtom
* aLocal
,
201 mozilla::dom::Element
* aElement
);
202 bool MustPruneForSanitizerAPI(int32_t aNamespace
, nsAtom
* aLocal
,
203 mozilla::dom::Element
* aElement
);
206 * Checks if a given local name (for an attribute) is on the given list
207 * of URL attribute names.
208 * @param aURLs the list of URL attribute names
209 * @param aLocalName the name to search on the list
210 * @return true if aLocalName is on the aURLs list and false otherwise
212 bool IsURL(const nsStaticAtom
* const* aURLs
, nsAtom
* aLocalName
);
215 * Struct for what attributes and their values are allowed.
217 struct AllowedAttributes
{
218 // The whitelist of permitted local names to use.
219 AtomsTable
* mNames
= nullptr;
220 // The local names of URL-valued attributes for URL checking.
221 const nsStaticAtom
* const* mURLs
= nullptr;
222 // Whether XLink attributes are allowed.
224 // Whether the style attribute is allowed.
226 // Whether to leave the value of the src attribute unsanitized.
227 bool mDangerousSrc
= false;
231 * Removes dangerous attributes from the element. If the style attribute
232 * is allowed, its value is sanitized. The values of URL attributes are
233 * sanitized, except src isn't sanitized when it is allowed to remain
234 * potentially dangerous.
236 * @param aElement the element whose attributes should be sanitized
237 * @param aAllowed options for sanitizing attributes
239 void SanitizeAttributes(mozilla::dom::Element
* aElement
,
240 AllowedAttributes aAllowed
);
241 // Currently only used for the Sanitizer API.
242 bool MustDropAttribute(mozilla::dom::Element
* aElement
,
243 int32_t aAttrNamespace
, nsAtom
* aAttrLocalName
);
244 bool MustDropFunkyAttribute(mozilla::dom::Element
* aElement
,
245 int32_t aAttrNamespace
, nsAtom
* aAttrLocalName
);
248 * Remove the named URL attribute from the element if the URL fails a
251 * @param aElement the element whose attribute to possibly modify
252 * @param aNamespace the namespace of the URL attribute
253 * @param aLocalName the local name of the URL attribute
254 * @param aFragmentsOnly allows same-document references only
255 * @return true if the attribute was removed and false otherwise
257 bool SanitizeURL(mozilla::dom::Element
* aElement
, int32_t aNamespace
,
258 nsAtom
* aLocalName
, bool aFragmentsOnly
= false);
261 * Checks a style rule for the presence of the 'binding' CSS property and
262 * removes that property from the rule.
264 * @param aDeclaration The style declaration to check
265 * @return true if the rule was modified and false otherwise
267 bool SanitizeStyleDeclaration(mozilla::DeclarationBlock
* aDeclaration
);
270 * Sanitizes an inline style element (an HTML or SVG <style>).
272 * Returns whether the style has changed.
274 static bool SanitizeInlineStyle(mozilla::dom::Element
*,
275 mozilla::StyleSanitizationKind
);
278 * Removes all attributes from an element node.
280 static void RemoveAllAttributes(mozilla::dom::Element
* aElement
);
283 * Removes all attributes from the descendants of an element but not from
284 * the element itself.
286 static void RemoveAllAttributesFromDescendants(mozilla::dom::Element
*);
288 static bool MatchesElementName(ElementNameSet
& aNames
, int32_t aNamespace
,
290 static bool MatchesAttributeMatchList(AttributesToElementsMap
& aMatchList
,
291 mozilla::dom::Element
& aElement
,
292 int32_t aAttrNamespace
,
293 nsAtom
* aAttrLocalName
);
295 static mozilla::UniquePtr
<ElementNameSet
> ConvertElements(
296 const nsTArray
<mozilla::dom::OwningStringOrSanitizerElementNamespace
>&
298 mozilla::ErrorResult
& aRv
);
300 static mozilla::UniquePtr
<ElementNameSet
> ConvertElements(
301 const mozilla::dom::OwningStarOrStringOrSanitizerElementNamespaceSequence
&
303 mozilla::ErrorResult
& aRv
);
305 static mozilla::UniquePtr
<AttributesToElementsMap
> ConvertAttributes(
306 const nsTArray
<mozilla::dom::SanitizerAttribute
>& aAttributes
,
307 mozilla::ErrorResult
& aRv
);
310 * Log a Console Service message to indicate we removed something.
311 * If you pass an element and/or attribute, their information will
312 * be appended to the message.
314 * @param aMessage the basic message to log.
315 * @param aDocument the base document we're modifying
316 * (used for the error message)
317 * @param aElement optional, the element being removed or modified.
318 * @param aAttribute optional, the attribute being removed or modified.
320 void LogMessage(const char* aMessage
, mozilla::dom::Document
* aDoc
,
321 mozilla::dom::Element
* aElement
= nullptr,
322 nsAtom
* aAttr
= nullptr);
325 * The whitelist of HTML elements.
327 static AtomsTable
* sElementsHTML
;
330 * The whitelist of non-presentational HTML attributes.
332 static AtomsTable
* sAttributesHTML
;
335 * The whitelist of presentational HTML attributes.
337 static AtomsTable
* sPresAttributesHTML
;
340 * The whitelist of SVG elements.
342 static AtomsTable
* sElementsSVG
;
345 * The whitelist of SVG attributes.
347 static AtomsTable
* sAttributesSVG
;
350 * The whitelist of SVG elements.
352 static AtomsTable
* sElementsMathML
;
355 * The whitelist of MathML attributes.
357 static AtomsTable
* sAttributesMathML
;
360 * The built-in baseline attribute allow list used by the Sanitizer API.
362 static AtomsTable
* sBaselineAttributeAllowlist
;
365 * The built-in baseline element allow list used by the Sanitizer API.
367 static AtomsTable
* sBaselineElementAllowlist
;
370 * The default configuration's attribute allow list used by the Sanitizer API.
372 static AtomsTable
* sDefaultConfigurationAttributeAllowlist
;
375 * The default configuration's element allow list used by the Sanitizer API.
377 static AtomsTable
* sDefaultConfigurationElementAllowlist
;
380 * Reusable null principal for URL checks.
382 static nsIPrincipal
* sNullPrincipal
;
384 // === Variables used to implement HTML Sanitizer API. ==
386 // This nsTreeSanitizer instance should behave like the Sanitizer API.
387 bool mIsForSanitizerAPI
= false;
389 bool mAllowCustomElements
= false;
390 bool mAllowUnknownMarkup
= false;
392 // An allow-list of elements to keep.
393 mozilla::UniquePtr
<ElementNameSet
> mAllowElements
;
395 // A deny-list of elements to block. (aka flatten)
396 mozilla::UniquePtr
<ElementNameSet
> mBlockElements
;
398 // A deny-list of elements to drop. (aka prune)
399 mozilla::UniquePtr
<ElementNameSet
> mDropElements
;
401 // An allow-list of attributes to keep.
402 mozilla::UniquePtr
<AttributesToElementsMap
> mAllowAttributes
;
404 // A deny-list of attributes to drop.
405 mozilla::UniquePtr
<AttributesToElementsMap
> mDropAttributes
;
408 #endif // nsTreeSanitizer_h_