thrift: fix multiple CVEs

CVE-2026-43868:
  Memory Allocation with Excessive Size Value vulnerability in Apache Thrift.

CVE-2026-43869:
  Improper Validation of Certificate with Host Mismatch vulnerability in Apache Thrift.
  This CVE only affects the Java client, which is not built by the recipe. Marked as
  'not-applicable-config'.
  Upstream commit:
    https://github.com/apache/thrift/commit/a30c552bd0808b7e19f35ad30212ba7a9aee8c66

CVE-2026-43870:
  Origin Validation Error, Improper Limitation of a Pathname to a Restricted Directory
  ('Path Traversal'), Improper Neutralization of CRLF Sequences in HTTP Headers
  ('HTTP Request/Response Splitting'), Uncontrolled Resource Consumption vulnerability
  in Apache Thrift.

Signed-off-by: Roland Kovacs <roland.kovacs@est.tech>
Signed-off-by: Anuj Mittal <anuj.mittal@oss.qualcomm.com>
This commit is contained in:
Roland Kovacs
2026-08-13 10:01:51 +05:30
committed by Anuj Mittal
parent 6e099da67d
commit 356ce58534
3 changed files with 1512 additions and 0 deletions
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,127 @@
From 0faaa79330a2864135948186858036676fdbc1b1 Mon Sep 17 00:00:00 2001
From: Jens Geyer <jensg@apache.org>
Date: Sat, 11 Apr 2026 12:29:16 +0200
Subject: [PATCH] Harden Node.js WebSocket server handling Client: nodejs
- Validate origin on WebSocket upgrade using the same CORS rules
as HTTP requests
- Fix path containment check to use trailing separator
- Replace deprecated new Buffer() with Buffer.alloc()
- Sanitize interpolated header values in upgrade response
(04)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This closes #3391
CVE: CVE-2026-43870
Upstream-Status: Backport [https://github.com/apache/thrift/commit/5e4f01d737e4d3845d07dde6da43981feee0cb9a]
Signed-off-by: Roland Kovacs <roland.kovacs@est.tech>
---
lib/nodejs/lib/thrift/web_server.js | 32 +++++++++++++++++++++--------
1 file changed, 24 insertions(+), 8 deletions(-)
diff --git a/lib/nodejs/lib/thrift/web_server.js b/lib/nodejs/lib/thrift/web_server.js
index a33f47aed..cf88bde1b 100644
--- a/lib/nodejs/lib/thrift/web_server.js
+++ b/lib/nodejs/lib/thrift/web_server.js
@@ -26,6 +26,10 @@ var log = require('./log');
var MultiplexedProcessor = require('./multiplexed_processor').MultiplexedProcessor;
+function sanitizeHeader(value) {
+ return (value || "").replace(/[\r\n]/g, "");
+}
+
var TBufferedTransport = require('./buffered_transport');
var TBinaryProtocol = require('./binary_protocol');
var InputBufferUnderrunError = require('./input_buffer_underrun_error');
@@ -83,7 +87,7 @@ var wsFrame = {
* @returns {Buffer} - The WebSocket frame, ready to send
*/
encode: function(data, mask, binEncoding) {
- var frame = new Buffer(wsFrame.frameSizeFromData(data, mask));
+ var frame = Buffer.alloc(wsFrame.frameSizeFromData(data, mask));
//Byte 0 - FIN & OPCODE
frame[0] = wsFrame.fin.FIN +
(binEncoding ? wsFrame.frameOpCodes.BIN : wsFrame.frameOpCodes.TEXT);
@@ -162,19 +166,19 @@ var wsFrame = {
}
//MASK
if (wsFrame.mask.TO_SERVER == (frame[1] & wsFrame.mask.TO_SERVER)) {
- result.mask = new Buffer(4);
+ result.mask = Buffer.alloc(4);
frame.copy(result.mask, 0, dataOffset, dataOffset + 4);
dataOffset += 4;
}
//Payload
- result.data = new Buffer(len);
+ result.data = Buffer.alloc(len);
frame.copy(result.data, 0, dataOffset, dataOffset+len);
if (result.mask) {
wsFrame.applyMask(result.data, result.mask);
}
//Next Frame
if (frame.length > dataOffset+len) {
- result.nextFrame = new Buffer(frame.length - (dataOffset+len));
+ result.nextFrame = Buffer.alloc(frame.length - (dataOffset+len));
frame.copy(result.nextFrame, 0, dataOffset+len, frame.length);
}
//Don't forward control frames
@@ -418,7 +422,8 @@ exports.createWebServer = function(options) {
var filename = path.resolve(path.join(baseDir, uri));
//Ensure the basedir path is not able to be escaped
- if (filename.indexOf(baseDir) != 0) {
+ var normalizedBase = baseDir.endsWith(path.sep) ? baseDir : baseDir + path.sep;
+ if (filename !== baseDir && filename.indexOf(normalizedBase) !== 0) {
response.writeHead(400, "Invalid request path", {});
response.end();
return;
@@ -510,6 +515,14 @@ exports.createWebServer = function(options) {
response.end();
}
}).on('upgrade', function(request, socket, head) {
+ //Verify CORS origin for WebSocket upgrades
+ if (request.headers.origin && options.cors) {
+ if (!options.cors["*"] && !options.cors[request.headers.origin]) {
+ socket.write("HTTP/1.1 403 Origin not allowed\r\n\r\n");
+ socket.destroy();
+ return;
+ }
+ }
//Lookup service
var svc;
try {
@@ -521,12 +534,15 @@ exports.createWebServer = function(options) {
//Perform upgrade
var hash = crypto.createHash("sha1");
hash.update(request.headers['sec-websocket-key'] + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
+ var origin = sanitizeHeader(request.headers.origin);
+ var host = sanitizeHeader(request.headers.host);
+ var reqUrl = sanitizeHeader(request.url);
socket.write("HTTP/1.1 101 Switching Protocols\r\n" +
"Upgrade: websocket\r\n" +
"Connection: Upgrade\r\n" +
"Sec-WebSocket-Accept: " + hash.digest("base64") + "\r\n" +
- "Sec-WebSocket-Origin: " + request.headers.origin + "\r\n" +
- "Sec-WebSocket-Location: ws://" + request.headers.host + request.url + "\r\n" +
+ "Sec-WebSocket-Origin: " + origin + "\r\n" +
+ "Sec-WebSocket-Location: ws://" + host + reqUrl + "\r\n" +
"\r\n");
//Handle WebSocket traffic
var data = null;
@@ -537,7 +553,7 @@ exports.createWebServer = function(options) {
//Prepend any existing decoded data
if (data) {
if (result.data) {
- var newData = new Buffer(data.length + result.data.length);
+ var newData = Buffer.alloc(data.length + result.data.length);
data.copy(newData);
result.data.copy(newData, data.length);
result.data = newData;
--
2.43.0
@@ -15,6 +15,8 @@ SRC_URI = "https://archive.apache.org/dist/${BPN}/${PV}/${BP}.tar.gz \
file://CVE-2026-55971.patch \
file://CVE-2026-58023.patch \
file://CVE-2026-48144.patch \
file://CVE-2026-43868.patch \
file://CVE-2026-43870.patch \
"
SRC_URI[sha256sum] = "b5d8311a779470e1502c027f428a1db542f5c051c8e1280ccd2163fa935ff2d6"
@@ -22,6 +24,8 @@ BBCLASSEXTEND = "native nativesdk"
CVE_PRODUCT = "apache:thrift"
CVE_STATUS[CVE-2026-43869] = "not-applicable-config: The issue is present in the Java client which is not built"
inherit pkgconfig cmake python3native
export STAGING_INCDIR