I suggest looking into the capability security model ( https://en.wikipedia.org/wiki/Capability-based_security ) and powerboxes ( https://en.wikipedia.org/wiki/File_dialog#Powerbox ).
The gist is access is controlled via references. "Reference" in this context means what the average programmer thinks it does, memory-safe pointers like references in Java or Python, though they can be implemented in other semantically-equivalent ways. References can be 'given' (passed to your code) but not 'taken' (hence the slogan "there is no ambient authority"). It is difficult to hack or infect what you cannot access!
Powerboxes are like the standard dialog boxes we are all used to that let us do things like open or print files, only they grant permission to do something in addition to designating which thing to do it to (hence the slogan "designation is authorization"). Powerboxes let you securely do the things people do in insecure systems with ambient authority. It is important that powerboxes be impossible to unintentionally answer, which is usually achieved by having them ignore input for a short time after they appear so that users do not mindlessly click "Okay" or "Yes" and they do not accidentally answer them by having their typing elsewhere redirected to the powerbox.
Most permissions should be single-use. For example, I may want to give some poseball the ability to animate me once, but I probably do not want to let it animate me forever after. This is achieved via passing facets ( http://wiki.erights.org/wiki/Walnut/Secure_Distributed_Computing/Capability_Patterns ), which are essentially classes using the Gang of Four proxy pattern to cause an error upon an attempt to use them when certain conditions are met, almost always after a single use or when explicitly revoked.
Client-side scripts can be made secure by using installation endowments ( https://www.cs.jhu.edu/~seaborn/plash/html/shell-inst-endowment.html ). This is essentially a powerbox that asks the user to grant the permissions a program always needs for basic functionality (e.g. to read its own files). It is a part of the user designating what to install, which they would have to do in any system. It can be adjusted (for permissions that are a range or finite set) or revoked (e.g. by uninstalling the program) whenever the user desires by browsing their installed programs. They should use other powerboxes for anything not in their installation endowment.
Please also consider fixing the space and time exhaustion attacks.
To prevent space exhaustion, have a RAM quota per user and per plot and ask the programmer how much RAM their script should receive when it is rezzed. Running out of RAM quota would simply prevent the object from rezzing, preferably with a notification to the user so that they understand why this occurred. Plots that allow someone other than the owner to rez objects, like sandboxes, probably need to allow the owner to divide RAM among each resident (if any) and guests. This solves the problem of users using up all the RAM in a simulator by rezzing an infinite amount of scripts. Users can only waste their own RAM quota.
To prevent time exhaustion, use a nested round-robin scheduler. Each simulator's scheduler rotates through each user and plot. To select a script to run, it rotates through each script attached to that user or rezzed on that plot. This solves the problem of users using up all the processing time in a simulator by rezzing an infinite amount of scripts. Users can only waste their own processor time.