Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
362 changes: 362 additions & 0 deletions specs/TrustedOriginSetting.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,362 @@
Origin Feature Configuration for WebView2
===

# Background

Many WebView2 applications need to apply different security and feature
policies depending on the origin of the content they host. In some scenarios,
applications must enable advanced capabilities for specific origins while
enforcing stricter protections for other origins.

By default, WebView2 enforces a single, uniform security model across all
origins. This creates two primary limitations:

- **Feature Access Control**: Applications cannot selectively enable
privileged features—such as specific APIs or advanced capabilities—for
certain origins only. As a result, developers must either expose these
features to all content or disable them entirely.

- **Performance and Security Trade-offs**: Security mechanisms such as
Enhanced Security Mode are essential for external content but may introduce
unnecessary overhead when applied to first‑party experiences.

For example, a content management system may need to grant full feature access
and relax certain security restrictions for its administrative interface,
while still applying strict security policies to user‑generated or external
content displayed within the same WebView2 instance.

The Origin Configuration API enables these scenarios by allowing applications
to configure origin-specific settings for different features. Applications can
define feature policies for specific origins or origin patterns, giving
developers fine‑grained control over how features and security mechanisms are
applied to content from various sources.

# Description

This specification introduces the following interfaces:

1. `ICoreWebView2Profile3`:

The ICoreWebView2Profile3 interface provides APIs for defining, applying,
and retrieving origin feature settings. It introduces the following
members:

- **CreateOriginFeatureSetting**: Creates a new
CoreWebView2OriginFeatureSetting object. The returned object can be
added to the collection passed to SetOriginFeatures to configure
feature behavior for origins.

- **SetOriginFeatures**: Applies the specified origin feature settings to
one or more origins associated with this profile.

- **GetEffectiveFeaturesForOrigin**: Asynchronously retrieves the origin feature
settings—both the feature identifier and its enabled/disabled state—for
a specified origin.

2. `ICoreWebView2OriginFeatureSetting`:

The ICoreWebView2OriginFeatureSetting interface represents a simple
pairing of a feature enumeration value and its corresponding feature
state (enabled or disabled). Currently, the feature enumeration supports
the following values:

- AccentColor
- EnhancedSecurityMode

# Example

## Configure Origin Settings for Origin Patterns

### C++ example

```cpp
void SetOriginFeatures()
{
auto stagingProfile3 =
m_webviewProfile.try_query<ICoreWebView2StagingProfile3>();

// Create feature settings
wil::com_ptr<ICoreWebView2StagingOriginFeatureSetting> accentColorSetting;
CHECK_FAILURE(stagingProfile3->CreateOriginFeatureSetting(
COREWEBVIEW2_ORIGIN_FEATURE_ACCENT_COLOR,
COREWEBVIEW2_ORIGIN_FEATURE_STATE_ENABLED,
&accentColorSetting));

wil::com_ptr<ICoreWebView2StagingOriginFeatureSetting> enhancedSecuritySetting;
CHECK_FAILURE(stagingProfile3->CreateOriginFeatureSetting(
COREWEBVIEW2_ORIGIN_FEATURE_ENHANCED_SECURITY_MODE,
COREWEBVIEW2_ORIGIN_FEATURE_STATE_ENABLED,
&enhancedSecuritySetting));

// Set features for origin patterns
ICoreWebView2StagingOriginFeatureSetting* features[] = {
accentColorSetting.get(),
enhancedSecuritySetting.get()
};

LPCWSTR origins[] = { L"https://*.contoso.com" };

CHECK_FAILURE(stagingProfile3->SetOriginFeatures(
ARRAYSIZE(origins),
origins,
ARRAYSIZE(features),
features));
}

void GetFeatureSettingsForOrigin()
{
auto stagingProfile3 =
m_webviewProfile.try_query<ICoreWebView2StagingProfile3>();

std::wstring origin = L"https://www.microsoft.com";

CHECK_FAILURE(
stagingProfile3->GetEffectiveFeaturesForOrigin(
origin.c_str(),
Callback<ICoreWebView2StagingGetEffectiveFeaturesForOriginCompletedHandler>(
[this, origin](HRESULT errorCode,
ICoreWebView2StagingOriginFeatureSettingCollectionView* result) -> HRESULT
{
if (SUCCEEDED(errorCode))
{
UINT32 count = 0;
CHECK_FAILURE(result->get_Count(&count));

std::wstring message = L"Features for origin: " + origin + L"\n";
for (UINT32 i = 0; i < count; i++)
{
wil::com_ptr<ICoreWebView2StagingOriginFeatureSetting> setting;
CHECK_FAILURE(result->GetValueAtIndex(i, &setting));

COREWEBVIEW2_ORIGIN_FEATURE feature;
COREWEBVIEW2_ORIGIN_FEATURE_STATE State;
CHECK_FAILURE(setting->get_Feature(&feature));
CHECK_FAILURE(setting->get_State(&State));

message += L"Feature: " + std::to_wstring(static_cast<int>(feature)) +
L", Enabled: " + (State ? L"True" : L"False") + L"\n";
}

MessageBoxW(m_appWindow->GetMainWindow(), message.c_str(), L"Origin Features", MB_OK);
}
return S_OK;
}).Get()));
}
```

