MonkeyModdingTroop / MonkeyLoader

A convenience and extendability focused mod loader using NuGet packages.
https://monkeymoddingtroop.github.io/MonkeyLoader/index.html
GNU Lesser General Public License v3.0
10 stars 3 forks source link

Fetching nuget packages from feeds #3

Open ljoonal opened 2 months ago

ljoonal commented 2 months ago

It'd make using and updating the game packs a lot simpler if MonkeyLoader was able to have a set of trusted feeds defined and then be able to automatically update the nuget packages from it.

Banane9 commented 2 months ago

Defining feeds is already a thing, but updating would have to be implemented 😅

ljoonal commented 2 months ago

Yeah... A few big issue I feel like we might bump into:

  1. Dealing with dependencies from nuget.org or such whilst trying to only accept allow listed or "verified" mods from feeds.
  2. Conflicting packages from different feeds (say I have my own developer feed and a general community run "verified mods" feed, and my own mods end up on that as well. How do we avoid the possible conflicts with say autoupdate?)
  3. Speaking of auto updating from nuget, how can we do it in a controlled manner? Is there some engine API surface that is trusted to GamePacks, that mods don't get to access, that then implements a possible GUI or such for updates?
  4. Dealing with offline (IO) status with the update code, prepatchers & restarting & such
Banane9 commented 2 months ago
  1. Dealing with dependencies from nuget.org or such whilst trying to only accept allow listed or "verified" mods from feeds.

Currently I have it setup so there's different categories for feeds. They'd have to be checked in order was my first idea, although that's kinda funky still I think. The main possibility for issues would be (2).

2. Conflicting packages from different feeds (say I have my own developer feed and a general community run "verified mods" feed, and my own mods end up on that as well. How do we avoid the possible conflicts with say autoupdate?)

Visual Studio and such do it by storing mappings for which package was loaded from where. This would essentially be like selecting the release channel between pre-release and stable in your example.

Perhaps a UI could show which feeds offer a particular package and then allow picking which one to use.

When installing through the loader, the source has to be picked. For manually added packages, the user would have to be asked to select one or none to update from.

3. Speaking of auto updating from nuget, how can we do it in a controlled manner? Is there some engine API surface that is trusted to GamePacks, that mods don't get to access, that then implements a possible GUI or such for updates?

Sadly that isn't a thing in C#/.net - the only thing that comes to mind right now would be splitting some things out into an extra package, so that everything that depends on that would be classified as a game pack.

(Though it would of course still ultimately be accessible through reflection and such, as any modder would be aware.)

4. Dealing with offline (IO) status with the update code, prepatchers & restarting & such

The loading the package metadata step and loading assemblies step are already separated at least, so it won't require any significant changes in that regard, I hope 🤔

The dependency checking could use some additional version checking though. Currently it just checks names.
Have to watch out with the game ones though, as some of them have 0.0.0 versions, which are set to 1.0.x for the references.

ljoonal commented 2 months ago

(Though it would of course still ultimately be accessible through reflection and such, as any modder would be aware.)

True, was just trying to figure out the best way to get the message across to modders that they wouldn't really be supposed to mess with the nuget handling related code from mods, and at least reflections would stand out more prominently when reviewing/vetting mods.... I guess that the nuget management methods could be in an extra namespace that is documented clearly to not be for mods, and could have a stacktrace check of the calling assembly if want to enforce that on at least a basic level...

Banane9 commented 2 months ago

There used to be something called Code Access Security, but that's apparently deprecated since .NET 4 - I found this, but it uses AppDomains, which are a pain to deal with and would probably make modding rather impossible. In general, the whole ability to just patch anything willy nilly makes it basically impossible to create any significant security, imo.
https://learn.microsoft.com/en-us/previous-versions/dotnet/framework/code-access-security/how-to-run-partially-trusted-code-in-a-sandbox

Splitting things out into an extra package that marks something as needing to be a game pack is probably the easiest approach, and any funny reflection or patching to invoke that would make something not pass vetting.
There would have to be a warning that game packs have access to deeper functionality and as such should only be used from vetted sources.

This could also apply to configs and such, so that random mods don't go around changing other's configs. 🤔
Although that would probably be a vetting exclusion criterium anyways.

Banane9 commented 2 months ago

Found two more things, that would suggest only part of CAS is dead?

https://learn.microsoft.com/en-us/archive/blogs/shawnfa/is-cas-dead-in-net-4
https://learn.microsoft.com/en-us/archive/blogs/shawnfa/using-secannotate-to-analyze-your-assemblies-for-transparency-violations-an-example

However the documentation for the attributes states that is deprecated and isn't supported anymore (at least for .net core) https://learn.microsoft.com/en-us/dotnet/api/system.security.securitycriticalattribute?view=net-8.0

https://www.codeproject.com/Articles/329666/Things-I-learned-while-implementing-my-first-Level

ljoonal commented 2 months ago

I'd say we don't need to make it impossible to access MonkeyLoader internals, as mods have code execution already anyways, and could just change whatever files MonkeyLoader uses for storing data (insert new game pack file for example). What I do think would be good is just make it clear that they shouldn't, not that they couldn't :smile:

Banane9 commented 2 months ago

I mean, that could be prohibited with the security stuff too, but... Pain and I'm not sure if it's still supported?

Either way, the best approach would then probably be to move the internals to a separate package so it's extremely obvious when something references that 🤔