Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: bafcdb281b02e381096bf71aa9345a8d7082c8da
      
https://github.com/WebKit/WebKit/commit/bafcdb281b02e381096bf71aa9345a8d7082c8da
  Author: Adrian Taylor <[email protected]>
  Date:   2026-09-01 (Tue, 01 Sep 2026)

  Changed paths:
    M Source/WebKit/Platform/IPC/JSIPCBinding.h
    A Source/WebKit/Platform/IPC/Untrusted.h

  Log Message:
  -----------
  [IPC] Add IPC::Untrusted<T>, a wrapper for values a privileged process must 
not trust
https://bugs.webkit.org/show_bug.cgi?id=322837
rdar://186078499

Reviewed by Zak Ridouh.

A privileged process cannot trust a web origin, site, registrable domain or URL
that a web content process supplied over IPC. Today that is enforced by
hand-written MESSAGE_CHECKs, which are only present on the code paths somebody
guarded. This adds the type that will let the compiler enforce it instead.

This is PR one of a fairly long series that will enforce this invariant.
Being raised in series for ease of review.

IPC::Untrusted<T> holds a T and exposes no accessor. The only ways to reach the
value are validate(), which runs a pre-declared validation procedure,
unsafeExtractWithoutValidation(), which must name an UnvalidatedReason, and its
ArgumentCoder, which forwards it. No procedures exist yet; this is just the
primitive.

Design points that are not obvious from the code:

- Failure is (wrapped) expected<T, ValidationFailure> rather than
  std::optional<T> because the existing checks are three-way, not two-way.
  WebProcessProxy::allowsFirstPartyAccess already distinguishes an expected
  race (ignore the message) from an impossible claim (terminate the connection).
  Using a bool would either terminate processes during normal navigation races
  or silently drop real attacks. valueMayBeLegitimate() is what stops the
  distinction being collapsed again at the point of use: a receiver asserts it
  rather than the validation result, so an Ignore drops the message while only a
  Terminate marks the message invalid and takes the sender down.

- A validator opts in by specializing IsValidationProcedureFor, once per type.
  A concept alone would let any type with a validateUntrusted() member serve as
  a validator, which would make "the set of ways to recover a trusted value"
  unbounded. The trait makes that set explicit and enumerable; a later commit
  confines the specializations to a small list of headers.

- UnvalidatedReason is deliberately an enum rather than a free-text comment, so
  the residual risk carried by the tree can be counted with grep rather than
  estimated.

- An authority states its procedure as a check on one value -
  checkUntrusted(const T&) returning an optional failure - and 
CanValidateUntrusted
  derives the rest: the value-returning validateUntrusted, and the lift over
  optionals and iterables. A check rather than a transform means nothing has
  to be copied to be checked, so an authority can be applied to a non-copyable
  WebCore::SecurityOrigin and to a value it does not own.

  Dispatch goes through checkAnyUntrusted rather than naming the lifts
  checkUntrusted, so the mixin's own overloads are never hidden by the derived
  class's and the lookup order is explicit: the authority's own procedure first,
  then the container lifts. A derived authority never declares 
validateUntrusted,
  so it never needs a using-declaration to republish the base's overloads.

- The wrapper has no default constructor. Swift/C++ interop instantiates the
  class template when a WebKit header reaches the Swift importer, and a default
  member initializer would then require T to be default-constructible, which
  WebCore::Site is not.

Alternative considered: attaching the untrustedness to the value types
themselves (a WebCore::UntrustedSecurityOriginData, say). That was rejected
because it would spread across WebCore, and because the same origin type is
trusted or not depending only on which side of the IPC boundary it came from,
which is a property of the transport rather than of the value.

* Source/WebKit/Platform/IPC/JSIPCBinding.h:
(IPC::jsValueForDecodedArgumentValue):
* Source/WebKit/Platform/IPC/Untrusted.h: Added.
(IPC::Validated::hasValue const):
(IPC::Validated::operator bool const):
(IPC::Validated::error const):
(IPC::Validated::operator*):
(IPC::Validated::operator* const):
(IPC::Validated::Validated):
(IPC::valueMayBeLegitimate):
(IPC::requires):
(IPC::Untrusted::Untrusted):
(IPC::Untrusted::validate):
(IPC::Untrusted::unsafeExtractWithoutValidation):
(IPC::ArgumentCoder<Untrusted<T>>::encode):
(IPC::ArgumentCoder<Untrusted<T>>::decode):
(IPC::CanValidateUntrusted::validateUntrusted const):
(IPC::CanValidateUntrusted::checkAnyUntrusted const):
(IPC::Validated::operator->):
(IPC::Validated::operator-> const):

Canonical link: https://commits.webkit.org/320234@main



To unsubscribe from these emails, change your notification settings at 
https://github.com/WebKit/WebKit/settings/notifications

Reply via email to