# Executing external Groovy script in Jenkins 2

**URL:** <https://community.jenkins.io/t/executing-external-groovy-script-in-jenkins-2/8802>\
**Category:** Ask a question\
**Tags:** question\
**Created:** [August 2, 2023, 12:32pm UTC](https://community.jenkins.io/t/executing-external-groovy-script-in-jenkins-2/8802 "2023-08-02T12:32:57Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![Nux](https://dub1.discourse-cdn.com/flex013/user_avatar/community.jenkins.io/nux/32/5165_2.png) [@Nux](https://community.jenkins.io/u/Nux)\
**Post date:** [August 2, 2023, 12:32pm UTC](https://community.jenkins.io/t/executing-external-groovy-script-in-jenkins-2/8802/1 "2023-08-02T12:32:57Z")

</div>

Hi.

I have some Groovy scripts that worked just fine in Jenkins 1.x but are now broken in 2.x. This is actually blocking my update, so I would be grateful for any suggestions on how to proceed.

I execute a system Groovy script in a post build step. The script is executed from the main instance or a node like so:  
/var/www/jenkins-groovy-helpers/JenkinsBuildHelper/UniwersalBuildChecker.groovy

I already used Permissive Script Security to try and disable additional security added in Jenkins 2.x (which honestly I don’t need as I’m the only person editing jobs).

It now breaks on this code I think:

```auto
// load class
def scriptDir = "/var/www/jenkins-groovy-helpers/JenkinsBuildHelper";
def parent = getClass().getClassLoader();
def loader = new GroovyClassLoader(parent);
def buildLogChecker = loader.parseClass(new File(scriptDir, "BuildLogChecker.groovy")).newInstance();

```

Can I load a groovy class in some other way? Or maybe I can enable some standalone/single-user/single-admin mode or something that disables all this security checks?

As you can imagine `BuildLogChecker` is used to check log, but also needs access to job description as it sets descriptions based on errors in the job log (`build.setDescription(...)`). It also sets results:

```java
if (!buildLogChecker.firstLogLines.error.isEmpty()) {
    build.setResult(Result.FAILURE);
} else if (!buildLogChecker.firstLogLines.warn.isEmpty()) {
    build.setResult(Result.UNSTABLE);
}

```

# Jenkins setup:

## Jenkins: 2.401.3 OS: Linux - 5.15.0-78-generic Java: 17.0.7 - Private Build (OpenJDK 64-Bit Server VM)

ansicolor:1.0.2  
ant:497.v94e7d9fffa\_b\_9  
antisamy-markup-formatter:159.v25b\_c67cd35fb\_  
apache-httpcomponents-client-4-api:4.5.14-150.v7a\_b\_9d17134a\_5  
bootstrap5-api:5.3.0-1  
bouncycastle-api:2.29  
branch-api:2.1122.v09cb\_8ea\_8a\_724  
build-timeout:1.31  
build-user-vars-plugin:1.9  
build-with-parameters:76.v9382db\_f78962  
caffeine-api:3.1.6-115.vb\_8b\_b\_328e59d8  
checks-api:2.0.0  
cloudbees-folder:6.815.v0dd5a\_cb\_40e0e  
command-launcher:100.v2f6722292ee8  
commons-lang3-api:3.12.0-36.vd97de6465d5b\_  
commons-text-api:1.10.0-36.vc008c8fcda\_7b\_  
copyartifact:705.v5295cffec284  
credentials:1271.v54b\_1c2c6388a\_  
credentials-binding:626.v8d9034b\_8ea\_cc  
description-setter:1.10  
display-url-api:2.3.7  
durable-task:510.v324450f8dca\_4  
echarts-api:5.4.0-5  
email-ext:2.100  
extended-choice-parameter:375.v72e4b\_a\_d33d33  
font-awesome-api:6.4.0-2  
git:5.2.0  
git-client:4.4.0  
github:1.37.1  
github-api:1.314-431.v78d72a\_3fe4c3  
github-branch-source:1728.v859147241f49  
gradle:2.8.1  
groovy:453.vcdb\_a\_c5c99890  
instance-identity:173.va\_37c494ec4e5  
ionicons-api:56.v1b\_1c8c49374e  
jackson2-api:2.15.2-350.v0c2f3f8fc595  
jakarta-activation-api:2.0.1-3  
jakarta-mail-api:2.0.1-3  
javadoc:233.vdc1a\_ec702cff  
javax-activation-api:1.2.0-6  
javax-mail-api:1.6.2-9  
jaxb:2.3.8-1  
jdk-tool:66.vd8fa\_64ee91b\_d  
jjwt-api:0.11.5-77.v646c772fddb\_0  
jquery3-api:3.7.0-1  
jsch:0.2.8-65.v052c39de79b\_2  
junit:1217.v4297208a\_a\_b\_ce  
ldap:682.v7b\_544c9d1512  
mailer:457.v3f72cb\_e015e5  
mapdb-api:1.0.9-28.vf251ce40855d  
matrix-auth:3.1.10  
matrix-project:789.v57a\_725b\_63c79  
mina-sshd-api-common:2.10.0-69.v28e3e36d18eb\_  
mina-sshd-api-core:2.10.0-69.v28e3e36d18eb\_  
okhttp-api:4.11.0-145.vcb\_8de402ef81  
pam-auth:1.10  
parameterized-trigger:2.46  
permissive-script-security:0.7  
pipeline-build-step:496.v2449a\_9a\_221f2  
pipeline-github-lib:42.v0739460cda\_c4  
pipeline-graph-analysis:202.va\_d268e64deb\_3  
pipeline-groovy-lib:656.va\_a\_ceeb\_6ffb\_f7  
pipeline-input-step:468.va\_5db\_051498a\_4  
pipeline-milestone-step:111.v449306f708b\_7  
pipeline-model-api:2.2144.v077a\_d1928a\_40  
pipeline-model-definition:2.2144.v077a\_d1928a\_40  
pipeline-model-extensions:2.2144.v077a\_d1928a\_40  
pipeline-rest-api:2.33  
pipeline-stage-step:305.ve96d0205c1c6  
pipeline-stage-tags-metadata:2.2144.v077a\_d1928a\_40  
pipeline-stage-view:2.33  
plain-credentials:143.v1b\_df8b\_d3b\_e48  
plugin-util-api:3.3.0  
postbuild-task:1.9  
postbuildscript:3.2.0-460.va\_fda\_0fa\_26720  
publish-over:0.22  
publish-over-ssh:1.25  
rebuild:320.v5a\_0933a\_e7d61  
resource-disposer:0.22  
rich-text-publisher-plugin:1.5  
role-strategy:670.vc71a\_a\_c00039e  
run-condition:1.6  
scm-api:676.v886669a\_199a\_a\_  
script-security:1251.vfe552ed55f8d  
snakeyaml-api:1.33-95.va\_b\_a\_e3e47b\_fa\_4  
ssh-credentials:305.v8f4381501156  
ssh-slaves:2.877.v365f5eb\_a\_b\_eec  
sshd:3.303.vefc7119b\_ec23  
structs:324.va\_f5d6774f3a\_d  
subversion:2.17.2  
text-finder:1.24  
text-finder-run-condition:6.vdf94e6f8d2c3  
throttle-concurrents:2.14  
timestamper:1.25  
token-macro:359.vb\_cde11682e0c  
trilead-api:2.84.v72119de229b\_7  
variant:59.vf075fe829ccb  
workflow-aggregator:596.v8c21c963d92d  
workflow-api:1241.v4edc8b\_44933b\_  
workflow-basic-steps:1017.vb\_45b\_302f0cea\_  
workflow-cps:3722.v85ce2a\_c6240b\_  
workflow-durable-task-step:1247.v7f9dfea\_b\_4fd0  
workflow-job:1316.vd2290d3341a\_f  
workflow-multibranch:756.v891d88f2cd46  
workflow-scm-step:415.v434365564324  
workflow-step-api:639.v6eca\_cd8c04a\_a\_  
workflow-support:848.v5a\_383b\_d14921  
ws-cleanup:0.45

---

<div class="post-metadata">

**Author:** ![mawinter69](https://dub1.discourse-cdn.com/flex013/user_avatar/community.jenkins.io/mawinter69/32/1625_2.png) [@mawinter69](https://community.jenkins.io/u/mawinter69)\
**Post date:** [August 2, 2023, 2:14pm UTC](https://community.jenkins.io/t/executing-external-groovy-script-in-jenkins-2/8802/2 "2023-08-02T14:14:35Z")

</div>

How exactly are you executing the post build groovy script. Are your jobs freestyle jobs or already pipeline?

---

<div class="post-metadata">

**Author:** ![mawinter69](https://dub1.discourse-cdn.com/flex013/user_avatar/community.jenkins.io/mawinter69/32/1625_2.png) [@mawinter69](https://community.jenkins.io/u/mawinter69)\
**Post date:** [August 2, 2023, 2:26pm UTC](https://community.jenkins.io/t/executing-external-groovy-script-in-jenkins-2/8802/3 "2023-08-02T14:26:45Z")

</div>

Also what is the exact error message you get?

---

<div class="post-metadata">

**Author:** ![Nux](https://dub1.discourse-cdn.com/flex013/user_avatar/community.jenkins.io/nux/32/5165_2.png) [@Nux](https://community.jenkins.io/u/Nux)\
**Post date:** [August 2, 2023, 5:47pm UTC](https://community.jenkins.io/t/executing-external-groovy-script-in-jenkins-2/8802/4 "2023-08-02T17:47:26Z")

</div>

It’s a freestyle job. I actually have a lot of jobs using this script.

The message from Jenkins 2.x says:

> [PostBuildScript] - [INFO] Executing post build scripts.  
> ERROR: Build step failed with exception  
> groovy.lang.MissingMethodException: No signature of method: java.lang.Class.newInstance() is applicable for argument types: (java.util.LinkedHashMap) values: [[ignoreMode:false, ignoreLevels:, maxLevel:error]]  
> Possible solutions: newInstance(), newInstance(), newInstance([Ljava.lang.Object;), isInstance(java.lang.Object)  
> at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onMethodCall(SandboxInterceptor.java:159)

I’m exectuing this as a set of scripts.

 ![obraz](https://europe1.discourse-cdn.com/flex013/uploads/jenkins/original/2X/1/1cfe89552b5db3d778799b4e19f0288fa32fd6c5.png)

---

<div class="post-metadata">

**Author:** ![mawinter69](https://dub1.discourse-cdn.com/flex013/user_avatar/community.jenkins.io/mawinter69/32/1625_2.png) [@mawinter69](https://community.jenkins.io/u/mawinter69)\
**Post date:** [August 2, 2023, 6:12pm UTC](https://community.jenkins.io/t/executing-external-groovy-script-in-jenkins-2/8802/5 "2023-08-02T18:12:52Z")

</div>

Have you unchecked the `Run in Groovy Sandbox`. This is a must to avoid that script security denies access to most Jenkins internals.

---

<div class="post-metadata">

**Author:** ![Nux](https://dub1.discourse-cdn.com/flex013/user_avatar/community.jenkins.io/nux/32/5165_2.png) [@Nux](https://community.jenkins.io/u/Nux)\
**Post date:** [August 2, 2023, 7:50pm UTC](https://community.jenkins.io/t/executing-external-groovy-script-in-jenkins-2/8802/6 "2023-08-02T19:50:54Z")

</div>

I’m running a script from a file and the file is common for a lot of jobs. I don’t have the Sandbox option for running a file (only for runing Groovy command)

---

<div class="post-metadata">

**Author:** ![bpedersen2](https://dub1.discourse-cdn.com/flex013/user_avatar/community.jenkins.io/bpedersen2/32/367_2.png) [@bpedersen2](https://community.jenkins.io/u/bpedersen2)\
**Post date:** [August 3, 2023, 7:21am UTC](https://community.jenkins.io/t/executing-external-groovy-script-in-jenkins-2/8802/7 "2023-08-03T07:21:38Z")

</div>

You probably should consider switching to modern and supported ways to achieve your goals instead ( as you did a extremly huge jump in versions, actually over 8 years in time). I recommend switching to use the warningsng plugin to do any build log evaluation.

and check e.g. [Dodging Security Issues of the Jenkins Groovy Plugin – A Java Developer's Weblog](http://blog.ehrnhoefer.com/2017-04-23-jenkins-groovy-security/)

---

<div class="post-metadata">

**Author:** ![Nux](https://dub1.discourse-cdn.com/flex013/user_avatar/community.jenkins.io/nux/32/5165_2.png) [@Nux](https://community.jenkins.io/u/Nux)\
**Post date:** [August 3, 2023, 9:33am UTC](https://community.jenkins.io/t/executing-external-groovy-script-in-jenkins-2/8802/8 "2023-08-03T09:33:24Z")

</div>

Hmm… It sounds like running Groovy scripts is no longer a viable option, and I need to create plugins instead. Or am I missing the point?

Security-wise, this seems a bit concerning. If users can edit jobs, they can potentially add shell scripts that could cause more damage than just breaking a Jenkins installation. While you can set up Jenkins nodes with a DMZ for strict security, it’s not required by Jenkins and admin can decide on what is safe. Blocking execution of Groovy scripts in a specific way without a clear opt-out option, while keeping shell script executions free, seems like a peculiar move (since both basically have the same security risks).

The article below only confirms my fears that once you allow certain functions, they are permitted in all jobs to be used in any way, rather than just allowing the execution of specific scripts that the admin confirmed were safe. And it seems, it is no longer possible to perform maintenance of Jenkins from within Jenkins using Groovy scripts, right? Or did any of this improve since 2017?

> **[Dodging Security Issues of the Jenkins Groovy Plugin](http://blog.ehrnhoefer.com/2017-04-23-jenkins-groovy-security/)**
>
> The recent Jenkins security advisory discloses a (quite obvious, in retrospect) security issue regarding the “Execute system Groovy script” build step (SECURITY-292).
> The recommended solution is to update the Groovy plugin to version 2.0+, which...

---

<div class="post-metadata">

**Author:** ![mawinter69](https://dub1.discourse-cdn.com/flex013/user_avatar/community.jenkins.io/mawinter69/32/1625_2.png) [@mawinter69](https://community.jenkins.io/u/mawinter69)\
**Post date:** [August 3, 2023, 9:50am UTC](https://community.jenkins.io/t/executing-external-groovy-script-in-jenkins-2/8802/9 "2023-08-03T09:50:50Z")

</div>

system groovy scripts still work in latest Jenkins (I’m making heavy use of this). It might be just your specific use case with trying to load a groovy script from within another groovy script that is broken. This might be related to having a newer groovy packaged now compared to your old Jenkins.

---

<div class="post-metadata">

**Author:** ![Nux](https://dub1.discourse-cdn.com/flex013/user_avatar/community.jenkins.io/nux/32/5165_2.png) [@Nux](https://community.jenkins.io/u/Nux)\
**Post date:** [August 3, 2023, 9:55am UTC](https://community.jenkins.io/t/executing-external-groovy-script-in-jenkins-2/8802/10 "2023-08-03T09:55:47Z")

</div>

How do you mange running same script in multiple tasks then?

---

<div class="post-metadata">

**Author:** ![mawinter69](https://dub1.discourse-cdn.com/flex013/user_avatar/community.jenkins.io/mawinter69/32/1625_2.png) [@mawinter69](https://community.jenkins.io/u/mawinter69)\
**Post date:** [August 3, 2023, 10:23am UTC](https://community.jenkins.io/t/executing-external-groovy-script-in-jenkins-2/8802/11 "2023-08-03T10:23:34Z")

</div>

we have thousands of jobs, that is impossible to maintain by hand. So we have a generator for the jobs (proprietary solution). But you can also use JobDSL to manage the jobs.  
But most jobs don’t need any groovy on our side.  
If I would have to start over again I would try to make use of pipeline and have the common parts moved into a shared library.

---

<div class="post-metadata">

**Author:** ![Nux](https://dub1.discourse-cdn.com/flex013/user_avatar/community.jenkins.io/nux/32/5165_2.png) [@Nux](https://community.jenkins.io/u/Nux)\
**Post date:** [August 7, 2023, 12:15pm UTC](https://community.jenkins.io/t/executing-external-groovy-script-in-jenkins-2/8802/12 "2023-08-07T12:15:13Z")

</div>

The problem was in another place. I thought it wasn’t able to create an instance of a loaded class, but that was not the case.

This was the class I was trying to load:

```auto
class BuildLogChecker {
	public def defaultOptions = [
		ignoreMode : false,	// e.g.: echo "[UniwersalBuildChecker] ignore:start" (reset with ignore:stop)
		ignoreLevels : [],	// e.g.: echo "[UniwersalBuildChecker] ignore:info, ignore:warn" (reset with ignore:stop)
		maxLevel : "error",	// e.g.: echo "[UniwersalBuildChecker] maxlevel:warn" (reset with maxlevel:error)
	];
	// current options
	private def options = defaultOptions.getClass().newInstance(defaultOptions);
// ...
}

```

This was not working and the exception was confusing because it was at `org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor`.

Still not sure if this a bug in the scriptsecurity plugin, but the workaround is not to use arrays like `defaultOptions` to create a new instance.

In this case I was able to use a simple function instead:

```auto
class BuildLogChecker {
	private def defaultOptions () {
		return [
			ignoreMode : false,	// e.g.: echo "[UniwersalBuildChecker] ignore:start" (reset with ignore:stop)
			ignoreLevels : [],	// e.g.: echo "[UniwersalBuildChecker] ignore:info, ignore:warn" (reset with ignore:stop)
			maxLevel : "error",	// e.g.: echo "[UniwersalBuildChecker] maxlevel:warn" (reset with maxlevel:error)
		];
	}
	// current options
	private def options = [];
	
	/**
	 * Default constructor.
	 */
	BuildLogChecker() {
		options = defaultOptions();
	}
// ...
}

```

So this works now in a Groovy script:

```auto
// load class
def scriptDir = "/var/www/jenkins-groovy-helpers/JenkinsBuildHelper";
def parent = getClass().getClassLoader();
def loader = new GroovyClassLoader(parent);
def buildLogChecker = loader.parseClass(new File(scriptDir, "BuildLogChecker.groovy")).newInstance();

```

So far so good 🙂

Permissive Security Plugin seems to mostly do it’s job, but I’ll have to do more testing.
