Вариант 1 (для олдов):
Если используется .net Framework, то можно воспользоваться стандартной штукой - AppDomain.
Просто создаёшь для этой недоверенной сборки новый AppDomain с ограниченными правами.
Примеры тут:
https://stackoverflow.com/questions/1357231/restri...
На .NET Core, 5 и 6 такое работать не будет, тк в них нет AppDomain.
Вариант 2 (просто не загружаем опасные штуки):
При помощи mono cecil можно проверить, какие методы вызываются в какой-то сторонней сборке, и просто не загружать её, если она использует что-то нелегальное (ну или заменить эти вызовы на что-то своё):
https://github.com/jbevain/cecil
Естественно, надо ещё проверить, чтобы эта сборка и в своих зависимостях тоже ничего опасного не делала
Вариант 3 (для зумеров):
В .NET Core вместо AppDomain предполагается использовать AssemblyLoadContext.
После загрузки плагина, можно посмотреть, какие ещё сборки он загрузил, и выгрузить всё, чему мы не доверяем - например System.IO.FileSystem
(Это я ещё не проверил. Обновлю ответ когда проверю, как это работает)