Jenkins Attack Vector

Jenkins, an open-source automation server, is widely utilized for building, deploying, and automating any project, making it a valuable target for Advanced Persistent Threat (APT) actors. Understanding the attack vectors and surfaces within Jenkins is crucial to safeguarding the platform and protecting organizational assets. This article delves into the potential attack vectors and surfaces within Jenkins, providing insights into securing your CI/CD pipeline.
Jenkins Attack Vector

Read In This Article


Jenkins, an open-source automation server, is widely utilized for building, deploying, and automating any project, making it a valuable target for Advanced Persistent Threat (APT) actors. Understanding the attack vectors and surfaces within Jenkins is crucial to safeguarding the platform and protecting organizational assets. This article delves into the potential attack vectors and surfaces within Jenkins, providing insights into securing your CI/CD pipeline.

Attack Vectors in Jenkins

🛡️ Credential Exploits

  • Credential Stuffing: Leveraging automated login requests to illicitly gain access.
  • API Key Exposure: Unintentionally revealing API keys in public repositories or logs.

🐚 Shell Exploits

  • Remote Code Execution (RCE): Enabling attackers to execute malicious code on remote servers.
  • Script Manipulation: Injecting malicious scripts to alter processes.

🛠️ Plugin Vulnerabilities

  • Outdated Plugins: Employing plugins that are outdated or contain vulnerabilities, rendering them exploitable.
  • Misconfigured Plugins: Utilizing plugins that are incorrectly configured, thereby revealing sensitive information.

🎯 Attack Surfaces in Jenkins

User Interface (UI)

  • Web Interface: Serving as the primary interaction point for both users and administrators.
  • API Endpoints: Facilitating interaction points for automated bots and integrations.

Log Recorders

  • Logs: Managing and storing logs in a manner that prevents the exposure of sensitive information.
  • Tasks: Ensuring that logs of tasks do not inadvertently reveal sensitive data.

📜 Script Console

Script Execution: Upholding a policy where only authorized scripts traverse the execution path.

Script Access: Imposing stringent access controls to the script console, ensuring only authorized personnel can interact.

💻 Jenkins CLI

Command Execution: Safeguarding the environment by permitting only authorized command executions.

Access Control: Implementing meticulous access controls to restrict CLI access to qualified personnel.

🗝️ Credentials

Storage: Adopting robust mechanisms to ensure credentials are stored with utmost security.

Transmission: Guaranteeing that credential transmission is enveloped in secure protocols.

🐚 Shell

Command Execution: Ensuring a secure environment where shell commands are executed securely.

Script Execution: Validating and ensuring that shell scripts are executed in a secure context.

🔌 Plugins

Plugin Security: Vigilantly ensuring that plugins do not become a gateway for vulnerabilities.

Plugin Access: Implementing stringent access controls to ensure only authorized personnel can manage plugins.

🎯 APT Report: Jenkins in the Crosshairs

Advanced Persistent Threats (APTs) meticulously target Jenkins, exploiting various vectors to gain unauthorized access, exfiltrate data, or establish a stronghold within an organization’s network.

APT Scenario:

Initial Access: Employing tactics like credential stuffing or exploiting vulnerabilities.

Establishing Foothold: Strategically installing malicious plugins or scripts.

Privilege Escalation: Exploiting misconfigurations or vulnerabilities.

Data Exfiltration: Utilizing outbound connections to siphon data.

Impact: Disrupting CI/CD pipelines and inducing data theft or deploying malicious code.

📚 Case Study

Target: A high-profile e-commerce platform fell victim.

Attack Vector: A known vulnerability in a plugin was exploited.

Impact: Resulted in unauthorized access to source code and subsequent data exfiltration.

🔍 Tools

Below are some example Shodan dorks that can be utilized to discover Jenkins servers:

http.title:”Dashboard [Jenkins]”

Identifying Jenkins servers by searching for web pages with a specific title.


Locating Jenkins servers based on the distinctive hash of the favicon.

port:”8080″ product:”Jenkins”

Searching for Jenkins servers operating on port 8080.


A straightforward dork that seeks instances of Jenkins across the web.

redteam jenkins mindmap

Jenkins Important Files: A Red Teaming Perspective

Red teaming involves simulating cyber-attacks to identify vulnerabilities and weaknesses in systems before actual attackers exploit them. In the context of Jenkins, various files and directories can be of particular interest during different stages of a red team operation. Let’s explore how the mentioned files might be leveraged and additional files that might be of interest.

1. Reconnaissance Stage:


Purpose: Stores user data, including usernames and potentially information about their roles.

Red Team Use: Identifying potential user accounts to target for access.


