Skip to content
Merged
Changes from 8 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
318 changes: 318 additions & 0 deletions specs/TrustedOriginSetting.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,318 @@
Trusted Origin Support for WebView2
===

# Background

WebView2 applications often require different security and feature policies for different origins based on trust levels. Some applications need to enable specific features only for trusted origins while applying stricter security measures to untrusted content.

Currently, WebView2 applies uniform security policies across all origins, which creates two key challenges:
- **Feature Access Control**: Applications cannot selectively enable advanced features (such as certain APIs or capabilities) only for origins they trust, forcing them to either expose these features to all origins or disable them entirely.
- **Performance vs Security Trade-offs**: Security features like Enhanced Security Mode, while important for untrusted content, can impact performance when applied to trusted origins where such protections may be unnecessary.

For example, a content management application might want to allow full feature access and disable security restrictions when loading trusted administrative interfaces, while maintaining strict security policies for user-generated or external content loaded in the same WebView2 instance.

The Trusted Origin API addresses these scenarios by allowing applications to designate specific origins as trusted, enabling fine-grained control over which security and feature policies apply to different content sources.

# Description

This specification introduces the following interfaces:

1. `ICoreWebView2Profile3`:

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

- **CreateTrustedOriginFeatureSetting**: Creates a new CoreWebView2TrustedOriginFeatureSetting object. The returned object can be added to the collection passed to SetTrustedOriginFeatures to configure feature behavior for trusted origins.

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

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

2. `ICoreWebView2TrustedOriginFeatureSetting`:

The ICoreWebView2TrustedOriginFeatureSetting 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
- PersistentStorage

# Example

## Set Origin Setting for an Origin Pattern

### C++ example

```cpp
// This method sets the trusted origin feature settings for the specified origin patterns.
// It takes a vector of origin patterns (e.g., "https://*.contoso.com") and a vector of
// feature-state pairs to configure for the trusted origins.
void ScenarioTrustedOrigin::SetFeatureForOrigins(
std::vector<std::wstring> originPatterns,
std::vector<std::pair<COREWEBVIEW2_TRUSTED_ORIGIN_FEATURE, COREWEBVIEW2_TRUSTED_ORIGIN_FEATURE_STATE>> features)
{
auto stagingProfile3 =
m_webviewProfile.try_query<ICoreWebView2StagingProfile3>();

// featureSettings holds wil::com_ptr for COM lifetime management (keeps refcount > 0).
// featureSettingsRaw holds raw pointers extracted from featureSettings to pass to the API.
// Both are needed because the API requires a pointer array, but we need smart pointers to prevent premature COM object destruction.
std::vector<wil::com_ptr<ICoreWebView2StagingTrustedOriginFeatureSetting>> featureSettings;
std::vector<ICoreWebView2StagingTrustedOriginFeatureSetting*> featureSettingsRaw;

for (const auto& [featureKind, featureState] : features)
{
wil::com_ptr<ICoreWebView2StagingTrustedOriginFeatureSetting> setting;
CHECK_FAILURE(stagingProfile3->CreateTrustedOriginFeatureSetting(
featureKind,
featureState,
&setting));
featureSettings.push_back(setting);
featureSettingsRaw.push_back(setting.get());
}

std::vector<LPCWSTR> origins;
for (const auto& pattern : originPatterns)
{
origins.push_back(pattern.c_str());
}

CHECK_FAILURE(
stagingProfile3->SetTrustedOriginFeatures(
static_cast<UINT32>(origins.size()),
origins.data(),
static_cast<UINT32>(featureSettingsRaw.size()),
featureSettingsRaw.data()));
}

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

TextInputDialog inputDialog(
m_appWindow->GetMainWindow(),
L"Get Trusted Origin Features",
L"Enter the origin to retrieve feature settings for:",
L"Origin:",
std::wstring(L"https://www.microsoft.com"),
false); // not read-only

if (inputDialog.confirmed)
{
std::wstring origin = inputDialog.input;

CHECK_FAILURE(
stagingProfile3->GetTrustedOriginFeatures(
origin.c_str(),
Callback<ICoreWebView2StagingGetTrustedOriginFeaturesCompletedHandler>(
[this, origin](HRESULT errorCode,
ICoreWebView2StagingTrustedOriginFeatureSettingCollectionView* 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<ICoreWebView2StagingTrustedOriginFeatureSetting> setting;
CHECK_FAILURE(result->GetValueAtIndex(i, &setting));

COREWEBVIEW2_TRUSTED_ORIGIN_FEATURE feature;
BOOL isEnabled;
CHECK_FAILURE(setting->get_Feature(&feature));
CHECK_FAILURE(setting->get_IsEnabled(&isEnabled));

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

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

### .NET/WinRT

```c#
using OriginFeatureSetting = System.Collections.Generic.KeyValuePair<CoreWebView2TrustedOriginFeature, CoreWebView2TrustedOriginFeatureState>;

// ...

