CVE-2022-36887
Description
CSRF in Jenkins Job Configuration History Plugin lets attackers delete or restore config history entries without authentication.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
CSRF in Jenkins Job Configuration History Plugin lets attackers delete or restore config history entries without authentication.
Vulnerability
Overview
The Jenkins Job Configuration History Plugin, up to version 1155.v28a_46a_cc06a_5, is vulnerable to cross-site request forgery (CSRF). This flaw allows an attacker to craft malicious web requests that, when a Jenkins administrator visits a page controlled by the attacker, can delete entries from job, agent, and system configuration history, or restore older versions of those configurations [1][3]. The root cause is that the plugin's endpoints (doRestore, doDeleteRevision) lacked proper CSRF protection, missing the @POST annotation that enforces a valid Crumb token [4].
Exploitation
Method
To exploit this CSRF vulnerability, an attacker must trick a Jenkins user with the necessary permissions (configure or delete entry rights) into clicking a crafted link or visiting a specially designed webpage. The attack does not require network access to Jenkins beyond what is available to the target user. The attacker constructs a cross-site request that invokes the unprotected doRestore or doDeleteRevision methods, passing a timestamp parameter to target a specific history entry [1][4]. Because the plugin did not validate the origin or require a confirmation token for state-changing actions, the forged request is executed in the authenticated session.
Impact
A successful CSRF attack can lead to unauthorized deletion of configuration history entries. This could remove forensic evidence of configuration changes, disrupt rollback capabilities, or restore an older, potentially less secure configuration. The impact is limited to actions available to the victim's permissions; attackers cannot gain full administrative control but can corrupt the configuration history record [1][3].
Mitigation
The vulnerability is fixed in Job Configuration History Plugin version 1156.v536a_97b_8d649 and later [2]. The fix adds @POST annotation to the vulnerable methods, ensuring they only accept POST requests with a valid CSRF token. Users should upgrade to the latest version. No workarounds are provided beyond ensuring Jenkins is configured to require a crumb issuer for form submissions [1][4].
AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
org.jenkins-ci.plugins:jobConfigHistoryMaven | < 1156.v536a_97b_8d649 | 1156.v536a_97b_8d649 |
Affected products
2- Range: unspecified
Patches
1536a97b8d649[SECURITY-2766] (#216)
4 files changed · +12 −2
src/main/java/hudson/plugins/jobConfigHistory/ComputerConfigHistoryAction.java+3 −0 modified@@ -35,6 +35,7 @@ import org.kohsuke.stapler.StaplerResponse; import org.kohsuke.stapler.export.Exported; import org.kohsuke.stapler.export.ExportedBean; +import org.kohsuke.stapler.verb.POST; import java.io.IOException; import java.text.ParseException; @@ -382,6 +383,7 @@ private XmlFile getOldConfigXml(String timestamp) { * @param rsp Outgoing StaplerResponse * @throws IOException If something goes wrong */ + @POST public final void doRestore(StaplerRequest req, StaplerResponse rsp) throws IOException { checkConfigurePermission(); final String timestamp = req.getParameter("timestamp"); @@ -413,6 +415,7 @@ public final void doForwardToRestoreQuestion(StaplerRequest req, StaplerResponse rsp.sendRedirect("restoreQuestion?timestamp=" + timestamp); } + @POST public final void doDeleteRevision(StaplerRequest req) { checkDeleteEntryPermission(); final String timestamp = req.getParameter("timestamp");
src/main/java/hudson/plugins/jobConfigHistory/JobConfigHistoryProjectAction.java+3 −0 modified@@ -36,6 +36,7 @@ import org.kohsuke.stapler.StaplerResponse; import org.kohsuke.stapler.export.Exported; import org.kohsuke.stapler.export.ExportedBean; +import org.kohsuke.stapler.verb.POST; import javax.xml.transform.Source; import javax.xml.transform.stream.StreamSource; @@ -463,6 +464,7 @@ private XmlFile getOldConfigXml(String timestamp) { * @param rsp Outgoing StaplerResponse * @throws IOException If something goes wrong */ + @POST public final void doRestore(StaplerRequest req, StaplerResponse rsp) throws IOException { checkConfigurePermission(); @@ -492,6 +494,7 @@ public final void doForwardToRestoreQuestion(StaplerRequest req, rsp.sendRedirect("restoreQuestion?timestamp=" + timestamp); } + @POST public final void doDeleteRevision(StaplerRequest req, StaplerResponse rsp) { checkDeleteEntryPermission(); final String timestamp = req.getParameter("timestamp");
src/main/java/hudson/plugins/jobConfigHistory/JobConfigHistoryRootAction.java+3 −0 modified@@ -39,6 +39,7 @@ import org.kohsuke.stapler.StaplerResponse; import org.kohsuke.stapler.export.Exported; import org.kohsuke.stapler.export.ExportedBean; +import org.kohsuke.stapler.verb.POST; import javax.servlet.ServletException; import java.io.ByteArrayInputStream; @@ -662,6 +663,7 @@ public boolean checkParameters(String name, String timestamp) { * @param rsp Outgoing StaplerResponse * @throws IOException If something goes wrong */ + @POST public final void doRestore(StaplerRequest req, StaplerResponse rsp) throws IOException { getAccessControlledObject().checkPermission(Item.CONFIGURE); @@ -743,6 +745,7 @@ public final void doForwardToRestoreQuestion(StaplerRequest req, rsp.sendRedirect("restoreQuestion?name=" + name); } + @POST public final void doDeleteRevision(StaplerRequest req, StaplerResponse rsp) { checkDeleteEntryPermission(); final String timestamp = req.getParameter("timestamp");
src/main/webapp/deleteRevisionAndTableEntry.js+3 −2 modified@@ -11,9 +11,10 @@ function removeEntryFromTable(id, timestamp, name, message) { if (name != null) { url += "&name=" + name; } - xmlHttp.open("GET", url, true); + xmlHttp.open("POST", url, true); + xmlHttp.setRequestHeader(document.head.getAttribute('data-crumb-header'), document.head.getAttribute('data-crumb-value')); xmlHttp.send(null); } else { return false; } -} \ No newline at end of file +}
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- github.com/advisories/GHSA-j896-j72w-cr32ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2022-36887ghsaADVISORY
- www.openwall.com/lists/oss-security/2022/07/27/1ghsamailing-listx_refsource_MLISTWEB
- github.com/jenkinsci/job-config-history-plugin/commit/536a97b8d649b3114f5db24ea32a7c63188a35c6ghsaWEB
- www.jenkins.io/security/advisory/2022-07-27/ghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.