CVE-2018-1000866
Description
A sandbox bypass vulnerability exists in Pipeline: Groovy Plugin 2.59 and earlier in groovy-sandbox/src/main/java/org/kohsuke/groovy/sandbox/SandboxTransformer.java, groovy-cps/lib/src/main/java/com/cloudbees/groovy/cps/SandboxCpsTransformer.java that allows attackers with Job/Configure permission, or unauthorized attackers with SCM commit privileges and corresponding pipelines based on Jenkinsfiles set up in Jenkins, to execute arbitrary code on the Jenkins master JVM
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
A sandbox bypass in Jenkins Pipeline: Groovy Plugin ≤2.59 allows attackers with Job/Configure or SCM commit privileges to execute arbitrary code on the Jenkins master JVM.
Vulnerability
A sandbox bypass vulnerability exists in Pipeline: Groovy Plugin version 2.59 and earlier, in groovy-sandbox/src/main/java/org/kohsuke/groovy/sandbox/SandboxTransformer.java and groovy-cps/lib/src/main/java/com/cloudbees/groovy/cps/SandboxCpsTransformer.java [2]. The flaw allows sandboxed Groovy scripts to escape the intended security restrictions [2].
Exploitation
An attacker needs either the Job/Configure permission in Jenkins, or unauthorized access via SCM commit privileges on a repository that triggers pipelines based on Jenkinsfiles [2]. No user interaction beyond the regular pipeline execution is required; the attacker's malicious script is executed when the pipeline runs [2].
Impact
Successful exploitation allows the attacker to execute arbitrary code on the Jenkins master JVM, completely bypassing the Groovy sandbox [2]. This can lead to full compromise of the Jenkins environment and the data it processes [2].
Mitigation
A fix was released in Pipeline: Groovy Plugin version 2.60 (via commit 0eb89aaf24065dbbdf6db84516ac1a52cd435e6d) [4]. Red Hat OpenShift Container Platform 3.11.82 includes the patched plugin as part of its bug fix update (RHBA-2019:0326 [1] and RHBA-2019:0327 [3]). Users should update to the latest plugin version. No workaround is documented for unpatched versions.
AI Insight generated on May 22, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
org.jenkins-ci.plugins.workflow:workflow-cpsMaven | < 2.60 | 2.60 |
org.jenkins-ci.plugins:script-securityMaven | < 1.48 | 1.48 |
Affected products
2- ghsa-coords2 versionspkg:maven/org.jenkins-ci.plugins/script-securitypkg:maven/org.jenkins-ci.plugins.workflow/workflow-cps
< 1.48+ 1 more
- (no CPE)range: < 1.48
- (no CPE)range: < 2.60
Patches
3e1c56eb6d85d[SECURITY-1186] Integration tests.
2 files changed · +16 −2
pom.xml+2 −2 modified@@ -70,7 +70,7 @@ <git-plugin.version>3.1.0</git-plugin.version> <workflow-support-plugin.version>2.21</workflow-support-plugin.version> <scm-api-plugin.version>2.2.6</scm-api-plugin.version> - <groovy-cps.version>1.24</groovy-cps.version> + <groovy-cps.version>1.25</groovy-cps.version> <structs-plugin.version>1.17</structs-plugin.version> </properties> <dependencies> @@ -97,7 +97,7 @@ <dependency> <groupId>org.jenkins-ci.plugins</groupId> <artifactId>script-security</artifactId> - <version>1.46</version> + <version>1.48</version> </dependency> <dependency> <groupId>org.jenkins-ci.plugins</groupId>
src/test/java/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinition2Test.java+14 −0 modified@@ -522,4 +522,18 @@ public void transformedSuperClass() throws Exception { WorkflowRun r = jenkins.buildAndAssertSuccess(job); jenkins.assertLogContains("OUTPUT: ybase", r); } + + @Issue("SECURITY-1186") + @Test + public void finalizer() throws Exception { + WorkflowJob p = jenkins.jenkins.createProject(WorkflowJob.class, "p"); + p.setDefinition(new CpsFlowDefinition("class Foo {\n" + + " @Override public void finalize() {\n" + + " }\n" + + "}\n" + + "echo 'Should never get here'", true)); + WorkflowRun b = jenkins.assertBuildStatus(Result.FAILURE, p.scheduleBuild2(0)); + jenkins.assertLogContains("Object.finalize()", b); + jenkins.assertLogNotContains("Should never get here", b); + } }
16c862ae9d40[SECURITY-1186] Integration tests.
3 files changed · +62 −1
pom.xml+1 −1 modified@@ -50,7 +50,7 @@ <dependency> <groupId>org.kohsuke</groupId> <artifactId>groovy-sandbox</artifactId> - <version>1.19</version> + <version>1.20</version> <exclusions> <exclusion> <groupId>org.codehaus.groovy</groupId>
src/test/java/org/jenkinsci/plugins/scriptsecurity/sandbox/groovy/SandboxInterceptorTest.java+15 −0 modified@@ -56,6 +56,7 @@ import org.apache.commons.lang.StringUtils; import org.codehaus.groovy.control.CompilerConfiguration; +import org.codehaus.groovy.control.MultipleCompilationErrorsException; import org.codehaus.groovy.runtime.GStringImpl; import org.codehaus.groovy.runtime.InvokerHelper; import static org.hamcrest.Matchers.*; @@ -1108,4 +1109,18 @@ public void dateTimeApi() throws Exception { assertEvaluate(new GenericWhitelist(), "2007-12-03T07:15:30", "java.time.LocalDateTime.parse('2007-12-03T10:15:30').minusHours(3).format(java.time.format.DateTimeFormatter.ISO_LOCAL_DATE_TIME)"); } + @Issue("SECURITY-1186") + @Test + public void finalizer() throws Exception { + try { + evaluate(new GenericWhitelist(), "class Test { public void finalize() { } }; null"); + fail("Finalizers should be rejected"); + } catch (MultipleCompilationErrorsException e) { + assertThat(e.getErrorCollector().getErrorCount(), equalTo(1)); + Exception innerE = e.getErrorCollector().getException(0); + assertThat(innerE, instanceOf(SecurityException.class)); + assertThat(innerE.getMessage(), containsString("Object.finalize()")); + } + } + }
src/test/java/org/jenkinsci/plugins/scriptsecurity/sandbox/groovy/SecureGroovyScriptTest.java+46 −0 modified@@ -38,6 +38,8 @@ import hudson.model.FreeStyleBuild; import hudson.model.Item; import hudson.model.Result; +import hudson.model.User; +import hudson.security.ACL; import hudson.security.Permission; import hudson.tasks.BuildStepDescriptor; import hudson.tasks.Publisher; @@ -48,6 +50,7 @@ import java.util.List; import java.util.Set; import jenkins.model.Jenkins; +import jenkins.security.NotReallyRoleSensitiveCallable; import org.apache.commons.io.FileUtils; import org.apache.commons.lang.StringUtils; import org.apache.tools.ant.DirectoryScanner; @@ -803,4 +806,47 @@ public void testSandboxClassResolution() throws Exception { } } + @Issue("SECURITY-1186") + @Test public void testFinalizersForbiddenInSandbox() throws Exception { + FreeStyleProject p = r.createFreeStyleProject(); + p.getPublishersList().add(new TestGroovyRecorder( + new SecureGroovyScript("class Test { public void finalize() { } }; null", true, null))); + FreeStyleBuild b = r.assertBuildStatus(Result.FAILURE, p.scheduleBuild2(0)); + r.assertLogContains("Object.finalize()", b); + } + + @Issue("SECURITY-1186") + @Test public void testFinalizersAllowedWithWholeScriptApproval() throws Exception { + r.jenkins.setSecurityRealm(r.createDummySecurityRealm()); + MockAuthorizationStrategy mockStrategy = new MockAuthorizationStrategy(); + mockStrategy.grant(Jenkins.READ).everywhere().to("dev"); + for (Permission p : Item.PERMISSIONS.getPermissions()) { + mockStrategy.grant(p).everywhere().to("dev"); + } + r.jenkins.setAuthorizationStrategy(mockStrategy); + + final FreeStyleProject p = r.createFreeStyleProject(); + p.getPublishersList().add(new TestGroovyRecorder( + new SecureGroovyScript("class Test { public void finalize() { } }; null", false, null))); + + ACL.impersonate(User.getById("dev", true).impersonate(), new NotReallyRoleSensitiveCallable<Void, Exception>() { + public Void call() throws Exception { + FreeStyleBuild b = r.assertBuildStatus(Result.FAILURE, p.scheduleBuild2(0)); + r.assertLogContains("UnapprovedUsageException", b); + return null; + } + }); + + Set<ScriptApproval.PendingScript> ps = ScriptApproval.get().getPendingScripts(); + assertEquals(1, ps.size()); + ScriptApproval.get().approveScript(ps.iterator().next().getHash()); + + ACL.impersonate(User.getById("dev", true).impersonate(), new NotReallyRoleSensitiveCallable<Void, Exception>() { + public Void call() throws Exception { + r.assertBuildStatus(Result.SUCCESS, p.scheduleBuild2(0)); + return null; + } + }); + } + }
0eb89aaf2406[SECURITY-1186] Forbid sandboxed classes from overriding finalize.
3 files changed · +44 −8
lib/pom.xml+1 −1 modified@@ -105,7 +105,7 @@ </build> <properties> - <groovy-sandbox.version>1.17</groovy-sandbox.version> + <groovy-sandbox.version>1.20</groovy-sandbox.version> </properties> <dependencies> <dependency>
lib/src/main/java/com/cloudbees/groovy/cps/SandboxCpsTransformer.java+10 −5 modified@@ -6,18 +6,13 @@ import org.codehaus.groovy.ast.FieldNode; import org.codehaus.groovy.ast.MethodNode; import org.codehaus.groovy.ast.expr.CastExpression; -import org.codehaus.groovy.ast.expr.ConstantExpression; -import org.codehaus.groovy.ast.expr.DeclarationExpression; import org.codehaus.groovy.ast.expr.Expression; -import org.codehaus.groovy.ast.expr.TupleExpression; import org.codehaus.groovy.ast.expr.VariableExpression; import org.codehaus.groovy.ast.stmt.Statement; import org.codehaus.groovy.classgen.GeneratorContext; import org.codehaus.groovy.control.SourceUnit; import org.kohsuke.groovy.sandbox.SandboxTransformer; -import java.util.List; - /** * {@link CpsTransformer} + {@link SandboxTransformer} * @@ -47,6 +42,7 @@ protected void processConstructors(ClassNode classNode) { */ @Override protected void visitNontransformedMethod(MethodNode m) { + st.forbidIfFinalizer(m); stv.visitMethod(m); } @@ -68,6 +64,15 @@ protected void visitNontransformedStatement(Statement s) { s.visit(stv); } + /** + * Overriding to allow for rejecting {@code finalize} methods when sandboxed. + */ + @Override + public void visitMethod(MethodNode m) { + st.forbidIfFinalizer(m); + super.visitMethod(m); + } + @Override public void visitCastExpression(final CastExpression exp) { if (exp.isCoerce()) {
lib/src/test/groovy/com/cloudbees/groovy/cps/sandbox/SandboxInvokerTest.groovy+33 −2 modified@@ -10,6 +10,11 @@ import org.jvnet.hudson.test.Issue import org.kohsuke.groovy.sandbox.ClassRecorder import java.awt.Point +import org.codehaus.groovy.control.MultipleCompilationErrorsException + +import static org.hamcrest.CoreMatchers.containsString +import static org.hamcrest.CoreMatchers.equalTo +import static org.hamcrest.CoreMatchers.instanceOf /** * @author Kohsuke Kawaguchi @@ -378,12 +383,10 @@ Script1.runit(SandboxedMethodClosure) SandboxedMethodClosure.call() SandboxInvokerTest$Base.noArg() Checker:checkedCast(Class,CpsClosure,Boolean,Boolean,Boolean) -CpsClosure.call() Script1.runit(CpsClosure) CpsClosure.call() SandboxInvokerTest$Base.noArg() Checker:checkedCast(Class,SandboxedMethodClosure,Boolean,Boolean,Boolean) -SandboxedMethodClosure.call() Script1.runit(SandboxedMethodClosure) SandboxedMethodClosure.call() SandboxInvokerTest$Base.noArg() @@ -475,4 +478,32 @@ return a + b + c + d ''') == 'firstsecondthirdfourth' } + @Issue("SECURITY-1186") + @Test + void finalizerForbidden() { + try { + evalCpsSandbox('class Test { @Override public void finalize() { } }; null'); + fail("Finalizers should be rejected"); + } catch (MultipleCompilationErrorsException e) { + assertThat(e.getErrorCollector().getErrorCount(), equalTo(1)); + Exception innerE = e.getErrorCollector().getException(0); + assertThat(innerE, instanceOf(SecurityException.class)); + assertThat(innerE.getMessage(), containsString("Object.finalize()")); + } + } + + @Issue("SECURITY-1186") + @Test + void nonCpsfinalizerForbidden() { + try { + evalCpsSandbox('class Test { @Override @NonCPS public void finalize() { } }; null'); + fail("Finalizers should be rejected"); + } catch (MultipleCompilationErrorsException e) { + assertThat(e.getErrorCollector().getErrorCount(), equalTo(1)); + Exception innerE = e.getErrorCollector().getException(0); + assertThat(innerE, instanceOf(SecurityException.class)); + assertThat(innerE.getMessage(), containsString("Object.finalize()")); + } + } + }
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
8- access.redhat.com/errata/RHBA-2019:0326ghsavendor-advisoryx_refsource_REDHATWEB
- access.redhat.com/errata/RHBA-2019:0327ghsavendor-advisoryx_refsource_REDHATWEB
- github.com/advisories/GHSA-gqhm-4h93-rrhgghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2018-1000866ghsaADVISORY
- github.com/jenkinsci/script-security-plugin/commit/16c862ae9d4038a3edbd8bdfb0fd1401a509d56bghsaWEB
- github.com/jenkinsci/workflow-cps-plugin/commit/0eb89aaf24065dbbdf6db84516ac1a52cd435e6dghsaWEB
- github.com/jenkinsci/workflow-cps-plugin/commit/e1c56eb6d85d513cb24dfe188e6f592d0ff84b38ghsaWEB
- jenkins.io/security/advisory/2018-10-29/ghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.