C
C#•6mo ago
IceReaper

Safe Plugin Loader - Forbid specific namespaces (and reflection usage)?

Im trying to wire a plugin loader where people can extend the application with custom plugins. To ensure people cannot do evil things in their plugin, i want to explicitly whitelist namespaces people can use. If anything forbidden is used in a plugin .dll, i want to reject loading it. The loading and unloading part is the easiest thing, but what about the namespace restrictions? Anyone has any idea how i can do that? Also i need to forbid the usage of .GetType or typeof() to get around reflection usage. My idea would be by either hand-parse the .dll, somehow find all namespace or function references, and evaluate this manualy as im unaware of any other method. But maybe there is?
17 Replies
Jimmacle
Jimmacle•6mo ago
if you want any level of control you cannot use precompiled code you'd be better off building a system that compiles plugins from source and uses roslyn to analyze the syntax beforehand
IceReaper
IceReaper•6mo ago
Hm.. thats also an interesting approach, but i guess shipping the whole toolchain to build project requires users - in this case gamers, as the plugins are for enhancing the game with custom mechanics - to have an sdk installed?
Jimmacle
Jimmacle•6mo ago
no, you only need to add a dependency on the relevant packages space engineers is an example of a game that does this
IceReaper
IceReaper•6mo ago
Oh, thats great to know 🙂 That defenitely sounds better then manualy parsing or using a decompiler
Jimmacle
Jimmacle•6mo ago
you could also consider a hybrid approach where you host a plugin website that devs submit source to and the analysis/compilation happens there but then the security isn't actually built into the game
IceReaper
IceReaper•6mo ago
Im building a framework for some games, not a specific game. so where the mods are located would be configurable by the one using the framework Ill just ensure the mod uses only allowed system namespaces, as for lists, dictionaries etc along the game api dll and no reflections
Jimmacle
Jimmacle•6mo ago
you may want to think about more granular control as well as in whitelisting by type or even member which would be doable with roslyn
Anchy
Anchy•6mo ago
umod is a c# modding api that has restricted namespaces, you distribute the source files and the api handles compilation like Jimmacle said maybe worth looking at I believe it's popular in the Rust (game) community
Jimmacle
Jimmacle•6mo ago
it started there afaik, used to be called oxide (because rust)
Anchy
Anchy•6mo ago
correct, I remember oxide 😄
Jimmacle
Jimmacle•6mo ago
also, another benefit of doing it the roslyn way is being able to publish those analyzers as a nuget package so plugin devs can use them to get identical errors in their IDE if they try to use something that isn't allowed
Aaron
Aaron•6mo ago
use a language designed around embedding lua, for example C# isn't designed for it, and attempts to do this, even ones built into the runtime itself (like CAS) always have issues
Jimmacle
Jimmacle•6mo ago
also that once you've loaded and executed a plugin there's no real way to unload it
Aaron
Aaron•6mo ago
and if this is for game modding (like you said a moment ago) locking things down just pushes the people who actually want to use those things for something to a different mod loader with less restrictions most unity modloaders these days have none whatsoever, with umod being the only notable exception? though it isn't really used often compared to BepInEx or Melonloader
Jimmacle
Jimmacle•6mo ago
whitelisting makes more sense if it's your game and you want to support modding in a safer way see: space engineers and the fact that i built an unrestricted plugin loader to get around it KEKW
Aaron
Aaron•6mo ago
if it's your own game, then like I said, use something made for it instead of hacking C# to do what you want having C# but it's actually a pseudo C# where you can't use most of the APIs because you never thought about the case where somebody would want it will just annoy people that know what C# normally has
IceReaper
IceReaper•6mo ago
I managed to build a solution in a single c# class which uses roslyn now. So mods have to ship the code sources. I scan the source code, check used types and functionality, verify it against a whitelist, compile the assembly in memory, and load it dynamically. works 🙂 thanks for the hint about using roslyn