Pipeline - Script Security

Issue

  • What is Sandbox mode?
  • How does script security affect Pipeline job types?
  • How do I know if I am running in the Groovy Sandbox?
  • Why am I getting RejectedAccessException?
  • In what order are blacklists and whitelists applied?
  • Why can’t I approve a script?
  • How are Shared Libraries affected by Script Security?
  • What does catching RejectedAccessException do?
  • Why is a whitelisted method rejected when running in the Groovy Sandbox?

Environment

Related

Resolution

What is Sandbox mode?

For Groovy CPS DSL, you have two modes: with or without sandbox. These are very different. Without the sandbox, the whole script must be approved, or this is done implicitly if the edit is done by an administrator.
With the sandbox, every method call (etc.) must be approved, regardless of user. For Groovy CPS DSL from SCM, currently only sandbox mode is offered.

JENKINS-28178 tracks alternatives.

Script Security - User’s Guide gives more context.

How does script security affect Pipeline job types?

Pipeline jobs can opt-in to “Use Groovy Sandbox”:

If checked, run this Groovy script in a sandbox with limited abilities. If unchecked, and you are not a Jenkins administrator, you will need to wait for an administrator to approve the script.

- Taken from help-sandbox

Multi-branch Pipeline jobs or Pipelines from SCM, currently only sandbox mode is offered. See the discussion in JENKINS-28178.

This means that these jobs may have their execution rejected. Users will see the results as RejectedAccessExceptions in the console output.

How do I know if I am running in the Groovy Sandbox?

If its a multi-branch Pipeline job, then the answer is currently (August 2018) yes!

Otherwise, there are a couple of ways to check:

  • Look at the job config in the UI - Is “Use Groovy Sandbox” selected?
  • Look at the job config.xml directly - Either by appending /config.xml to the job URL, or by navigating directly to $JENKINS_HOME/jobs/<job_name>/config.xml. There, look for <sandbox>true</sandbox>, or <sandbox>false</sandbox>.

Why am I getting RejectedAccessException?

Scripts run inside the Sandbox are subject to the following:

  • generic-whitelist - This file contains a list of accepted Groovy methods. Any attempt to use a Groovy method not listed here will result in a RejectedAccessException.
  • jenkins-whitelist - This file contains a list of accepted Jenkins methods. Any attempt to use a Jenkins method not listed here will result in a ‘RejectedAccessException’.
  • blacklist - This file contains a list of methods that are explicitly not allowed.

In what order are blacklists and whitelists applied?

Blacklists are not “applied”. This is merely a list of methods which we know should never be added to a custom whitelist. There is no runtime effect beyond a warning displayed if you were to go to approve such a method. The runtime system is a whitelist one—nothing is permitted unless it is in some whitelist.

Why can’t I approve a script?

This is caused by jobs running inside the Sandbox that also uses unsafe methods (see “Why am I getting RejectedAccessException?”). Jobs running inside the Sandbox cannot have unsafe methods approved.

For Groovy CPS DSL from SCM, currently only sandbox mode is offered.

How are Shared Libraries affected by Script Security?

Shared Libraries are either considered “trusted”, or not, depending on where they are declared.

Trusted, in this context, means that the execution is run outside of the sandbox.

Global Shared Libraries are always considered trusted.

Folder-level Shared Libraries are not considered trusted.

Shared libraries are all outside the sandbox. If you catch a RejectedAccessException and don’t throw it onward to cause the build to fail, you’ll never get the actual script approval for it.

What does catching RejectedAccessException do?

This can dangerous, depending on what you do with the exception.

An example scenario:

try {
	// some step(s) that may fail
} catch(e) {
	// catch exception
}

The above uses Groovy syntax sugar in the catch block, to basically say, “catch all exceptions”.

Anywhere in a Pipeline that catches exceptions needs to make sure they re-throw RejectedAccessExceptions.

For example, amending the previous example:

try {
	// some step(s) that may fail
} catch(e) {
	if (e instanceof RejectedAccessException) {
		throw e
	}
}

The above could also be written as:

try {
	// some step(s) that may fail
} catch(RejectedAccessException e) {
	throw e	
} catch(e) {
	// catch exception
}

Using the instanceof approach probably performs slightly better, but the difference will be negligible.

So why are we doing this?

RejectedAccessExceptions that are never thrown during a build never make it to Script Approval to add to the pending list. See also Why am I unable to see a method in In-process Script Approval?

Why is a whitelisted method rejected when running in the Groovy Sandbox?

It’s possible this is caused by no configured ACL.

Running Pipelines allows access to ACL-aware methods. See ACL-aware methods section of Script Security wiki for details.

When using the Approve assuming permission check option, it is expected that Access Control is already configured. If no Access Control is configured then Jenkins cannot perform the required access control checks.

See also https://jenkins.io/doc/book/managing/script-approval/#approve-assuming-permissions-check

Have more questions? Submit a request

0 Comments

Please sign in to leave a comment.