Purpose: Contains information about default update sites and update centers.

Red Team Use: Identifying outdated plugins or configurations that can be exploited.

2. Initial Access Stage:


Purpose: Stores encrypted credentials used by Jenkins.

Red Team Use: Decrypting or leveraging credentials to gain unauthorized access.

3. Establishing Foothold Stage:


Purpose: Used for encrypting sensitive data in Jenkins.

Red Team Use: Potentially decrypting sensitive data or impersonating the Jenkins instance.

4. Privilege Escalation Stage:


Purpose: Stores configuration and status information about node monitoring.

Red Team Use: Identifying misconfigurations or vulnerabilities in node monitoring that can be exploited for privilege escalation.

5. Lateral Movement Stage:


Purpose: Contains logs of tasks performed by Jenkins.

Red Team Use: Identifying tasks that could be manipulated or identifying additional systems to target.

6. Impact Stage:


Purpose: Stores build histories and configurations for specific Jenkins jobs.

Red Team Use: Manipulating or deleting build histories to disrupt CI/CD pipelines and operations.

Additional Files of Interest:

7. Data Exfiltration Stage:


Purpose: Contains data related to the workspace of each job.

Red Team Use: Identifying sensitive data or artifacts that can be exfiltrated.

8. Persistence Stage:


Purpose: Stores Jenkins plugins and their configurations.

Red Team Use: Installing malicious plugins or manipulating existing ones to maintain access.

9. Obfuscation Stage:


Purpose: Contains global configuration options for Jenkins.

Red Team Use: Modifying configurations to obfuscate malicious activities or disable security features.

10. Cleanup Stage:


Purpose: Contains various logs related to Jenkins operations.

Red Team Use: Deleting or modifying logs to erase traces of the attack.

Jenkins: Critical Paths and API Endpoints in Red Teaming

Red teaming involves ethical hackers simulating cyber-attacks to identify and rectify vulnerabilities. In the context of Jenkins, understanding the critical paths and API endpoints is vital for both attackers and defenders. Below, we explore these aspects across various stages of red teaming.

1. Reconnaissance Stage:

Path: /bitnami/Jenkins/home/users/

Purpose: Houses user data.

Red Team Use: Identifying user accounts and roles for targeted phishing or brute-force attacks.

API Endpoint: /whoAmI/api/json

Purpose: Provides information about the authenticated user.

Red Team Use: Confirming successful authentication and gathering user details.

2. Initial Access Stage:

Path: /bitnami/Jenkins/home/secrets/

Purpose: Stores encrypted secrets.

Red Team Use: Extracting secrets for decrypting sensitive data.

API Endpoint: /securityRealm/commenceLogin

Purpose: Initiates user login.

Red Team Use: Automating login attempts for credential stuffing or brute-force attacks.

3. Establishing Foothold Stage:

Path: /bitnami/Jenkins/home/jobs/

Purpose: Contains configurations and data for Jenkins jobs.

Red Team Use: Identifying jobs to manipulate or exploit.

API Endpoint: /job/[job-name]/build

Purpose: Triggers a build for a specific job.

Red Team Use: Initiating malicious builds or disrupting CI/CD pipelines.

4. Privilege Escalation Stage:

Path: /bitnami/Jenkins/home/plugins/

Purpose: Stores Jenkins plugins and configurations.

Red Team Use: Identifying vulnerable plugins to exploit.

API Endpoint: /pluginManager/api/json

Purpose: Provides details about installed plugins.

Red Team Use: Identifying outdated or vulnerable plugins for exploitation.

5. Lateral Movement Stage:

Path: /bitnami/Jenkins/home/nodes/

Purpose: Contains data related to Jenkins nodes.

Red Team Use: Identifying nodes to target or exploit.

API Endpoint: /computer/(node-name)/api/json

Purpose: Provides details about a specific node.

Red Team Use: Gathering information about nodes for targeted attacks.

6. Impact Stage:

Path: /bitnami/Jenkins/home/workspace/

Purpose: Contains workspace data for Jenkins jobs.

Red Team Use: Identifying data or artifacts to manipulate or exfiltrate.

API Endpoint: /job/[job-name]/lastBuild/consoleText

Purpose: Retrieves the console output from the last build of a job.

Red Team Use: Identifying errors or information to further exploit the environment.

Additional Paths and API Endpoints:

7. Data Exfiltration Stage:

API Endpoint: /view/All/api/json

Purpose: Provides details about all jobs and views.

Red Team Use: Identifying valuable data or configurations to exfiltrate.

8. Persistence Stage:

API Endpoint: /createItem

