fix(scripting): block dangerous System types in the script sandbox (Core.Scripting-001)
ForbiddenTypeAnalyzer used only a namespace-prefix deny-list. System.Environment, System.AppDomain, System.GC and System.Activator live directly in the System namespace, which must stay allowed for primitives (Math, String, ...), so they were never caught — an operator-authored predicate could call System.Environment.Exit(0) and terminate the in-process OPC UA server. Add a type-granular deny-list (ForbiddenFullTypeNames) checked by fully-qualified type name after the namespace-prefix check; legitimate System types are unaffected. Regression tests assert scripts referencing Environment/AppDomain/GC/Activator are rejected at analysis time. Core.Scripting suite: 68/68 pass. Resolves code-review finding Core.Scripting-001 (Critical). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -29,12 +29,13 @@ public sealed class TimedScriptEvaluatorTests
|
||||
[Fact]
|
||||
public async Task Script_longer_than_timeout_throws_ScriptTimeoutException()
|
||||
{
|
||||
// Scripts can't easily do Thread.Sleep in the sandbox (System.Threading.Thread
|
||||
// is denied). But a tight CPU loop exceeds any short timeout.
|
||||
// Scripts can't reach the sandbox-denied process surface (System.Threading.Thread
|
||||
// and System.Environment are both denied — Core.Scripting-001). A tight CPU loop
|
||||
// that never returns exceeds any short timeout without touching a forbidden type.
|
||||
var inner = ScriptEvaluator<FakeScriptContext, int>.Compile(
|
||||
"""
|
||||
var end = Environment.TickCount64 + 5000;
|
||||
while (Environment.TickCount64 < end) { }
|
||||
long acc = 0;
|
||||
while (true) { acc++; if (acc < 0) break; }
|
||||
return 1;
|
||||
""");
|
||||
var timed = new TimedScriptEvaluator<FakeScriptContext, int>(
|
||||
@@ -54,8 +55,8 @@ public sealed class TimedScriptEvaluatorTests
|
||||
// paths aren't misclassified as timeouts.
|
||||
var inner = ScriptEvaluator<FakeScriptContext, int>.Compile(
|
||||
"""
|
||||
var end = Environment.TickCount64 + 10000;
|
||||
while (Environment.TickCount64 < end) { }
|
||||
long acc = 0;
|
||||
while (true) { acc++; if (acc < 0) break; }
|
||||
return 1;
|
||||
""");
|
||||
var timed = new TimedScriptEvaluator<FakeScriptContext, int>(
|
||||
@@ -119,8 +120,8 @@ public sealed class TimedScriptEvaluatorTests
|
||||
{
|
||||
var inner = ScriptEvaluator<FakeScriptContext, int>.Compile(
|
||||
"""
|
||||
var end = Environment.TickCount64 + 5000;
|
||||
while (Environment.TickCount64 < end) { }
|
||||
long acc = 0;
|
||||
while (true) { acc++; if (acc < 0) break; }
|
||||
return 1;
|
||||
""");
|
||||
var timed = new TimedScriptEvaluator<FakeScriptContext, int>(
|
||||
|
||||
Reference in New Issue
Block a user