Blazor WebAssembly fails to start on HTTP LAN origins because `crypto.subtle` is required unconditionally
- Dominant language
- C#
- Stars
- 18.3k
- Forks
- 5.6k
- PR merge metrics
- PR metrics pending
Description
### Description
I am running a standalone Blazor WebAssembly application on a private local network. I would like to serve the application over plain HTTP because the application is only accessible inside my local network and is not exposed to the Internet. In this scenario, setting up HTTPS certificates for local hostnames or IP addresses adds unnecessary complexity.
The application works correctly when accessed through `http://localhost`, but it fails during WebAssembly runtime startup when accessed through an HTTP origin using either a local IP address or a local hostname, for example:
* `http://192.168.178.34:5160`
* `http://mypiewifi`
I understand that browsers expose `crypto.subtle` only in secure contexts. Consequently, `window.crypto.subtle` is unavailable for these HTTP origins.
However, the .NET WebAssembly runtime currently appears to treat `crypto.subtle` as an unconditional startup requirement. This causes the runtime to abort before the Blazor application itself starts.
I would like to know whether `crypto.subtle` really needs to be a mandatory startup requirement for the entire browser WebAssembly runtime, or whether this check could be made conditional / optional for applications that do not require functionality depending on `SubtleCrypto`.
### Reproduction Steps
1. Create a new standalone Blazor WebAssembly application using the standard template.
2. Run the application through the normal development server using `http://localhost`.
3. Confirm that the application starts normally.
4. Configure the server to listen on a LAN IP address instead of `localhost`, for example:
`http://192.168.178.34:5160`
5. Open the same application using that LAN address.
6. The application fails during .NET WebAssembly runtime initialization.
The same behavior can also be reproduced with a local hostname such as:
`http://mypiewifi`
No application-specific authentication, cryptography, or WebAuthn functionality is required to reproduce the problem
### Expected behavior
I would expect a standalone Blazor WebAssembly application that does not require `SubtleCrypto` to be able to start from an ordinary HTTP origin on a private/local network.
At minimum, I would expect the runtime to provide a fallback or to make functionality that requires `crypto.subtle` conditional, rather than aborting the entire WebAssembly runtime during startup.
`http://localhost` already demonstrates that the application itself can operate without HTTPS; the difference is that browsers treat `localhost` as a trustworthy origin.
### Actual behavior
The browser console reports:
```text
MONO_WASM: Assert failed: This engine doesn't support crypto.subtle. Please use a modern version.
Error: Assert failed: This engine doesn't support crypto.subtle. Please use a modern version.
Uncaught (in promise) Error: Failed to start platform.
Reason: Error: Assert failed: This engine doesn't support crypto.subtle. Please use a modern version.
```
In the affected HTTP context:
```javascript
window.isSecureContext
// false
window.crypto
// Crypto {}
window.crypto?.subtle
// undefined
typeof window.crypto?.subtle
// "undefined"
```
The failure occurs before the application starts.
The relevant runtime code is in `src/mono/browser/runtime/loader/polyfills.ts`, where the runtime performs an assertion equivalent to:
```typescript
mono_assert(
ENVIRONMENT_IS_SHELL ||
globalThis.crypto &&
typeof globalThis.crypto.subtle === "object",
"This engine doesn't support crypto.subtle. Please use a modern version."
);
```
The corresponding `crypto.getRandomValues` capability is checked separately.
### Regression?
I believe this behavior has existed for several .NET releases. I first encountered it with an earlier Blazor WebAssembly application and believe I also saw it with .NET 9 and .NET 10.
I have not established the exact version in which the `crypto.subtle` startup assertion was introduced, so I would not consider this a confirmed regression.
### Known Workarounds
A) **You can polyfil `crypto.subtle` API yourself.**
B) HTTPS works around the problem because it creates a secure browser context in which `crypto.subtle` is available.
`http://localhost` also works because browsers treat localhost as a trustworthy origin.
For a private LAN application, however, HTTPS requires creating and distributing/trusting certificates for local hostnames or IP addresses. I would prefer to use plain HTTP for this particular scenario.
### Configuration
* Application type: Standalone Blazor WebAssembly
* Target framework: `net11.0`
* .NET version: 11.0.0-rc.1.26425.128
* `Microsoft.AspNetCore.Components.WebAssembly`: 11.0.0-rc.1.26425.128
* OS: Windows 11 x64
* Browser: Microsoft Edge (Chromium)
* Hosting: Kestrel / HTTP
* Origin that works: `http://localhost`
* Origin that fails: `http://192.168.178.34:5160`
* Local hostname that fails: `http://mypiewifi`
The application is a normal standalone Blazor WebAssembly application and does not use authentication, WebAuthn, or application-level cryptographic functionality.
### Other information
I investigated this down to the .NET runtime source because the failure initially appeared to be related to Blazor or Kestrel.
The startup assertion is in the .NET runtime rather than in the application or Kestrel configuration.
The `verifyEnvironment()` infrastructure was originally introduced in the browser WebAssembly runtime to detect required browser/runtime features. The original implementation did not contain the `crypto.subtle` assertion.
Relevant runtime source:
https://github.com/dotnet/runtime/blob/main/src/mono/browser/runtime/loader/polyfills.ts
The original `verifyEnvironment()` implementation was introduced in:
https://github.com/dotnet/runtime/commit/4a880ef
Related issue:
https://github.com/dotnet/runtime/issues/84574
My main question is therefore whether requiring `crypto.subtle` during *global WebAssembly runtime startup* is intentional.
If `crypto.subtle` is required for a specific runtime feature, would it be possible to initialize the runtime without it and only require `SubtleCrypto` when that particular functionality is actually used?
This would allow standalone Blazor WebAssembly applications to run over HTTP on isolated/private networks where HTTPS is not otherwise necessary.
Contributor guide
Assessment
This issue has not been assessed yet.