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

Reply via email to