After 10 Nov 2026 Microsoft will stop publishing security patches, bug fixes, and support for .NET 8 and .NET 9. If you stay on those versions you’ll run unsupported runtimes in production, exposing your systems to unpatched vulnerabilities. The safest path is to inventory, retarget to .NET 10 LTS, clean up obsolete SDKs, and lock the change in your CI/CD pipeline before the deadline.
Inventory Your .NET 8/9 Assets
using System;
using System.Diagnostics;
using System.Text.RegularExpressions;
class Program
{
static void Main()
{
var psi = new ProcessStartInfo
{
FileName = "dotnet",
Arguments = "--list-sdks",
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true
};
using var proc = Process.Start(psi)!;
proc.WaitForExit();
var output = proc.StandardOutput.ReadToEnd();
// Example output line: " 3.1.300 [C:\Program Files\dotnet\sdk]"
var sdkRegex = new Regex(@"^\s*(\d+\.\d+\.\d+)\s+\[(.+)\]$", RegexOptions.Multiline);
foreach (Match m in sdkRegex.Matches(output))
{
var version = m.Groups[1].Value;
var path = m.Groups[2].Value;
if (version.StartsWith("8.") || version.StartsWith("9."))
Console.WriteLine($"Found {version} at {path}");
}
}
}
Run this console app on any build agent or developer workstation to list every installed .NET SDK. The regex isolates the version number and install path, flagging anything that starts with 8. or 9. as out‑of‑support after Nov 2026. Capture the output (e.g., redirect to a file) and feed it into your asset inventory spreadsheet or CMDB.
Retarget Projects to .NET 10 LTS
using System;
using System.IO;
using System.Xml.Linq;
class Program
{
static void Main(string[] args)
{
if (args.Length == 0)
{
Console.WriteLine("Usage: Retarget <path-to.csproj>");
return;
}
var projPath = args[0];
var doc = XDocument.Load(projPath);
var ns = doc.Root!.Name.Namespace;
var tf = doc.Root.Element(ns + "PropertyGroup")?
.Element(ns + "TargetFramework");
if (tf == null)
{
Console.WriteLine("No <TargetFramework> found.");
return;
}
Console.WriteLine($"Current TFM: {tf.Value}");
tf.Value = "net10.0";
doc.Save(projPath);
Console.WriteLine("Updated to net10.0");
}
}
The snippet loads a .csproj file, locates the <TargetFramework> element, and rewrites its value to net10.0. After running the tool, restore and build the project (dotnet restore && dotnet build) to verify that your code compiles against the new LTS runtime. Repeat for every project identified in the inventory step.
Update Container Images & Clean Up Obsolete SDKs
using System;
using System.Threading.Tasks;
using Docker.DotNet;
using Docker.DotNet.Models;
class Program
{
static async Task Main()
{
var client = new DockerClientConfiguration(new Uri("npipe://./pipe/docker_engine"))
.CreateClient();
const string image = "mcr.microsoft.com/dotnet/aspnet:10.0";
var pullParams = new ImagePullParameters { Tag = "latest" };
Console.WriteLine($"Pulling {image} ...");
await client.Images.CreateImageAsync(
new ImagesCreateParameters { FromImage = image, Tag = "latest" },
pullParams,
new Progress<JSONMessage>(msg =>
{ if (!string.IsNullOrEmpty(msg.Status)) Console.WriteLine(msg.Status); })
);
Console.WriteLine("Image updated. Now prune old SDK/runtime images:");
var images = await client.Images.ListImagesAsync(new ImagesListParameters { All = true });
foreach (var img in images)
{
foreach var repoTag in img.RepoTags ?? Array.Empty<string>()
{
if (repoTag.Contains("8.") || repoTag.Contains("9."))
{
Console.WriteLine($"Removing {repoTag}");
await client.Images.DeleteImageAsync(img.ID, new ImageDeleteParameters { Force = true });
}
}
}
}
}
Prerequisite: add the Docker.DotNet NuGet package. This program pulls the latest aspnet:10.0 base image and then scans the local Docker store for any image tags containing 8. or 9.—the unsupported runtimes—and removes them. Run it on your build agents and any host that builds or stores container images to guarantee that production deployments pull only the supported .NET 10 base.
Enable SDK Vulnerability Detection & Lock CI/CD
using System;
using System.IO;
class Program
{
static void Main()
{
var propsPath = Path.Combine(Environment.CurrentDirectory, "Directory.Build.props");
var content = @"<Project>
<PropertyGroup>
<CheckSdkVulnerabilities>true</CheckSdkVulnerabilities>
</PropertyGroup>
</Project>";
if (!File.Exists(propsPath))
{
File.WriteAllText(propsPath, content);
Console.WriteLine($"Created {propsPath} with vulnerability check enabled.");
}
else
{
var existing = File.ReadAllText(propsPath);
if (!existing.Contains("<CheckSdkVulnerabilities>true</CheckSdkVulnerabilities>"))
{
File.AppendAllText(propsPath, Environment.NewLine + content);
Console.WriteLine("Appended SDK vulnerability check to existing file.");
}
else
{
Console.WriteLine("SDK vulnerability check already present.");
}
}
}
}
Adding <CheckSdkVulnerabilities>true</CheckSdkVulnerabilities> to a Directory.Build.props file makes MSBuild warn you at build time if the SDK version is out of date or lacks the latest servicing patch. Commit this file to your repository and verify that your build pipelines (Azure Pipelines, GitHub Actions, etc.) treat warnings as failures. Then update the pipeline’s setup-dotnet step to use the .NET 10 SDK (version: '10.0.x'). This guarantees that future builds cannot inadvertently drift back to .NET 8/9.
Take Action Today
- Run the inventory script on every build server,
- commit the retargeting tool’s output, and merge the
Directory.Build.propschange into your main branch. - Once those steps are done, schedule a focused sprint to retarget all remaining projects, rebuild container images, and validate with security scans.
Completing this before the Nov 10 2026 EOS date keeps you inside Microsoft’s support window and ensures you receive critical patches through Nov 2028.

Top comments (0)