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
