Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: 722d0b38a97ce1a15ca4d7d1cb051215d11f96da
https://github.com/WebKit/WebKit/commit/722d0b38a97ce1a15ca4d7d1cb051215d11f96da
Author: Basuke Suzuki <[email protected]>
Date: 2026-08-19 (Wed, 19 Aug 2026)
Changed paths:
A Source/WTF/Scripts/GenerateSecurityFlags.rb
A Source/WTF/Scripts/Preferences/SecurityFlags.yaml
M Source/WTF/WTF.xcodeproj/project.pbxproj
M Source/WTF/wtf/CMakeLists.txt
M Source/WebKit/CMakeLists.txt
M Source/WebKit/DerivedSources-input.xcfilelist
M Source/WebKit/DerivedSources-output.xcfilelist
M Source/WebKit/DerivedSources.make
M Source/WebKit/GPUProcess/GPUProcess.cpp
M Source/WebKit/GPUProcess/GPUProcess.h
M Source/WebKit/GPUProcess/GPUProcess.messages.in
M Source/WebKit/GPUProcess/GPUProcessCreationParameters.h
M Source/WebKit/GPUProcess/GPUProcessCreationParameters.serialization.in
M Source/WebKit/ModelProcess/ModelProcess.cpp
M Source/WebKit/ModelProcess/ModelProcess.h
M Source/WebKit/ModelProcess/ModelProcess.messages.in
M Source/WebKit/ModelProcess/ModelProcessCreationParameters.h
M Source/WebKit/ModelProcess/ModelProcessCreationParameters.serialization.in
M Source/WebKit/NetworkProcess/NetworkProcess.cpp
M Source/WebKit/NetworkProcess/NetworkProcess.h
M Source/WebKit/NetworkProcess/NetworkProcess.messages.in
M Source/WebKit/NetworkProcess/NetworkProcessCreationParameters.h
M
Source/WebKit/NetworkProcess/NetworkProcessCreationParameters.serialization.in
M Source/WebKit/Scripts/IPCTestingHeaders-input.xcfilelist
M Source/WebKit/Scripts/IPCTestingHeaders-output.xcfilelist
A Source/WebKit/Scripts/SecurityFlagsTemplates/SecurityFlags.cpp.erb
A Source/WebKit/Scripts/SecurityFlagsTemplates/SecurityFlags.h.erb
A
Source/WebKit/Scripts/SecurityFlagsTemplates/SecurityFlags.serialization.in.erb
M Source/WebKit/Sources.txt
M Source/WebKit/SourcesCMakeCocoa.txt
M Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm
M Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStorePrivate.h
M Source/WebKit/UIProcess/GPU/GPUProcessProxy.cpp
M Source/WebKit/UIProcess/GPU/GPUProcessProxy.h
M Source/WebKit/UIProcess/Model/ModelProcessProxy.cpp
M Source/WebKit/UIProcess/Model/ModelProcessProxy.h
M Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp
M Source/WebKit/UIProcess/Network/NetworkProcessProxy.h
A Source/WebKit/UIProcess/SecurityFlagsController.cpp
A Source/WebKit/UIProcess/SecurityFlagsController.h
M Source/WebKit/WebKit.xcodeproj/project.pbxproj
M Tools/TestWebKitAPI/SourcesCocoa.txt
M Tools/TestWebKitAPI/Tests/IPC/ArgumentCoderTests.cpp
A Tools/TestWebKitAPI/Tests/WebKit/WKWebView/SecurityFlags.mm
Log Message:
-----------
[SecurityFlags] Introduce SecurityFlags and propagate them to the privileged
child processes
https://bugs.webkit.org/show_bug.cgi?id=321950
rdar://185129202
Reviewed by Chris Dumez.
Build the WebKit side of a remote disable switch for shipped security fixes. A
list fetched from
a server names flags, and every flag named is turned off at runtime, so a fix
that turns out to
cause a stability or web-compatibility regression can be disabled without
waiting for a software
update. This change is the mechanism only: there is no transport yet and
nothing consumes a
flag.
SecurityFlags.yaml is a deliberately strict schema of two fields,
humanReadableDescription and
condition; the type is always bool and the default is always the secure value.
The key is the
radar number of the fix, and that same string is the YAML key, the wire
identifier and the C++
member name, so there is no name transformation anywhere and renaming a key is
a protocol
change. Radar numbers are what keep a key unique over time, since one list is
served to every OS
version we still support. humanReadableDescription is required because the key
says nothing
about what the flag guards. GenerateSecurityFlags.rb stays separate from
GeneratePreferences.rb
because an explicit field whitelist is what stops this schema from drifting into
UnifiedWebPreferences.yaml's.
The list is the whole truth rather than a set of edits: setDisabledFlagsNamed
builds a fresh
all-enforced value and turns off only the names it carries, so a name dropping
out moves that
flag back to enforced and an empty list resets everything, which is what makes
a disablement
that itself causes trouble undoable. Every flag defaults to its secure value,
so the window
before a list arrives and any failure to fetch one both fail safe. An unknown
name is ignored
rather than treated as an error, because entries stay in the list for years and
an older WebKit
routinely sees names for flags it does not have.
SecurityFlagsController owns the one authoritative value for the UIProcess, as
a singleton
rather than state on a process proxy because the value is device-global while
the proxies are
per-pool. Reading a flag through it is safe from any thread, and setting them
asserts the main run
loop because that is what propagateToChildProcesses() needs. It reaches the
Networking, GPU and
Model processes in their creation parameters at
launch and over a new SecurityFlagsDidChange message while they are running.
Unlike its
SharedPreferencesForWebProcessDidChange neighbour that message carries no
ProcessIdentifier and
takes no reply, which serve per-connection scoping and a version barrier and do
not apply here;
the stale direction is fail safe because a child that has not received an
update keeps
enforcing.
SecurityFlags stores a WTF::BitSet of the *disabled* flags, so the secure
default falls out of
zero initialisation and the representation matches what the list expresses.
concurrentGet gives
an atomic per-flag read, a single relaxed word load, so a check can run on
whatever thread it
lands on, which matters because the GPU process dispatches stream receivers off
the main thread;
flags are independent of each other, so a stale read only delays a change. One
std::atomic
instead would have capped the type at 128 flags on 64-bit Apple platforms, past
which it
silently takes a lock on every security check.
The BitSet stays private and off the wire: serialization goes through a getter
and a CreateUsing
factory converting to and from plain 64-bit words, so the wire form does not
depend on which
word type BitSet picked and no new general-purpose ArgumentCoder is needed. The
factory rejects
a word with a bit belonging to no flag rather than dropping it quietly, since
the sender is the
UIProcess and that can only mean a bug. Copy assignment is deleted because
assigning the words
wholesale is not safe against a reader on another thread. The description is
marked
[WebKitPlatform] so the coder lands in libWebKitPlatform.a, without which the
round-trip tests
fail to link TestIPC -- the same reason EditingRange and
ShareableResourceHandle are marked that
way.
The generator validates the raw YAML node tree rather than the parsed hash,
because YAML
silently collapses a repeated key and keeps only the last one, so by the time
load_file has
returned a duplicated flag is invisible and someone else's description has been
discarded. One
pass covers ordering, duplication within a file, and a key defined in two flag
files, which
would otherwise only surface as a C++ redefinition. Ordering is by radar number
rather than by
string, because a string sort puts radar1000000000 before radar99999999 and the
file has to be
kept sorted by hand. A leading zero is rejected because radar0184485266 and
radar184485266 would
be two wire identifiers for one radar.
Disabling a flag is reachable only from testing SPI, and that SPI is compiled
out unless
ENGINEERING_BUILD is set. That is keyed on the build configuration rather than
on the SDK, so it
is off for Production -- the configuration a customer build uses -- and the
entry point does not
exist there at all. A client embedding WebKit must not be able to weaken a
shipped security fix.
It is on for Debug and Release, which is also what the open-source bots build,
so the API tests
driving the SPI compile and run there rather than being skipped as an
internal-SDK-only build
would leave them.
The flags are never sent to the WebContent process, which we assume is
compromised, so a check
there would be worthless. There is no per-flag process scoping to express that;
the struct
simply has no path to WebContent. That is also why the member is added to the
three
*ProcessCreationParameters separately rather than to the shared
AuxiliaryProcessCreationParameters, which looks like the obvious single place
but is embedded in
WebProcessCreationParameters too.
The one entry is radar184485266, the radar for this feature. It guards no fix
and exists to
validate the mechanism end to end before anything in production depends on it.
Tests: ArgumentCoderSecurityFlags.SecureDefaultRoundTrips
ArgumentCoderSecurityFlags.DisabledFlagRoundTrips
ArgumentCoderSecurityFlags.BitBelongingToNoFlagIsRejectedNotCrashed
SecurityFlagsTest.SecureByDefault
SecurityFlagsTest.DidChangeReachesRunningProcess
SecurityFlagsTest.CreationParametersReachNewProcess
SecurityFlagsTest.UnknownFlagNameIsIgnored
* Source/WTF/Scripts/GenerateSecurityFlags.rb: Added.
* Source/WTF/Scripts/Preferences/SecurityFlags.yaml: Added.
* Source/WTF/WTF.xcodeproj/project.pbxproj:
* Source/WTF/wtf/CMakeLists.txt:
* Source/WebKit/CMakeLists.txt:
* Source/WebKit/DerivedSources-input.xcfilelist:
* Source/WebKit/DerivedSources-output.xcfilelist:
* Source/WebKit/DerivedSources.make:
* Source/WebKit/Scripts/IPCTestingHeaders-input.xcfilelist:
* Source/WebKit/Scripts/IPCTestingHeaders-output.xcfilelist:
* Source/WebKit/Scripts/SecurityFlagsTemplates/SecurityFlags.cpp.erb: Added.
* Source/WebKit/Scripts/SecurityFlagsTemplates/SecurityFlags.h.erb: Added.
*
Source/WebKit/Scripts/SecurityFlagsTemplates/SecurityFlags.serialization.in.erb:
Added.
* Source/WebKit/Sources.txt:
* Source/WebKit/SourcesCMakeCocoa.txt:
* Source/WebKit/UIProcess/SecurityFlagsController.h: Added.
* Source/WebKit/UIProcess/SecurityFlagsController.cpp: Added.
(WebKit::SecurityFlagsController::singleton):
(WebKit::SecurityFlagsController::setDisabledFlagsNamed):
(WebKit::SecurityFlagsController::propagateToChildProcesses):
* Source/WebKit/GPUProcess/GPUProcess.h:
(WebKit::GPUProcess::securityFlags):
* Source/WebKit/GPUProcess/GPUProcess.cpp:
(WebKit::GPUProcess::securityFlagsDidChange):
(WebKit::GPUProcess::initializeGPUProcess):
* Source/WebKit/GPUProcess/GPUProcess.messages.in:
* Source/WebKit/GPUProcess/GPUProcessCreationParameters.h:
* Source/WebKit/GPUProcess/GPUProcessCreationParameters.serialization.in:
* Source/WebKit/NetworkProcess/NetworkProcess.h:
(WebKit::NetworkProcess::securityFlags):
* Source/WebKit/NetworkProcess/NetworkProcess.cpp:
(WebKit::NetworkProcess::initializeNetworkProcess):
(WebKit::NetworkProcess::securityFlagsDidChange):
(WebKit::NetworkProcess::isSecurityFlagEnabledForTesting):
* Source/WebKit/NetworkProcess/NetworkProcess.messages.in:
* Source/WebKit/NetworkProcess/NetworkProcessCreationParameters.h:
*
Source/WebKit/NetworkProcess/NetworkProcessCreationParameters.serialization.in:
* Source/WebKit/ModelProcess/ModelProcess.h:
(WebKit::ModelProcess::securityFlags):
* Source/WebKit/ModelProcess/ModelProcess.cpp:
(WebKit::ModelProcess::securityFlagsDidChange):
(WebKit::ModelProcess::initializeModelProcess):
* Source/WebKit/ModelProcess/ModelProcess.messages.in:
* Source/WebKit/ModelProcess/ModelProcessCreationParameters.h:
* Source/WebKit/ModelProcess/ModelProcessCreationParameters.serialization.in:
* Source/WebKit/UIProcess/GPU/GPUProcessProxy.h:
* Source/WebKit/UIProcess/GPU/GPUProcessProxy.cpp:
(WebKit::GPUProcessProxy::GPUProcessProxy):
(WebKit::GPUProcessProxy::securityFlagsDidChange):
* Source/WebKit/UIProcess/Network/NetworkProcessProxy.h:
* Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp:
(WebKit::NetworkProcessProxy::sendCreationParametersToNewProcess):
(WebKit::NetworkProcessProxy::securityFlagsDidChange):
(WebKit::NetworkProcessProxy::isSecurityFlagEnabledForTesting):
* Source/WebKit/UIProcess/Model/ModelProcessProxy.h:
* Source/WebKit/UIProcess/Model/ModelProcessProxy.cpp:
(WebKit::ModelProcessProxy::ModelProcessProxy):
(WebKit::ModelProcessProxy::securityFlagsDidChange):
* Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStorePrivate.h:
* Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm:
(+[WKWebsiteDataStore _setDisabledSecurityFlagsForTesting:]):
(-[WKWebsiteDataStore
_isSecurityFlagEnabledInNetworkProcessForTesting:completionHandler:]):
* Source/WebKit/WebKit.xcodeproj/project.pbxproj:
* Tools/TestWebKitAPI/Tests/IPC/ArgumentCoderTests.cpp:
(TestWebKitAPI::TEST(ArgumentCoderSecurityFlags, SecureDefaultRoundTrips)):
(TestWebKitAPI::TEST(ArgumentCoderSecurityFlags, DisabledFlagRoundTrips)):
(TestWebKitAPI::TEST(ArgumentCoderSecurityFlags,
BitBelongingToNoFlagIsRejectedNotCrashed)):
* Tools/TestWebKitAPI/SourcesCocoa.txt:
* Tools/TestWebKitAPI/Tests/WebKit/WKWebView/SecurityFlags.mm: Added.
(TestWebKitAPI::flagStateInNetworkProcess):
(TestWebKitAPI::launchNetworkProcess):
(TestWebKitAPI::TEST_F(SecurityFlagsTest, SecureByDefault)):
(TestWebKitAPI::TEST_F(SecurityFlagsTest, DidChangeReachesRunningProcess)):
(TestWebKitAPI::TEST_F(SecurityFlagsTest, CreationParametersReachNewProcess)):
(TestWebKitAPI::TEST_F(SecurityFlagsTest, UnknownFlagNameIsIgnored)):
Canonical link: https://commits.webkit.org/319461@main
To unsubscribe from these emails, change your notification settings at
https://github.com/WebKit/WebKit/settings/notifications