Re: Groovy sandboxing
Jochen Theodorou <[email protected]>
| Newsgroups | gmane.comp.lang.groovy.user |
|---|---|
| Message-ID | <[email protected]> |
sorry for the late reply... but yes, I think that sounds good On 8/10/26 13:17, Paul King wrote: > I would really like to explore this further at some point but I don't > think I will have cycles before 6 GA. Jochen, what about adding a > summary of your analysis to the threat model to justify why we > consider sandboxing today as something outside the language? > > AI suggestion of what a summary could look like: > > Why not sandbox inside the language? The most complete in-language > mechanism available to Groovy would be to interpose on the > invokedynamic bootstrap, through which method calls, property gets and > extended casts are linked. That would carry a long way, and Groovy 6's > consolidation onto a single dispatch path makes it more practical than > it once was. It does not reach a guarantee. Statically compiled code > emits direct invocations and never reaches the bootstrap; AST > transformations can emit bytecode that does the same; library code not > written in Groovy is unaffected; code can spawn a further Groovy > compilation through a classloader; precompiled statically-compiled > dependencies were fixed at their own compile time; and @Grab can > introduce arbitrary artefacts. Closing any one of these does not close > the category, which is why this model treats isolation as belonging > outside the language rather than inside it. > > That doesn't really move us forward but sets the scene for if/when we > do? Thoughts? > > Paul. > > On Wed, Aug 5, 2026 at 9:26 PM Jochen Theodorou <[email protected]> wrote: >> >> On 8/3/26 21:40, ski n wrote: >> [...] >>> This library however isn't really a sandbox, but works more with >>> intecepton, than really with isolation. Though you can use blacklisting/ >>> whitelisting approaches, but those are not long term solutions. >>> I think better solutions have already been proposed here. >>> >>> To add to this information, Gilles Duboscq, researcher at Oracle writese: >>> >>> "For JVM languages there is Espresso <https://www.graalvm.org/latest/ >>> reference-manual/espresso/> which is a Truffle implementation of the JVM. >>> >>> Sandboxing it presents some challenges though, especially around native >>> code: by default espresso uses the standard java and native code of >>> OpenJDK for its standard library. >>> >>> To truly sandbox espresso, this native should either itself be sandboxed >>> or not used as all and Truffle APIs used instead. >>> >>> We did some experiments in that direction already though, with a "no- >>> native" mode that can already run some simple workloads. >>> >>> Combining this with Polyglot Isolates could be a path forward for using >>> this sandboxing with JVM languages." >>> >>> All of our Groovy are dynamically run, so we use JIT, but native is also >>> something to consider. >> Paul is currently trying to improve the usage as Groovy for native >> compilation. >> >> I spend some time looking at Espresso and found a few things that are >> insteresting. >> >> * Espresso and probably Truffel itself has a notion of host code and >> guest code. >> * Espresso replaces a lot of JDK calls in the guest with its own code. >> This is done using substitutions, not by modifying the JDK >> * Espresso builds it list of substitutions at build time of Espresso >> * guest code can not and is not supposed to influence that mechanism >> >> And for Groovy as guest going the way of substitutions this concludes to >> Groovy would have to be extending Espresso with Substitutions in >> Espresso itself, registering them at build time of Espresso. >> >> So unless we essentially form Espresso or make a Groovy variant of >> Espresso in which we add our own Substitutions this would not work. >> Though I do think it would be possible to do this. In the end I think we >> would have to change the bytecode of the SubstitutionsCollector, which >> is a generated class. Licensing could become an issue, though. >> >> The question is what we would even achieve? All method call operations, >> including the invokedynamic we use could be replaced at runtime with >> Espresso/Truffle logic and nodes. Espresso even replaces calls to native >> methods. Then any runtime compiled or precompiled Groovy program/script >> run as guest would be affected. Essentially that is the Jenkins idea, >> just on a different level. >> >> What this solution would not be able is of course to limit VM parameters >> like memory consumption. The guest can be seen as running in a >> lightweight JVM, which is the one that would have to be restricted from >> using too much CPU/Memory. >> >> And while the Espresso approach would be a more complete solution then >> the Jenkins idea it made me think that we probably have everything we >> need to achieve something similar. Almost all significant calls go >> through out invokedynamic mechanism, which means there is a central >> method, that is called to provide the JIT with a MethodHandles graph, >> used to actually do the method execution. That method is called a >> bootstrap method (just explaining for people that have no idea how >> invokedynamic works). The logic behind the bootstrap method is a runtime >> implementation detail and changing this would not require changes to >> Groovy code. We could then in theory implement some kind of >> restrictions. Currently supported would be method calls, property get, >> and extended casts. >> >> But it does not solve all cases, not even all cases of method calls. >> Static compilation bypasses this. AST Transforms could add bytecode that >> implements normal method calls (that is part of what static compilation >> does) and thus bypass this. Library code is not under our control with >> this, unless it is written in Groovy. If you somehow manage to spawn a >> Groovy in Groovy (technically possible with some class loader magic) you >> could probably bypass this. Even if you forbid static compilation, >> precompiled code with static compilation would be like any other library >> not affected, since this is on the compiler level and the compiler is >> already done for the library. And of course the worst thing, grapes >> could introduce who knows what (though that can be controlled). I am >> just trying to say, that this mechanism looks like it could do the Job, >> and probably would carry far, but by itself it is no reliable solution - >> unless you require everything in source, no library usage beyond what >> you control (especially no grapes), no AST transforms, beyond the >> builtin ones and no direct usage of Class loaders. Maybe that would then >> work out... >> >> But there are probably holes in this shield. As I said the Espresso >> variant would be much more complete just by its nature already. >> >> bye Jochen