var profile = webView2.CoreWebView2.Profile;

// Create feature settings collection
var features = new[]
{
new OriginFeatureSetting(CoreWebView2TrustedOriginFeature.AccentColor, CoreWebView2TrustedOriginFeatureState.Enabled),
new OriginFeatureSetting(CoreWebView2TrustedOriginFeature.PersistentStorage, CoreWebView2TrustedOriginFeatureState.Disabled),
new OriginFeatureSetting(CoreWebView2TrustedOriginFeature.EnhancedSecurityMode, CoreWebView2TrustedOriginFeatureState.Enabled)
};

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

// Get features for a specific origin
var originFeatures = await profile.GetTrustedOriginFeaturesAsync("https://app.contoso.com");
```


# API details

## C++
```cpp
/// Specifies the feature types that can be configured for trusted origins.
[v1_enum]
typedef enum COREWEBVIEW2_TRUSTED_ORIGIN_FEATURE {
/// Specifies the accent color feature for the origin.
/// By default, the accent color feature is disabled for all origins.
COREWEBVIEW2_TRUSTED_ORIGIN_FEATURE_ACCENT_COLOR,
/// Specifies persistent storage capabilities for the origin.
/// By default, persistent storage is disabled for all origins.
COREWEBVIEW2_TRUSTED_ORIGIN_FEATURE_PERSISTENT_STORAGE,
/// Specifies enhanced security mode settings for the origin.
/// 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.

COREWEBVIEW2_TRUSTED_ORIGIN_FEATURE_ENHANCED_SECURITY_MODE,
} COREWEBVIEW2_TRUSTED_ORIGIN_FEATURE;

/// Specifies the state of the trusted origin feature.
[v1_enum]
typedef enum COREWEBVIEW2_TRUSTED_ORIGIN_FEATURE_STATE {
/// Sets the enabled state of the trusted origin feature.
COREWEBVIEW2_TRUSTED_ORIGIN_FEATURE_STATE_ENABLED,
/// Sets the disabled state of the trusted origin feature.
COREWEBVIEW2_TRUSTED_ORIGIN_FEATURE_STATE_DISABLED,
} COREWEBVIEW2_TRUSTED_ORIGIN_FEATURE_STATE;

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


/// This is the ICoreWebView2Profile interface for trusted origin feature management.
interface ICoreWebView2StagingProfile3 : IUnknown {
/// Creates a CoreWebView2TrustedOriginFeatureSetting 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
/// SetTrustedOriginFeatures to configure features for trusted origins.
HRESULT CreateTrustedOriginFeatureSetting(
[in] COREWEBVIEW2_TRUSTED_ORIGIN_FEATURE featureKind,
[in] COREWEBVIEW2_TRUSTED_ORIGIN_FEATURE_STATE featureState
, [out, retval] ICoreWebView2StagingTrustedOriginFeatureSetting** value);

/// Configures one or more feature settings for the specified origins.
///
/// This method applies feature configurations—such as accent color support,
/// persistent storage, or enhanced security mode—to trusted origins. Origins
/// may be provided as exact origin strings or as wildcard patterns.
///
/// For examples of origin pattern matching, see the table in:
/// https://learn.microsoft.com/en-us/dotnet/api/microsoft.web.webview2.core.corewebview2.addwebresourcerequestedfilter.
///
/// 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/*`.
HRESULT SetTrustedOriginFeatures(
[in] UINT32 originsCount,
[in] LPCWSTR* originPatterns,
[in] UINT32 featureCount,
[in] ICoreWebView2StagingTrustedOriginFeatureSetting** features
);

/// Gets the feature configurations for a specified origin.
/// Returns a collection of feature settings that have been configured for the origin.
/// If no features have been configured for the origin, an empty collection is returned.
/// The origin should have a valid scheme and host (e.g. "https://www.example.com"),
/// otherwise the method fails with `E_INVALIDARG`.
/// The returned collection contains all the features that are part of `CoreWebView2TrustedOriginFeature`.
HRESULT GetTrustedOriginFeatures(
[in] LPCWSTR origin
, [in] ICoreWebView2StagingGetTrustedOriginFeaturesCompletedHandler* handler);
}

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

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


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

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

## MIDL3

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

enum CoreWebView2TrustedOriginFeatureState
{
Enabled = 0,
Disabled = 1,
};
enum CoreWebView2TrustedOriginFeature
{
AccentColor = 0,
PersistentStorage = 1,
EnhancedSecurityMode = 2,
};

runtimeclass CoreWebView2TrustedOriginFeatureSetting
{
// ICoreWebView2StagingTrustedOriginFeatureSetting members
CoreWebView2TrustedOriginFeature Feature { get; };

Boolean IsEnabled { get; };
}

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

Windows.Foundation.IAsyncOperation<IVectorView<CoreWebView2TrustedOriginFeatureSetting> > GetTrustedOriginFeaturesAsync(String origin);
}
}
}
```