Callable
and RoleSensitive
Callable
is essentially an API of Jenkins through the controller/agent communication channel.
This lets Jenkins plugins execute complex computations on the other end of such a channel.
Care needs to be taken to prevent users able to control agent processes from exploiting this and sending a malicious Callable
to the controller for execution.
Follow the instructions in the Remoting Callables developer documentation to implement Callable
safely.
CrumbExclusion
CrumbExclusion
is an extension point that allows excluding certain URLs from CSRF protection.
Wherever possible, do not use it to allow bypassing CSRF protection.
Since Jenkins 2.96, requests using Basic authentication providing an API token do not need to provide a CSRF token (crumb).
Most of the time, only unauthenticated requests (through UnprotectedRootAction
) when integrating with external systems will need to bypass CSRF protection.
Implementations of CrumbExclusion
need to only allow bypassing CSRF protection for the specific URLs that do not need it.
Make sure that the |
When disabling CSRF protection for an endpoint receiving POST
requests, be sure to only allow performing safe actions, like informing Jenkins about events that are verified again afterwards anyway before actions are being taken.
If the URLs without CSRF protection are provided by an UnprotectedRootAction
, be sure to distinguish between authenticated and unauthenticated (anonymous) requests:
Do not allow additional access or act on objects only because the current user has permission to access them.
UnprotectedRootAction
An UnprotectedRootAction
is a RootAction
that is available even to users without Overall/Read.
Types implementing UnprotectedRootAction
should be kept minimal to reduce the surface that is publicly exposed.
Be careful to not open up access to otherwise protected objects to users lacking otherwise necessary permissions to access them by having public fields or getters.
While many types check for permissions in StaplerProxy#getTarget
, many others do not, and permission checks are expected to be implemented in the getters granting access to navigate to these objects.
See the Stapler reference documentation for how requests are handled in Jenkins.
Api
/ @Exported
When exposing objects using the Jenkins remote API, be sure to check necessary permissions in @Exported
getters and only expose objects the current user has permission to know about and access.
Do not rely on permission checks in internal APIs to exist.
Permission checks done in StaplerProxy#getTarget to control Stapler routing have no effect on Api / @Exported .
For @ExportedBean annotated types, it may therefore be necessary to implement permission checks both in StaplerProxy , as well as on getters returning this type.
|
Other programs should generally be invoked using a Launcher
instance bound to the appropriate agent through its channel.
Directly using Runtime#exec
and similar Java APIs is usually a bug and can in some cases constitute a security vulnerability:
While users with the permissions to configure and run jobs may be able to invoke arbitrary tools on those agents, they should not be able to run programs on the Jenkins controller.
Most Jenkins controllers archive artifacts on the Jenkins controller file system, so even possible constraints, such as for the command to exist on the controller’s file system, or not taking any arguments, is trivially bypassed. |
Plugins that integrate with external services may encounter problems establishing connections via HTTPS due to various SSL/TLS issues. An easy way to prevent issues due to misconfigurations is to override the hostname verifier (to not perform hostname validation) and/or trust manager (to accept all certificates).
This is a very unsafe behavior and must never be the default in plugins distributed by the Jenkins project. Ignoring SSL/TLS errors is only permitted if the following constraints are both followed:
Ignoring SSL/TLS errors is limited to the specific connections opened by the plugin.
Plugins should never cause SSL/TLS errors to be ignored for the entire Jenkins controller.
As a consequence, APIs like HttpsURLConnection#setDefaultHostnameVerifier
or HttpsURLConnection#setDefaultSSLSocketFactory
must not be called by plugins.
The only exceptions to this rule are dedicated plugins with only this purpose, like skip-certificate-check.
Ignoring SSL/TLS problems for specific connections (e.g. HttpsURLConnection#setHostnameVerifier
or HttpsURLConnection#setSSLSocketFactory
) is allowed, but users need to opt in to this behavior.
By default, SSL/TLS problems must not be ignored.
Ideally, users have fine-grained control over which connections should ignore errors. For example, if a plugin allows integrating with a set of several different remote services, ignoring SSL/TLS errors should be a per-service option, rather than a single global option.
Plugin developers need to be careful when working with user-provided content. This can take many forms, but common data formats are XML, JSON, and YAML, and are provided through potentially untrusted sources.
If you’re implementing form validation for a build step whose configuration is provided as XML, or a post-build step that processes a file in the workspace, be sure to treat the contents as not fully trusted.
ObjectInputStream
)Deserializing untrusted content can easily result in a remote code execution (RCE) vulnerability.
To prevent this, use ObjectInputStreamEx
and pass hudson.remoting.ClassFilter.DEFAULT
.
This will integrate your deserialization mechanism with JEP-200.
Note that this may require adding a hudson.remoting.ClassFilter
to your plugin that allows deserializing further safe types.
Make sure to review these types for potentially unsafe readResolve
and readObject
implementations.
If at all possible, prefer serializing object graphs using types already approved.
Be sure to review the OWASP Cheat Sheet for XML External Entity prevention and the Semgrep cheat sheet on XXE.
All content should be treated as untrusted except in very specific circumstances.
XMLUtils
provides functionality to perform common XML operations safely.
When using jackson-databind, make sure to depend on 2.10.x or newer, and only use the "safe" replacement APIs to prevent deserialization vulnerabilities: Use activateDefaultTyping
instead of enableDefaultTyping
.
See the documentation on polymorphic deserialization.
X-Stream is bundled with Jenkins.
Jenkins plugins generally should not use it directly, but only through XStream2
.
When processing YAML, be sure to look into the parser library’s security documentation. It needs to be configured to prevent the instantiation of arbitrary types.
When using SnakeYAML, make sure to never use the parameterless new Yaml()
constructor, but to pass a SafeConstructor
as argument (or otherwise restrict what can be deserialized).
Additionally, use at least version 1.26 to get denial-of-service protection ("billion laughs").
Consider depending on the SnakeYAML API Plugin instead of bundling SnakeYAML with your plugin.
Many Jenkins plugins allow the use of Groovy to extend their capabilities. For example, the Email Extension Plugin allows executing a script to determine whether an email should be sent.
All such functionality, if available to users without Overall/Administer, must integrate with Script Security Plugin.
org.codehaus.groovy.transform.ASTTransformation
Plugins such as Script Security and Pipeline:Groovy allow non-admin users of Jenkins to run scripts in a sandbox. As of late 2024, a blocklist prevents use of known unsafe AST transformations that previously caused security issues.
Plugin-contributed Groovy AST transformations, in particular those applying globally through META-INF/services
, need to be written with this in mind.
Substantial functionality that allows users to circumvent Script Security sandbox protections must not be provided by other plugins.