### .NET/WinRT

```c#
public void SetOriginFeatures()
{
// Create feature settings collection
var features = new Dictionary<CoreWebView2OriginFeature, CoreWebView2OriginFeatureState>
{
{ CoreWebView2OriginFeature.AccentColor, CoreWebView2OriginFeatureState.Enabled },
{ CoreWebView2OriginFeature.EnhancedSecurityMode, CoreWebView2OriginFeatureState.Enabled },
};

// Set features for origin patterns
var origins = new[] { "https://*.contoso.com" };
m_webviewProfile.SetOriginFeatures(origins, features);
}

private async Task GetFeatureSettingsForOriginAsync()
{
var settings = await m_webviewProfile.GetEffectiveFeaturesForOriginAsync("https://www.microsoft.com/");
var builder = new StringBuilder();
foreach (var setting in settings) {
builder.AppendLine($"Feature: {setting.Feature}, Enabled = {setting.State}");
}
m_appWindow.AsyncMessageBox(builder.ToString(), "Origin features");
}
```


# API details

## C++
```cpp
/// Specifies the feature types that can be configured for origins.
[v1_enum]
typedef enum COREWEBVIEW2_ORIGIN_FEATURE {
/// Specifies the accent color feature for the origin.
/// This controls whether the origin can use the AccentColor CSS keyword, which provides
/// access to the system's accent color. The AccentColor keyword can be used in CSS color
/// properties to match the operating system's accent color, enabling
/// better integration with the native UI theme.
/// By default, the accent color feature is disabled for all origins.
///
/// For more information about CSS color keywords, see:
/// https://developer.mozilla.org/en-US/docs/Web/CSS/color_value
COREWEBVIEW2_ORIGIN_FEATURE_ACCENT_COLOR,
/// Specifies enhanced security mode settings for the origin.
/// Enhanced Security Mode provides additional protections by disabling or restricting
/// certain web platform features that may pose security risks, such as JIT compilation,
/// certain JavaScript APIs, and other potentially dangerous capabilities. This feature
/// is particularly useful for protecting against zero-day exploits and reducing attack
/// surface. When enabled for an origin, that origin will have Enhanced Security Mode
/// applied; when disabled, normal security mode is used.
/// Enhanced security mode can be configured globally via EnhancedSecurityModeLevel API on profile.
Copy link
Contributor

@oldnewthing oldnewthing Jan 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unclear how this interacts with the global EnhancedSecurityModeLevel.

Is it

Feature Enabled Feature Disabled Feature not set
EnhancedSecurityModeLevel = Off Strict Off Off
EnhancedSecurityModeLevel = Strict Strict Off Strict

or is it

Feature Enabled Feature Disabled Feature not set
EnhancedSecurityModeLevel = Off Strict Off Off
EnhancedSecurityModeLevel = Strict Strict Off Off

What if EnhancedSecurityModeLevel is set to a level that isn't Off or Strict? (E.g., we add a new level "Extreme".) How do we fill in the new row?

Feature Enabled Feature Disabled Feature not set
EnhancedSecurityModeLevel = Off Strict Off Off
EnhancedSecurityModeLevel = Strict Strict Off Strict
EnhancedSecurityModeLevel = Extreme ? ? ?

One thing that would help is to rename the feature to StrictEnhancedSecurityMode. That way, if we add "Extreme" later, it would be a separate feature: ExtremeEnhancedSecurityMode.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please update documentation to explicitly state that if the ESM isn't configured for an origin then ESM is set based on the global profile property.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, please rename like Raymond suggests: COREWEBVIEW2_ORIGIN_FEATURE_ENHANCED_SECURITY_MODE -> COREWEBVIEW2_ORIGIN_FEATURE_STRICT_ENHANCED_SECURITY_MODE

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After internal discussions we decided that having ESM level as Strict and Off is causing confusion. ESM only has two states in webview2 which is enabled and disabled. In future we don't expect any more states.

We'll change the ESMLevel API and have something like Profile.ESMState which will take only two values, i.e., Enabled or Disabled. For now, the documentation still refers to the older ESMLevel API but before going to experimental we'll update it with the new ESM toggle API and ensure that we clearly define the relationship between the two APIs.

/// If Enhanced Security Mode is not configured for an origin, the global profile setting will apply.
///
/// For more information about Enhanced Security Mode, see:
/// https://learn.microsoft.com/en-us/microsoft-edge/webview2/concepts/security
COREWEBVIEW2_ORIGIN_FEATURE_ENHANCED_SECURITY_MODE,
} COREWEBVIEW2_ORIGIN_FEATURE;

/// Specifies the state of the origin feature.
[v1_enum]
typedef enum COREWEBVIEW2_ORIGIN_FEATURE_STATE {
/// Sets the enabled state of the origin feature.
COREWEBVIEW2_ORIGIN_FEATURE_STATE_ENABLED,
/// Sets the disabled state of the origin feature.
COREWEBVIEW2_ORIGIN_FEATURE_STATE_DISABLED,
} COREWEBVIEW2_ORIGIN_FEATURE_STATE;

/// Receives the result of the `GetEffectiveFeaturesForOrigin` method.
interface ICoreWebView2StagingGetEffectiveFeaturesForOriginCompletedHandler : IUnknown {
/// Provides the result of the corresponding asynchronous method.
HRESULT Invoke([in] HRESULT errorCode, [in] ICoreWebView2StagingOriginFeatureSettingCollectionView* result);
}


/// This is the ICoreWebView2Profile interface for origin feature management.
interface ICoreWebView2StagingProfile3 : IUnknown {
/// Creates a CoreWebView2OriginFeatureSetting objects. This object represents a specific feature and its state (enabled or disabled).
/// This method allows creating a feature settings object that can be used with
/// SetOriginFeatures to configure features for origins.
HRESULT CreateOriginFeatureSetting(
[in] COREWEBVIEW2_ORIGIN_FEATURE featureKind,
[in] COREWEBVIEW2_ORIGIN_FEATURE_STATE featureState
, [out, retval] ICoreWebView2StagingOriginFeatureSetting** value);

/// Configures one or more feature settings for the specified origins.
///
/// This method applies feature configurations—such as accent color support,
/// or enhanced security mode—to origins. Origins
/// may be provided as exact origin strings or as wildcard patterns.
///
/// The origin pattern can be an exact origin string or a wildcard pattern.
/// For wildcard patterns, `*` matches zero or more characters.
/// Examples:
/// | Origin Filter String | What It Matches | Description |
/// |---------|-----------------|-------------|
/// | `https://contoso.com` | Only `https://contoso.com` | Matches the exact origin with specific protocol and hostname |
/// | `https://[*.]contoso.com` | `https://app.contoso.com`,`https://api.contoso.com`,`https://admin.contoso.com` | Matches any subdomain under the specified domain |
/// | `*://contoso.com` | `https://contoso.com`,`http://contoso.com`,`ftp://contoso.com` | Matches any protocol for the specified hostname |
/// | `https://www.microsoft.com:*` | `https://www.microsoft.com:123` | Matches any port for the specified origin |
/// | `[*.]example.com` | `https://www.example.com`,`http://abc.example.com` | Matches any subdomain with any protocol for the specified domain |
/// | `https://xn--qei.example/` | `https://❤.example/`,`https://xn--qei.example/` | Normalized punycode matches with corresponding Non-ASCII hostnames |
///
/// Calling this method multiple times with the same (featureKind, featureState)
/// pair overwrites the previous configuration; the most recent call takes
/// precedence.
///
/// When multiple configurations exist for the same feature but specify
/// different featureState values, the configuration whose origin pattern is
/// more specific takes precedence.
///
/// The specificity of an origin pattern is determined by the presence and
/// placement of wildcards. Three wildcard categories influence specificity:
/// - Wildcards in the port (for example, `https://www.example.com:*/*`)
/// - Wildcards in the scheme (for example, `*://www.example.com:123/*`)
/// - Wildcards in the hostname (for example, `https://*.example.com:123/*`)
///
/// If one pattern is more specific in one component but less specific in
/// another, specificity is evaluated in the following order:
/// 1. Hostname
/// 2. Scheme
/// 3. Port
///
/// For example, the following patterns are ordered by precedence:
/// `https://www.example.com:*/*` → `*://www.example.com:123/*` → `https://*.example.com:123/*`.
///
/// To reset the origin list for a particular (feature, state) pair, call
/// SetOriginFeatures with an empty origin list or nullptr for the same
/// feature setting.
/// For example,
/// SetOriginFeatures(1, {"https://microsoft.com"}, 1, {{ESM: Enabled}});
/// SetOriginFeatures(0, {}, 1, {{ESM: Enabled}}); // Resets {ESM: Enabled}
HRESULT SetOriginFeatures(
[in] UINT32 originsCount,
[in] LPCWSTR* originPatterns,
[in] UINT32 featureCount,
[in] ICoreWebView2StagingOriginFeatureSetting** features
);

