Re: Groovy sandboxing

Jochen Theodorou <[email protected]>
Newsgroups gmane.comp.lang.groovy.user
Message-ID <[email protected]>
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.