From 0003f76301ec6c231c2606fda0bc62fa239e9a5b Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Fri, 22 May 2026 09:27:15 -0400 Subject: [PATCH] fix(scripting): correct System.Threading.Thread enforcement in analyzer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit System.Threading.Thread is in the System.Threading namespace (not System.Threading.Thread), so the existing ForbiddenNamespacePrefixes entry "System.Threading.Thread" never matched — the namespace prefix check compared against the type's containing namespace, which is System.Threading. Move Thread into ForbiddenFullTypeNames (alongside Environment / AppDomain / GC / Activator) where it is matched by exact fully-qualified type name, which actually fires. Remove the dead namespace-prefix entry and document why. The Rejects_Thread_new_at_compile test now passes. (Core.Scripting-010.) Co-Authored-By: Claude Opus 4.7 (1M context) --- .../ForbiddenTypeAnalyzer.cs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting/ForbiddenTypeAnalyzer.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting/ForbiddenTypeAnalyzer.cs index 67c617d..f69eed2 100644 --- a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting/ForbiddenTypeAnalyzer.cs +++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting/ForbiddenTypeAnalyzer.cs @@ -63,7 +63,10 @@ public static class ForbiddenTypeAnalyzer "System.Net", "System.Diagnostics", // catches Process, ProcessStartInfo, EventLog, Trace/Debug file sinks "System.Reflection", - "System.Threading.Thread", // raw Thread — blocks the thread-pool + // System.Threading.Thread is NOT in this list: Thread's containing namespace is + // "System.Threading" (not "System.Threading.Thread"), so a prefix check on + // "System.Threading.Thread" never matches. Thread is denied type-granularly via + // ForbiddenFullTypeNames instead so the check actually fires. "System.Threading.Tasks", // Task.Run / Parallel — scripts are synchronous predicates // and have no legitimate need to start background work; // a Task fan-out outlives the evaluation timeout entirely @@ -92,6 +95,11 @@ public static class ForbiddenTypeAnalyzer /// System.ActivatorCreateInstance is a /// reflection-equivalent escape that constructs a forbidden type by name /// without ever naming it syntactically. + /// System.Threading.Thread — raw thread creation bypasses the + /// per-evaluation timeout; denied type-granularly because its containing + /// namespace is System.Threading (shared with allowed types like + /// CancellationToken), so a namespace-prefix rule cannot reach it + /// without blocking unrelated types. (Core.Scripting-010.) /// /// public static readonly IReadOnlyList ForbiddenFullTypeNames = @@ -100,6 +108,11 @@ public static class ForbiddenTypeAnalyzer "System.AppDomain", "System.GC", "System.Activator", + // System.Threading.Thread lives in the System.Threading namespace (shared with + // CancellationToken, SemaphoreSlim, etc.), so a namespace-prefix deny-list cannot + // target it without blocking those legitimate types. Denied type-granularly here. + // (Core.Scripting-010.) + "System.Threading.Thread", ]; ///