Skip to content

Inheritance security rules violated by type: 'System.Net.Http.WebRequestHandler'. Derived types must either match the security accessibility of the base type or be less accessible. #18280

@clairernovotny

Description

@clairernovotny

Using the latest System.Net.Http 4.1.1 as per #17770 (comment), results in an exception when starting a web app that's .NET 4.6.1:

Inheritance security rules violated by type: 'System.Net.Http.WebRequestHandler'. Derived types must either match the security accessibility of the base type or be less accessible.

I've emailed a repro to @davidsh


Execution plan & status

[UPDATED by karelz]

High-level plan:
A. Revert HttpClientHandler implementation in net46 build of CoreFX back to using original .NET Framework HTTP stack instead of WinHTTP (WinHttpHandler) based stack.
B. Revise implementation of the 8 new APIs on HttpClientHandler we introduced in 4.1.0.0 OOB package so that it works accordingly for the net46 build.

Execution plan:

  1. Validate feasibility of [A]

    • a. Port HttpClientHandler from NetFX (remove WinHttpHandler build dependency for net46 build).
    • b. Add APTCA (on assembly only, no security attributes should be necessary for types or methods - same as in Desktop source code).
      • Run the SecAnnotate tool to verify the claim above - Result: Passed
    • c. Manually test the 2 scenarios (simplified and @onovotny’s) - Result: Verified
  2. Validate feasibility of [B]

    • a. Investigate the 2 remaining APIs (DefaultProxyCredentials, MaxConnectionsPerServer) which we do not know if we can implement. - Result: They are in the bucket 4.a below.
  3. Full testing of [A] implementation (cost: 1d)

    • a. Make changes in master
    • b. Test all ~7 end-to-end scenarios reported by community (ask for help from community, provide steps to consume master packages on myget)
      • Self hosting ASP.NET Core from Windows Service - validated by @annemartijn0 (here)
      • Azure Storage API - validated by @karelkrivanek (here)
      • Raven.Database package + usage of new HttpClientHandler - validated by @jahmai (here)
      • Direct dependency on System.Net.Http - validated by @pollax (here)
      • 4.6 console app depending on System.Net.Http - validated by @MikeGoldsmith (here)
      • 4.6 Azure webjob (console app) with ServiceBus - validated by @chadwackerman (here)
      • 4.6 Azure Batch app - validated by @chadwackerman (here)
      • Not-yet-described scenario by @dluxfordhpf
  4. Full implementation and testing of [B]

    • a. Decide on design of 4 APIs (CheckCertificateRevocationList, SslProtocols, DefaultProxyCredentials, MaxConnectionsPerServer) which we can’t implement “correctly” - we have 3 choices - either throw PlatformNotSupportedException, or do nothing, or set the properties domain-wide instead of per-HttpClient-instance
      • i. Implement the decision (cost: 2d)
      • ii. List all libraries on NuGet (e.g. WCF?) which use the APIs we will be technically breaking, contact them
    • b. Implement 5 APIs which we know how to implement (cost: 3d)
    • c. Final testing on master branch package - covered by [3.b]
  5. Ship final packages

    • a. Port changes into release/1.1.0 branch
    • b. Produce new package - 4.3.1
    • c. Test most of ~7 end-to-end scenarios reported by community (ask for help from community, provide steps to consume 4.3.1 stable package from myget feed - see here)
    • d. Publish package on nuget.org - https://www.nuget.org/packages/System.Net.Http/4.3.1

Impact of the change - Breaking changes

Here's list of technical breaking changes caused by the proposed solution. It includes workarounds for each.
Note that these new behaviors are specific when running on net46 / Desktop. When you run on .NET Core, the behavior is intact.

  1. HttpClientHandler.CheckCertificateRevocationList (introduced in System.Net.Http 4.1)
    • New behavior: Throws PlatformNotSupportedException
    • Workaround: Use ServicePointManager.CheckCertificateRevocationList instead (impacts the whole AppDomain, not just single HttpClientHandler as it did in System.Net.Http 4.1-4.3)
  2. HttpClientHandler.SslProtocols (introduced in System.Net.Http 4.1)
    • New behavior: Throws PlatformNotSupportedException
    • Workaround: Use ServicePointManager.SecurityProtocol instead (impacts the whole AppDomain, not just single HttpClientHandler as it did in System.Net.Http 4.1-4.3)
  3. HttpClientHandler.ServerCertificateCustomValidationCallback (introduced in System.Net.Http 4.1)
    • New behavior: Works fine, except that the first parameter of type HttpRequestMessage is always null
    • Workaround: Use ServicePointManager.ServerCertificateValidationCallback
  4. HTTP/2.0 support (introduced in System.Net.Http 4.1)
    • New behavior: System.Net.Http (for net46 = Desktop) no longer supports HTTP/2.0 protocol on Windows 10.
    • Workaround: Target System.Net.Http.WinHttpHandler NuGet package instead.
    • Details:
      • HTTP/2.0 support is part of the new CoreFx HTTP stack which on Windows is based on WinHTTP. The original HTTP stack in .NET Framework 4.6 did not support HTTP/2.0 protocol. If HTTP/2.0 protocol is needed, there is a separate NuGet package, System.Net.Http.WinHttpHandler which provides a new HttpClient handler. This handler is similar in features to HttpClientHandler (the normal default handler for HttpClient) but will support HTTP/2.0 protocol. When using HttpClient on .NET Core runtime, the WinHttpHandler is actually built-in to HttpClientHandler. But on .NET Framework, you need to explicitly use WinHttpHandler.
      • Regardless of whether you are running using .NET Framework runtime (with WinHttpHandler) or .NET Core runtime using HttpClientHandler (or WinHttpHandler), there are additional requirements in order to get HTTP/2.0 protocol working on Windows:
        • The client must be running on Windows 10 Anniversary Build (build 14393 or later).
        • The HttpRequestMessage.Version must be explicitly set to 2.0 (the default is normally 1.1). Sample code:
            var handler = new WinHttpHandler();
            var client = new HttpClient(handler);
            var request = new HttpRequestMessage(HttpMethod.Get, "http://www.example.com");
            request.Version = new Version(2, 0);

            HttpResponseMessage response = await client.SendAsync(request);

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions