diff --git a/dom/base/DOMParser.cpp b/dom/base/DOMParser.cpp index 146ee197cf6da..464d4a8d38e8b 100644 --- a/dom/base/DOMParser.cpp +++ b/dom/base/DOMParser.cpp @@ -23,6 +23,7 @@ #include "nsJSUtils.h" #include "nsError.h" #include "nsPIDOMWindow.h" +#include "nsTaintingUtils.h" #include "mozilla/BasePrincipal.h" #include "mozilla/LoadInfo.h" #include "mozilla/NullPrincipal.h" diff --git a/dom/base/Document.cpp b/dom/base/Document.cpp index 6271850e22b6b..d8708e225b954 100644 --- a/dom/base/Document.cpp +++ b/dom/base/Document.cpp @@ -418,6 +418,7 @@ #include "nsStringIterator.h" #include "nsStyleSheetService.h" #include "nsStyleStruct.h" +#include "nsTaintingUtils.h" #include "nsTextNode.h" #include "nsUnicharUtils.h" #include "nsWrapperCache.h" diff --git a/dom/base/Element.cpp b/dom/base/Element.cpp index 4a3a26bb07008..cc044a95ea0be 100644 --- a/dom/base/Element.cpp +++ b/dom/base/Element.cpp @@ -181,6 +181,7 @@ #include "nsStyleStruct.h" #include "nsStyledElement.h" #include "nsTArray.h" +#include "nsTaintingUtils.h" #include "nsTextNode.h" #include "nsThreadUtils.h" #include "nsViewManager.h" @@ -3919,9 +3920,7 @@ void Element::SetInnerHTML(const nsAString& aInnerHTML, ErrorResult& aError) { // TaintFox: innerHTML sink. - nsAutoString id; - this->GetId(id); - ReportTaintSink(aInnerHTML, "innerHTML", id); + ReportTaintSink(aInnerHTML, "innerHTML", this); SetInnerHTMLInternal(aInnerHTML, aError); } @@ -3943,9 +3942,7 @@ void Element::SetOuterHTML(const nsAString& aOuterHTML, ErrorResult& aError) { } // TaintFox: outerHTML sink. - nsAutoString id; - this->GetId(id); - ReportTaintSink(aOuterHTML, "outerHTML", id); + ReportTaintSink(aOuterHTML, "outerHTML", this); if (OwnerDoc()->IsHTMLDocument()) { nsAtom* localName; @@ -3995,7 +3992,7 @@ enum nsAdjacentPosition { eBeforeBegin, eAfterBegin, eBeforeEnd, eAfterEnd }; void Element::InsertAdjacentHTML(const nsAString& aPosition, const nsAString& aText, ErrorResult& aError) { // TaintFox: insertAdjacentHTML sink - ReportTaintSink(aText, "insertAdjacentHTML"); + ReportTaintSink(aText, "insertAdjacentHTML", this); nsAdjacentPosition position; if (aPosition.LowerCaseEqualsLiteral("beforebegin")) { @@ -4126,7 +4123,7 @@ void Element::InsertAdjacentText(const nsAString& aWhere, RefPtr textNode = OwnerDoc()->CreateTextNode(aData); // TaintFox: insertAdjacentHTML sink - ReportTaintSink(aData, "insertAdjacentText"); + ReportTaintSink(aData, "insertAdjacentText", this); InsertAdjacent(aWhere, textNode, aError); } diff --git a/dom/base/Location.cpp b/dom/base/Location.cpp index 2b469dafd8d22..eded157af3d6f 100644 --- a/dom/base/Location.cpp +++ b/dom/base/Location.cpp @@ -27,6 +27,7 @@ #include "nsDocShell.h" #include "nsGlobalWindowOuter.h" #include "nsPIDOMWindowInlines.h" +#include "nsTaintingUtils.h" #include "mozilla/Likely.h" #include "nsCycleCollectionParticipant.h" #include "mozilla/BasePrincipal.h" diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp index 56da84a42a046..17dc8f7eb5a32 100644 --- a/dom/base/Navigator.cpp +++ b/dom/base/Navigator.cpp @@ -92,6 +92,7 @@ #include "MediaManager.h" #include "nsJSUtils.h" +#include "nsTaintingUtils.h" #include "mozilla/dom/Promise.h" diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp index 322fbf5584344..8a9a7302f351e 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -382,6 +382,7 @@ #include "nsTLiteralString.h" #include "nsTPromiseFlatString.h" #include "nsTStringRepr.h" +#include "nsTaintingUtils.h" #include "nsTextFragment.h" #include "nsTextNode.h" #include "nsThreadManager.h" diff --git a/dom/base/nsGlobalWindowInner.cpp b/dom/base/nsGlobalWindowInner.cpp index 27748eed74059..c843a0ec4e7ca 100644 --- a/dom/base/nsGlobalWindowInner.cpp +++ b/dom/base/nsGlobalWindowInner.cpp @@ -300,6 +300,7 @@ #include "nsTLiteralString.h" #include "nsTObserverArray.h" #include "nsTStringRepr.h" +#include "nsTaintingUtils.h" #include "nsThreadUtils.h" #include "nsWeakReference.h" #include "nsWindowMemoryReporter.h" diff --git a/dom/base/nsGlobalWindowOuter.cpp b/dom/base/nsGlobalWindowOuter.cpp index 1cafbf0049244..78753bc567f9d 100644 --- a/dom/base/nsGlobalWindowOuter.cpp +++ b/dom/base/nsGlobalWindowOuter.cpp @@ -80,6 +80,7 @@ // Helper Classes #include "nsJSUtils.h" +#include "nsTaintingUtils.h" #include "jsapi.h" #include "jsfriendapi.h" #include "js/CallAndConstruct.h" // JS::Call diff --git a/dom/base/nsINode.cpp b/dom/base/nsINode.cpp index c91311594c487..2a63b006da754 100644 --- a/dom/base/nsINode.cpp +++ b/dom/base/nsINode.cpp @@ -97,6 +97,7 @@ #include "nsRange.h" #include "nsString.h" #include "nsStyleConsts.h" +#include "nsTaintingUtils.h" #include "nsTextNode.h" #include "nsUnicharUtils.h" #include "nsWindowSizes.h" diff --git a/dom/base/nsJSUtils.cpp b/dom/base/nsJSUtils.cpp index 85b19a98581a7..27673c72be8e6 100644 --- a/dom/base/nsJSUtils.cpp +++ b/dom/base/nsJSUtils.cpp @@ -229,337 +229,4 @@ bool nsTAutoJSString::init(const JS::Value& v) { } template bool nsTAutoJSString::init(const JS::Value&); -template bool nsTAutoJSString::init(const JS::Value&); - -LazyLogModule gTaintLog("Taint"); - -static TaintOperation GetTaintOperation(JSContext *cx, const char* name) -{ - if (cx) { - return JS_GetTaintOperation(cx, name); - } - - return TaintOperation(name); -} - -static TaintOperation GetTaintOperation(JSContext *cx, const char* name, const nsAString& arg) -{ - if (cx && JS::CurrentGlobalOrNull(cx)) { - JS::RootedValue argval(cx); - if (mozilla::dom::ToJSValue(cx, arg, &argval)) { - return JS_GetTaintOperation(cx, name, argval); - } - } - - return TaintOperation(name); -} - -static TaintOperation GetTaintOperation(JSContext *cx, const char* name, const nsTArray &args) -{ - if (cx && JS::CurrentGlobalOrNull(cx)) { - JS::RootedValue argval(cx); - - if (mozilla::dom::ToJSValue(cx, args, &argval)) { - return JS_GetTaintOperation(cx, name, argval); - } - } - - return TaintOperation(name); -} - -static TaintOperation GetTaintOperation(JSContext *cx, const char* name, const mozilla::dom::Element* element) -{ - if (element) { - nsTArray args; - nsAutoString elementDesc; - - element->Describe(elementDesc); - args.AppendElement(elementDesc); - - return GetTaintOperation(cx, name, args); - } - - return TaintOperation(name); -} - -static TaintOperation GetTaintOperation(JSContext *cx, const char* name, const mozilla::dom::Element* element, - const nsAString &str, const nsAString &attr) -{ - if (element) { - nsTArray args; - - nsAutoString elementDesc; - element->Describe(elementDesc); - args.AppendElement(elementDesc); - - nsAutoString attributeName; - attributeName.Append(attr); - attributeName.AppendLiteral("=\""); - nsAutoString value; - value.Append(str); - for (uint32_t i = value.Length(); i > 0; --i) { - if (value[i - 1] == char16_t('"')) value.Insert(char16_t('\\'), i - 1); - } - attributeName.Append(value); - attributeName.Append('"'); - args.AppendElement(attributeName); - - return GetTaintOperation(cx, name, args); - } - - return TaintOperation(name); -} - -TaintOperation GetTaintOperation(const char* name) -{ - return GetTaintOperation(nsContentUtils::GetCurrentJSContext(), name); -} - -nsresult MarkTaintOperation(StringTaint& aTaint, const char* name) { - JSContext *cx = nsContentUtils::GetCurrentJSContext(); - auto op = GetTaintOperation(cx, name); - op.set_native(); - aTaint.extend(op); - return NS_OK; -} - -static nsresult MarkTaintOperation(JSContext *cx, nsACString &str, const char* name) -{ - if (str.isTainted()) { - auto op = GetTaintOperation(cx, name); - op.set_native(); - str.Taint().extend(op); - } - return NS_OK; -} - -nsresult MarkTaintOperation(nsACString &str, const char* name) -{ - return MarkTaintOperation(nsContentUtils::GetCurrentJSContext(), str, name); -} - -static nsresult MarkTaintOperation(JSContext *cx, nsAString &str, const char* name) -{ - if (str.isTainted()) { - auto op = GetTaintOperation(cx, name); - op.set_native(); - str.Taint().extend(op); - } - return NS_OK; -} - -nsresult MarkTaintOperation(nsAString &str, const char* name) -{ - return MarkTaintOperation(nsContentUtils::GetCurrentJSContext(), str, name); -} - -static nsresult MarkTaintOperation(JSContext *cx, nsAString &str, const char* name, const nsTArray &args) -{ - if (str.isTainted()) { - auto op = GetTaintOperation(cx, name, args); - op.set_native(); - str.Taint().extend(op); - } - return NS_OK; -} - -nsresult MarkTaintOperation(nsAString &str, const char* name, const nsTArray &args) -{ - return MarkTaintOperation(nsContentUtils::GetCurrentJSContext(), str, name, args); -} - -static nsresult MarkTaintSource(nsAString &str, TaintOperation operation) { - operation.setSource(); - operation.set_native(); - str.Taint().overlay(0, str.Length(), operation); - return NS_OK; -} - -static nsresult MarkTaintSource(mozilla::dom::DOMString &str, TaintOperation operation) { - operation.setSource(); - operation.set_native(); - str.Taint().overlay(0, str.Length(), operation); - return NS_OK; -} - -nsresult MarkTaintSource(JSContext* cx, JSString* str, const char* name) -{ - TaintOperation op = GetTaintOperation(cx, name); - op.setSource(); - op.set_native(); - JS_MarkTaintSource(cx, str, op); - return NS_OK; -} - -nsresult MarkTaintSource(JSContext* cx, JS::MutableHandle aValue, const char* name) -{ - TaintOperation op = GetTaintOperation(cx, name); - op.setSource(); - op.set_native(); - JS_MarkTaintSource(cx, aValue, op); - return NS_OK; -} - -nsresult MarkTaintSource(JSContext* cx, JS::MutableHandle aValue, const char* name, const nsAString &arg) -{ - TaintOperation op = GetTaintOperation(cx, name, arg); - op.setSource(); - op.set_native(); - JS_MarkTaintSource(cx, aValue, op); - return NS_OK; -} - -nsresult MarkTaintSource(nsAString &str, const char* name) -{ - return MarkTaintSource(str, GetTaintOperation(nsContentUtils::GetCurrentJSContext(), name)); -} - -nsresult MarkTaintSource(nsAString &str, const char* name, const nsAString &arg) -{ - return MarkTaintSource(str, GetTaintOperation(nsContentUtils::GetCurrentJSContext(), name, arg)); -} - -nsresult MarkTaintSource(nsAString &str, const char* name, const nsTArray &arg) -{ - return MarkTaintSource(str, GetTaintOperation(nsContentUtils::GetCurrentJSContext(), name, arg)); -} - -nsresult MarkTaintSourceElement(nsAString &str, const char* name, const mozilla::dom::Element* element) -{ - return MarkTaintSource(str, GetTaintOperation(nsContentUtils::GetCurrentJSContext(), name, element)); -} - -nsresult MarkTaintSourceAttribute(nsAString &str, const char* name, const mozilla::dom::Element* element, - const nsAString &attr) -{ - return MarkTaintSource(str, GetTaintOperation(nsContentUtils::GetCurrentJSContext(), name, element, str, attr)); -} - -nsresult MarkTaintSource(mozilla::dom::DOMString &str, const char* name) -{ - return MarkTaintSource(str, GetTaintOperation(nsContentUtils::GetCurrentJSContext(), name)); -} - -nsresult MarkTaintSource(mozilla::dom::DOMString &str, const char* name, const nsAString &arg) -{ - return MarkTaintSource(str, GetTaintOperation(nsContentUtils::GetCurrentJSContext(), name, arg)); -} - -nsresult MarkTaintSource(mozilla::dom::DOMString &str, const char* name, const nsTArray &arg) -{ - return MarkTaintSource(str, GetTaintOperation(nsContentUtils::GetCurrentJSContext(), name, arg)); -} - -nsresult MarkTaintSourceElement(mozilla::dom::DOMString &str, const char* name, const mozilla::dom::Element* element) -{ - return MarkTaintSource(str, GetTaintOperation(nsContentUtils::GetCurrentJSContext(), name, element)); -} - -nsresult MarkTaintSourceAttribute(mozilla::dom::DOMString &str, const char* name, const mozilla::dom::Element* element, - const nsAString &attr) -{ - nsAutoString nsStr; - str.ToString(nsStr); - return MarkTaintSource(str, GetTaintOperation(nsContentUtils::GetCurrentJSContext(), name, element, nsStr, attr)); -} - -nsresult ReportTaintSink(JSContext *cx, const nsAString &str, const char* name, const nsAString &arg) -{ - if (!str.isTainted()) { - return NS_OK; - } - - if (!cx) { - return NS_ERROR_FAILURE; - } - - if (!nsContentUtils::IsSafeToRunScript() || !JS::CurrentGlobalOrNull(cx)) { - return NS_ERROR_FAILURE; - } - - JS::RootedValue argval(cx); - if (!mozilla::dom::ToJSValue(cx, arg, &argval)) - return NS_ERROR_FAILURE; - - JS::RootedValue strval(cx); - if (!mozilla::dom::ToJSValue(cx, str, &strval)) - return NS_ERROR_FAILURE; - - JS_ReportTaintSink(cx, strval, name, argval); - - return NS_OK; -} - -nsresult ReportTaintSink(JSContext *cx, const nsAString &str, const char* name) -{ - if (!str.isTainted()) { - return NS_OK; - } - - if (!cx) { - return NS_ERROR_FAILURE; - } - - if (!nsContentUtils::IsSafeToRunScript() || !JS::CurrentGlobalOrNull(cx)) { - return NS_ERROR_FAILURE; - } - - JS::RootedValue strval(cx); - if (!mozilla::dom::ToJSValue(cx, str, &strval)) { - return NS_ERROR_FAILURE; - } - - JS_ReportTaintSink(cx, strval, name); - - return NS_OK; -} - -nsresult ReportTaintSink(JSContext *cx, const nsACString &str, const char* name) -{ - if (!str.isTainted()) { - return NS_OK; - } - - if (!cx) { - return NS_ERROR_FAILURE; - } - - if (!nsContentUtils::IsSafeToRunScript() || !JS::CurrentGlobalOrNull(cx)) { - return NS_ERROR_FAILURE; - } - - JS::RootedValue strval(cx); - if (!mozilla::dom::ToJSValue(cx, str, &strval)) { - return NS_ERROR_FAILURE; - } - - JS_ReportTaintSink(cx, strval, name); - - return NS_OK; -} - -nsresult ReportTaintSink(const nsAString &str, const char* name, const nsAString &arg) -{ - return ReportTaintSink(nsContentUtils::GetCurrentJSContext(), str, name, arg); -} - -nsresult ReportTaintSink(const nsAString &str, const char* name) -{ - return ReportTaintSink(nsContentUtils::GetCurrentJSContext(), str, name); -} - -nsresult ReportTaintSink(const nsACString &str, const char* name) -{ - return ReportTaintSink(nsContentUtils::GetCurrentJSContext(), str, name); -} - -nsresult ReportTaintSink(JSContext* cx, JS::Handle aValue, const char* name) { - - if (!nsContentUtils::IsSafeToRunScript() || !JS::CurrentGlobalOrNull(cx)) { - return NS_ERROR_FAILURE; - } - - JS_ReportTaintSink(cx, aValue, name); - - return NS_OK; -} +template bool nsTAutoJSString::init(const JS::Value&); \ No newline at end of file diff --git a/dom/base/nsJSUtils.h b/dom/base/nsJSUtils.h index 90baf1aab9c66..b3ecdd97c1a16 100644 --- a/dom/base/nsJSUtils.h +++ b/dom/base/nsJSUtils.h @@ -263,60 +263,4 @@ using nsAutoJSString = nsTAutoJSString; // Note that this is guaranteed to be UTF-8. using nsAutoJSCString = nsTAutoJSString; -// Get a taint operation -TaintOperation GetTaintOperation(const char* name); - -// Extend the taintflow -nsresult MarkTaintOperation(nsAString &str, const char* name); -nsresult MarkTaintOperation(nsACString &str, const char* name); -nsresult MarkTaintOperation(nsAString &str, const char* name, const nsTArray &arg); -nsresult MarkTaintOperation(StringTaint& aTaint, const char* name); - -// TaintFox: Add taint source information to a string -nsresult MarkTaintSource(nsAString &str, const char* name); - -// TaintFox: Add taint source information to a string -nsresult MarkTaintSource(nsAString &str, const char* name, const nsAString &arg); - -nsresult MarkTaintSource(nsAString &str, const char* name, const nsTArray &arg); - -nsresult MarkTaintSourceElement(nsAString &str, const char* name, const mozilla::dom::Element* element); - -nsresult MarkTaintSourceAttribute(nsAString &str, const char* name, const mozilla::dom::Element* element, - const nsAString &attr); - -// TaintFox: Add taint source information to a string -nsresult MarkTaintSource(mozilla::dom::DOMString &str, const char* name); - -// TaintFox: Add taint source information to a string -nsresult MarkTaintSource(mozilla::dom::DOMString &str, const char* name, const nsAString &arg); - -nsresult MarkTaintSource(mozilla::dom::DOMString &str, const char* name, const nsTArray &arg); - -nsresult MarkTaintSourceElement(mozilla::dom::DOMString &str, const char* name, const mozilla::dom::Element* element); - -// TaintFox: Add taint source information to a string -nsresult MarkTaintSourceAttribute(mozilla::dom::DOMString &str, const char* name, const mozilla::dom::Element* element, - const nsAString &attr); - -nsresult MarkTaintSource(JSContext* aCx, JS::MutableHandle aValue, const char* name); - -nsresult MarkTaintSource(JSContext* aCx, JS::MutableHandle aValue, const char* name, const nsAString &arg); - -nsresult MarkTaintSource(JSContext* aCx, JSString* str, const char* name); - -// TaintFox: Report taint flows into DOM related sinks. -nsresult ReportTaintSink(JSContext *cx, const nsAString &str, const char* name); - -// TaintFox: Report taint flows into DOM related sinks. -nsresult ReportTaintSink(const nsAString &str, const char* name); - -nsresult ReportTaintSink(const nsACString &str, const char* name); - -nsresult ReportTaintSink(JSContext *cx, const nsAString &str, const char* name, const nsAString &arg); - -nsresult ReportTaintSink(const nsAString &str, const char* name, const nsAString &arg); - -nsresult ReportTaintSink(JSContext* cx, JS::Handle aValue, const char* name); - #endif /* nsJSUtils_h__ */ diff --git a/dom/base/nsStyledElement.cpp b/dom/base/nsStyledElement.cpp index 28e4dff4cb4be..a426014488412 100644 --- a/dom/base/nsStyledElement.cpp +++ b/dom/base/nsStyledElement.cpp @@ -29,6 +29,7 @@ #include "nsXULElement.h" #include "nsContentUtils.h" #include "nsStyleUtil.h" +#include "nsTaintingUtils.h" using namespace mozilla; using namespace mozilla::dom; @@ -58,9 +59,7 @@ bool nsStyledElement::ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute, nsresult nsStyledElement::CheckTaintSinkSetAttr(int32_t aNamespaceID, nsAtom* aName, const nsAString& aValue) { if (aNamespaceID == kNameSpaceID_None && aName == nsGkAtoms::style) { - nsAutoString id; - this->GetId(id); - ReportTaintSink(aValue, "element.style", id); + ReportTaintSink(aValue, "element.style", this); } return nsStyledElementBase::CheckTaintSinkSetAttr(aNamespaceID, aName, aValue); diff --git a/dom/events/MessageEvent.cpp b/dom/events/MessageEvent.cpp index 6740f0c71570f..fef18d4431584 100644 --- a/dom/events/MessageEvent.cpp +++ b/dom/events/MessageEvent.cpp @@ -17,6 +17,8 @@ #include "mozilla/HoldDropJSObjects.h" #include "jsapi.h" +#include "nsTaintingUtils.h" + namespace mozilla::dom { NS_IMPL_CYCLE_COLLECTION_CLASS(MessageEvent) diff --git a/dom/fetch/Fetch.cpp b/dom/fetch/Fetch.cpp index 2a541fa43f8d8..27258a47ebe13 100644 --- a/dom/fetch/Fetch.cpp +++ b/dom/fetch/Fetch.cpp @@ -27,6 +27,7 @@ #include "nsStreamUtils.h" #include "nsStringStream.h" #include "nsProxyRelease.h" +#include "nsTaintingUtils.h" #include "mozilla/ErrorResult.h" #include "mozilla/dom/BindingDeclarations.h" diff --git a/dom/html/HTMLAnchorElement.cpp b/dom/html/HTMLAnchorElement.cpp index 2fbce78d223fa..68c9a2b42021e 100644 --- a/dom/html/HTMLAnchorElement.cpp +++ b/dom/html/HTMLAnchorElement.cpp @@ -21,6 +21,7 @@ #include "mozilla/dom/Document.h" #include "nsPresContext.h" #include "nsIURI.h" +#include "nsTaintingUtils.h" #include "nsWindowSizes.h" NS_IMPL_NS_NEW_HTML_ELEMENT(Anchor) @@ -192,9 +193,7 @@ already_AddRefed HTMLAnchorElement::GetHrefURI() const { nsresult HTMLAnchorElement::CheckTaintSinkSetAttr(int32_t aNamespaceID, nsAtom* aName, const nsAString& aValue) { if (aNamespaceID == kNameSpaceID_None && aName == nsGkAtoms::href) { - nsAutoString id; - this->GetId(id); - ReportTaintSink(aValue, "a.href", id); + ReportTaintSink(aValue, "a.href", this); } return nsGenericHTMLElement::CheckTaintSinkSetAttr(aNamespaceID, aName, aValue); diff --git a/dom/html/HTMLAreaElement.cpp b/dom/html/HTMLAreaElement.cpp index f3aa5d9f422a8..b697c9eba782f 100644 --- a/dom/html/HTMLAreaElement.cpp +++ b/dom/html/HTMLAreaElement.cpp @@ -88,9 +88,7 @@ void HTMLAreaElement::UnbindFromTree(bool aNullParent) { nsresult HTMLAreaElement::CheckTaintSinkSetAttr(int32_t aNamespaceID, nsAtom* aName, const nsAString& aValue) { if (aNamespaceID == kNameSpaceID_None && aName == nsGkAtoms::href) { - nsAutoString id; - this->GetId(id); - ReportTaintSink(aValue, "area.href", id); + ReportTaintSink(aValue, "area.href", this); } return nsGenericHTMLElement::CheckTaintSinkSetAttr(aNamespaceID, aName, aValue); diff --git a/dom/html/HTMLEmbedElement.cpp b/dom/html/HTMLEmbedElement.cpp index d4648aa8e3017..ad07083be78b3 100644 --- a/dom/html/HTMLEmbedElement.cpp +++ b/dom/html/HTMLEmbedElement.cpp @@ -18,6 +18,7 @@ #include "nsIWidget.h" #include "nsContentUtils.h" #include "nsFrameLoader.h" +#include "nsTaintingUtils.h" #ifdef XP_MACOSX # include "mozilla/EventDispatcher.h" # include "mozilla/dom/Event.h" @@ -90,9 +91,7 @@ void HTMLEmbedElement::UnbindFromTree(bool aNullParent) { nsresult HTMLEmbedElement::CheckTaintSinkSetAttr(int32_t aNamespaceID, nsAtom* aName, const nsAString& aValue) { if (aNamespaceID == kNameSpaceID_None && aName == nsGkAtoms::src) { - nsAutoString id; - this->GetId(id); - ReportTaintSink(aValue, "embed.src", id); + ReportTaintSink(aValue, "embed.src", this); } return nsGenericHTMLElement::CheckTaintSinkSetAttr(aNamespaceID, aName, aValue); diff --git a/dom/html/HTMLFormElement.cpp b/dom/html/HTMLFormElement.cpp index 4048fc06c37fa..996160c703d05 100644 --- a/dom/html/HTMLFormElement.cpp +++ b/dom/html/HTMLFormElement.cpp @@ -69,6 +69,7 @@ #include "RadioNodeList.h" #include "nsLayoutUtils.h" +#include "nsTaintingUtils.h" #include "mozAutoDocUpdate.h" #include "nsIHTMLCollection.h" @@ -2189,9 +2190,7 @@ void HTMLFormElement::MaybeFireFormRemoved() { nsresult HTMLFormElement::CheckTaintSinkSetAttr(int32_t aNamespaceID, nsAtom* aName, const nsAString& aValue) { if (aNamespaceID == kNameSpaceID_None && aName == nsGkAtoms::action) { - nsAutoString id; - this->GetId(id); - ReportTaintSink(aValue, "form.action", id); + ReportTaintSink(aValue, "form.action", this); } return nsGenericHTMLElement::CheckTaintSinkSetAttr(aNamespaceID, aName, aValue); diff --git a/dom/html/HTMLIFrameElement.cpp b/dom/html/HTMLIFrameElement.cpp index 45228fccffb5f..687512e57af86 100644 --- a/dom/html/HTMLIFrameElement.cpp +++ b/dom/html/HTMLIFrameElement.cpp @@ -20,6 +20,7 @@ #include "nsContentUtils.h" #include "nsSandboxFlags.h" #include "nsNetUtil.h" +#include "nsTaintingUtils.h" NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(IFrame) @@ -156,13 +157,9 @@ nsMapRuleToAttributesFunc HTMLIFrameElement::GetAttributeMappingFunction() nsresult HTMLIFrameElement::CheckTaintSinkSetAttr(int32_t aNamespaceID, nsAtom* aName, const nsAString& aValue) { if (aNamespaceID == kNameSpaceID_None && aName == nsGkAtoms::src) { - nsAutoString id; - this->GetId(id); - ReportTaintSink(aValue, "iframe.src", id); + ReportTaintSink(aValue, "iframe.src", this); } else if (aNamespaceID == kNameSpaceID_None && aName == nsGkAtoms::srcdoc) { - nsAutoString id; - this->GetId(id); - ReportTaintSink(aValue, "iframe.srcdoc", id); + ReportTaintSink(aValue, "iframe.srcdoc", this); } return nsGenericHTMLElement::CheckTaintSinkSetAttr(aNamespaceID, aName, aValue); diff --git a/dom/html/HTMLImageElement.cpp b/dom/html/HTMLImageElement.cpp index 3dbc3c608ac12..a0424fc004528 100644 --- a/dom/html/HTMLImageElement.cpp +++ b/dom/html/HTMLImageElement.cpp @@ -50,6 +50,7 @@ #include "mozilla/RestyleManager.h" #include "nsLayoutUtils.h" +#include "nsTaintingUtils.h" using namespace mozilla::net; using mozilla::Maybe; @@ -300,9 +301,7 @@ nsresult HTMLImageElement::CheckTaintSinkSetAttr(int32_t aNamespaceID, nsAtom* a (aName == nsGkAtoms::src || aName == nsGkAtoms::srcset)) { // Taintfox: img.src / img.srcset sink const char* sink = (aName == nsGkAtoms::src) ? "img.src" : "img.srcset"; - nsAutoString id; - this->GetId(id); - ReportTaintSink(aValue, sink, id); + ReportTaintSink(aValue, sink, this); } return nsGenericHTMLElement::CheckTaintSinkSetAttr(aNamespaceID, aName, aValue); diff --git a/dom/html/HTMLInputElement.cpp b/dom/html/HTMLInputElement.cpp index 64790f778c67c..7094b834c22a1 100644 --- a/dom/html/HTMLInputElement.cpp +++ b/dom/html/HTMLInputElement.cpp @@ -74,6 +74,7 @@ #include "nsReadableUtils.h" #include "nsUnicharUtils.h" #include "nsLayoutUtils.h" +#include "nsTaintingUtils.h" #include "nsVariant.h" #include "mozilla/ContentEvents.h" diff --git a/dom/html/HTMLMediaElement.cpp b/dom/html/HTMLMediaElement.cpp index 74df6c859b7e3..6bbb16b9dbd61 100644 --- a/dom/html/HTMLMediaElement.cpp +++ b/dom/html/HTMLMediaElement.cpp @@ -129,6 +129,7 @@ #include "nsQueryObject.h" #include "nsRange.h" #include "nsSize.h" +#include "nsTaintingUtils.h" #include "nsThreadUtils.h" #include "nsURIHashKey.h" #include "nsURLHelper.h" @@ -4743,9 +4744,7 @@ int32_t HTMLMediaElement::TabIndexDefault() { return 0; } nsresult HTMLMediaElement::CheckTaintSinkSetAttr(int32_t aNamespaceID, nsAtom* aName, const nsAString& aValue) { if (aNamespaceID == kNameSpaceID_None && aName == nsGkAtoms::src) { - nsAutoString id; - this->GetId(id); - ReportTaintSink(aValue, "media.src", id); + ReportTaintSink(aValue, "media.src", this); } return nsGenericHTMLElement::CheckTaintSinkSetAttr(aNamespaceID, aName, aValue); diff --git a/dom/html/HTMLObjectElement.cpp b/dom/html/HTMLObjectElement.cpp index b69e3adcf8fe8..82c4a0eda9707 100644 --- a/dom/html/HTMLObjectElement.cpp +++ b/dom/html/HTMLObjectElement.cpp @@ -19,6 +19,7 @@ #include "nsIContentInlines.h" #include "nsIWidget.h" #include "nsContentUtils.h" +#include "nsTaintingUtils.h" #ifdef XP_MACOSX # include "mozilla/EventDispatcher.h" # include "mozilla/dom/Event.h" @@ -115,9 +116,7 @@ void HTMLObjectElement::UnbindFromTree(bool aNullParent) { nsresult HTMLObjectElement::CheckTaintSinkSetAttr(int32_t aNamespaceID, nsAtom* aName, const nsAString& aValue) { if (aNamespaceID == kNameSpaceID_None && aName == nsGkAtoms::data) { - nsAutoString id; - this->GetId(id); - ReportTaintSink(aValue, "object.data", id); + ReportTaintSink(aValue, "object.data", this); } return nsGenericHTMLElement::CheckTaintSinkSetAttr(aNamespaceID, aName, aValue); diff --git a/dom/html/HTMLScriptElement.cpp b/dom/html/HTMLScriptElement.cpp index 04c7b3d64db7f..b34da05792e1b 100644 --- a/dom/html/HTMLScriptElement.cpp +++ b/dom/html/HTMLScriptElement.cpp @@ -22,6 +22,7 @@ #include "nsDOMJSUtils.h" #include "nsIScriptError.h" #include "nsISupportsImpl.h" +#include "nsTaintingUtils.h" #include "mozilla/dom/HTMLScriptElement.h" #include "mozilla/dom/HTMLScriptElementBinding.h" #include "mozilla/StaticPrefs_dom.h" @@ -106,9 +107,7 @@ nsresult HTMLScriptElement::Clone(dom::NodeInfo* aNodeInfo, nsresult HTMLScriptElement::CheckTaintSinkSetAttr(int32_t aNamespaceID, nsAtom* aName, const nsAString& aValue) { if (aNamespaceID == kNameSpaceID_None && aName == nsGkAtoms::src) { - nsAutoString id; - this->GetId(id); - ReportTaintSink(aValue, "script.src", id); + ReportTaintSink(aValue, "script.src", this); } return nsGenericHTMLElement::CheckTaintSinkSetAttr(aNamespaceID, aName, aValue); @@ -145,9 +144,7 @@ void HTMLScriptElement::SetInnerHTML(const nsAString& aInnerHTML, ErrorResult& aError) { aError = nsContentUtils::SetNodeTextContent(this, aInnerHTML, true); // Taintfox: script.innerHTML sink - nsAutoString id; - this->GetId(id); - ReportTaintSink(aInnerHTML, "script.innerHTML", id); + ReportTaintSink(aInnerHTML, "script.innerHTML", this); } void HTMLScriptElement::GetText(nsAString& aValue, ErrorResult& aRv) const { @@ -159,9 +156,7 @@ void HTMLScriptElement::GetText(nsAString& aValue, ErrorResult& aRv) const { void HTMLScriptElement::SetText(const nsAString& aValue, ErrorResult& aRv) { aRv = nsContentUtils::SetNodeTextContent(this, aValue, true); // Taintfox: script.text sink - nsAutoString id; - this->GetId(id); - ReportTaintSink(aValue, "script.text", id); + ReportTaintSink(aValue, "script.text", this); } // variation of this code in SVGScriptElement - check if changes @@ -249,9 +244,7 @@ bool HTMLScriptElement::Supports(const GlobalObject& aGlobal, void HTMLScriptElement::SetTextContentInternal(const nsAString& aTextContent, nsIPrincipal* aScriptedPrincipal, ErrorResult& aError) { - nsAutoString id; - this->GetId(id); - ReportTaintSink(aTextContent, "script.textContent", id); + ReportTaintSink(aTextContent, "script.textContent", this); aError = nsContentUtils::SetNodeTextContent(this, aTextContent, true); } } // namespace mozilla::dom diff --git a/dom/html/HTMLSourceElement.cpp b/dom/html/HTMLSourceElement.cpp index 0e7ea3e5be14a..c2bfd57b867e9 100644 --- a/dom/html/HTMLSourceElement.cpp +++ b/dom/html/HTMLSourceElement.cpp @@ -79,9 +79,7 @@ nsresult HTMLSourceElement::CheckTaintSinkSetAttr(int32_t aNamespaceID, nsAtom* (aName == nsGkAtoms::src || aName == nsGkAtoms::srcset)) { // Taintfox: img.src / img.srcset sink const char* sink = (aName == nsGkAtoms::src) ? "source.src" : "source.srcset"; - nsAutoString id; - this->GetId(id); - ReportTaintSink(aValue, sink, id); + ReportTaintSink(aValue, sink, this); } return nsGenericHTMLElement::CheckTaintSinkSetAttr(aNamespaceID, aName, aValue); diff --git a/dom/html/HTMLTrackElement.cpp b/dom/html/HTMLTrackElement.cpp index 759afb4cff4bb..0458d5f4c042e 100644 --- a/dom/html/HTMLTrackElement.cpp +++ b/dom/html/HTMLTrackElement.cpp @@ -33,6 +33,7 @@ #include "nsISupportsPrimitives.h" #include "nsNetUtil.h" #include "nsStyleConsts.h" +#include "nsTaintingUtils.h" #include "nsThreadUtils.h" #include "nsVideoFrame.h" @@ -493,9 +494,7 @@ void HTMLTrackElement::CancelChannelAndListener() { nsresult HTMLTrackElement::CheckTaintSinkSetAttr(int32_t aNamespaceID, nsAtom* aName, const nsAString& aValue) { if (aNamespaceID == kNameSpaceID_None && aName == nsGkAtoms::src) { - nsAutoString id; - this->GetId(id); - ReportTaintSink(aValue, "track.src", id); + ReportTaintSink(aValue, "track.src", this); } return nsGenericHTMLElement::CheckTaintSinkSetAttr(aNamespaceID, aName, aValue); diff --git a/dom/localstorage/LSObject.cpp b/dom/localstorage/LSObject.cpp index 6258ae7481338..cfed388c4ef30 100644 --- a/dom/localstorage/LSObject.cpp +++ b/dom/localstorage/LSObject.cpp @@ -50,6 +50,7 @@ #include "nsString.h" #include "nsTArray.h" #include "nsTStringRepr.h" +#include "nsTaintingUtils.h" #include "nsThread.h" #include "nsThreadUtils.h" #include "nsXULAppAPI.h" diff --git a/dom/moz.build b/dom/moz.build index 5a3b2d26d3477..56140a71b361d 100644 --- a/dom/moz.build +++ b/dom/moz.build @@ -96,6 +96,7 @@ DIRS += [ "xhr", "worklet", "script", + "tainting", "payments", "websocket", "serializers", diff --git a/dom/push/PushSubscription.cpp b/dom/push/PushSubscription.cpp index ea513fcaa5a32..fd336b2d70f31 100644 --- a/dom/push/PushSubscription.cpp +++ b/dom/push/PushSubscription.cpp @@ -10,6 +10,7 @@ #include "nsIPushService.h" #include "nsIScriptObjectPrincipal.h" #include "nsServiceManagerUtils.h" +#include "nsTaintingUtils.h" #include "mozilla/Base64.h" #include "mozilla/Unused.h" diff --git a/dom/script/ScriptElement.cpp b/dom/script/ScriptElement.cpp index 7c1b06d20ed32..aee47e9e27a0e 100644 --- a/dom/script/ScriptElement.cpp +++ b/dom/script/ScriptElement.cpp @@ -18,6 +18,7 @@ #include "nsIParser.h" #include "nsGkAtoms.h" #include "nsContentSink.h" +#include "nsTaintingUtils.h" using namespace mozilla; using namespace mozilla::dom; diff --git a/dom/serviceworkers/ServiceWorkerEvents.cpp b/dom/serviceworkers/ServiceWorkerEvents.cpp index 396e1f1a282cb..ad7c952a6dcb0 100644 --- a/dom/serviceworkers/ServiceWorkerEvents.cpp +++ b/dom/serviceworkers/ServiceWorkerEvents.cpp @@ -47,6 +47,7 @@ #include "nsSerializationHelper.h" #include "nsServiceManagerUtils.h" #include "nsStreamUtils.h" +#include "nsTaintingUtils.h" #include "xpcpublic.h" using namespace mozilla; diff --git a/dom/storage/LocalStorage.cpp b/dom/storage/LocalStorage.cpp index 492da60aa547c..fb5b0d69e805f 100644 --- a/dom/storage/LocalStorage.cpp +++ b/dom/storage/LocalStorage.cpp @@ -23,6 +23,7 @@ #include "mozilla/Preferences.h" #include "mozilla/EnumSet.h" #include "nsJSUtils.h" +#include "nsTaintingUtils.h" #include "nsThreadUtils.h" #include "nsContentUtils.h" #include "nsServiceManagerUtils.h" diff --git a/dom/storage/PartitionedLocalStorage.cpp b/dom/storage/PartitionedLocalStorage.cpp index f7a8e3bfaaabc..53f4fad4f1534 100644 --- a/dom/storage/PartitionedLocalStorage.cpp +++ b/dom/storage/PartitionedLocalStorage.cpp @@ -10,6 +10,7 @@ #include "PartitionedLocalStorage.h" #include "SessionStorageCache.h" #include "nsContentUtils.h" +#include "nsTaintingUtils.h" #include "mozilla/dom/StorageBinding.h" diff --git a/dom/storage/SessionStorage.cpp b/dom/storage/SessionStorage.cpp index 694fd371607a0..16ba3fe7a68a3 100644 --- a/dom/storage/SessionStorage.cpp +++ b/dom/storage/SessionStorage.cpp @@ -17,6 +17,7 @@ #include "nsContentUtils.h" #include "nsIPrincipal.h" #include "nsPIDOMWindow.h" +#include "nsTaintingUtils.h" #include "nsThreadUtils.h" namespace mozilla::dom { diff --git a/dom/tainting/moz.build b/dom/tainting/moz.build new file mode 100644 index 0000000000000..d5e1aacebf290 --- /dev/null +++ b/dom/tainting/moz.build @@ -0,0 +1,22 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + + +EXPORTS += [ + "nsTaintingUtils.h" +] + +UNIFIED_SOURCES += [ + "nsTaintingUtils.cpp" +] + +LOCAL_INCLUDES += [ + "/dom/base", +] + +include("/ipc/chromium/chromium-config.mozbuild") + +FINAL_LIBRARY = "xul" diff --git a/dom/tainting/nsTaintingUtils.cpp b/dom/tainting/nsTaintingUtils.cpp new file mode 100644 index 0000000000000..4628e311e7077 --- /dev/null +++ b/dom/tainting/nsTaintingUtils.cpp @@ -0,0 +1,442 @@ +/* -*- 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/. */ +/* + * Modifications Copyright SAP SE. 2019-2021. All rights reserved. + */ + +#include "nsTaintingUtils.h" + +#include +#include +#include "jsfriendapi.h" +#include "mozilla/dom/ToJSValue.h" +#include "nsContentUtils.h" +#include "nsString.h" +#include "mozilla/Logging.h" +#include "mozilla/Preferences.h" + +#if !defined(DEBUG) && !defined(MOZ_ENABLE_JS_DUMP) +# include "mozilla/StaticPrefs_browser.h" +#endif + +using namespace mozilla; +using namespace mozilla::dom; + +#define PREFERENCES_TAINTING "tainting." +#define PREFERENCES_TAINTING_ACTIVE PREFERENCES_TAINTING "active" +#define PREFERENCES_TAINTING_SOURCE PREFERENCES_TAINTING "source." +#define PREFERENCES_TAINTING_SINK PREFERENCES_TAINTING "sink." + +static LazyLogModule gTaintLog("Taint"); + +inline bool isActive(const char* name) { + return Preferences::GetBool(PREFERENCES_TAINTING_ACTIVE, true) && Preferences::GetBool(name, true); +} + +inline bool isSinkActive(const char* name) { + std::string s(PREFERENCES_TAINTING_SINK); + s.append(name); + return isActive(s.c_str()); +} + +inline bool isSourceActive(const char* name) { + std::string s(PREFERENCES_TAINTING_SOURCE); + s.append(name); + return isActive(s.c_str()); +} + + +static TaintOperation GetTaintOperation(JSContext *cx, const char* name) +{ + if (cx) { + return JS_GetTaintOperation(cx, name); + } + + return TaintOperation(name); +} + +static TaintOperation GetTaintOperation(JSContext *cx, const char* name, const nsAString& arg) +{ + if (cx && JS::CurrentGlobalOrNull(cx)) { + JS::RootedValue argval(cx); + if (mozilla::dom::ToJSValue(cx, arg, &argval)) { + return JS_GetTaintOperation(cx, name, argval); + } + } + + return TaintOperation(name); +} + +static TaintOperation GetTaintOperation(JSContext *cx, const char* name, const nsTArray &args) +{ + if (cx && JS::CurrentGlobalOrNull(cx)) { + JS::RootedValue argval(cx); + + if (mozilla::dom::ToJSValue(cx, args, &argval)) { + return JS_GetTaintOperation(cx, name, argval); + } + } + + return TaintOperation(name); +} + +static TaintOperation GetTaintOperation(JSContext *cx, const char* name, const mozilla::dom::Element* element) +{ + if (element) { + nsTArray args; + nsAutoString elementDesc; + + element->Describe(elementDesc); + args.AppendElement(elementDesc); + + return GetTaintOperation(cx, name, args); + } + + return TaintOperation(name); +} + +static TaintOperation GetTaintOperation(JSContext *cx, const char* name, const mozilla::dom::Element* element, + const nsAString &str, const nsAString &attr) +{ + if (element) { + nsTArray args; + + nsAutoString elementDesc; + element->Describe(elementDesc); + args.AppendElement(elementDesc); + + nsAutoString attributeName; + attributeName.Append(attr); + attributeName.AppendLiteral("=\""); + nsAutoString value; + value.Append(str); + for (uint32_t i = value.Length(); i > 0; --i) { + if (value[i - 1] == char16_t('"')) value.Insert(char16_t('\\'), i - 1); + } + attributeName.Append(value); + attributeName.Append('"'); + args.AppendElement(attributeName); + + return GetTaintOperation(cx, name, args); + } + + return TaintOperation(name); +} + +TaintOperation GetTaintOperation(const char* name) +{ + return GetTaintOperation(nsContentUtils::GetCurrentJSContext(), name); +} + +nsresult MarkTaintOperation(StringTaint& aTaint, const char* name) { + JSContext *cx = nsContentUtils::GetCurrentJSContext(); + auto op = GetTaintOperation(cx, name); + op.set_native(); + aTaint.extend(op); + return NS_OK; +} + +static nsresult MarkTaintOperation(JSContext *cx, nsACString &str, const char* name) +{ + if (str.isTainted()) { + auto op = GetTaintOperation(cx, name); + op.set_native(); + str.Taint().extend(op); + } + return NS_OK; +} + +nsresult MarkTaintOperation(nsACString &str, const char* name) +{ + return MarkTaintOperation(nsContentUtils::GetCurrentJSContext(), str, name); +} + +static nsresult MarkTaintOperation(JSContext *cx, nsAString &str, const char* name) +{ + if (str.isTainted()) { + auto op = GetTaintOperation(cx, name); + op.set_native(); + str.Taint().extend(op); + } + return NS_OK; +} + +nsresult MarkTaintOperation(nsAString &str, const char* name) +{ + return MarkTaintOperation(nsContentUtils::GetCurrentJSContext(), str, name); +} + +static nsresult MarkTaintOperation(JSContext *cx, nsAString &str, const char* name, const nsTArray &args) +{ + if (str.isTainted()) { + auto op = GetTaintOperation(cx, name, args); + op.set_native(); + str.Taint().extend(op); + } + return NS_OK; +} + +nsresult MarkTaintOperation(nsAString &str, const char* name, const nsTArray &args) +{ + return MarkTaintOperation(nsContentUtils::GetCurrentJSContext(), str, name, args); +} + +static nsresult MarkTaintSource(nsAString &str, TaintOperation operation) { + operation.setSource(); + operation.set_native(); + str.Taint().overlay(0, str.Length(), operation); + return NS_OK; +} + +static nsresult MarkTaintSource(mozilla::dom::DOMString &str, TaintOperation operation) { + operation.setSource(); + operation.set_native(); + str.Taint().overlay(0, str.Length(), operation); + return NS_OK; +} + +nsresult MarkTaintSource(JSContext* cx, JSString* str, const char* name) +{ + if (isSourceActive(name)) { + TaintOperation op = GetTaintOperation(cx, name); + op.setSource(); + op.set_native(); + JS_MarkTaintSource(cx, str, op); + } + return NS_OK; +} + +nsresult MarkTaintSource(JSContext* cx, JS::MutableHandle aValue, const char* name) +{ + if (isSourceActive(name)) { + TaintOperation op = GetTaintOperation(cx, name); + op.setSource(); + op.set_native(); + JS_MarkTaintSource(cx, aValue, op); + } + return NS_OK; +} + +nsresult MarkTaintSource(JSContext* cx, JS::MutableHandle aValue, const char* name, const nsAString &arg) +{ + if (isSourceActive(name)) { + TaintOperation op = GetTaintOperation(cx, name, arg); + op.setSource(); + op.set_native(); + JS_MarkTaintSource(cx, aValue, op); + } + return NS_OK; +} + +nsresult MarkTaintSource(nsAString &str, const char* name) +{ + if (isSourceActive(name)) { + return MarkTaintSource(str, GetTaintOperation(nsContentUtils::GetCurrentJSContext(), name)); + } + return NS_OK; +} + +nsresult MarkTaintSource(nsAString &str, const char* name, const nsAString &arg) +{ + if (isSourceActive(name)) { + return MarkTaintSource(str, GetTaintOperation(nsContentUtils::GetCurrentJSContext(), name, arg)); + } + return NS_OK; +} + +nsresult MarkTaintSource(nsAString &str, const char* name, const nsTArray &arg) +{ + if (isSourceActive(name)) { + return MarkTaintSource(str, GetTaintOperation(nsContentUtils::GetCurrentJSContext(), name, arg)); + } + return NS_OK; +} + +nsresult MarkTaintSourceElement(nsAString &str, const char* name, const mozilla::dom::Element* element) +{ + if (isSourceActive(name)) { + return MarkTaintSource(str, GetTaintOperation(nsContentUtils::GetCurrentJSContext(), name, element)); + } + return NS_OK; +} + +nsresult MarkTaintSourceAttribute(nsAString &str, const char* name, const mozilla::dom::Element* element, + const nsAString &attr) +{ + if (isSourceActive(name)) { + return MarkTaintSource(str, GetTaintOperation(nsContentUtils::GetCurrentJSContext(), name, element, str, attr)); + } + return NS_OK; +} + +nsresult MarkTaintSource(mozilla::dom::DOMString &str, const char* name) +{ + if (isSourceActive(name)) { + return MarkTaintSource(str, GetTaintOperation(nsContentUtils::GetCurrentJSContext(), name)); + } + return NS_OK; +} + +nsresult MarkTaintSource(mozilla::dom::DOMString &str, const char* name, const nsAString &arg) +{ + if (isSourceActive(name)) { + return MarkTaintSource(str, GetTaintOperation(nsContentUtils::GetCurrentJSContext(), name, arg)); + } + return NS_OK; +} + +nsresult MarkTaintSource(mozilla::dom::DOMString &str, const char* name, const nsTArray &arg) +{ + if (isSourceActive(name)) { + return MarkTaintSource(str, GetTaintOperation(nsContentUtils::GetCurrentJSContext(), name, arg)); + } + return NS_OK; +} + +nsresult MarkTaintSourceElement(mozilla::dom::DOMString &str, const char* name, const mozilla::dom::Element* element) +{ + if (isSourceActive(name)) { + return MarkTaintSource(str, GetTaintOperation(nsContentUtils::GetCurrentJSContext(), name, element)); + } + return NS_OK; +} + +nsresult MarkTaintSourceAttribute(mozilla::dom::DOMString &str, const char* name, const mozilla::dom::Element* element, + const nsAString &attr) +{ + if (isSourceActive(name)) { + nsAutoString nsStr; + str.ToString(nsStr); + return MarkTaintSource(str, GetTaintOperation(nsContentUtils::GetCurrentJSContext(), name, element, nsStr, attr)); + } + return NS_OK; +} + +nsresult ReportTaintSink(JSContext *cx, const nsAString &str, const char* name, const nsAString &arg) +{ + if (!str.isTainted()) { + return NS_OK; + } + + if (!cx) { + return NS_ERROR_FAILURE; + } + + if (!nsContentUtils::IsSafeToRunScript() || !JS::CurrentGlobalOrNull(cx)) { + return NS_ERROR_FAILURE; + } + + if (!isSinkActive(name)) { + return NS_OK; + } + + JS::RootedValue argval(cx); + if (!mozilla::dom::ToJSValue(cx, arg, &argval)) + return NS_ERROR_FAILURE; + + JS::RootedValue strval(cx); + if (!mozilla::dom::ToJSValue(cx, str, &strval)) + return NS_ERROR_FAILURE; + + JS_ReportTaintSink(cx, strval, name, argval); + + return NS_OK; +} + +nsresult ReportTaintSink(JSContext *cx, const nsAString &str, const char* name) +{ + if (!str.isTainted()) { + return NS_OK; + } + + if (!cx) { + return NS_ERROR_FAILURE; + } + + if (!nsContentUtils::IsSafeToRunScript() || !JS::CurrentGlobalOrNull(cx)) { + return NS_ERROR_FAILURE; + } + + if (!isSinkActive(name)) { + return NS_OK; + } + + JS::RootedValue strval(cx); + if (!mozilla::dom::ToJSValue(cx, str, &strval)) { + return NS_ERROR_FAILURE; + } + + JS_ReportTaintSink(cx, strval, name); + + return NS_OK; +} + +nsresult ReportTaintSink(JSContext *cx, const nsACString &str, const char* name) +{ + if (!str.isTainted()) { + return NS_OK; + } + + if (!cx) { + return NS_ERROR_FAILURE; + } + + if (!nsContentUtils::IsSafeToRunScript() || !JS::CurrentGlobalOrNull(cx)) { + return NS_ERROR_FAILURE; + } + + if (!isSinkActive(name)) { + return NS_OK; + } + + JS::RootedValue strval(cx); + if (!mozilla::dom::ToJSValue(cx, str, &strval)) { + return NS_ERROR_FAILURE; + } + + JS_ReportTaintSink(cx, strval, name); + + return NS_OK; +} + +nsresult ReportTaintSink(const nsAString &str, const char* name, const nsAString &arg) +{ + return ReportTaintSink(nsContentUtils::GetCurrentJSContext(), str, name, arg); +} + +nsresult ReportTaintSink(const nsAString &str, const char* name, const mozilla::dom::Element* element) +{ + nsAutoString elementDesc; + if (element) { + element->Describe(elementDesc); + } + return ReportTaintSink(str, name, elementDesc); +} + +nsresult ReportTaintSink(const nsAString &str, const char* name) +{ + return ReportTaintSink(nsContentUtils::GetCurrentJSContext(), str, name); +} + +nsresult ReportTaintSink(const nsACString &str, const char* name) +{ + return ReportTaintSink(nsContentUtils::GetCurrentJSContext(), str, name); +} + +nsresult ReportTaintSink(JSContext* cx, JS::Handle aValue, const char* name) { + + if (!nsContentUtils::IsSafeToRunScript() || !JS::CurrentGlobalOrNull(cx)) { + return NS_ERROR_FAILURE; + } + + if (!isSinkActive(name)) { + return NS_OK; + } + + JS_ReportTaintSink(cx, aValue, name); + + return NS_OK; +} diff --git a/dom/tainting/nsTaintingUtils.h b/dom/tainting/nsTaintingUtils.h new file mode 100644 index 0000000000000..e342cb7863696 --- /dev/null +++ b/dom/tainting/nsTaintingUtils.h @@ -0,0 +1,86 @@ +/* -*- 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/. */ +/* + * Modifications Copyright SAP SE. 2019-2021. All rights reserved. + */ + +#ifndef nsTaintingUtils_h__ +#define nsTaintingUtils_h__ + +/** + * This is not a generated file. It contains common utility functions + * invoked from the JavaScript code generated from IDL interfaces. + * The goal of the utility functions is to cut down on the size of + * the generated code itself. + */ + +#include "mozilla/dom/DOMString.h" +#include "jsapi.h" + +#include "mozilla/dom/Element.h" + +#include "nsString.h" + + +// Get a taint operation +TaintOperation GetTaintOperation(const char* name); + +// Extend the taintflow +nsresult MarkTaintOperation(nsAString &str, const char* name); +nsresult MarkTaintOperation(nsACString &str, const char* name); +nsresult MarkTaintOperation(nsAString &str, const char* name, const nsTArray &arg); +nsresult MarkTaintOperation(StringTaint& aTaint, const char* name); + +// TaintFox: Add taint source information to a string +nsresult MarkTaintSource(nsAString &str, const char* name); + +// TaintFox: Add taint source information to a string +nsresult MarkTaintSource(nsAString &str, const char* name, const nsAString &arg); + +nsresult MarkTaintSource(nsAString &str, const char* name, const nsTArray &arg); + +nsresult MarkTaintSourceElement(nsAString &str, const char* name, const mozilla::dom::Element* element); + +nsresult MarkTaintSourceAttribute(nsAString &str, const char* name, const mozilla::dom::Element* element, + const nsAString &attr); + +// TaintFox: Add taint source information to a string +nsresult MarkTaintSource(mozilla::dom::DOMString &str, const char* name); + +// TaintFox: Add taint source information to a string +nsresult MarkTaintSource(mozilla::dom::DOMString &str, const char* name, const nsAString &arg); + +nsresult MarkTaintSource(mozilla::dom::DOMString &str, const char* name, const nsTArray &arg); + +nsresult MarkTaintSourceElement(mozilla::dom::DOMString &str, const char* name, const mozilla::dom::Element* element); + +// TaintFox: Add taint source information to a string +nsresult MarkTaintSourceAttribute(mozilla::dom::DOMString &str, const char* name, const mozilla::dom::Element* element, + const nsAString &attr); + +nsresult MarkTaintSource(JSContext* aCx, JS::MutableHandle aValue, const char* name); + +nsresult MarkTaintSource(JSContext* aCx, JS::MutableHandle aValue, const char* name, const nsAString &arg); + +nsresult MarkTaintSource(JSContext* aCx, JSString* str, const char* name); + +// TaintFox: Report taint flows into DOM related sinks. +nsresult ReportTaintSink(JSContext *cx, const nsAString &str, const char* name); + +// TaintFox: Report taint flows into DOM related sinks. +nsresult ReportTaintSink(const nsAString &str, const char* name); + +nsresult ReportTaintSink(const nsAString &str, const char* name, const mozilla::dom::Element* element); + +nsresult ReportTaintSink(const nsACString &str, const char* name); + +nsresult ReportTaintSink(JSContext *cx, const nsAString &str, const char* name, const nsAString &arg); + +nsresult ReportTaintSink(const nsAString &str, const char* name, const nsAString &arg); + +nsresult ReportTaintSink(JSContext* cx, JS::Handle aValue, const char* name); + +#endif /* nsTaintingUtils_h__ */ diff --git a/dom/url/URL.cpp b/dom/url/URL.cpp index d23b22a9ff68a..986bd36232021 100644 --- a/dom/url/URL.cpp +++ b/dom/url/URL.cpp @@ -21,6 +21,7 @@ #include "nsIURIMutator.h" #include "nsJSUtils.h" #include "nsNetUtil.h" +#include "nsTaintingUtils.h" namespace mozilla::dom { diff --git a/dom/websocket/WebSocket.cpp b/dom/websocket/WebSocket.cpp index 2d4861a600439..5bfdb3d4a4a7b 100644 --- a/dom/websocket/WebSocket.cpp +++ b/dom/websocket/WebSocket.cpp @@ -51,6 +51,7 @@ #include "mozilla/dom/CloseEvent.h" #include "mozilla/net/WebSocketEventService.h" #include "nsJSUtils.h" +#include "nsTaintingUtils.h" #include "nsIScriptError.h" #include "nsNetUtil.h" #include "nsIAuthPrompt.h" diff --git a/dom/xhr/XMLHttpRequestMainThread.cpp b/dom/xhr/XMLHttpRequestMainThread.cpp index b5d5e6afc7464..42321d8613aae 100644 --- a/dom/xhr/XMLHttpRequestMainThread.cpp +++ b/dom/xhr/XMLHttpRequestMainThread.cpp @@ -55,6 +55,7 @@ #include "nsLayoutCID.h" #include "nsReadableUtils.h" #include "nsSandboxFlags.h" +#include "nsTaintingUtils.h" #include "nsIURI.h" #include "nsIURIMutator.h" diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 8f92fb16b6643..47a1f9f5a4144 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -4031,3 +4031,102 @@ pref("dom.sitepermsaddon-provider.separatedBlocklistedDomains", "shopee.co.th,sh // Log level for logger in URLQueryStrippingListService pref("privacy.query_stripping.listService.logLevel", "Error"); + + +// Tainting Preferences +// All preferences related to taint-tracking + + +// Sources and sinks are all active by default, the idea here is to provide a complete +// list for users to disable to suit their needs. + +// Add a single switch to disable tainting completely +pref("tainting.active", true); + +// Sources +pref("tainting.source.MessageEvent", true); +pref("tainting.source.PushMessageData", true); +pref("tainting.source.PushSubscription.endpoint", true); +pref("tainting.source.WebSocket.MessageEvent.data", true); +pref("tainting.source.XMLHttpRequest.response", true); +pref("tainting.source.document.baseURI", true); +pref("tainting.source.document.cookie", true); +pref("tainting.source.document.documentURI", true); +pref("tainting.source.document.referrer", true); +pref("tainting.source.element.getAttribute", true); +pref("tainting.source.element.getAttributeNS", true); +pref("tainting.source.input.value", true); +pref("tainting.source.localStorage.getItem", true); +pref("tainting.source.location.hash", true); +pref("tainting.source.location.host", true); +pref("tainting.source.location.hostname", true); +pref("tainting.source.location.href", true); +pref("tainting.source.location.origin", true); +pref("tainting.source.location.pathname", true); +pref("tainting.source.location.port", true); +pref("tainting.source.location.protocol", true); +pref("tainting.source.location.search", true); +pref("tainting.source.script.innerHTML", true); +pref("tainting.source.sessionStorage.getItem", true); +pref("tainting.source.window.name", true); + +// Sinks +pref("tainting.sink.EventSource", true); +pref("tainting.sink.Function.ctor", true); +pref("tainting.sink.Range.createContextualFragment(fragment)", true); +pref("tainting.sink.WebSocket", true); +pref("tainting.sink.WebSocket.send", true); +pref("tainting.sink.XMLHttpRequest.open(password)", true); +pref("tainting.sink.XMLHttpRequest.open(url)", true); +pref("tainting.sink.XMLHttpRequest.open(username)", true); +pref("tainting.sink.XMLHttpRequest.send", true); +pref("tainting.sink.XMLHttpRequest.setRequestHeader(name)", true); +pref("tainting.sink.XMLHttpRequest.setRequestHeader(value)", true); +pref("tainting.sink.a.href", true); +pref("tainting.sink.area.href", true); +pref("tainting.sink.document.cookie", true); +pref("tainting.sink.document.writeln", true); +pref("tainting.sink.document.write", true); +pref("tainting.sink.element.style", true); +pref("tainting.sink.embed.src", true); +pref("tainting.sink.eval", true); +pref("tainting.sink.eventHandler", true); +pref("tainting.sink.fetch.body", true); +pref("tainting.sink.fetch.url", true); +pref("tainting.sink.form.action", true); +pref("tainting.sink.iframe.src", true); +pref("tainting.sink.iframe.srcdoc", true); +pref("tainting.sink.img.src", true); +pref("tainting.sink.img.srcset", true); +pref("tainting.sink.innerHTML", true); +pref("tainting.sink.insertAdjacentHTML", true); +pref("tainting.sink.insertAdjacentText", true); +pref("tainting.sink.localStorage.setItem", true); +pref("tainting.sink.localStorage.setItem(key)", true); +pref("tainting.sink.location.assign", true); +pref("tainting.sink.location.hash", true); +pref("tainting.sink.location.host", true); +pref("tainting.sink.location.href", true); +pref("tainting.sink.location.pathname", true); +pref("tainting.sink.location.port", true); +pref("tainting.sink.location.protocol", true); +pref("tainting.sink.location.replace", true); +pref("tainting.sink.location.search", true); +pref("tainting.sink.media.src", true); +pref("tainting.sink.navigator.sendBeacon(body)", true); +pref("tainting.sink.navigator.sendBeacon(url)", true); +pref("tainting.sink.object.data", true); +pref("tainting.sink.outerHTML", true); +pref("tainting.sink.script.innerHTML", true); +pref("tainting.sink.script.src", true); +pref("tainting.sink.script.text", true); +pref("tainting.sink.script.textContent", true); +pref("tainting.sink.sessionStorage.setItem", true); +pref("tainting.sink.sessionStorage.setItem(key)", true); +pref("tainting.sink.setInterval", true); +pref("tainting.sink.setTimeout", true); +pref("tainting.sink.source", true); +pref("tainting.sink.srcset", true); +pref("tainting.sink.track.src", true); +pref("tainting.sink.window.open", true); +pref("tainting.sink.window.postMessage", true); diff --git a/netwerk/base/nsURLHelper.cpp b/netwerk/base/nsURLHelper.cpp index 15c1f2a98014e..a4dfae63294c8 100644 --- a/netwerk/base/nsURLHelper.cpp +++ b/netwerk/base/nsURLHelper.cpp @@ -25,6 +25,7 @@ #include "mozilla/Tokenizer.h" #include "nsEscape.h" #include "nsDOMString.h" +#include "nsTaintingUtils.h" #include "mozilla/net/rust_helper.h" #include "mozilla/net/DNS.h"