From b397c049cb55dd3b9112998cddfaee062e2aa925 Mon Sep 17 00:00:00 2001 From: David Klein Date: Fri, 24 Jan 2025 16:25:01 +0100 Subject: [PATCH 1/3] Custom source names Added an option to specify a custom source name via `String.tainted()`. This allows us to define our own sinks when, e.g., doing dynamic code rewriting via babel. --- js/src/builtin/String.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/js/src/builtin/String.cpp b/js/src/builtin/String.cpp index 98f1e7aabefb..148570d7e4c3 100644 --- a/js/src/builtin/String.cpp +++ b/js/src/builtin/String.cpp @@ -141,9 +141,17 @@ js::str_tainted(JSContext* cx, unsigned argc, Value* vp) if (!str || str->length() == 0) return false; + std::string source("manual taint source"); + if(args.length() >= 2 && args.hasDefined(1)) { + RootedString src_str(cx, ArgToLinearString(cx, args, 1)); + if (src_str && src_str->length() > 0) { + UniqueChars src = JS_EncodeStringToUTF8(cx, src_str); + source = std::string(src.get()); + } + } // We store the string as argument for a manual taint operation. This way it's easy to see what // the original value of a manually tainted string was for debugging/testing. - TaintOperation op = TaintOperation("manual taint source", true, TaintLocationFromContext(cx), { taintarg(cx, str) }); + TaintOperation op = TaintOperation(source.c_str(), true, TaintLocationFromContext(cx), { taintarg(cx, str) }); op.setSource(); SafeStringTaint taint(0, str->length(), op); From cae7ebfeeff4e453dc5ac52d04fdf9b0c9b3b181 Mon Sep 17 00:00:00 2001 From: David Klein Date: Fri, 24 Jan 2025 22:42:23 +0100 Subject: [PATCH 2/3] Dynamic Sink Support Added support to dynamically insert custom sinks by inserting `foxhound_sink(str, name)` calls. --- js/src/builtin/String.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/js/src/builtin/String.cpp b/js/src/builtin/String.cpp index 148570d7e4c3..f9c0a8a56068 100644 --- a/js/src/builtin/String.cpp +++ b/js/src/builtin/String.cpp @@ -125,6 +125,8 @@ static bool str_encodeURI_Component(JSContext* cx, unsigned argc, Value* vp); static bool str_foxhound(JSContext* cx, unsigned argc, Value* vp); +static bool foxhound_sink(JSContext* cx, unsigned argc, Value* vp); + /* * Global string methods */ @@ -734,6 +736,7 @@ static const JSFunctionSpec string_functions[] = { JS_FN("decodeURIComponent", str_decodeURI_Component, 1, JSPROP_RESOLVING), JS_FN("encodeURIComponent", str_encodeURI_Component, 1, JSPROP_RESOLVING), JS_FN("foxhound", str_foxhound, 1, JSPROP_RESOLVING), + JS_FN("foxhound_sink", foxhound_sink, 2, JSPROP_RESOLVING), JS_FS_END, }; @@ -5335,6 +5338,25 @@ JSString* js::EncodeURI(JSContext* cx, const char* chars, size_t length) { return sb.finishString(); } +static bool foxhound_sink(JSContext* cx, unsigned argc, Value* vp) { + AutoJSMethodProfilerEntry pseudoFrame(cx, "foxhound_sink"); + CallArgs args = CallArgsFromVp(argc, vp); + RootedString str(cx, ArgToLinearString(cx, args, 0)); + if (!str) { + return false; + } + + RootedString sink(cx, ArgToLinearString(cx, args, 1)); + if (!sink) { + return false; + } + UniqueChars sinkchars = JS_EncodeStringToUTF8(cx, sink); + JS_ReportTaintSink(cx, str, sinkchars.get()); + + args.rval().setUndefined(); + return true; +} + static bool str_foxhound(JSContext* cx, unsigned argc, Value* vp) { AutoJSMethodProfilerEntry pseudoFrame(cx, "foxhound"); CallArgs args = CallArgsFromVp(argc, vp); From d5ca2042473f57421b24053a7c26586c8d2b87e6 Mon Sep 17 00:00:00 2001 From: David Klein Date: Tue, 28 Jan 2025 12:41:08 +0100 Subject: [PATCH 3/3] Resolved Encoding Issue --- js/src/builtin/String.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/src/builtin/String.cpp b/js/src/builtin/String.cpp index f9c0a8a56068..166323fa370f 100644 --- a/js/src/builtin/String.cpp +++ b/js/src/builtin/String.cpp @@ -147,7 +147,7 @@ js::str_tainted(JSContext* cx, unsigned argc, Value* vp) if(args.length() >= 2 && args.hasDefined(1)) { RootedString src_str(cx, ArgToLinearString(cx, args, 1)); if (src_str && src_str->length() > 0) { - UniqueChars src = JS_EncodeStringToUTF8(cx, src_str); + UniqueChars src = JS_EncodeStringToLatin1(cx, src_str); source = std::string(src.get()); } } @@ -5350,7 +5350,7 @@ static bool foxhound_sink(JSContext* cx, unsigned argc, Value* vp) { if (!sink) { return false; } - UniqueChars sinkchars = JS_EncodeStringToUTF8(cx, sink); + UniqueChars sinkchars = JS_EncodeStringToLatin1(cx, sink); JS_ReportTaintSink(cx, str, sinkchars.get()); args.rval().setUndefined();