fix(security): deny Environment/GC and ADO.NET provider namespaces; close reflection-gateway list (GetTypes/EntryPoint/Declared*/DynamicInvoke)

Claude-Session: https://claude.ai/code/session_01MtdgwpEeCUn6cUA5f1LMPj
This commit is contained in:
Joseph Doherty
2026-07-09 15:38:12 -04:00
parent dbd3ed2fc7
commit d19ab93d39
4 changed files with 80 additions and 3 deletions
@@ -42,6 +42,23 @@ public static class ScriptTrustPolicy
"System.Net",
"System.Runtime.InteropServices",
"Microsoft.Win32",
// Whole type — no legitimate script use. Exposes process control
// (Exit/FailFast), the host environment, and secrets via environment
// variables (SCADABRIDGE_API_KEY). Callers needing a line break use "\n".
"System.Environment",
// Whole type — GC control (Collect, KeepAlive, memory pressure knobs) has
// no legitimate script use.
"System.GC",
// Concrete ADO.NET provider namespaces. Scripts reach a DbConnection ONLY
// via the Database helper, whose abstract System.Data.Common types stay
// allowed; forbidding the concrete providers closes the arbitrary-host
// `new SqlConnection("Server=attacker")` channel. Deliberately NOT
// forbidding System.Data or System.Data.Common broadly — only these
// concrete provider namespaces.
"Microsoft.Data",
"System.Data.SqlClient",
"System.Data.Odbc",
"System.Data.OleDb",
];
/// <summary>
@@ -85,6 +102,18 @@ public static class ScriptTrustPolicy
"GetRuntimeMethods",
"MethodHandle",
"TypeHandle",
"GetTypes",
"EntryPoint",
"DeclaredMethods",
"DeclaredMembers",
"DeclaredConstructors",
"DynamicInvoke",
// DELIBERATELY EXCLUDED: "Invoke". The syntactic pass rejects a gateway
// member regardless of receiver, and delegate.Invoke() is a legitimate,
// common script pattern (Func<>/Action<> invocation). MethodInfo.Invoke
// (the reflection late-bind) is already caught semantically via the
// System.Reflection scope, so excluding "Invoke" here avoids a
// false-positive blast radius without weakening the reflection deny-list.
};
/// <summary>