jenkinsci / jenkinsci/workflow-cps-plugin
[JENKINS-71524] Using a method reference in a parallel step causes a script security exception
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 186
- Forks
- 212
- Avg merge
- 12h 12m
- Merged PRs (30d)
- 8
Description
When using a method reference as the value in a parallel step's map, I get a SecurityException.
Repro case:
A pipeline job with sandbox enabled and this script
def a() {
println 'hello world'
}
(this.&a)() // this is fine
parallel(['a': { -> this.a() }]) // this is also fine
parallel(['a': this.&a]) // throws SecurityException
Will throw an exception with this stack
java.lang.SecurityException: Rejecting unsandboxed method call: WorkflowScript.a() at org.kohsuke.groovy.sandbox.impl.RejectEverythingInterceptor.onMethodCall(RejectEverythingInterceptor.java:44) at org.kohsuke.groovy.sandbox.impl.Checker$1.call(Checker.java:178) at org.kohsuke.groovy.sandbox.impl.Checker.checkedCall(Checker.java:182) at org.kohsuke.groovy.sandbox.impl.SandboxedMethodClosure.doCall(SandboxedMethodClosure.java:26) at org.kohsuke.groovy.sandbox.impl.SandboxedMethodClosure.doCall(SandboxedMethodClosure.java:34) 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:98) at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325) at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1225) at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1034) at groovy.lang.Closure.call(Closure.java:420) at groovy.lang.Closure.call(Closure.java:414) at org.jenkinsci.plugins.workflow.cps.CpsBodyExecution.launch(CpsBodyExecution.java:134) at org.jenkinsci.plugins.workflow.cps.CpsBodyInvoker.launch(CpsBodyInvoker.java:188) at org.jenkinsci.plugins.workflow.cps.DSL$ThreadTaskImpl.lambda$invokeBodiesAndSwitchToAsyncMode$0(DSL.java:784) at org.jenkinsci.plugins.workflow.cps.CpsStepContext.withBodyInvokers(CpsStepContext.java:534) at org.jenkinsci.plugins.workflow.cps.DSL$ThreadTaskImpl.invokeBodiesAndSwitchToAsyncMode(DSL.java:774) at org.jenkinsci.plugins.workflow.cps.DSL$ThreadTaskImpl.eval(DSL.java:739) at org.jenkinsci.plugins.workflow.cps.CpsThread.runNextChunk(CpsThread.java:198) at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.run(CpsThreadGroup.java:420) at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:330) at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:294) at org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService$2.call(CpsVmExecutorService.java:67) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at hudson.remoting.SingleLaneExecutorService$1.run(SingleLaneExecutorService.java:139) at jenkins.util.ContextResettingExecutorService$1.run(ContextResettingExecutorService.java:30) at jenkins.security.ImpersonatingExecutorService$1.run(ImpersonatingExecutorService.java:70) at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) at java.base/java.lang.Thread.run(Thread.java:829)
This same job will work correctly without the sandbox.
This works correctly, even with the sandbox, on our previous Jenkins:
Jenkins 2.121.2 workflow-cps-plugin 2.61 script-security-plugin 1.49
(yes it's been a hot minute since the last upgrade)
Originally reported by sean_sutherland, imported from: Using a method reference in a parallel step causes a script security exception
- status: Open
- priority: Major
- component(s): script-security-plugin, workflow-cps-plugin
- resolution: Unresolved
- votes: 1
- watchers: 2
- imported: 2025-12-07
Raw content of original issue
When using a method reference as the value in a parallel step's map, I get a SecurityException. Repro case:
A pipeline job with sandbox enabled and this script
def a() { println 'hello world' } (this.&a)() // this is fine parallel(['a': { -> this.a() }]) // this is also fine parallel(['a': this.&a]) // throws SecurityExceptionWill throw an exception with this stack
java.lang.SecurityException: Rejecting unsandboxed method call: WorkflowScript.a() at org.kohsuke.groovy.sandbox.impl.RejectEverythingInterceptor.onMethodCall(RejectEverythingInterceptor.java:44) at org.kohsuke.groovy.sandbox.impl.Checker$1.call(Checker.java:178) at org.kohsuke.groovy.sandbox.impl.Checker.checkedCall(Checker.java:182) at org.kohsuke.groovy.sandbox.impl.SandboxedMethodClosure.doCall(SandboxedMethodClosure.java:26) at org.kohsuke.groovy.sandbox.impl.SandboxedMethodClosure.doCall(SandboxedMethodClosure.java:34) 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:98) at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325) at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1225) at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1034) at groovy.lang.Closure.call(Closure.java:420) at groovy.lang.Closure.call(Closure.java:414) at org.jenkinsci.plugins.workflow.cps.CpsBodyExecution.launch(CpsBodyExecution.java:134) at org.jenkinsci.plugins.workflow.cps.CpsBodyInvoker.launch(CpsBodyInvoker.java:188) at org.jenkinsci.plugins.workflow.cps.DSL$ThreadTaskImpl.lambda$invokeBodiesAndSwitchToAsyncMode$0(DSL.java:784) at org.jenkinsci.plugins.workflow.cps.CpsStepContext.withBodyInvokers(CpsStepContext.java:534) at org.jenkinsci.plugins.workflow.cps.DSL$ThreadTaskImpl.invokeBodiesAndSwitchToAsyncMode(DSL.java:774) at org.jenkinsci.plugins.workflow.cps.DSL$ThreadTaskImpl.eval(DSL.java:739) at org.jenkinsci.plugins.workflow.cps.CpsThread.runNextChunk(CpsThread.java:198) at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.run(CpsThreadGroup.java:420) at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:330) at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:294) at org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService$2.call(CpsVmExecutorService.java:67) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at hudson.remoting.SingleLaneExecutorService$1.run(SingleLaneExecutorService.java:139) at jenkins.util.ContextResettingExecutorService$1.run(ContextResettingExecutorService.java:30) at jenkins.security.ImpersonatingExecutorService$1.run(ImpersonatingExecutorService.java:70) at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) at java.base/java.lang.Thread.run(Thread.java:829)This same job will work correctly without the sandbox.
This works correctly, even with the sandbox, on our previous Jenkins:
Jenkins 2.121.2 workflow-cps-plugin 2.61 script-security-plugin 1.49(yes it's been a hot minute since the last upgrade)
environment
CloudBees CI Managed Controller 2.375.3.4-rolling<br/>
workflow-cps-plugin 3606.v0b_d8b_e512dcf<br/>
script-security-plugin 1229.v4880b_b_e905a_6<br/>
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the parallel step and the SandboxedMethodClosure and RejectEverythingInterceptor frames in the reported stack trace, comparing method-reference execution with the working closure and direct-call cases. Reproduce the sandboxed pipeline using the versions listed in the environment, then verify that the method reference no longer raises a SecurityException while sandbox protection remains intact.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- groovy, java
- Domain
- devtools, security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100