New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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. #11100

Closed
onovotny opened this Issue Aug 24, 2016 · 193 comments

Comments

Projects
None yet
@onovotny
Member

onovotny commented Aug 24, 2016

Using the latest System.Net.Http 4.1.1 as per #9846 (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)
  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


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);

@davidsh davidsh self-assigned this Aug 24, 2016

@ericstj

This comment has been minimized.

Member

ericstj commented Sep 8, 2016

I happened to look at this today from another report. /cc @ChadNedzlek

This looks like it might be due to missing security attributes on the out-of-band System.Net.Http.dll compared to the inbox System.Net.Http.dll. Inbox version has AllowPartiallyTrustedCallers. So does the inbox System.Net.Http.WebRequest.dll. This means everything is treated as SecurityTransparent unless annotated otherwise.

The OOB System.Net.Http.dll is missing AllowPartiallyTrustedCallers, which makes everything security-critical. Now when the inbox WebRequest.dll loads the OOB System.Net.Http.dll it violates the security rule, since WebReqeuestHandler is transparent, but HttpClientHandler which it derives from is critical.

My repro:

  1. File > new desktop application
  2. Project properties > signing > enable strongname signing
  3. Add reference to System.Net.Http.WebRequest
  4. Install System.Net.Http 4.1.0.
  5. In the main, just call new WebRequestHandler();
@fabiodiluca

This comment has been minimized.

fabiodiluca commented Sep 12, 2016

ericstj is right, I have the same problem here. This is a critical issue on System.Net.Http 4.1.0 that should be repaired. I can't use this library with .net4.6.1 because it lacks consistency.

@dluxfordhpf

This comment has been minimized.

dluxfordhpf commented Sep 12, 2016

This problem is a significant pain to deal with, and in particularly makes using the Azure KeyVault client painful for my team. The only painless alternative is to downgrade to .NET 4.5.2, which is not acceptable.

Also, the workaround listed previously is insufficient. If you want to use NET 4.6.x, what we've found is you have to do the following this for it to work reliably: disable dependency checking, downgrade System.Net.Http, edit the CSPROJ and disable automatic binding redirect, modify the app.config, and typically clean/exit VS/and rebuild as I've often seen System.Net.Http in use, even for trivial projects. Here's the procedure that reliably fixes this.

  1. Right click the project in Visual Studio and select Manage NuGet Packages.
  2. Goto the Installed tab.
  3. Scroll down to SYSTEM.Net.Http – not Microsoft.Net.Http.
  4. In the right hand pane, if Installed is not 4.0.0.0, then set Version to 4.0.0.0.
  5. In the right hand pane, set Dependency behavior to Ignore Dependencies. If you do NOT do this, the Microsoft.IdentityModel.Clients.ActiveDirectory package will be substantially downgraded, which is NOT correct.
  6. Click Update - this button should really be labeled "Change To Version".
  7. In the Preview window, verify that the ONLY change listed is "Installing System.Net.Http". If you forgot to set Dependency behavior correctly, the additional change will be listed here.
  8. Click OK/Yes/I Agree on the confirm dialogs and wait for processing to complete. When complete, the package listing will show two version numbers – the check mark is next to the one that is in use.
  9. On the NuGet Installed tab, select the listing for Microsoft.IdentityModel.Clients.ActiveDirectory.
  10. In the right-hand details pane, set Dependency behavior to "Ignore". If you do not do this, any subsequent NuGet adds will fail when NuGet's validation for this package runs.
  11. In Visual Studio, select File|Save All.
  12. Open the CSPROJ file for this project in a text editor.
  13. In /Project/PropertyGroup*1 (the first PropertyGroup element of Project), add the following line, or change the value of this element if it already exists:
    <AutoGenerateBindingRedirects>false</AutoGenerateBindingRedirects>
  14. Save the file, then reload the project in Visual Studio.
  15. Open the app.config file for this project.
  16. Find the line for System.Net.Http and edit it to redirect it to 4.0.0.0 instead of 4.1.0.0. So find this:
<dependentAssembly> 
<assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> 
<bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" /> 
</dependentAssembly> 

And change it to this:

<dependentAssembly> 
<assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> 
<bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.0.0.0" /> 
</dependentAssembly> 
  1. Rebuild the project. If you get an exception when running Azure Key Vault code, one or more *.config files in the bin/debug or similar directories have not been updated. You may have to exit Visual Studio to clear them and rebuild.
@fabiodiluca

This comment has been minimized.

fabiodiluca commented Sep 12, 2016

dluxfordhpf, thanks for your time explaining how you have worked this out. Redirecting to System.Net.Http 4.0 worked for me in .net4.6.1, But is still very hard to maintain (the nuget dependency). Looking forward the version that will fix this.

@ericstj

This comment has been minimized.

Member

ericstj commented Sep 12, 2016

Redirecting could cause problems if folks are using any of the new API added in System.Net.Http 4.1.0.

in particularly makes using the Azure KeyVault client painful for my team

@ChadNedzlek had the same problem and was able to workaround it by passing in an HttpClient he created himself to the KeyVaultClient constructor. If you don't use WebRequestHandler you'll avoid the problem.

EG:

var handler = new HttpClientHandler();
// configure handler
// eg: handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => errors == SslPolicyErrors.None;
var client = new HttpClient(handler);
var kvclient = new KeyVaultClient(async (authority, resource, scope) => "foo", client);

@davidsh I think you need to put AllowPartiallyTrustedCallers back on System.Net.Http.dll. /cc @morganbr

@guillaumeraymond

This comment has been minimized.

guillaumeraymond commented Sep 20, 2016

@dluxfordhpf Big thanks for the steps.
It is temporary and we hope a fix soon but still, I can continue to work on the project !

