review(Core.Scripting): block Unsafe.As sandbox bypass (Security)

Re-review at 7286d320. Core.Scripting-017 (Medium, Security): System.Runtime.CompilerServices.Unsafe
added to ForbiddenFullTypeNames (Unsafe.As bypasses the type system without an unsafe context;
CWE-843 type-confusion into SetVirtualTag) + regression tests (rejects Unsafe.As, still allows
benign CompilerServices attributes). -018: refresh stale rejection message. Sandbox holds.
This commit is contained in:
Joseph Doherty
2026-06-19 11:06:56 -04:00
parent 65e6af6001
commit 38c48a009c
3 changed files with 174 additions and 10 deletions
@@ -569,4 +569,46 @@ public sealed class ScriptSandboxTests
"""));
ex.Message.ShouldContain("Core.Scripting-013");
}
// --- Core.Scripting-017: System.Runtime.CompilerServices.Unsafe accessible ---
// System.Runtime.CompilerServices is not in ForbiddenNamespacePrefixes (only .InteropServices
// and .Loader are blocked). Unsafe.As<TFrom, TTo> / Unsafe.As<T>(object) allow raw type-
// reinterpretation without unsafe context at the call site — bypassing the CLR's type-safety
// checks and enabling type confusion / managed heap corruption. The fix adds
// System.Runtime.CompilerServices.Unsafe to ForbiddenFullTypeNames (type-granular, shared
// namespace with harmless CompilerServices types like CallerMemberName, MethodImpl).
/// <summary>Verifies that Unsafe.As type-reinterpretation is rejected at compile time (Core.Scripting-017).</summary>
[Fact]
public void Rejects_Unsafe_As_at_compile()
{
// System.Runtime.CompilerServices.Unsafe.As<T>(object) bypasses CLR type checks
// entirely, enabling type confusion and managed heap corruption without requiring
// 'unsafe' context at the call site. It must be blocked. (Core.Scripting-017.)
Should.Throw<ScriptSandboxViolationException>(() =>
ScriptEvaluator<FakeScriptContext, int>.Compile(
"""
var x = ctx.GetTag("X").Value;
var s = System.Runtime.CompilerServices.Unsafe.As<string>(x);
return 0;
"""));
}
/// <summary>Verifies that MethodImplAttribute (a benign CompilerServices type) is still usable (Core.Scripting-017).</summary>
[Fact]
public async Task Benign_CompilerServices_attribute_still_usable()
{
// System.Runtime.CompilerServices.MethodImplOptions is a harmless enum used
// with [MethodImpl]. Local functions in scripts can bear it. Denying only
// System.Runtime.CompilerServices.Unsafe (type-granular) must not block this.
var evaluator = ScriptEvaluator<FakeScriptContext, int>.Compile(
"""
[System.Runtime.CompilerServices.MethodImpl(
System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
static int Helper(int x) => x * 2;
return Helper(21);
""");
var result = await evaluator.RunAsync(new FakeScriptContext(), TestContext.Current.CancellationToken);
result.ShouldBe(42);
}
}