docs(tests): fix CommentChecker findings across tests/ — 13,392 → 0 (repo-wide scan clean)
Comment/XML-doc changes only: - add summaries to ~10k test methods, fixtures, fakes and helpers (+ <param> on theories, <returns> on async Task methods, <inheritdoc/> on interface implementations the checker can resolve) - strip ~2.6k project-tracking references (WP*, P*-*, row-NN, Task N, #NN, Component-0NN) from comments, keeping the explanatory text; reword false positives in comments only - real docs on fakes implementing BCL/library interfaces (IDisposable, ILogger, IOptionsMonitor, IAsyncLifetime) - reword the last 5 src/ false positives (CWE-1236, failures-1, year-0001, M365) Only non-comment edits: four one-line nested classes split across lines so members can carry docs. Build 0 errors / 0 warnings.
This commit is contained in:
@@ -3,7 +3,7 @@ using ZB.MOM.WW.ScadaBridge.ScriptAnalysis;
|
||||
namespace ZB.MOM.WW.ScadaBridge.ScriptAnalysis.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// M3.1: adversarial + legitimate cases for the fused trust validator. Reject
|
||||
/// Adversarial + legitimate cases for the fused trust validator. Reject
|
||||
/// cases exercise the semantic pass (alias / using static / global::), the
|
||||
/// reflection-gateway hardening pass, and the namespace deny-list union; clean
|
||||
/// cases pin the allowed exceptions (Tasks, CancellationToken, Diagnostics
|
||||
@@ -11,6 +11,8 @@ namespace ZB.MOM.WW.ScadaBridge.ScriptAnalysis.Tests;
|
||||
/// </summary>
|
||||
public class ScriptTrustValidatorTests
|
||||
{
|
||||
/// <summary>Verifies that runtime escape APIs are rejected.</summary>
|
||||
/// <param name="code">The script source containing a runtime escape API call.</param>
|
||||
[Theory]
|
||||
[InlineData("object o = new object(); System.Runtime.CompilerServices.Unsafe.As<object, string>(ref o);")]
|
||||
[InlineData("System.Runtime.CompilerServices.RuntimeHelpers.GetUninitializedObject(typeof(object));")]
|
||||
@@ -22,6 +24,8 @@ public class ScriptTrustValidatorTests
|
||||
Assert.NotEmpty(ScriptTrustValidator.FindViolations(code));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that compiler-support constructs are allowed.</summary>
|
||||
/// <param name="code">The script source using compiler-support APIs.</param>
|
||||
[Theory]
|
||||
[InlineData("await System.Threading.Tasks.Task.Delay(1);")]
|
||||
[InlineData("string Name([System.Runtime.CompilerServices.CallerMemberName] string name = \"\") => name;")]
|
||||
@@ -32,6 +36,7 @@ public class ScriptTrustValidatorTests
|
||||
|
||||
// ---- Reject (non-empty violations) --------------------------------------
|
||||
|
||||
/// <summary>Verifies that a <c>using</c> of the System.IO namespace is rejected.</summary>
|
||||
[Fact]
|
||||
public void Rejects_SystemIo_Using()
|
||||
{
|
||||
@@ -39,6 +44,7 @@ public class ScriptTrustValidatorTests
|
||||
Assert.NotEmpty(ScriptTrustValidator.FindViolations(code));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a global-qualified System.IO reference is rejected.</summary>
|
||||
[Fact]
|
||||
public void Rejects_SystemIo_GlobalQualified()
|
||||
{
|
||||
@@ -46,6 +52,7 @@ public class ScriptTrustValidatorTests
|
||||
Assert.NotEmpty(ScriptTrustValidator.FindViolations(code));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that an aliased System.IO reference is rejected.</summary>
|
||||
[Fact]
|
||||
public void Rejects_SystemIo_Aliased()
|
||||
{
|
||||
@@ -53,6 +60,7 @@ public class ScriptTrustValidatorTests
|
||||
Assert.NotEmpty(ScriptTrustValidator.FindViolations(code));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a <c>using static</c> of a System.IO type is rejected.</summary>
|
||||
[Fact]
|
||||
public void Rejects_SystemIo_UsingStatic()
|
||||
{
|
||||
@@ -60,6 +68,7 @@ public class ScriptTrustValidatorTests
|
||||
Assert.NotEmpty(ScriptTrustValidator.FindViolations(code));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that reflection-gateway members are rejected on a permitted type.</summary>
|
||||
[Fact]
|
||||
public void Rejects_ReflectionGateway_OffPermittedType()
|
||||
{
|
||||
@@ -67,6 +76,7 @@ public class ScriptTrustValidatorTests
|
||||
Assert.NotEmpty(ScriptTrustValidator.FindViolations(code));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the <c>dynamic</c> keyword is rejected.</summary>
|
||||
[Fact]
|
||||
public void Rejects_Dynamic_Keyword()
|
||||
{
|
||||
@@ -74,6 +84,7 @@ public class ScriptTrustValidatorTests
|
||||
Assert.NotEmpty(ScriptTrustValidator.FindViolations(code));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that <c>Activator.CreateInstance</c> is rejected.</summary>
|
||||
[Fact]
|
||||
public void Rejects_Activator_CreateInstance()
|
||||
{
|
||||
@@ -81,6 +92,7 @@ public class ScriptTrustValidatorTests
|
||||
Assert.NotEmpty(ScriptTrustValidator.FindViolations(code));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that System.Runtime.InteropServices usage is rejected.</summary>
|
||||
[Fact]
|
||||
public void Rejects_RuntimeInteropServices()
|
||||
{
|
||||
@@ -88,6 +100,7 @@ public class ScriptTrustValidatorTests
|
||||
Assert.NotEmpty(ScriptTrustValidator.FindViolations(code));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that Microsoft.Win32 usage is rejected.</summary>
|
||||
[Fact]
|
||||
public void Rejects_MicrosoftWin32()
|
||||
{
|
||||
@@ -95,6 +108,7 @@ public class ScriptTrustValidatorTests
|
||||
Assert.NotEmpty(ScriptTrustValidator.FindViolations(code));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that <c>Thread.Sleep</c> is rejected.</summary>
|
||||
[Fact]
|
||||
public void Rejects_Threading_Thread_Sleep()
|
||||
{
|
||||
@@ -102,6 +116,7 @@ public class ScriptTrustValidatorTests
|
||||
Assert.NotEmpty(ScriptTrustValidator.FindViolations(code));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that all System.Net usage is rejected.</summary>
|
||||
[Fact]
|
||||
public void Rejects_All_SystemNet()
|
||||
{
|
||||
@@ -109,6 +124,7 @@ public class ScriptTrustValidatorTests
|
||||
Assert.NotEmpty(ScriptTrustValidator.FindViolations(code));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that reflection-gateway members are rejected on an allowed Task type.</summary>
|
||||
[Fact]
|
||||
public void Rejects_ReflectionGateway_OffAllowedTaskType()
|
||||
{
|
||||
@@ -119,6 +135,7 @@ public class ScriptTrustValidatorTests
|
||||
Assert.NotEmpty(ScriptTrustValidator.FindViolations(code));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that forbidden IO nested inside an allowed <c>Task.Run</c> lambda is rejected.</summary>
|
||||
[Fact]
|
||||
public void Rejects_ForbiddenIo_NestedInAllowedTaskRunLambda()
|
||||
{
|
||||
@@ -129,6 +146,7 @@ public class ScriptTrustValidatorTests
|
||||
Assert.NotEmpty(ScriptTrustValidator.FindViolations(code));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a forbidden mutex used as a generic argument under an allowed Tasks prefix is rejected.</summary>
|
||||
[Fact]
|
||||
public void Rejects_ForbiddenMutex_AsGenericArg_UnderAllowedTasksPrefix()
|
||||
{
|
||||
@@ -139,6 +157,7 @@ public class ScriptTrustValidatorTests
|
||||
Assert.NotEmpty(ScriptTrustValidator.FindViolations(code));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a direct threading mutex is rejected independently of <c>Thread.Sleep</c>.</summary>
|
||||
[Fact]
|
||||
public void Rejects_DirectThreadingMutex_NotThreadSleep()
|
||||
{
|
||||
@@ -148,6 +167,7 @@ public class ScriptTrustValidatorTests
|
||||
Assert.NotEmpty(ScriptTrustValidator.FindViolations(code));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that <c>FileInfo</c> used as a generic argument is rejected.</summary>
|
||||
[Fact]
|
||||
public void Rejects_ForbiddenFileInfo_AsGenericArg()
|
||||
{
|
||||
@@ -157,6 +177,7 @@ public class ScriptTrustValidatorTests
|
||||
Assert.NotEmpty(ScriptTrustValidator.FindViolations(code));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that <c>nameof</c> applied to a forbidden type is rejected.</summary>
|
||||
[Fact]
|
||||
public void Rejects_NameOf_ForbiddenType()
|
||||
{
|
||||
@@ -166,6 +187,7 @@ public class ScriptTrustValidatorTests
|
||||
Assert.NotEmpty(ScriptTrustValidator.FindViolations(code));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a qualified <c>Process</c> type reference is rejected.</summary>
|
||||
[Fact]
|
||||
public void Rejects_Process_QualifiedType()
|
||||
{
|
||||
@@ -173,6 +195,7 @@ public class ScriptTrustValidatorTests
|
||||
Assert.NotEmpty(ScriptTrustValidator.FindViolations(code));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a bare <c>Process</c> identifier introduced via a <c>using</c> is rejected.</summary>
|
||||
[Fact]
|
||||
public void Rejects_Process_BareIdentifier_ViaUsing()
|
||||
{
|
||||
@@ -185,6 +208,7 @@ public class ScriptTrustValidatorTests
|
||||
|
||||
// ---- Clean (empty violations) -------------------------------------------
|
||||
|
||||
/// <summary>Verifies that <c>Task.Delay</c> is allowed.</summary>
|
||||
[Fact]
|
||||
public void Allows_TasksDelay()
|
||||
{
|
||||
@@ -192,6 +216,7 @@ public class ScriptTrustValidatorTests
|
||||
Assert.Empty(ScriptTrustValidator.FindViolations(code));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that <c>Stopwatch</c> from System.Diagnostics is allowed while <c>Process</c> is not.</summary>
|
||||
[Fact]
|
||||
public void Allows_DiagnosticsStopwatch_NotProcess()
|
||||
{
|
||||
@@ -199,6 +224,7 @@ public class ScriptTrustValidatorTests
|
||||
Assert.Empty(ScriptTrustValidator.FindViolations(code));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that <c>CancellationTokenSource</c> is allowed.</summary>
|
||||
[Fact]
|
||||
public void Allows_CancellationTokenSource()
|
||||
{
|
||||
@@ -206,6 +232,7 @@ public class ScriptTrustValidatorTests
|
||||
Assert.Empty(ScriptTrustValidator.FindViolations(code));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that LINQ and <c>Math</c> usage is allowed.</summary>
|
||||
[Fact]
|
||||
public void Allows_LinqAndMath()
|
||||
{
|
||||
@@ -213,6 +240,7 @@ public class ScriptTrustValidatorTests
|
||||
Assert.Empty(ScriptTrustValidator.FindViolations(code));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that <c>Alarms.CurrentAsync</c> and the <c>ScriptAlarm</c> type are allowed.</summary>
|
||||
[Fact]
|
||||
public void Allows_AlarmsCurrentAsync_AndTheScriptAlarmType()
|
||||
{
|
||||
@@ -231,6 +259,7 @@ public class ScriptTrustValidatorTests
|
||||
Assert.Empty(ScriptTrustValidator.FindViolations(code));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the <c>Log</c> global is allowed.</summary>
|
||||
[Fact]
|
||||
public void Allows_TheLogGlobal()
|
||||
{
|
||||
@@ -249,6 +278,7 @@ public class ScriptTrustValidatorTests
|
||||
Assert.Empty(ScriptTrustValidator.FindViolations(code));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the forbidden scopes do not cover the Commons script surface.</summary>
|
||||
[Fact]
|
||||
public void ForbiddenScopes_DoNotCover_TheCommonsScriptSurface()
|
||||
{
|
||||
@@ -261,9 +291,9 @@ public class ScriptTrustValidatorTests
|
||||
.Namespace!.StartsWith(scope, StringComparison.Ordinal));
|
||||
}
|
||||
|
||||
// ---- ScriptAnalysis-003: adversarial bypass-vector coverage --------------
|
||||
// ---- Adversarial bypass-vector coverage --------------
|
||||
|
||||
// (a) TPA-FALLBACK DEGRADATION (the SA-001 hole). Forces Pass 1 onto the
|
||||
// (a) TPA-FALLBACK DEGRADATION (the original bypass hole). Forces Pass 1 onto the
|
||||
// minimal fallback reference set (DefaultAssemblies + ForbiddenAnchorAssemblies)
|
||||
// — the set used on a single-file/AOT/trimmed host with no TPA list — and
|
||||
// proves a BARE forbidden type inside an ALLOWED namespace is STILL caught.
|
||||
@@ -272,18 +302,20 @@ public class ScriptTrustValidatorTests
|
||||
// bare identifier — so `Process.Start` slipped the validator entirely. The
|
||||
// anchor assemblies folded into the fallback close that hole.
|
||||
|
||||
/// <summary>Verifies that the minimal fallback reference set still rejects a bare <c>Process</c> introduced via a <c>using</c>.</summary>
|
||||
[Fact]
|
||||
public void TpaFallback_StillRejects_BareProcess_ViaUsing()
|
||||
{
|
||||
// The documented forbidden-type-in-allowed-namespace case: System.Diagnostics
|
||||
// is allowed (Stopwatch/Debug), the `using` is not flagged, and `Process`
|
||||
// is a BARE identifier. Against the minimal fallback set this must still
|
||||
// be rejected — otherwise the SA-001 fallback hole is open.
|
||||
// be rejected — otherwise the fallback hole is open.
|
||||
var minimal = ScriptTrustPolicy.BuildMinimalFallbackReferences();
|
||||
var code = "using System.Diagnostics; var p = Process.Start(\"x\");";
|
||||
Assert.NotEmpty(ScriptTrustValidator.FindViolations(code, minimal));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the minimal fallback reference set still rejects a bare <c>Socket</c> introduced via a <c>using</c>.</summary>
|
||||
[Fact]
|
||||
public void TpaFallback_StillRejects_BareSocket_ViaUsing()
|
||||
{
|
||||
@@ -295,6 +327,7 @@ public class ScriptTrustValidatorTests
|
||||
Assert.NotEmpty(ScriptTrustValidator.FindViolations(code, minimal));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the minimal fallback reference set still allows <c>Stopwatch</c>.</summary>
|
||||
[Fact]
|
||||
public void TpaFallback_StillAllows_DiagnosticsStopwatch()
|
||||
{
|
||||
@@ -305,6 +338,7 @@ public class ScriptTrustValidatorTests
|
||||
Assert.Empty(ScriptTrustValidator.FindViolations(code, minimal));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the minimal fallback references resolve <c>Process</c> as a forbidden type.</summary>
|
||||
[Fact]
|
||||
public void MinimalFallbackReferences_Resolve_Process_AsForbidden()
|
||||
{
|
||||
@@ -323,6 +357,7 @@ public class ScriptTrustValidatorTests
|
||||
// (a forbidden namespace) even though it is invoked in receiver position — the
|
||||
// semantic pass resolves the reduced extension method's containing type, so the
|
||||
// forbidden namespace is caught through the invocation itself.
|
||||
/// <summary>Verifies that an extension method from a forbidden namespace is rejected.</summary>
|
||||
[Fact]
|
||||
public void Rejects_ExtensionMethod_InForbiddenNamespace()
|
||||
{
|
||||
@@ -337,6 +372,7 @@ public class ScriptTrustValidatorTests
|
||||
// VisitIdentifierName compares Identifier.ValueText, which decodes both the
|
||||
// verbatim '@' prefix and \uXXXX escapes — so neither spelling evades the
|
||||
// ForbiddenIdentifiers deny-list.
|
||||
/// <summary>Verifies that a verbatim-identifier <c>Activator</c> reference is rejected.</summary>
|
||||
[Fact]
|
||||
public void Rejects_VerbatimIdentifier_Activator()
|
||||
{
|
||||
@@ -344,6 +380,7 @@ public class ScriptTrustValidatorTests
|
||||
Assert.NotEmpty(ScriptTrustValidator.FindViolations(code));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a Unicode-escaped <c>Activator</c> identifier is rejected.</summary>
|
||||
[Fact]
|
||||
public void Rejects_UnicodeEscapedIdentifier_Activator()
|
||||
{
|
||||
@@ -356,6 +393,7 @@ public class ScriptTrustValidatorTests
|
||||
// language-feature gate: a benign `unsafe` block reaches no forbidden API, so
|
||||
// it must NOT be a false positive — while a forbidden API used INSIDE an unsafe
|
||||
// block is still caught (the walker descends into the block).
|
||||
/// <summary>Verifies that an unsafe block without forbidden APIs is allowed.</summary>
|
||||
[Fact]
|
||||
public void Allows_BenignUnsafeBlock_NoForbiddenApi()
|
||||
{
|
||||
@@ -363,6 +401,7 @@ public class ScriptTrustValidatorTests
|
||||
Assert.Empty(ScriptTrustValidator.FindViolations(code));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a forbidden API inside an unsafe block is rejected.</summary>
|
||||
[Fact]
|
||||
public void Rejects_ForbiddenApi_InsideUnsafeBlock()
|
||||
{
|
||||
@@ -375,6 +414,7 @@ public class ScriptTrustValidatorTests
|
||||
// must stay clean (the walker inspects name/member nodes, never trivia or
|
||||
// literal text). Reconstructing a forbidden API from runtime strings is outside
|
||||
// the static validator's remit (documented sandbox caveat).
|
||||
/// <summary>Verifies that a forbidden namespace mentioned only in a comment is allowed.</summary>
|
||||
[Fact]
|
||||
public void Allows_ForbiddenNamespace_InCommentOnly()
|
||||
{
|
||||
@@ -382,6 +422,7 @@ public class ScriptTrustValidatorTests
|
||||
Assert.Empty(ScriptTrustValidator.FindViolations(code));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a forbidden namespace mentioned only in a string literal is allowed.</summary>
|
||||
[Fact]
|
||||
public void Allows_ForbiddenNamespace_InStringLiteralOnly()
|
||||
{
|
||||
@@ -389,10 +430,12 @@ public class ScriptTrustValidatorTests
|
||||
Assert.Empty(ScriptTrustValidator.FindViolations(code));
|
||||
}
|
||||
|
||||
// ---- PLAN-05 Task 21: hardened deny-list additions -----------------------
|
||||
// ---- Hardened deny-list additions -----------------------
|
||||
|
||||
// Environment (whole type), GC, and the concrete ADO.NET provider namespaces
|
||||
// (Microsoft.Data / System.Data.SqlClient / .Odbc / .OleDb) are now forbidden.
|
||||
/// <summary>Verifies that scripts using hardened deny-list APIs are flagged as violations.</summary>
|
||||
/// <param name="code">The script source expected to be flagged.</param>
|
||||
[Theory]
|
||||
[InlineData("Environment.Exit(0);")]
|
||||
[InlineData("Environment.FailFast(\"x\");")]
|
||||
@@ -402,6 +445,8 @@ public class ScriptTrustValidatorTests
|
||||
|
||||
// Syntactic gateway closure (matters in TPA-degraded fallback mode): these
|
||||
// reflection-gateway members are rejected regardless of receiver.
|
||||
/// <summary>Verifies that the syntactic pass flags reflection-gateway members regardless of receiver.</summary>
|
||||
/// <param name="code">The script source expected to be flagged.</param>
|
||||
[Theory]
|
||||
[InlineData("typeof(string).Assembly.GetTypes()")]
|
||||
[InlineData("asm.EntryPoint")]
|
||||
@@ -409,6 +454,8 @@ public class ScriptTrustValidatorTests
|
||||
|
||||
// Must NOT regress legitimate scripts: Task.Delay stays allowed and
|
||||
// delegate.Invoke() is deliberately NOT on the reflection-gateway list.
|
||||
/// <summary>Verifies that legitimate scripts are not flagged as violations.</summary>
|
||||
/// <param name="code">The script source expected to be allowed.</param>
|
||||
[Theory]
|
||||
[InlineData("await Task.Delay(1);")]
|
||||
[InlineData("Func<int,int> f = x => x; f.Invoke(3);")]
|
||||
|
||||
Reference in New Issue
Block a user