CVE-2022-30945
Description
Jenkins Pipeline: Groovy Plugin 2689.v434009a_31b_f1 and earlier allows loading any Groovy source files on the classpath of Jenkins and Jenkins plugins in sandboxed pipelines.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Jenkins Pipeline: Groovy Plugin allows sandbox bypass by loading arbitrary Groovy files from classpath, enabling potential code execution.
Vulnerability
Pipeline: Groovy Plugin up to version 2689.v434009a_31b_f1 allows pipelines to load any Groovy source file present on the classpath of Jenkins and its plugins, even in sandboxed pipelines. This feature was intended for Global Shared Libraries to bypass sandbox protections, but a missing allowlist permits arbitrary file loading, potentially bypassing the Groovy sandbox [1].
Exploitation
An attacker with the ability to define a sandboxed pipeline (default for untrusted users) could exploit this vulnerability if a malicious Groovy file is available on the classpath. However, the Jenkins security team has not identified any such file in Jenkins core or plugins, making successful exploitation very unlikely but not impossible [1].
Impact
Successful exploitation allows an attacker to bypass the Groovy sandbox, potentially leading to arbitrary code execution with the privileges of the Jenkins controller process, compromising confidentiality, integrity, and availability [1].
Mitigation
Fixed in Pipeline: Groovy Plugin version 2692.v76b_089ccd026, released on 2022-05-17. The fix introduces an allowlist of Groovy source files that can be loaded in pipelines; any other file is rejected. Plugin developers can extend the GroovySourceFileAllowlist extension point to add their own files [1][2][3]. All users should upgrade to the latest version.
AI Insight generated on May 21, 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 | < 2692.v76b | 2692.v76b |
Affected products
2- Jenkins project/Jenkins Pipeline: Groovy Pluginv5Range: unspecified
Patches
276b089ccd026[SECURITY-359]
1 file changed · +2 −1
src/main/java/org/jenkinsci/plugins/workflow/cps/GroovySourceFileAllowlist.java+2 −1 modified@@ -193,7 +193,8 @@ public DefaultAllowlist() throws IOException { ALLOWED_SOURCE_FILES.addAll(Arrays.asList( // pipeline-model-definition "/org/jenkinsci/plugins/pipeline/modeldefinition/agent/impl/LabelAndOtherFieldAgentScript.groovy", - "/org/jenkinsci/plugins/pipeline/modeldefinition/parser/GlobalStageNameTestConditionalScript.groovy" + "/org/jenkinsci/plugins/pipeline/modeldefinition/parser/GlobalStageNameTestConditionalScript.groovy", + "/org/jenkinsci/plugins/pipeline/modeldefinition/parser/GlobalStepCountTestConditionalScript.groovy" )); } }
76a7681702f4[SECURITY-359]
4 files changed · +343 −2
src/main/java/org/jenkinsci/plugins/workflow/cps/CpsGroovyShellFactory.java+1 −1 modified@@ -111,7 +111,7 @@ private ImportCustomizer makeImportCustomizer() { private ClassLoader makeClassLoader() { ClassLoader cl = Jenkins.get().getPluginManager().uberClassLoader; - return GroovySandbox.createSecureClassLoader(cl); + return new GroovySourceFileAllowlist.ClassLoaderImpl(execution, GroovySandbox.createSecureClassLoader(cl)); } public CpsGroovyShell build() {
src/main/java/org/jenkinsci/plugins/workflow/cps/GroovySourceFileAllowlist.java+225 −0 added@@ -0,0 +1,225 @@ +/* + * The MIT License + * + * Copyright 2022 CloudBees, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.jenkinsci.plugins.workflow.cps; + +import edu.umd.cs.findbugs.annotations.CheckForNull; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import hudson.Extension; +import hudson.ExtensionList; +import hudson.ExtensionPoint; +import hudson.Main; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Enumeration; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import jenkins.util.SystemProperties; +import org.apache.commons.lang.StringUtils; + +/** + * Determines what Groovy source files can be loaded in Pipelines. + * + * In Pipeline, the standard behavior of {@code GroovyClassLoader} would allow Groovy source files from core or plugins + * to be loaded as long as they are somewhere on the classpath. This includes things like Groovy views, which are not + * intended to be available to pipelines. When these files are loaded, they are loaded by the trusted + * {@link CpsGroovyShell} and are not sandbox-transformed, which means that allowing arbitrary Groovy source files to + * be loaded is potentially unsafe. + * + * {@link ClassLoaderImpl} blocks all Groovy source files from being loaded by default unless they are allowed by an + * implementation of this extension point. + */ +public abstract class GroovySourceFileAllowlist implements ExtensionPoint { + private static final Logger LOGGER = Logger.getLogger(GroovySourceFileAllowlist.class.getName()); + private static final String DISABLED_PROPERTY = GroovySourceFileAllowlist.class.getName() + ".DISABLED"; + @SuppressFBWarnings(value = "MS_SHOULD_BE_FINAL", justification = "Non-final for script console access") + static boolean DISABLED = SystemProperties.getBoolean(DISABLED_PROPERTY); + + /** + * Checks whether a given Groovy source file is allowed to be loaded by {@link CpsFlowExecution#getTrustedShell}. + * + * @param groovySourceFileUrl the absolute URL to the Groovy source file as returned by {@link ClassLoader#getResource} + * @return {@code true} if the Groovy source file may be loaded, {@code false} otherwise + */ + public abstract boolean isAllowed(String groovySourceFileUrl); + + public static List<GroovySourceFileAllowlist> all() { + return ExtensionList.lookup(GroovySourceFileAllowlist.class); + } + + /** + * {@link ClassLoader} that acts normally except for returning {@code null} from {@link #getResource} and + * {@link #getResources} when looking up Groovy source files if the files are not allowed by + * {@link GroovySourceFileAllowlist}. + */ + static class ClassLoaderImpl extends ClassLoader { + private static final String LOG_MESSAGE_TEMPLATE = + "Preventing {0} from being loaded without sandbox protection in {1}. " + + "To allow access to this file, add any suffix of its URL to the system property ‘" + + DefaultAllowlist.ALLOWED_SOURCE_FILES_PROPERTY + "’ (use commas to separate multiple files). If you " + + "want to allow any Groovy file on the Jenkins classpath to be accessed, you may set the system " + + "property ‘" + DISABLED_PROPERTY + "’ to true."; + + private final String owner; + + public ClassLoaderImpl(@CheckForNull CpsFlowExecution execution, ClassLoader parent) { + super(parent); + this.owner = describeOwner(execution); + } + + private static String describeOwner(@CheckForNull CpsFlowExecution execution) { + if (execution != null) { + try { + return execution.getOwner().getExecutable().toString(); + } catch (IOException e) { + // Not significant in this context. + } + } + return "unknown"; + } + + @Override + public URL getResource(String name) { + URL url = super.getResource(name); + if (DISABLED || url == null || !endsWithIgnoreCase(name, ".groovy") || isAllowed(url)) { + return url; + } + // Note: This message gets printed twice because of https://github.com/apache/groovy/blob/41b990d0a20e442f29247f0e04cbed900f3dcad4/src/main/org/codehaus/groovy/control/ClassNodeResolver.java#L184-L186. + LOGGER.log(Level.WARNING, LOG_MESSAGE_TEMPLATE, new Object[] { url, owner }); + return null; + } + + @Override + public Enumeration<URL> getResources(String name) throws IOException { + Enumeration<URL> urls = super.getResources(name); + if (DISABLED || !urls.hasMoreElements() || !endsWithIgnoreCase(name, ".groovy")) { + return urls; + } + List<URL> filteredUrls = new ArrayList<>(); + while (urls.hasMoreElements()) { + URL url = urls.nextElement(); + if (isAllowed(url)) { + filteredUrls.add(url); + } else { + LOGGER.log(Level.WARNING, LOG_MESSAGE_TEMPLATE, new Object[] { url, owner }); + } + } + return Collections.enumeration(filteredUrls); + } + + private static boolean isAllowed(URL url) { + String urlString = url.toString(); + for (GroovySourceFileAllowlist allowlist : GroovySourceFileAllowlist.all()) { + if (allowlist.isAllowed(urlString)) { + return true; + } + } + return false; + } + + private static boolean endsWithIgnoreCase(String value, String suffix) { + int suffixLength = suffix.length(); + return value.regionMatches(true, value.length() - suffixLength, suffix, 0, suffixLength); + } + } + + /** + * Allows Groovy source files used to implement DSLs in plugins that were created before + * {@link GroovySourceFileAllowlist} was introduced. + */ + @Extension + public static class DefaultAllowlist extends GroovySourceFileAllowlist { + private static final Logger LOGGER = Logger.getLogger(DefaultAllowlist.class.getName()); + private static final String ALLOWED_SOURCE_FILES_PROPERTY = DefaultAllowlist.class.getCanonicalName() + ".ALLOWED_SOURCE_FILES"; + /** + * A list containing suffixes of known-good Groovy source file URLs that need to be accessible to Pipeline code. + */ + /* Note: Actual ClassLoader resource URLs depend on environmental factors such as webroot settings and whether + * we are currently testing one of the plugins in the list, so default-allowlist only contains the path + * component of the resource URLs, and we allow any resource URL that ends with one of the entries in the list. + * + * We could try to load the exact URLs at runtime, but then we would have to account for dynamic plugin loading + * (especially when a new Jenkins controller is initialized) and the fact that workflow-cps is always a + * dependency of these plugins. + */ + static final List<String> ALLOWED_SOURCE_FILES = new ArrayList<>(); + + public DefaultAllowlist() throws IOException { + // We load custom entries first to improve performance in case .groovy is used for the property. + String propertyValue = SystemProperties.getString(ALLOWED_SOURCE_FILES_PROPERTY, ""); + for (String groovyFile : propertyValue.split(",")) { + groovyFile = StringUtils.trimToNull(groovyFile); + if (groovyFile != null) { + if (groovyFile.endsWith(".groovy")) { + ALLOWED_SOURCE_FILES.add(groovyFile); + LOGGER.log(Level.INFO, "Allowing Pipelines to access {0}", groovyFile); + } else { + LOGGER.log(Level.WARNING, "Ignoring invalid Groovy source file: {0}", groovyFile); + } + } + } + loadDefaultAllowlist(ALLOWED_SOURCE_FILES); + // Some plugins use test-specific Groovy DSLs. + if (Main.isUnitTest) { + ALLOWED_SOURCE_FILES.addAll(Arrays.asList( + // pipeline-model-definition + "/org/jenkinsci/plugins/pipeline/modeldefinition/agent/impl/LabelAndOtherFieldAgentScript.groovy", + "/org/jenkinsci/plugins/pipeline/modeldefinition/parser/GlobalStageNameTestConditionalScript.groovy" + )); + } + } + + private static void loadDefaultAllowlist(List<String> allowlist) throws IOException { + try (InputStream is = GroovySourceFileAllowlist.class.getResourceAsStream("GroovySourceFileAllowlist/default-allowlist"); + BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));) { + String line; + while ((line = reader.readLine()) != null) { + line = line.trim(); + if (!line.isEmpty() && !line.startsWith("#")) { + allowlist.add(line); + } + } + } + } + + @Override + public boolean isAllowed(String groovySourceFileUrl) { + for (String sourceFile : ALLOWED_SOURCE_FILES) { + if (groovySourceFileUrl.endsWith(sourceFile)) { + return true; + } + } + return false; + } + } + +}
src/main/resources/org/jenkinsci/plugins/workflow/cps/GroovySourceFileAllowlist/default-allowlist+53 −0 added@@ -0,0 +1,53 @@ +# This list is ordered from most popular to least popular plugin to minimize performance impact. +# pipeline-model-definition +/org/jenkinsci/plugins/pipeline/modeldefinition/ModelInterpreter.groovy +/org/jenkinsci/plugins/pipeline/modeldefinition/agent/impl/AnyScript.groovy +/org/jenkinsci/plugins/pipeline/modeldefinition/agent/impl/LabelScript.groovy +/org/jenkinsci/plugins/pipeline/modeldefinition/agent/impl/NoneScript.groovy +/org/jenkinsci/plugins/pipeline/modeldefinition/when/impl/AbstractChangelogConditionalScript.groovy +/org/jenkinsci/plugins/pipeline/modeldefinition/when/impl/AllOfConditionalScript.groovy +/org/jenkinsci/plugins/pipeline/modeldefinition/when/impl/AnyOfConditionalScript.groovy +/org/jenkinsci/plugins/pipeline/modeldefinition/when/impl/BranchConditionalScript.groovy +/org/jenkinsci/plugins/pipeline/modeldefinition/when/impl/ChangeLogConditionalScript.groovy +/org/jenkinsci/plugins/pipeline/modeldefinition/when/impl/ChangeRequestConditionalScript.groovy +/org/jenkinsci/plugins/pipeline/modeldefinition/when/impl/ChangeSetConditionalScript.groovy +/org/jenkinsci/plugins/pipeline/modeldefinition/when/impl/EnvironmentConditionalScript.groovy +/org/jenkinsci/plugins/pipeline/modeldefinition/when/impl/EqualsConditionalScript.groovy +/org/jenkinsci/plugins/pipeline/modeldefinition/when/impl/ExpressionConditionalScript.groovy +/org/jenkinsci/plugins/pipeline/modeldefinition/when/impl/IsRestartedRunConditionalScript.groovy +/org/jenkinsci/plugins/pipeline/modeldefinition/when/impl/NotConditionalScript.groovy +/org/jenkinsci/plugins/pipeline/modeldefinition/when/impl/TagConditionalScript.groovy +/org/jenkinsci/plugins/pipeline/modeldefinition/when/impl/TriggeredByConditionalScript.groovy +# pipeline-model-extensions +/org/jenkinsci/plugins/pipeline/modeldefinition/agent/CheckoutScript.groovy +# docker-workflow +/org/jenkinsci/plugins/docker/workflow/Docker.groovy +/org/jenkinsci/plugins/docker/workflow/declarative/AbstractDockerPipelineScript.groovy +/org/jenkinsci/plugins/docker/workflow/declarative/DockerPipelineFromDockerfileScript.groovy +/org/jenkinsci/plugins/docker/workflow/declarative/DockerPipelineScript.groovy +# kubernetes +/org/csanchez/jenkins/plugins/kubernetes/pipeline/KubernetesDeclarativeAgentScript.groovy +# amazon-ecs +/com/cloudbees/jenkins/plugins/amazonecs/pipeline/ECSDeclarativeAgentScript.groovy +# workflow-remote-loader: +/org/jenkinsci/plugins/workflow/remoteloader/FileLoaderDSL/FileLoaderDSLImpl.groovy +# confluence-publisher +/com/myyearbook/hudson/plugins/confluence/publishConfluence.groovy +# openshift-client +/com/openshift/jenkins/plugins/OpenShiftDSL.groovy +# ownership: +/org/jenkinsci/plugins/ownership/model/workflow/OwnershipGlobalVariable/Impl.groovy +# templating-engine: +/org/boozallen/plugins/jte/init/primitives/hooks/AnnotatedMethod.groovy +/org/boozallen/plugins/jte/init/primitives/hooks/Hooks.groovy +# datetime-constraint +/org/jenkinsci/plugins/curfew/Checkpoint.groovy +/org/jenkinsci/plugins/curfew/Curfew.groovy +# redis-notifier +/com/tsoft/jenkins/plugin/RedisClient.groovy +# alauda-pipeline +/io/alauda/jenkins/plugins/pipeline/AlaudaDSL.groovy +# alauda-devops-pipeline +/com/alauda/jenkins/plugins/AlaudaDevopsDSL.groovy +/com/alauda/jenkins/plugins/AlaudaPlatformDSL.groovy +/com/alauda/jenkins/plugins/StorageDSL.groovy
src/test/java/org/jenkinsci/plugins/workflow/cps/CpsFlowExecutionTest.java+64 −1 modified@@ -50,6 +50,7 @@ import org.hamcrest.Matchers; import org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException; import org.jenkinsci.plugins.scriptsecurity.sandbox.whitelists.Whitelisted; +import org.jenkinsci.plugins.workflow.cps.GroovySourceFileAllowlist.DefaultAllowlist; import org.jenkinsci.plugins.workflow.flow.FlowExecution; import org.jenkinsci.plugins.workflow.flow.FlowExecutionOwner; import org.jenkinsci.plugins.workflow.job.WorkflowJob; @@ -61,6 +62,8 @@ import org.jenkinsci.plugins.workflow.support.pickles.TryRepeatedly; import org.jenkinsci.plugins.workflow.test.steps.SemaphoreStep; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.hasItem; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@ -71,6 +74,7 @@ import org.junit.Rule; import org.junit.Test; import org.jvnet.hudson.test.BuildWatcher; +import org.jvnet.hudson.test.FlagRule; import org.jvnet.hudson.test.Issue; import org.jvnet.hudson.test.JenkinsRule; import org.jvnet.hudson.test.JenkinsSessionRule; @@ -83,6 +87,10 @@ public class CpsFlowExecutionTest { @ClassRule public static BuildWatcher buildWatcher = new BuildWatcher(); @Rule public JenkinsSessionRule sessions = new JenkinsSessionRule(); @Rule public LoggerRule logger = new LoggerRule(); + @Rule public FlagRule<Boolean> secretField = new FlagRule<>(() -> CpsFlowExecutionTest.SECRET, v -> CpsFlowExecutionTest.SECRET = v); + // We intentionally avoid using the static fields so that tests can call setProperty before the classes are initialized. + @Rule public FlagRule<String> groovySourceFileAllowlistDisabled = FlagRule.systemProperty("org.jenkinsci.plugins.workflow.cps.GroovySourceFileAllowlist.DISABLED"); + @Rule public FlagRule<String> groovySourceFileAllowlistFiles = FlagRule.systemProperty("org.jenkinsci.plugins.workflow.cps.GroovySourceFileAllowlist.DefaultAllowlist.ALLOWED_SOURCE_FILES"); @Test public void getCurrentExecutions() throws Throwable { sessions.then(r -> { @@ -441,7 +449,6 @@ public void configureShell(@CheckForNull CpsFlowExecution context, GroovyShell s } private void trustedShell(final boolean pos) throws Throwable { - SECRET = false; sessions.then(r -> { WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition("new foo().attempt()", true)); @@ -464,4 +471,60 @@ private void trustedShell(final boolean pos) throws Throwable { * This field shouldn't be visible to regular script. */ public static boolean SECRET; + + @Issue("SECURITY-359") + @Test public void groovySourcesCannotBeUsedByDefault() throws Throwable { + logger.record(GroovySourceFileAllowlist.class, Level.INFO).capture(100); + sessions.then(r -> { + WorkflowJob p = r.createProject(WorkflowJob.class); + p.setDefinition(new CpsFlowDefinition( + "new hudson.model.View.main()", true)); + WorkflowRun b = r.buildAndAssertStatus(Result.FAILURE, p); + r.assertLogContains("unable to resolve class hudson.model.View.main", b); + assertThat(logger.getMessages(), hasItem(containsString("/hudson/model/View/main.groovy from being loaded without sandbox protection in " + b))); + }); + } + + @Issue("SECURITY-359") + @Test public void groovySourcesCanBeUsedIfAllowlistIsDisabled() throws Throwable { + System.setProperty("org.jenkinsci.plugins.workflow.cps.GroovySourceFileAllowlist.DISABLED", "true"); + sessions.then(r -> { + WorkflowJob p = r.createProject(WorkflowJob.class); + p.setDefinition(new CpsFlowDefinition( + "new hudson.model.View.main()", true)); + WorkflowRun b = r.buildAndAssertSuccess(p); + }); + } + + @Issue("SECURITY-359") + @Test public void groovySourcesCanBeUsedIfAddedToSystemProperty() throws Throwable { + System.setProperty("org.jenkinsci.plugins.workflow.cps.GroovySourceFileAllowlist.DefaultAllowlist.ALLOWED_SOURCE_FILES", "/just/an/example.groovy,/hudson/model/View/main.groovy"); + logger.record(DefaultAllowlist.class, Level.INFO).capture(100); + sessions.then(r -> { + WorkflowJob p = r.createProject(WorkflowJob.class); + p.setDefinition(new CpsFlowDefinition( + "new hudson.model.View.main()", true)); + WorkflowRun b = r.buildAndAssertSuccess(p); + assertThat(logger.getMessages(), hasItem(containsString("Allowing Pipelines to access /hudson/model/View/main.groovy"))); + }); + } + + @Issue("SECURITY-359") + @Test public void groovySourcesCanBeUsedIfAllowed() throws Throwable { + sessions.then(r -> { + WorkflowJob p = r.createProject(WorkflowJob.class); + p.setDefinition(new CpsFlowDefinition( + "(new trusted.foo()).attempt()", true)); + WorkflowRun b = r.buildAndAssertSuccess(p); + assertTrue(SECRET); + }); + } + + @TestExtension("groovySourcesCanBeUsedIfAllowed") + public static class TestAllowlist extends GroovySourceFileAllowlist { + @Override + public boolean isAllowed(String groovyResourceUrl) { + return groovyResourceUrl.endsWith("/trusted/foo.groovy"); + } + } }
Vulnerability mechanics
Root cause
"The `GroovyClassLoader` used in sandboxed pipelines previously allowed loading any Groovy source file found on the classpath without sandbox protection."
Attack vector
An attacker with the ability to configure a Pipeline can load arbitrary Groovy source files present on the Jenkins controller or plugin classpaths. Because these files are loaded by the trusted `CpsGroovyShell` without sandbox transformation, this allows the execution of arbitrary code in the context of the Jenkins controller. This bypasses the intended security restrictions of sandboxed pipelines. [patch_id=18315]
Affected code
The vulnerability affects `CpsGroovyShellFactory.java`, which initializes the class loader for sandboxed pipelines. The fix introduces `GroovySourceFileAllowlist.java` and `ClassLoaderImpl` to restrict which Groovy source files can be loaded. [patch_id=18315] [patch_id=18316]
What the fix does
The fix introduces a new `GroovySourceFileAllowlist` extension point and a custom `ClassLoaderImpl` that wraps the standard secure class loader. This implementation intercepts requests to load `.groovy` files and verifies them against an allowlist before permitting the load. Files not on the allowlist are blocked, preventing the loading of unauthorized or sensitive Groovy source files from the classpath. [patch_id=18315] [patch_id=18316]
Preconditions
- authThe attacker must have permission to configure and execute a Pipeline.
Generated on May 17, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
6- github.com/advisories/GHSA-2xvx-rw9p-xgfcghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2022-30945ghsaADVISORY
- www.openwall.com/lists/oss-security/2022/05/17/8ghsamailing-listx_refsource_MLISTWEB
- github.com/jenkinsci/workflow-cps-plugin/commit/76a7681702f42d65f77bbaa5463f146876ea62dbghsaWEB
- github.com/jenkinsci/workflow-cps-plugin/commit/76b089ccd026b68012b0deb30c217395f7ca7dc2ghsaWEB
- www.jenkins.io/security/advisory/2022-05-17/ghsax_refsource_CONFIRMWEB
News mentions
1- Jenkins Security Advisory 2022-05-17Jenkins Security Advisories · May 17, 2022