Headline
CVE-2022-31860: Groovy Shell Sandboxing Best Practices
An issue was discovered in OpenRemote through 1.0.4 allows attackers to execute arbitrary code via a crafted Groovy rule.
Just relying on the Security Manager does not solve all the issues. There are multiple reasons why Security Manager is unsuited. Most importantly, it relies on the assumption that critical methods already incorporate the due permission checks. As already pointed out, this is not always the case. In the Java SE API alone, there are plenty of examples; expanding the scope to further 3rd party libraries, you will rarely see good implementations performing permission checks. This cannot be retrofitted. Security Manager was designed for protecting a desktop system; in contrast, on a multi-user system, you need additional protection against attacks on other users.
A working approach is what Jenkins does: intercept all method calls and member accesses and check against a configured whitelist. This is implemented in https://github.com/jenkinsci/script-security-plugin
A crucial thing here is how to maintain a usable whitelist. The Jenkins approach works with extensive lists of method signatures (plus blacklists). While this is a conservative approach, it’s probably tedious to maintain. You should start with the smallest possible API subset that you want to offer. At best, there is a dedicated API for script users that hides all implementation details.
There are still some corner cases, in particular regarding resource exhaustion. Think for instance about the following script:
for( int x = 7; true; x *= x );
This infinite loop will keep the CPU busy while there is no method call or field assingment to be intercepted. IMHO, the best way to handle this would be to execute the script in a separate thread and stop it after a given timeout. Yes, I mean calling Thread.stop(), because interrupts will just be ignored. Finally, scripts may raise any Throwable, even checked ones whithout declaring them; you should always use catch Throwable around a script.