/// Gets the effective feature settings for a specified origin.
/// Returns a collection of feature settings for all the features in
/// `COREWEBVIEW2_ORIGIN_FEATURE`. This collection contains the effective
/// (computed) setting values for all features, including features that were
/// not explicitly configured via `SetOriginFeatures` and thus have their
/// default values.
/// The order of features in the returned collection is not guaranteed.
/// The origin should have a valid scheme and host (e.g. "https://www.example.com"),
/// otherwise the method fails with `E_INVALIDARG`.
HRESULT GetEffectiveFeaturesForOrigin(
[in] LPCWSTR origin
, [in] ICoreWebView2StagingGetEffectiveFeaturesForOriginCompletedHandler* handler);
}

/// Represents a feature setting configuration for a origin.
interface ICoreWebView2StagingOriginFeatureSetting : IUnknown {
/// The feature type for this setting.
[propget] HRESULT Feature([out, retval] COREWEBVIEW2_ORIGIN_FEATURE* value);

/// Indicates whether the feature is enabled for the origin.
[propget] HRESULT State([out, retval] COREWEBVIEW2_ORIGIN_FEATURE_STATE* value);
}


/// A collection of origin settings.
interface ICoreWebView2StagingOriginFeatureSettingCollectionView : IUnknown {
/// Gets the number of objects contained in the `OriginFeatureSettingCollection`.
[propget] HRESULT Count([out, retval] UINT32* value);

/// Gets the object at the specified index.
HRESULT GetValueAtIndex(
[in] UINT32 index
, [out, retval] ICoreWebView2StagingOriginFeatureSetting** value);
}
```

## MIDL3

```c#
namespace Microsoft.Web.WebView2.Core
{

enum CoreWebView2OriginFeatureState
{
Enabled = 0,
Disabled = 1,
};
enum CoreWebView2OriginFeature
{
AccentColor = 0,
EnhancedSecurityMode = 1,
};

runtimeclass CoreWebView2OriginFeatureSetting
{
// ICoreWebView2StagingOriginFeatureSetting members
CoreWebView2OriginFeature Feature { get; };

CoreWebView2OriginFeatureState State { get; };
}

runtimeclass CoreWebView2Profile
{
[interface_name("Microsoft.Web.WebView2.Core.CoreWebView2Profile_Manual5")]
{
void SetOriginFeatures(
Windows.Foundation.Collections.IIterable<String> origins,
Windows.Foundation.Collections.IIterable<
Windows.Foundation.Collections.IKeyValuePair<CoreWebView2OriginFeature, CoreWebView2OriginFeatureState> > features);

Windows.Foundation.IAsyncOperation<IVectorView<CoreWebView2OriginFeatureSetting> > GetEffectiveFeaturesForOriginAsync(String origin);
}
}
}
```