From 53b27b60f8d021074c3e13c47cdaca8d16d1f6ee Mon Sep 17 00:00:00 2001 From: Lawrence Angrave Date: Tue, 27 Oct 2026 18:26:41 +0000 Subject: [PATCH 1/2] Upgrade to .NET 10 and update NuGet packages to remove known vulnerabilities - Target net10.0 in all projects; global.json requires SDK 10.0.100+ (rollForward latestFeature); CI uses 10.0.x - Docker: sdk/aspnet 10.0-noble images; TaskEngine uses libasound2t64 and no longer needs the libssl1.1 workaround (Speech SDK 1.53 works with OpenSSL 3) - Bump Microsoft/EF Core packages to 10.0.14, Npgsql EF to 10.0.3, RestSharp 114, Speech SDK 1.53, Box.V2.Core 6.20.2, Swashbuckle 9.0.6, Microsoft.OpenApi 1.6.31, Protobuf/Grpc.Tools, CsvHelper 33 and test packages - Remove unused packages that pulled in vulnerable dependencies: EntityFrameworkCore.SqlServer, VisualStudio.Web.CodeGeneration.Design, Extensions.Hosting (now part of the shared framework), EntityFramework 6 (UnitTests) - Npgsql 9+ reads "timestamp without time zone" as DateTimeKind.Unspecified (Npgsql 8 legacy mode returned Utc); add an EF value converter so DateTimes read from the DB are Utc again and API JSON keeps its trailing 'Z' `dotnet list package --vulnerable --include-transitive` is now clean for all projects. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/ci.yaml | 2 +- API.Dockerfile | 8 ++-- ClassTranscribeDatabase/CTDbContext.cs | 16 ++++++++ .../ClassTranscribeDatabase.csproj | 28 ++++++------- ClassTranscribeDatabase/global.json | 5 ++- .../ClassTranscribeServer.csproj | 41 +++++++++---------- ClassTranscribeServer/global.json | 5 ++- DevExperiments/DevExperiments.csproj | 14 +++---- TaskEngine.Dockerfile | 21 ++++------ TaskEngine/TaskEngine.csproj | 14 +++---- TaskEngine/global.json | 5 ++- .../TestAzureCognitiveServices.csproj | 4 +- TestRemoteLLM/TestRemoteLLM.csproj | 6 +-- UnitTests/UnitTests.csproj | 15 ++++--- 14 files changed, 98 insertions(+), 86 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 1771a154..e165f2e5 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -17,7 +17,7 @@ jobs: - uses: actions/setup-dotnet@v1 with: - dotnet-version: '8.0.x' # SDK Version to use; x will use the latest version of the channel + dotnet-version: '10.0.x' # SDK Version to use; x will use the latest version of the channel - uses: actions/cache@v4 with: diff --git a/API.Dockerfile b/API.Dockerfile index 93857aa6..06407943 100644 --- a/API.Dockerfile +++ b/API.Dockerfile @@ -13,8 +13,8 @@ #FROM mcr.microsoft.com/dotnet/sdk:8.0-bookworm-slim-amd64 as build -FROM mcr.microsoft.com/dotnet/sdk:8.0-bookworm-slim AS build -#notyet FROM mcr.microsoft.com/dotnet/sdk:10.0-noble AS build +#FROM mcr.microsoft.com/dotnet/sdk:8.0-bookworm-slim AS build +FROM mcr.microsoft.com/dotnet/sdk:10.0-noble AS build # See https://mcr.microsoft.com/en-us/product/dotnet/sdk/tags # Running the AMD64 version is of the SDK is broken @@ -42,8 +42,8 @@ COPY ./ClassTranscribeDatabase ./ClassTranscribeDatabase WORKDIR /src/ClassTranscribeServer RUN dotnet publish ClassTranscribeServer.csproj -c Release -o /app --no-restore -#Not yet FROM mcr.microsoft.com/dotnet/aspnet:10.0-noble AS publish_base -FROM mcr.microsoft.com/dotnet/aspnet:8.0-bookworm-slim as publish_base +FROM mcr.microsoft.com/dotnet/aspnet:10.0-noble AS publish_base +#FROM mcr.microsoft.com/dotnet/aspnet:8.0-bookworm-slim as publish_base # FROM mcr.microsoft.com/dotnet/aspnet:7.0.14-bookworm-slim as publish_base # FROM mcr.microsoft.com/dotnet/core/aspnet:3.1.3-bionic as publish_base diff --git a/ClassTranscribeDatabase/CTDbContext.cs b/ClassTranscribeDatabase/CTDbContext.cs index 053a22d7..af93068e 100644 --- a/ClassTranscribeDatabase/CTDbContext.cs +++ b/ClassTranscribeDatabase/CTDbContext.cs @@ -192,6 +192,22 @@ public CTDbContext(DbContextOptions options, IHttpContextAccessor h _httpContextAccessor = httpContextAccessor; } + /// + /// All DateTimes are stored as UTC in "timestamp without time zone" columns. + /// Npgsql 8 (legacy timestamp mode) read these back as DateTimeKind.Utc, so the JSON included a trailing 'Z'. + /// Npgsql 9+ reads them as DateTimeKind.Unspecified, so we restore the Utc kind here to keep the API output unchanged. + /// + protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) + { + configurationBuilder.Properties().HaveConversion(); + configurationBuilder.Properties().HaveConversion(); + } + + private class UtcDateTimeConverter : Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter + { + public UtcDateTimeConverter() : base(v => v, v => DateTime.SpecifyKind(v, DateTimeKind.Utc)) { } + } + /// /// These are additional modifications made in setting up the various tables of the database. /// Things like many-to-many relationships and queryfilters and alternative keys are defined here. diff --git a/ClassTranscribeDatabase/ClassTranscribeDatabase.csproj b/ClassTranscribeDatabase/ClassTranscribeDatabase.csproj index e43371f8..4bf9d74b 100644 --- a/ClassTranscribeDatabase/ClassTranscribeDatabase.csproj +++ b/ClassTranscribeDatabase/ClassTranscribeDatabase.csproj @@ -1,7 +1,7 @@  - net8.0 + net10.0 @@ -28,30 +28,30 @@ - - + + - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive - + - - - + + + - + diff --git a/ClassTranscribeDatabase/global.json b/ClassTranscribeDatabase/global.json index 215288b9..512142d2 100644 --- a/ClassTranscribeDatabase/global.json +++ b/ClassTranscribeDatabase/global.json @@ -1,5 +1,6 @@ { "sdk": { - "version": "8.0" + "version": "10.0.100", + "rollForward": "latestFeature" } -} \ No newline at end of file +} diff --git a/ClassTranscribeServer/ClassTranscribeServer.csproj b/ClassTranscribeServer/ClassTranscribeServer.csproj index 65c581f9..28f72101 100644 --- a/ClassTranscribeServer/ClassTranscribeServer.csproj +++ b/ClassTranscribeServer/ClassTranscribeServer.csproj @@ -1,7 +1,7 @@  - net8.0 + net10.0 InProcess 232163e5-4e61-44e2-a21b-f2c37da7a892 Linux @@ -42,34 +42,31 @@ - - - - - - + + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - + + + + - - - - - - + + + + + + diff --git a/ClassTranscribeServer/global.json b/ClassTranscribeServer/global.json index 215288b9..512142d2 100644 --- a/ClassTranscribeServer/global.json +++ b/ClassTranscribeServer/global.json @@ -1,5 +1,6 @@ { "sdk": { - "version": "8.0" + "version": "10.0.100", + "rollForward": "latestFeature" } -} \ No newline at end of file +} diff --git a/DevExperiments/DevExperiments.csproj b/DevExperiments/DevExperiments.csproj index 9fbad1a5..e1596790 100644 --- a/DevExperiments/DevExperiments.csproj +++ b/DevExperiments/DevExperiments.csproj @@ -2,7 +2,7 @@ Exe - net8.0 + net10.0 @@ -10,12 +10,12 @@ - - - - - - + + + + + + diff --git a/TaskEngine.Dockerfile b/TaskEngine.Dockerfile index 4a0ac085..2bae1fef 100644 --- a/TaskEngine.Dockerfile +++ b/TaskEngine.Dockerfile @@ -1,5 +1,5 @@ -FROM mcr.microsoft.com/dotnet/sdk:8.0-bookworm-slim as build -#not yet FROM mcr.microsoft.com/dotnet/sdk:10.0-noble AS build +#FROM mcr.microsoft.com/dotnet/sdk:8.0-bookworm-slim as build +FROM mcr.microsoft.com/dotnet/sdk:10.0-noble AS build # See https://mcr.microsoft.com/en-us/product/dotnet/sdk/tags #See more comments in API.Dockerfile # RUN ls @@ -25,8 +25,8 @@ COPY ./TaskEngine ./TaskEngine WORKDIR /src/TaskEngine RUN dotnet publish TaskEngine.csproj -c Release -o /app --no-restore -FROM mcr.microsoft.com/dotnet/aspnet:8.0 as publish_base -#notyet FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS publish_base +#FROM mcr.microsoft.com/dotnet/aspnet:8.0 as publish_base +FROM mcr.microsoft.com/dotnet/aspnet:10.0-noble AS publish_base # https://hub.docker.com/_/microsoft-dotnet-aspnet/ # force AMD64 build here: the ssl1.1.1 workaround below assumes amd64 @@ -34,17 +34,14 @@ FROM mcr.microsoft.com/dotnet/aspnet:8.0 as publish_base # See https://docs.microsoft.com/en-us/azure/cognitive-services/speech-service/quickstarts/setup-platform # 10.0 libasound2 replaced with libasound2t64 -RUN apt-get update && apt-get install -y build-essential libssl-dev ca-certificates libasound2 wget && \ +RUN apt-get update && apt-get install -y build-essential libssl-dev ca-certificates libasound2t64 wget && \ apt-get install -y netcat-traditional && apt-get -q update # Microsoft 8.0 issue: https://github.com/Azure-Samples/cognitive-services-speech-sdk/issues/2204 -# This will install OpenSSL 1.1.1 because it is needed by the Speech SDK. -# RUN ARCH=$(dpkg --print-architecture) -# COPY ./install-speech-hack-libssl1.sh / -# RUN wget /install-speech-hack-libssl1.sh - -RUN wget http://archive.ubuntu.com/ubuntu/pool/main/o/openssl/libssl1.1_1.1.0g-2ubuntu4_amd64.deb -RUN dpkg -i libssl1.1_1.1.0g-2ubuntu4_amd64.deb +# Previously we installed OpenSSL 1.1.1 here because older Speech SDKs needed it. +# Speech SDK 1.53+ works with the OpenSSL 3 that ships with Ubuntu 24.04 (noble), so the hack is no longer needed. +# RUN wget http://archive.ubuntu.com/ubuntu/pool/main/o/openssl/libssl1.1_1.1.0g-2ubuntu4_amd64.deb +# RUN dpkg -i libssl1.1_1.1.0g-2ubuntu4_amd64.deb FROM publish_base AS publish diff --git a/TaskEngine/TaskEngine.csproj b/TaskEngine/TaskEngine.csproj index 31504a84..2974cc78 100644 --- a/TaskEngine/TaskEngine.csproj +++ b/TaskEngine/TaskEngine.csproj @@ -2,7 +2,7 @@ Exe - net8.0 + net10.0 @@ -16,17 +16,17 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + - + diff --git a/TaskEngine/global.json b/TaskEngine/global.json index 215288b9..512142d2 100644 --- a/TaskEngine/global.json +++ b/TaskEngine/global.json @@ -1,5 +1,6 @@ { "sdk": { - "version": "8.0" + "version": "10.0.100", + "rollForward": "latestFeature" } -} \ No newline at end of file +} diff --git a/TestAzureCognitiveServices/TestAzureCognitiveServices.csproj b/TestAzureCognitiveServices/TestAzureCognitiveServices.csproj index 35e56bac..78746b1a 100644 --- a/TestAzureCognitiveServices/TestAzureCognitiveServices.csproj +++ b/TestAzureCognitiveServices/TestAzureCognitiveServices.csproj @@ -2,11 +2,11 @@ Exe - net8.0 + net10.0 - + diff --git a/TestRemoteLLM/TestRemoteLLM.csproj b/TestRemoteLLM/TestRemoteLLM.csproj index 2acfcc44..9fe73fcd 100644 --- a/TestRemoteLLM/TestRemoteLLM.csproj +++ b/TestRemoteLLM/TestRemoteLLM.csproj @@ -2,14 +2,14 @@ Exe - net8.0 + net10.0 enable enable - - + + diff --git a/UnitTests/UnitTests.csproj b/UnitTests/UnitTests.csproj index d5910c15..2f92b792 100644 --- a/UnitTests/UnitTests.csproj +++ b/UnitTests/UnitTests.csproj @@ -1,24 +1,23 @@ - net8.0 + net10.0 false - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + From f3896d4d0afa5d835652f3808a3f6922710720e0 Mon Sep 17 00:00:00 2001 From: Lawrence Angrave Date: Tue, 27 Oct 2026 18:53:50 +0000 Subject: [PATCH 2/2] CI: use actions/setup-dotnet@v4; remove stale amd64/libssl comment Co-Authored-By: Claude Opus 5.5 --- .github/workflows/ci.yaml | 2 +- TaskEngine.Dockerfile | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index e165f2e5..caf025b2 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -15,7 +15,7 @@ jobs: steps: - uses: actions/checkout@v3 - - uses: actions/setup-dotnet@v1 + - uses: actions/setup-dotnet@v4 with: dotnet-version: '10.0.x' # SDK Version to use; x will use the latest version of the channel diff --git a/TaskEngine.Dockerfile b/TaskEngine.Dockerfile index 2bae1fef..09c5e3b4 100644 --- a/TaskEngine.Dockerfile +++ b/TaskEngine.Dockerfile @@ -29,7 +29,6 @@ RUN dotnet publish TaskEngine.csproj -c Release -o /app --no-restore FROM mcr.microsoft.com/dotnet/aspnet:10.0-noble AS publish_base # https://hub.docker.com/_/microsoft-dotnet-aspnet/ -# force AMD64 build here: the ssl1.1.1 workaround below assumes amd64 # Install prerequisites for Azure Speech Services: build-essential libssl-dev ca-certificates libasound2 wget # See https://docs.microsoft.com/en-us/azure/cognitive-services/speech-service/quickstarts/setup-platform # 10.0 libasound2 replaced with libasound2t64