| title | ASP.NET Core Blazor Hybrid security considerations |
|---|---|
| ai-usage | ai-assisted |
| author | guardrex |
| description | Learn about security considerations when developing apps in Blazor Hybrid. |
| monikerRange | >= aspnetcore-6.0 |
| ms.author | wpickett |
| ms.custom | mvc |
| ms.date | 11/11/2025 |
| uid | blazor/hybrid/security/security-considerations |
This article describes security considerations for Blazor Hybrid apps.
Blazor Hybrid apps that render web content execute .NET code inside a platform Web View. The .NET code interacts with the web content via an interop channel between the .NET code and the Web View.
The web content rendered into the Web View can come from assets provided by the app from either of the following locations:
- The
wwwrootfolder in the app. - A source external to the app. For example, a network source, such as the Internet.
A trust boundary exists between the .NET code and the code that runs inside the Web View. .NET code is provided by the app and any trusted third-party packages that you've installed. After the app is built, the .NET code Web View content sources can't change.
In contrast to the .NET code sources of content, content sources from the code that runs inside the Web View can come not only from the app but also from external sources. For example, static assets from an external Content Delivery Network (CDN) might be used or rendered by an app's Web View.
Consider the code inside the Web View as untrusted in the same way that code running inside the browser for a web app isn't trusted. The same threats and general security recommendations apply to untrusted resources in Blazor Hybrid apps as for other types of apps.
If possible, avoid loading content from a third-party origin. To mitigate risk, you might be able to serve content directly from the app by downloading the external assets, verifying that they're safe to serve to users, and placing them into the app's wwwroot folder for packaging with the rest of the app. When the external content is downloaded for inclusion in the app, we recommend scanning it for viruses and malware before placing it into the wwwroot folder of the app.
If your app must reference content from an external origin, we recommend that you use common web security approaches to provide the app with an opportunity to block the content from loading if the content is compromised:
- Serve content securely with TLS/HTTPS.
- Institute a Content Security Policy (CSP). For more information, see xref:blazor/security/content-security-policy.
- Perform Subresource Integrity (SRI) checks.
Even if all of the resources are packed into the app and don't load from any external origin, remain cautious about problems in the resources' code that run inside the Web View, as the resources might have vulnerabilities that could allow cross-site scripting (XSS) attacks.
In general, the Blazor framework protects against XSS by dealing with HTML in safe ways. However, some programming patterns allow Razor components to inject raw HTML into rendered output, such as rendering content from an untrusted source. For example, rendering HTML content directly from a database should be avoided. Additionally, JavaScript libraries used by the app might manipulate HTML in unsafe ways to inadvertently or deliberately render unsafe output.
For these reasons, it's best to apply the same protections against XSS that are normally applied to web apps. Prevent loading scripts from unknown sources and don't implement potentially unsafe JavaScript features, such as eval and other unsafe JavaScript primitives. Establishing a CSP is recommended to reduce these security risks.
If the code inside the Web View is compromised, the code gains access to all of the content inside the Web View and might interact with the host via the interop channel. For that reason, any content coming from the Web View (events, JS interop) must be treated as untrusted and validated in the same way as for other sensitive contexts, such as in a compromised Blazor Server app that can lead to malicious attacks on the host system.
Don't store sensitive information, such as credentials, security tokens, or sensitive user data, in the context of the Web View, as it makes the information available to a cyberattacker if the Web View is compromised. There are safer alternatives, such as handling the sensitive information directly within the native portion of the app.
When using an iframe to display external content within a Blazor Hybrid page, we recommend that users leverage sandboxing features to ensure that the content is isolated from the parent page containing the app. In the following Razor component example, the sandbox attribute is present for the <iframe> tag to apply sandboxing features to the admin.html page:
<iframe sandbox src="https://contoso.com/admin.html" />Warning
The sandbox attribute isn't supported in early browser versions. For more information, see Can I use: sandbox.
Links to URLs outside of the app are opened in an appropriate external app, not loaded within the Web View. We don't recommend overriding the default behavior.
The xref:Microsoft.AspNetCore.Components.WebView.Maui.BlazorWebView control uses the currently-installed, platform-specific native Web View. Since the native Web View is periodically updated with support for new APIs and fixes for security issues, it may be necessary to ensure that an app is using a Web View version that meets the app's requirements.
Use one of the following approaches to keep the Web View current in deployed apps:
- On all platforms: Check the Web View version and prompt the user to take any necessary steps to update it.
- Only on Windows: Package a fixed-version Web View within the app, using it in place of the system's shared Web View. For more information, see the Use and distribute a fixed version of the Windows
WebView2Runtime section.
The Android Web View is distributed and updated via the Google Play Store. Check the Web View version by reading the User-Agent string. Read the Web View's navigator.userAgent property using JavaScript interop and optionally cache the value using a singleton service if the user agent string is required outside of a Razor component context.
When using the Android Emulator:
- Use an emulated device with Google Play Services preinstalled. Emulated devices without Google Play Services preinstalled aren't supported.
- Install Google Chrome from the Google Play Store. If Google Chrome is already installed, update Chrome from the Google Play Store. If an emulated device doesn't have the latest version of Chrome installed, it might not have the latest version of the Android Web View installed.
iOS and :::no-loc text="Mac Catalyst"::: both use WKWebView, a Safari-based control, which is updated by the operating system. Similar to the Android case, determine the Web View version by reading the Web View's User-Agent string.
On Windows, the Chromium-based Microsoft Edge WebView2 is required to run Blazor Web Apps.
The newest installed version of WebView2, known as the :::no-loc text="Evergreen distribution":::, is used. If you wish to ship a specific version of WebView2 with the app, use the :::no-loc text="Fixed Version distribution"::: (see the Use and distribute a fixed version of the Windows WebView2 Runtime section).
For more information on checking the currently-installed WebView2 version and the distribution modes, see the WebView2 distribution documentation.
Follow the guidance in this section to use and distribute a fixed version of the Chromium-based Microsoft Edge WebView2 Runtime.
Download the Fixed Version installer packages from Microsoft Edge WebView2: Download the WebView2 Runtime.
The following steps place the packages into Runtimex86, Runtimex64, and RuntimeARM64 folders in the app's solution folder, maintaining the files outside of the project to keep the Solution Explorer view of the project focused on the app's developer assets.
After downloading a runtime, use the expand command in a command shell to expand the .cab file from the system's C:\Users\{USERNAME}\Downloads folder into the solution's root folder:
expand {PATH TO THE PACKAGE} -F:* {PATH TO THE DESTINATION FOLDER}
Placeholders:
{PATH TO THE PACKAGE}: The path to the package.{PATH TO THE DESTINATION FOLDER}: The path to the destination folder, which is the project's solution folder.
The following example uses:
- The x86 runtime package
.cabfile (Microsoft.WebView2.FixedVersionRuntime.114.0.1823.79.x86.cab). - A package path of
C:\Users\{USERNAME}\Downloads\, where the{USERNAME}placeholder is the Windows user profile name. - A solution folder path of
C:\src\MySolution\.
expand "C:\Users\{USERNAME}\Downloads\Microsoft.WebView2.FixedVersionRuntime.114.0.1823.79.x86.cab" -F:* C:\src\MySolution\
Rename the folder to Runtimex86 with the Rename-Item PowerShell cmdlet:
rename-item "C:\src\MySolution\Microsoft.WebView2.FixedVersionRuntime.114.0.1823.79.x64" "C:\src\MySolution\Runtimex86"Repeat the preceding steps for the x64 and ARM64 runtimes.
Add the following code to CreateMauiApp method in MauiProgram.cs:
#if WINDOWS
string relativePath = @"Runtime";
string basePath = AppContext.BaseDirectory;
string wvrPath = Path.Combine(basePath, relativePath);
Environment.SetEnvironmentVariable("WEBVIEW2_BROWSER_EXECUTABLE_FOLDER", wvrPath);
#endifIn the app's project file (.csproj), add the following after the existing <MauiAsset> element:
<MauiAsset Include="..\Runtimex86\**"
LogicalName="Runtime\%(RecursiveDir)%(Filename)%(Extension)"
Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows' And ('$(PlatformTarget)' == 'x86')" />
<MauiAsset Include="..\Runtimex64\**"
LogicalName="Runtime\%(RecursiveDir)%(Filename)%(Extension)"
Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows' And ('$(PlatformTarget)' == 'x64')" />
<MauiAsset Include="..\RuntimeARM64\**"
LogicalName="Runtime\%(RecursiveDir)%(Filename)%(Extension)"
Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows' And ('$(PlatformTarget)' == 'ARM64')" />- xref:blazor/hybrid/security/index
- xref:blazor/security/index
