← All issues

[19] Fix format string issue in WebExtension error handling

Severity: Low | Component: WebKit Web Extensions error utilities | 8dea243

Rated Low because reachability requires an installed extension calling these binding APIs (not a normal web origin), and the analyst flags as unverified whether any pre-fix path actually passed an extension-derived string as the format argument — without that, the latent format-string surface remains theoretical.

Source/WebKit/Shared/Extensions/WebExtensionUtilities.cpp

-String toErrorString(const String& callingAPIName, const String& sourceKey, String underlyingErrorString, ...)
+String toErrorString(const String& callingAPIName, const String& sourceKey, const String& underlyingErrorString)
{
ASSERT(!underlyingErrorString.isEmpty());
- va_list arguments;
- va_start(arguments, underlyingErrorString);
- String formattedUnderlyingErrorString = formatString(underlyingErrorString.utf8().data(), arguments).trim(...);
- va_end(arguments);
+ String formattedUnderlyingErrorString = underlyingErrorString.trim(...);
...
- return formatString("Invalid call to %s. The '%s' value is invalid, because %s.", callingAPIName.utf8().data(), source.utf8().data(), lowercaseFirst(formattedUnderlyingErrorString).utf8().data());
+ return makeString("Invalid call to "_s, callingAPIName, ". The '"_s, source, "' value is invalid, because "_s, lowercaseFirst(formattedUnderlyingErrorString), "."_s);
}

toErrorString() loses its trailing variadic and the internal va_list/vsnprintf/CFStringCreateWithFormatAndArguments/_vsnwprintf plumbing (the static formatString helpers are deleted entirely). The companion toWebExtensionError template variadic in WebExtensionUtilities.h collapses to a non-variadic inline. All ~30+ call sites across UIProcess/WebProcess extension API files are rewritten so the formatted error message is built by WTF::makeString(...)NSString* arguments wrapped in String(...), integers passed natively — and handed to toErrorString/toWebExtensionError as a single fixed const String&.

Use of a runtime-constructed string as a printf-style format argument, allowing %-specifiers in tainted data to be interpreted as conversion specifications.

printf-family functions interpret a format string for conversion specifiers (%s, %@, %n, %llu) and read one variadic argument per specifier from a va_list. WTF::String::utf8().data() returns a const char* view of a possibly runtime-constructed string — including any literal % characters. WTF::makeString(...) builds a String by typed-piece concatenation with no format interpretation. WTF_ATTRIBUTE_PRINTF is a compiler hint that enables -Wformat-family checking — but only when the format is a literal at the call site, not when it flows through a String parameter.

The pre-fix toErrorString took a variadic ... and forwarded underlyingErrorString.utf8().data() as the format. Any path where underlyingErrorString could be influenced by attacker-controlled data — extension-supplied script ID, ruleset name, match pattern, URL, NSString fed into a %@ slot — would let %-specifiers in that data be interpreted as conversion specifications, producing mismatched-argument reads (stack disclosure) or, on the vsnprintf path, an OOB write via %n. On Cocoa, CFStringCreateWithFormatAndArguments follows CF semantics where unmatched %@ consumes a pointer-sized argument off the va_list and Objective-C-decodes it.

🔒

Detailed analysis of the format-string surface and whether the pre-fix code was ever reachable with attacker-influenced format input.

Subscribe to read more

🔒

Multiple reusable audit patterns identified, including grep starting points for variadic printf-style helpers across WebKit.

Subscribe to read more