Class SandboxTransformer

java.lang.Object
org.codehaus.groovy.control.CompilationUnit.PrimaryClassNodeOperation
org.codehaus.groovy.control.customizers.CompilationCustomizer
org.kohsuke.groovy.sandbox.SandboxTransformer

public class SandboxTransformer extends org.codehaus.groovy.control.customizers.CompilationCustomizer
Transforms Groovy code at compile-time to intercept when the script interacts with the outside world.

Sometimes you'd like to run Groovy scripts in a sandbox environment, where you only want it to access limited subset of the rest of JVM. This transformation makes that possible by letting you inspect every step of the script execution when it makes method calls and property/field/array access.

Once the script is transformed, every intercepted operation results in a call to Checker, which further forwards the call to GroovyInterceptor for inspection.

To use it, add it to the CompilerConfiguration, like this:

 def cc = new CompilerConfiguration()
 cc.addCompilationCustomizers(new SandboxTransformer())
 sh = new GroovyShell(cc)
 

By default, this code intercepts everything that can be intercepted, which are:

  • Method calls (instance method and static method)
  • Object allocation (that is, a constructor call except of the form "this(...)" and "super(...)")
  • Property access (e.g., z=foo.bar, z=foo."bar") and assignment (e.g., foo.bar=z, foo."bar"=z)
  • Attribute access (e.g., z=foo.@bar) and assignments (e.g., foo.@bar=z)
  • Array access and assignment (z=x[y] and x[y]=z)

You can disable interceptions selectively by setting respective interceptXXX flags to false.

There'll be a substantial hit to the performance of the execution.

Author:
Kohsuke Kawaguchi
  • Nested Class Summary

    Nested Classes
    Modifier and Type
    Class
    Description
    static class 
     
  • Constructor Summary

    Constructors
    Constructor
    Description
     
  • Method Summary

    Modifier and Type
    Method
    Description
    void
    call(org.codehaus.groovy.control.SourceUnit source, org.codehaus.groovy.classgen.GeneratorContext context, org.codehaus.groovy.ast.ClassNode classNode)
     
    org.codehaus.groovy.ast.ClassCodeExpressionTransformer
    createVisitor(org.codehaus.groovy.control.SourceUnit source)
    Deprecated.
    org.codehaus.groovy.ast.ClassCodeExpressionTransformer
    createVisitor(org.codehaus.groovy.control.SourceUnit source, org.codehaus.groovy.ast.ClassNode clazz)
     
    void
    forbidIfFinalizer(org.codehaus.groovy.ast.MethodNode m)
    Object.finalize() is called by the JVM outside of the sandbox, so overriding it in a sandboxed script is not allowed.
    static boolean
    isKnownSafeCast(org.codehaus.groovy.ast.ClassNode type, org.codehaus.groovy.ast.expr.Expression exp)
    Return true if this cast is statically known to be safe and does not need to be checked at runtime.
    void
    processConstructors(org.codehaus.groovy.ast.ClassCodeExpressionTransformer visitor, org.codehaus.groovy.ast.ClassNode classNode)
    Apply SECURITY-582 (and part of SECURITY-1754) fix to constructors.

    Methods inherited from class org.codehaus.groovy.control.customizers.CompilationCustomizer

    getPhase

    Methods inherited from class org.codehaus.groovy.control.CompilationUnit.PrimaryClassNodeOperation

    needSortedInput

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Constructor Details

    • SandboxTransformer

      public SandboxTransformer()
  • Method Details

    • call

      public void call(org.codehaus.groovy.control.SourceUnit source, org.codehaus.groovy.classgen.GeneratorContext context, org.codehaus.groovy.ast.ClassNode classNode)
      Specified by:
      call in class org.codehaus.groovy.control.CompilationUnit.PrimaryClassNodeOperation
    • forbidIfFinalizer

      public void forbidIfFinalizer(org.codehaus.groovy.ast.MethodNode m)
      Object.finalize() is called by the JVM outside of the sandbox, so overriding it in a sandboxed script is not allowed.
    • processConstructors

      public void processConstructors(org.codehaus.groovy.ast.ClassCodeExpressionTransformer visitor, org.codehaus.groovy.ast.ClassNode classNode)
      Apply SECURITY-582 (and part of SECURITY-1754) fix to constructors. For example, given code like this:
      
       class B { }
       class A extends B {
           A(T1 p1, ..., TM pM) {
               super(U1 a1, ..., UN aN) // or `this(...)`
               ...
           }
       }
       
      processConstructors(org.codehaus.groovy.ast.ClassCodeExpressionTransformer, org.codehaus.groovy.ast.ClassNode) will transform it into something like this:
      
       class B { }
       class A extends B {
           A(T1 p1, ..., TM pM) {
               this(Checker.checkedSuperConstructor( // or `Checker.checkedThisConstructor`
                       B.class,
                       new Object[]{a1, ..., aN},
                       new Object[]{p1, ..., pM},
                       new Class<?>[]{SuperConstructorWrapper.class, T1.class, ..., TM.class}), // or `ThisConstructorWrapper.class`
                   p1, ..., pM)
           }
           A(Checker.SuperConstructorWrapper $cw, T1 p1, ..., TM pM) { // Or `Checker.ThisConstructorWrapper $cw`
               super($cw.arg(1), ... cw.arg(N)) // or `this(...)`
               ...
           }
       }
       
    • createVisitor

      @Deprecated public org.codehaus.groovy.ast.ClassCodeExpressionTransformer createVisitor(org.codehaus.groovy.control.SourceUnit source)
      Deprecated.
    • createVisitor

      public org.codehaus.groovy.ast.ClassCodeExpressionTransformer createVisitor(org.codehaus.groovy.control.SourceUnit source, org.codehaus.groovy.ast.ClassNode clazz)
    • isKnownSafeCast

      public static boolean isKnownSafeCast(org.codehaus.groovy.ast.ClassNode type, org.codehaus.groovy.ast.expr.Expression exp)
      Return true if this cast is statically known to be safe and does not need to be checked at runtime.
      See Also: