diff --git a/docs/core/compatibility/3.1-5.0.md b/docs/core/compatibility/3.1-5.0.md index 9f0d38628ae55..3b8cd29537295 100644 --- a/docs/core/compatibility/3.1-5.0.md +++ b/docs/core/compatibility/3.1-5.0.md @@ -122,6 +122,7 @@ If you're migrating from version 3.1 of .NET Core, ASP.NET Core, or EF Core to v ## Core .NET libraries +- [UTF-7 code paths are obsolete](#utf-7-code-paths-are-obsolete) - [Vector\ always throws NotSupportedException for unsupported types](#vectort-always-throws-notsupportedexception-for-unsupported-types) - [Default ActivityIdFormat is W3C](#default-activityidformat-is-w3c) - [Behavior change for Vector2.Lerp and Vector4.Lerp](#behavior-change-for-vector2lerp-and-vector4lerp) @@ -129,6 +130,10 @@ If you're migrating from version 3.1 of .NET Core, ASP.NET Core, or EF Core to v - [CounterSet.CreateCounterSetInstance now throws InvalidOperationException if instance already exist](#countersetcreatecountersetinstance-now-throws-invalidoperationexception-if-instance-already-exists) - [Microsoft.DotNet.PlatformAbstractions package removed](#microsoftdotnetplatformabstractions-package-removed) +[!INCLUDE [utf-7-code-paths-obsolete](../../../includes/core-changes/corefx/5.0/utf-7-code-paths-obsolete.md)] + +*** + [!INCLUDE [vectort-throws-notsupportedexception](../../../includes/core-changes/corefx/5.0/vectort-throws-notsupportedexception.md)] *** diff --git a/docs/core/compatibility/corefx.md b/docs/core/compatibility/corefx.md index 1d80006bc07f6..6cdfa8456dd41 100644 --- a/docs/core/compatibility/corefx.md +++ b/docs/core/compatibility/corefx.md @@ -11,6 +11,7 @@ The following breaking changes are documented on this page: | Breaking change | Version introduced | | - | :-: | +| [UTF-7 code paths are obsolete](#utf-7-code-paths-are-obsolete) | 5.0 | | [Vector\ always throws NotSupportedException for unsupported types](#vectort-always-throws-notsupportedexception-for-unsupported-types) | 5.0 | | [Default ActivityIdFormat is W3C](#default-activityidformat-is-w3c) | 5.0 | | [Behavior change for Vector2.Lerp and Vector4.Lerp](#behavior-change-for-vector2lerp-and-vector4lerp) | 5.0 | @@ -41,6 +42,10 @@ The following breaking changes are documented on this page: ## .NET 5.0 +[!INCLUDE [utf-7-code-paths-obsolete](../../../includes/core-changes/corefx/5.0/utf-7-code-paths-obsolete.md)] + +*** + [!INCLUDE [vectort-throws-notsupportedexception](../../../includes/core-changes/corefx/5.0/vectort-throws-notsupportedexception.md)] *** diff --git a/includes/core-changes/corefx/5.0/utf-7-code-paths-obsolete.md b/includes/core-changes/corefx/5.0/utf-7-code-paths-obsolete.md new file mode 100644 index 0000000000000..4461ed12a6a10 --- /dev/null +++ b/includes/core-changes/corefx/5.0/utf-7-code-paths-obsolete.md @@ -0,0 +1,171 @@ +### UTF-7 code paths are obsolete + +The UTF-7 encoding is no longer in wide use among applications, and many specs now [forbid its use](https://security.stackexchange.com/a/68609/3573) in interchange. It's also occasionally [used as an attack vector](https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=utf-7) in applications that don't anticipate encountering UTF-7-encoded data. Microsoft warns against use of because it doesn't provide error detection. + +Consequently, the property and constructors are now obsolete. Additionally, and no longer allow you to specify `UTF-7`. + +#### Change description + +Previously, you could create an instance of the UTF-7 encoding by using the APIs. For example: + +```csharp +Encoding enc1 = Encoding.GetEncoding("utf-7"); // By name. +Encoding enc2 = Encoding.GetEncoding(65000); // By code page. +``` + +Additionally, an instance that represents the UTF-7 encoding was enumerated by the method, which enumerates all the instances registered on the system. + +Starting in .NET 5.0, the property and constructors are obsolete and produce warning `SYSLIB0001` (or `MSLIB0001` in preview versions). However, to reduce the number of warnings that callers receive when using the class, the type itself is not marked obsolete. + +```csharp +// The next line generates warning SYSLIB0001. +UTF7Encoding enc = new UTF7Encoding(); +// The next line does not generate a warning. +byte[] bytes = enc.GetBytes("Hello world!"); +``` + +Additionally, the methods treat the encoding name `utf-7` and the code page `65000` as `unknown`. Treating the encoding as `unknown` causes the method to throw an . + +```csharp +// Throws ArgumentException, same as calling Encoding.GetEncoding("unknown"). +Encoding enc = Encoding.GetEncoding("utf-7"); +``` + +Finally, the method doesn't include the UTF-7 encoding in the array that it returns. The encoding is excluded because it cannot be instantiated. + +```csharp +foreach (EncodingInfo encInfo in Encoding.GetEncodings()) +{ + // The next line would throw if GetEncodings included UTF-7. + Encoding enc = Encoding.GetEncoding(encInfo.Name); +} +``` + +#### Reason for change + +Many applications call `Encoding.GetEncoding("encoding-name")` with an encoding name value that's provided by an untrusted source. For example, a web client or server might take the `charset` portion of the `Content-Type` header and pass the value directly to `Encoding.GetEncoding` without validating it. This could allow a malicious endpoint to specify `Content-Type: ...; charset=utf-7`, which could cause the receiving application to misbehave. + +Additionally, disabling UTF-7 code paths allows optimizing compilers, such as those used by Blazor, to remove these code paths entirely from the resulting application. As a result, the compiled applications run more efficiently and take less disk space. + +#### Version introduced + +5.0 Preview 8 + +#### Recommended action + +In most cases, you don't need to take any action. However, for apps that have previously activated UTF-7-related code paths, consider the guidance that follows. + +- If your app calls with unknown encoding names provided by an untrusted source: + + Instead, compare the encoding names against a configurable allow list. The configurable allow list should at minimum include the industry-standard "utf-8". Depending on your clients and regulatory requirements, you may also need to allow region-specific encodings, such as "GB18030". + + If you don't implement an allow list, will return any that's built into the system or that's registered via a custom . Audit your service's requirements to validate that this is the desired behavior. UTF-7 continues to be disabled by default unless your application re-enables the compatibility switch mentioned later in this article. + +- If you're using or within your own protocol or file format: + + Switch to using or . UTF-8 is an industry standard and is widely supported across languages, operating systems, and runtimes. Using UTF-8 eases future maintenance of your code and makes it more interoperable with the rest of the ecosystem. + +- If you're comparing an instance against : + + Instead, consider performing a check against the well-known UTF-7 code page, which is `65000`. By comparing against the code page, you avoid the warning and also handle some edge cases, such as if somebody called `new UTF7Encoding()` or subclassed the type. + + ```csharp + void DoSomething(Encoding enc) + { + // Don't perform the check this way. + // It produces a warning and misses some edge cases. + if (enc == Encoding.UTF7) + { + // Encoding is UTF-7. + } + + // Instead, perform the check this way. + if (enc != null && enc.CodePage == 65000) + { + // Encoding is UTF-7. + } + } + ``` + +- If you must use or : + + You can suppress the `SYSLIB0001` warning in code or within your project's *.csproj* file. + + ```csharp + #pragma warning disable SYSLIB0001 // Disable the warning. + Encoding enc = Encoding.UTF7; + #pragma warning restore SYSLIB0001 // Re-enable the warning. + ``` + + ```xml + + + net5.0 + + $(NoWarn);SYSLIB0001 + + + ``` + + > [!NOTE] + > Suppressing `SYSLIB0001` only disables the and obsoletion warnings. It doesn't disable any other warnings or change the behavior of APIs like . + +- If you must support `Encoding.GetEncoding("utf-7", ...)`: + + You can re-enable support for this via a compatibility switch. This compatibility switch can be specified in the application's *.csproj* file or in a [run-time configuration file](../../../../docs/core/run-time-config/index.md), as shown in the following examples. + + In the application's *.csproj* file: + + ```xml + + + net5.0 + + true + + + ``` + + In the application's *runtimeconfig.template.json* file: + + ```json + { + "configProperties": { + "System.Text.Encoding.EnableUnsafeUTF7Encoding": true + } + } + ``` + + > [!TIP] + > If you re-enable support for UTF-7, you should perform a security review of code that calls . + +#### Category + +- Core .NET libraries +- Security + +#### Affected APIs + +- +- +- +- +- +- +- +- + +