Purpose: Endpoint to create new items (e.g., jobs).

Red Team Use: Creating malicious jobs or items to maintain access.

9. Obfuscation Stage:

API Endpoint: /job/[job-name]/doDelete

Purpose: Deletes a specified job.

Red Team Use: Deleting jobs to obfuscate activities and erase traces.

10. Cleanup Stage:

Path: /bitnami/Jenkins/home/logs/

Purpose: Contains various Jenkins logs.

Red Team Use: Modifying or deleting logs to conceal the attack.

Jenkins Plugin Security and Development Guidelines

Jenkins, a widely-used CI/CD tool, allows developers to extend its functionality through plugins. However, the development and use of plugins must be approached with a security-first mindset to prevent vulnerabilities and ensure the stability of the Jenkins environment.

Jenkins Plugin Security:

Dependency Scanning:

Ensure all dependencies of your plugin are free from known vulnerabilities.

Use tools like OWASP Dependency-Check to identify and fix issues.

Code Review:

Conduct regular code reviews to identify potential security issues.

Ensure that no secrets or sensitive data are hardcoded in the plugin code.

Access Control:

Implement strict access controls and ensure that only authorized users can configure or use the plugin.

Use Jenkins’ built-in functions like Jenkins.checkPermission to enforce permissions.

public void doSomeAction(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException {


    // Action code here


Input Validation:

Validate and sanitize all inputs to prevent injection attacks.

Use allow-lists and regular expressions to validate data.

public FormValidation doCheckName(@QueryParameter String value) {

    if (value.matches("^[a-zA-Z0-9_]+$")) {

        return FormValidation.ok();

    } else {

        return FormValidation.error("Invalid name");



Output Encoding:

Ensure all outputs are properly encoded to prevent XSS attacks.

Use functions like Util.escape to encode data.

String safeOutput = Util.escape(inputString);

Jenkins Plugin Development Guidelines:

Follow the MVC Architecture:

Separate the Model, View, and Controller to ensure clean and maintainable code.

Use Jenkins API:

Leverage Jenkins API for accessing built-in functionalities and objects.

Implement Descriptors:

Descriptors (like BuildStepDescriptor or DescriptorImpl) help in defining global configurations and settings.


public static final class DescriptorImpl extends BuildStepDescriptor<Builder> {

    public boolean isApplicable(Class<? extends AbstractProject> aClass) {

        return true;


    public String getDisplayName() {

        return "My Plugin Name";



Define Configurations:

Use config.jelly to define the configuration options in the UI.

<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form">

    <f:entry title="Parameter" field="parameter">

        <f:textbox />



Handle Build Steps:

Implement Builder class to define actions to be taken during a build step.

public class MyBuilder extends Builder {

    private final String parameter;


    public MyBuilder(String parameter) {

        this.parameter = parameter;



    public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) {

        // Build step actions here

        return true;



Manage Plugin Dependencies:

Ensure your pom.xml correctly defines all dependencies and Jenkins version.









Vulnerability Testing on Jenkins Plugins : Telegram : Google Metadata : Linkedin : Krypotwire : warrior Compressed File Viewer : CIFS : Git Forensics apk size Viewer : ZOOM

Possible Findings

Zoom Meeting Plugin

Source Code :

Auth Token/Integrity Token of Zoom

The Jenkins server stores the Auth Token/Integrity Token of Zoom in unencrypted manner , where they can be viewed by users with access to the master file. This file can be viewed by Overall/Manage permission on Jenkins.

Integration tokens are typically generated by the application that you are connecting to. For example, to generate a Zoom channel integration token, you would go to your Zoom account settings and navigate to the Integrations page. Once you have generated the integration token, you would need to provide it to the other application that you are connecting to.

Integration tokens can be sensitive because they allow the two applications to access each other’s data. For example, if you connect your Zoom account to a CRM (customer relationship managements) system using an integration token, the CRM system would be able to access your Zoom contact list and meeting schedule.


Auth Token stored in plain text


The impact of this can lead to complete zoom account takeover / hijacking

Telegram Notification Bot Plugin

 Telegram Notification Bot Plugin console output

Source Code :

Telegram Plugin stores the Bot Token in plain test in unencrypted way in its global configuration file on the Jenkins master, where they can be viewed by users with access to the master file system. which can lead to Telegram Bot Hijacking.


Bot token stored in plain text (unencrypted)


Telegram Bot Takeover

CompressFileViewer Plugin

Full Source code :

There seems to be one potential XSS vulnerability in web interface of the plugin :

const url = document.getElementsByClassName(‘hiddenData’)[1].innerText

This code retrieves the URL of the compressed file list from the hiddenData element on the web page. If the hiddenData element contains malicious JavaScript code, that code will be executed when the openAndInsertExtractedFiles() function is called.

var xhr = new XMLHttpRequest();'GET', url, true);

xhr.responseType = 'blob';

xhr.onload = function(e) {

if (this.status == 200) { openAndInsertExtractedFiles(this.response)



xhr.onerror = function(e) {

alert("Error " + + " occurred while receiving the

compressed file.");




Full Source Code :

package jenkins.plugins.publish_over_cifs;

import hudson.FilePath;

import jcifs.CIFSContext;

import jcifs.smb.SmbFile;

import jenkins.plugins.publish_over.BPBuildInfo; import jenkins.plugins.publish_over.BPDefaultClient; import jenkins.plugins.publish_over.BapPublisherException; import;





public class CifsClient extends BPDefaultClient<CifsTransfer> {

private final CifsHelper helper = new CifsHelper(); private final BPBuildInfo buildInfo; private final String baseUrl;

private String context;

private int bufferSize;

final private CIFSContext cifsContext;

public CifsClient(final CIFSContext cifsContext, final BPBuildInfo buildInfo, final String baseUrl, final int bufferSize) {

this.buildInfo = buildInfo;

this.baseUrl = baseUrl;

this.bufferSize = bufferSize;

context = baseUrl;

this.cifsContext = cifsContext;


protected String getContext() { return context; }

CIFSContext getCifsContext() { return cifsContext; }


public boolean changeToInitialDirectory() { context = baseUrl;

return true;


public boolean changeDirectory(final String directory) { final String newLocation = createUrlForSubDir(directory); final SmbFile dir = createFile(newLocation);

if (helper.exists(dir, newLocation) && helper.canRead(dir, newLocation)) { context = newLocation;

return true;

} else {

return false;



private String createUrlForSubDir(final String directory) {

return directory.endsWith("/") ? context + directory : context + directory

+  '/';


public boolean makeDirectory(final String directory) {

final String newDirectoryUrl = createUrlForSubDir(directory); final SmbFile dir = createFile(newDirectoryUrl);

if (helper.exists(dir, newDirectoryUrl)) throw new BapPublisherException(

Messages.exception_mkdir_directoryExists(helper.hideUserInfo(newDirectoryUrl))); if (buildInfo.isVerbose())

buildInfo.println(Messages.console_mkdir(helper.hideUserInfo(newDirectoryUrl))); helper.mkdirs(dir, newDirectoryUrl);

return true;


public void deleteTree() throws IOException {

if (buildInfo.isVerbose())


final SmbFile[] files = helper.listFiles(createFile(context), context); if (files == null) throw new

BapPublisherException(Messages.exception_listFilesReturnedNull(helper.hideUserInfo( context)));

for (final SmbFile file : files) {

if (buildInfo.isVerbose())






public void beginTransfers(final CifsTransfer transfer) { if (!transfer.hasConfiguredSourceFiles())

throw new BapPublisherException(Messages.exception_noSourceFiles());


public void transferFile(final CifsTransfer transfer, final FilePath filePath, final InputStream content) throws IOException {

final String newFileUrl = context + filePath.getName(); if (buildInfo.isVerbose())

buildInfo.println(Messages.console_copy(helper.hideUserInfo(newFileUrl))); final OutputStream out = createFile(newFileUrl).getOutputStream();

try {

IOUtils.copy(content, out, bufferSize);

} finally {




public void disconnect() {


public void disconnectQuietly() {


@SuppressWarnings("PMD.PreserveStackTrace") // security private SmbFile createFile(final String url) {

try {

return createSmbFile(url);

} catch (MalformedURLException mue) { throw new





protected SmbFile createSmbFile(final String url) throws MalformedURLException


return new SmbFile(url, cifsContext);



there is a one potential security issue in the code. The createFile() method does not properly validate the input URL, which could allow an attacker to inject malicious code. example, an attacker could pass a URL that contains a PowerShell script, which would then be executed when the createFile() method is called.

Google Metadata

Source Code :


import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import;

import; import; import; import; import;


import hudson.model.InvisibleAction;

import hudson.model.Run;

import java.util.Map;

import java.util.function.Supplier;


*  A build's {@link InvisibleAction} containing metadata.


*  This is intended as append-only store for metadata information. Metadata


providing code simply call {@link #add(MetadataValue)} to contribute

*  metadata, and {@link #getMetadata()} to consume metadata.


public class MetadataContainer extends InvisibleAction {

private final Multimap<String, MetadataValue> metadata;

private /* final */ transient Supplier<ObjectMapper> objectMapper;

public MetadataContainer() {

this.metadata = ArrayListMultimap.create();



private Object readResolve() {

objectMapper = Suppliers.memoize(ObjectMapper::new)::get; return this;



*  @return the metadata contained.


public Multimap<String, MetadataValue> getMetadata() { return Multimaps.unmodifiableMultimap(metadata);



*  Add a {@link MetadataValue} to this container.

*  @param mv the given {@link MetadataValue} to add.

*  @return this {@link MetadataContainer}.


public MetadataContainer add(MetadataValue mv) { metadata.put(mv.getKey(), mv);

return this;



*  {@code add} a list of elements


public <T extends MetadataValue> MetadataContainer addAll(Iterable<T> mvs) { for (T mv : mvs) {



return this;



*  {@code remove} a list of elements


public void removeAll(String key) {




*  @return the serialized form of the metadata;


public Map<String, String> getSerializedMetadata() { return Maps.newHashMap(Maps.transformValues(

metadata.asMap(), this::listSerialize));



*  @param build

*           a given build.

*  @return the {@link MetadataContainer} for the given build.


public static synchronized MetadataContainer of(Run<?, ?> build) { MetadataContainer container = build.getAction(MetadataContainer.class); if (container == null) {

container = new MetadataContainer();



return container;



*  @param metadataValue

*           the metadata value to be serialized.

*  @return serialized form of the given {@link MetadataValue}.

*  @throws MetadataSerializationException

*            when serialization runs into problem.


public String serialize(MetadataValue metadataValue)

throws MetadataSerializationException {

return listSerialize(ImmutableList.of(metadataValue));



*  @param values

*           the metadata values to be serialized.

*  @return serialized form of the given {@link MetadataValue}.

*  @throws MetadataSerializationException


when serialization runs into problem.


public <T extends MetadataValue> String listSerialize(Iterable<T> values) { try {

return getObjectMapper()

.writerFor(new TypeReference<Iterable<MetadataValue>>() {})


} catch (JsonProcessingException ex) {

throw new MetadataSerializationException(ex);




*  @param clazz class of the {@link MetadataValue} object to be deserialized.

*  @param serialized the string to deserialize.

*  @return the deserialized {@link MetadataValue} object.


public <T extends MetadataValue> T deserialize(Class<T> clazz, String serialized) {

return Iterables.getOnlyElement(listDeserialize(clazz, serialized));



*  @param clazz the class of the {@link MetadataValue} to be deserialize.

*  @param serialized the serialized form to be deserialized.

*  @return a list of deserialized objects.


public <T extends MetadataValue> Iterable<T> listDeserialize(Class<T> clazz, String serialized) {

try {

return getObjectMapper().readValue(


new TypeReference<Iterable<T>>() {}


} catch (Exception ex) {

throw new MetadataSerializationException(ex);




*  @return an {@link ObjectMapper} used for {@link #serialize(MetadataValue)}

*         and {@link #deserialize(Class, String)}.


private ObjectMapper getObjectMapper() {

return objectMapper.get();



*  @param build a given {@link Run}.

*  @return the metadata contained in the {@link MetadataContainer} of the

*         given {@link Run}.


public static Multimap<String, MetadataValue> getMetadata(Run<?, ?> build) { return of(build).getMetadata();



There are a few potential security vulnerabilities in the above code :

Insecure deserialization: The deserialize() and listDeserialize() methods do not properly validate the input string before deserializing it. This could allow an attacker to inject malicious code into Jenkins application.

cross-Site Scripting (XSS): The serialize() and listSerialize() methods serialize the MetadataValue objects to JSON. If the MetadataValue objects contain malicious JavaScript code, then the XSS vulnerability could be exploited when the serialized JSON is rendered in a web browser.

Remote Code Execution (RCE): The deserialize() and listDeserialize() methods deserialize the JSON strings to MetadataValue objects. If the serialized JSON contains malicious code, then the RCE vulnerability could be exploited when the MetadataValue objects are executed.







Jenkins, while pivotal in automating and streamlining operations, can be susceptible to various attack vectors if not secured meticulously. Organizations must prioritize securing Jenkins by understanding potential attack vectors and surfaces, implementing robust security practices, and continuously monitoring for anomalous activities to safeguard their CI/CD pipelines against APTs and other cyber threats.

👑 Security Researchers:

Negin Nourbakhsh

Fazel Mohammad Ali Pour

Parsa Momeni

Surya Dev Singh

Free Consultation

For a Free Consultation And Analysis Of Your Business, Please Fill Out The Opposite Form, Our Team Will Contact You As Soon As Possible.