@karelz karelz modified the milestones: 1.2.0, 1.1.0 Sep 23, 2016

@robertmclaws

This comment has been minimized.

robertmclaws commented Oct 13, 2016

@terrajobst This is a blocking production issue. Any idea when we can get a fix onto NuGet? Thanks!

@b3nt0

This comment has been minimized.

b3nt0 commented Oct 17, 2016

Just ran into this myself. Would be awesome if we didn't descend into dependency hell in .Net. It's heading that way.

EDIT: Fixed with a prior comments suggestion to use the system httpclient??
new KeyVaultClient(GetAccessToken, new HttpClient(new HttpClientHandler()))
That seemed to get it...

@MichaelVach

This comment has been minimized.

MichaelVach commented Nov 2, 2016

The problem is only becoming worse as more and more nuget packages from Microsoft take a dependency on the latest version of System.Net.Http. I am probably not the only one who constantly upgrades his Microsoft nuget packages to the latest pre-release version. For example packages that no longer work for me in their latest version:

Microsoft.IdentityModel.Clients.ActiveDirectory
Microsoft.TeamFoundationServer.Client
Microsoft.VisualStudio.Services.Client.
....

@robertmclaws

This comment has been minimized.

robertmclaws commented Nov 2, 2016

I still don't understand why this package is still available. @terrajobst @coolcsh can we get this package taken down/fixed? It's REALLY causing issues with complex app environments. Wasted several hours trying to keep the offending package from creeping into the build. Thanks!

@dluxfordhpf

This comment has been minimized.

dluxfordhpf commented Nov 2, 2016

We are looking at binding to the System.Net.Http in the NET Framework instead of this broken thing from NuGet. I agree, this problem is ridiculous, and very expensive to deal with as you must synchronize NuGet versions between projects, prevent auto binding updates, and fix/check your app.config. What surprises me is that it’s in such a widely used assembly. Perhaps MS doesn’t really care about KeyVault that much?

@guillaumeraymond

This comment has been minimized.

guillaumeraymond commented Nov 2, 2016

It is also used by the ActiveDirectory Nugget

@sandersaares

This comment has been minimized.

sandersaares commented Nov 3, 2016

I have reverted some libraries from targeting .NET Standard due to this and related issues where broken NuGet packages just mess up apps that target .NET Standard. This is a sorry state of things.

@terrajobst

This comment has been minimized.

Member

terrajobst commented Nov 4, 2016

Thanks for filing. We're actively looking into this. Stay tuned.

@CodingGorilla

This comment has been minimized.

CodingGorilla commented Nov 14, 2016

This has become a significant issue for me; we use a lot of our own nuget packages internally. And it seems nuget just will not let those bindingRedirects alone. Everytime we update one of our internal packages, it changes the redirect back to newVersion="4.1.0.0". Is there a way to stop it from doing that, or is there a fix on the horizon?

@mdsharpe

This comment has been minimized.

mdsharpe commented Nov 16, 2016

Encountered when running application over HTTPS, which worked fine over HTTP. Not sure if any other significant differences.
Workaround of setting newversion="4.0.0.0" worked for me.

@jahmai

This comment has been minimized.

jahmai commented Nov 19, 2016

Still an issue in NETStandard 1.6.1. Why?!

@LoulG

This comment has been minimized.

LoulG commented Nov 19, 2016

System.Net.Http 4.3.0 is out. Someone tried ?

@jahmai

This comment has been minimized.

jahmai commented Nov 19, 2016

@LoulG Yep, still a problem I'm afraid.

@robertmclaws

This comment has been minimized.

robertmclaws commented Nov 19, 2016

I spoke with @terrajobst on Twitter, and he said it's actually a bigger problem, and they have like 10 people working on it now. I'm personally not sure why they are not pulling the versions of this package displaying the problem, as I thought that's what package management was for. But the next we can do at this point is wait.

@odinnou

This comment has been minimized.

odinnou commented Nov 20, 2016

@LoulG same here, I have updated all my Nuget Packages, with the release of .net core 1.1 and i got this issue

System.TypeLoadException: 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.

Firstly, I think it was due to IdentityServer/IdentityServer3.AccessTokenValidation but, with reading this issue I understand my situation t_t, I spent several hours to try to solve it

EDIT :
OMG,
Workaround of setting newversion="4.0.0.0" worked for me too

I try to update to 4.3 but, same issue :(((

@HalidCisse

This comment has been minimized.

HalidCisse commented Nov 20, 2016

same issue here after upgrading

@parismiguel

This comment has been minimized.

parismiguel commented Mar 25, 2017

thank you @karelz and my sincere apologies for messing this topic.... hope to get some help in the new one as instructed. Warm regards,

@Workshop2

This comment has been minimized.

Workshop2 commented May 15, 2017

I have seemed to have encountered this via a perfect storm.

I am using the Azure Functions preview with a combination of both Azure Key Vault (2.0.6) and Octopus Client (4.15.3).

I have tried upgrading to System.Net.Http to 4.3.2 however it still fails when trying to use Key Vault.

Any tips?

@karelz

@karelz

This comment has been minimized.

Member

karelz commented May 15, 2017

Can you please make sure that the assembly from 4.3.2 nuget package is really used at runtime? (it was fixed in 4.3.1)

LHCGreg added a commit to LHCGreg/mal-api that referenced this issue Jul 8, 2017

Fix breakage in .NET 4.6 apps by adding dep on System.Net.Http 4.3.1.
See dotnet/corefx#11100.

If a .NET 4.6 app references a package that uses System.Net.Http, it
would get:

Could not load file or assembly 'System.Diagnostics.DiagnosticSource, Version=4.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment