RationalGeek
RationalGeek

Reputation: 9609

Implementing untrusted plugins in .NET web application

I'd like to develop an application that accepts plugins from the user community, similar to how Chrome or Firefox does. This would be a web application, so each "instance" of the application for individual users would run different plugins (plugins would be loaded as singleton instances, but would be "active" only for certain users). I'm planning on implementing the application in .NET, and trying to come up with an architecture for the plugin model.

Here are my desired attributes:

It seems like System.AddIn is my best bet, but I am unclear on how I can force the loaded addins to only work through the API that I provide, and not load any other assemblies. Does System.AddIn provide that functionality? Also, can System.AddIn be used with ASP.NET / IIS?

What other options do I have besides System.Addin?

Upvotes: 13

Views: 426

Answers (3)

Patrick D'Souza
Patrick D'Souza

Reputation: 3571

You could try using AppDomains and handle the unhandled exceptions. To avoid appdomain crashes, you will have to handle the AppDomain.UnhandledException

In the above link, note the following statement

Starting with the .NET Framework 4, this event is not raised for exceptions that corrupt the state of the process, such as stack overflows or access violations, unless the event handler is security-critical and has the HandleProcessCorruptedStateExceptionsAttribute attribute.

So you may need to explicitly handle some configuration.

I have read a lot of issues claiming that when unhandled exceptions occur on different threads in the child domain, the bubble up and bring down the parent domain. If so, then loading all the plugins into a separate process with a appdomain per plugin or loading the plugins into separate process may be advisable.

I also came across the following question on SO that I believe you would find very helpful

Upvotes: 1

mfeingold
mfeingold

Reputation: 7134

It looks like your primary concern is isolation (for security as well as for robustness).

As such your best option here is to activate your addin in a separate AppDomain. Within this domain you can control what assemblies you would allow to be loaded (see AppDomainSetup class).

Your main code will be also protected from anything untoward happening inside a plugin: All the plugin methods will have to work with are copies of the core objects (unless objects you pass over are inherited from MarshalByRefObject, in which case all bets are off). The exceptions in the addin methods can be handled by wrapping all calls in try except, or through AppDomain's UnhandledExcption event.

Keep in mind that there is a performance penalty for crossing the AppDomain boundaries. The call is essentially a remoting call.

Another potential problem is how do you plan to manage the AppDomains. I never tried to create more than a few AppDomains in a process, but I would expect trouble here. Combining Addins for multiple users in a single domain wold challenge the protection you are trying to build into this

In response to @RationalGeek question - UnhandledException event allows to do that - sort of. You can subscribe to this event in both your core domain as well as the plugin domain, but there is a lot of uncertainties in doing it this way - see the article I referenced for more details. May be a better option would be to wrap every call to your API in try/except

Upvotes: 5

Dahlia
Dahlia

Reputation: 21

Why not just use reflection and discover available plug-ins at run time? Assembly.LoadFile to get assembly, GetExportedTypes to get your objects Create an instance with Activator.CreateInstance

Then just run the plug-in in a try loop to make sure it does not affect the system. Though you will need some significant architecture to provide actual stability.

Stay away from MEF unless you have complex scenarios for plug-in management. If it's just allowing users to use theirs and including a few of your own, just use reflection.

Upvotes: -1

Related Questions