Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
169 changes: 169 additions & 0 deletions SPECS/azurelinux-image-tools/CVE-2026-39882.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
From d3070852ca48669c5dbd6b4559c3a9cab8c9eb99 Mon Sep 17 00:00:00 2001
From: AllSpark <allspark@microsoft.com>
Date: Mon, 20 Apr 2026 13:51:02 +0000
Subject: [PATCH] Limit OTLP HTTP response body to 4 MiB and treat excess as
non-retryable; add tests exposure var; apply to logs, metrics, traces HTTP
exporters

Signed-off-by: Azure Linux Security Servicing Account <azurelinux-security@microsoft.com>
Upstream-reference: AI Backport of https://github.com/open-telemetry/opentelemetry-go/commit/5e363de517dba6db62736b2f5cdef0e0929b4cd0.patch
---
.../otlptrace/otlptracehttp/export_test.go | 8 ++++++++
.../otlp/otlplog/otlploghttp/client.go | 20 +++++++++++++++++--
.../otlp/otlpmetric/otlpmetrichttp/client.go | 20 +++++++++++++++++--
.../otlp/otlptrace/otlptracehttp/client.go | 20 +++++++++++++++++--
4 files changed, 62 insertions(+), 6 deletions(-)
create mode 100644 exporters/otlp/otlptrace/otlptracehttp/export_test.go

diff --git a/exporters/otlp/otlptrace/otlptracehttp/export_test.go b/exporters/otlp/otlptrace/otlptracehttp/export_test.go
new file mode 100644
index 0000000..bbc3376
--- /dev/null
+++ b/exporters/otlp/otlptrace/otlptracehttp/export_test.go
@@ -0,0 +1,8 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+package otlptracehttp
+
+// MaxResponseBodySize exposes the package-level maxResponseBodySize variable
+// to allow tests to override it.
+var MaxResponseBodySize = &maxResponseBodySize
diff --git a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp/client.go b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp/client.go
index 59be105..8000956 100644
--- a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp/client.go
+++ b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp/client.go
@@ -121,6 +121,14 @@ var ourTransport = &http.Transport{
ExpectContinueTimeout: 1 * time.Second,
}

+// maxResponseBodySize is the maximum number of bytes to read from a response
+// body. It is set to 4 MiB per the OTLP specification recommendation to
+// mitigate excessive memory usage caused by a misconfigured or malicious
+// server. If exceeded, the response is treated as a not-retryable error.
+// This is a variable to allow tests to override it.
+var maxResponseBodySize int64 = 4 * 1024 * 1024
+
+
func (c *httpClient) uploadLogs(ctx context.Context, data []*logpb.ResourceLogs) error {
// The Exporter synchronizes access to client methods. This is not called
// after the Exporter is shutdown. Only thing to do here is send data.
@@ -164,7 +172,11 @@ func (c *httpClient) uploadLogs(ctx context.Context, data []*logpb.ResourceLogs)

// Read the partial success message, if any.
var respData bytes.Buffer
- if _, err := io.Copy(&respData, resp.Body); err != nil {
+ if _, err := io.Copy(&respData, http.MaxBytesReader(nil, resp.Body, maxResponseBodySize)); err != nil {
+ var maxBytesErr *http.MaxBytesError
+ if errors.As(err, &maxBytesErr) {
+ return fmt.Errorf("response body too large: exceeded %d bytes", maxBytesErr.Limit)
+ }
return err
}
if respData.Len() == 0 {
@@ -195,7 +207,11 @@ func (c *httpClient) uploadLogs(ctx context.Context, data []*logpb.ResourceLogs)
// message to be returned. It will help in
// debugging the actual issue.
var respData bytes.Buffer
- if _, err := io.Copy(&respData, resp.Body); err != nil {
+ if _, err := io.Copy(&respData, http.MaxBytesReader(nil, resp.Body, maxResponseBodySize)); err != nil {
+ var maxBytesErr *http.MaxBytesError
+ if errors.As(err, &maxBytesErr) {
+ return fmt.Errorf("response body too large: exceeded %d bytes", maxBytesErr.Limit)
+ }
return err
}
respStr := strings.TrimSpace(respData.String())
diff --git a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp/client.go b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp/client.go
index 26af47e..21a0368 100644
--- a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp/client.go
+++ b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp/client.go
@@ -53,6 +53,14 @@ var ourTransport = &http.Transport{
ExpectContinueTimeout: 1 * time.Second,
}

+// maxResponseBodySize is the maximum number of bytes to read from a response
+// body. It is set to 4 MiB per the OTLP specification recommendation to
+// mitigate excessive memory usage caused by a misconfigured or malicious
+// server. If exceeded, the response is treated as a not-retryable error.
+// This is a variable to allow tests to override it.
+var maxResponseBodySize int64 = 4 * 1024 * 1024
+
+
// newClient creates a new HTTP metric client.
func newClient(cfg oconf.Config) (*client, error) {
httpClient := cfg.Metrics.HTTPClient
@@ -168,7 +176,11 @@ func (c *client) UploadMetrics(ctx context.Context, protoMetrics *metricpb.Resou

// Read the partial success message, if any.
var respData bytes.Buffer
- if _, err := io.Copy(&respData, resp.Body); err != nil {
+ if _, err := io.Copy(&respData, http.MaxBytesReader(nil, resp.Body, maxResponseBodySize)); err != nil {
+ var maxBytesErr *http.MaxBytesError
+ if errors.As(err, &maxBytesErr) {
+ return fmt.Errorf("response body too large: exceeded %d bytes", maxBytesErr.Limit)
+ }
return err
}
if respData.Len() == 0 {
@@ -199,7 +211,11 @@ func (c *client) UploadMetrics(ctx context.Context, protoMetrics *metricpb.Resou
// message to be returned. It will help in
// debugging the actual issue.
var respData bytes.Buffer
- if _, err := io.Copy(&respData, resp.Body); err != nil {
+ if _, err := io.Copy(&respData, http.MaxBytesReader(nil, resp.Body, maxResponseBodySize)); err != nil {
+ var maxBytesErr *http.MaxBytesError
+ if errors.As(err, &maxBytesErr) {
+ return fmt.Errorf("response body too large: exceeded %d bytes", maxBytesErr.Limit)
+ }
return err
}
respStr := strings.TrimSpace(respData.String())
diff --git a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/client.go b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/client.go
index c7b1a55..6bb898f 100644
--- a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/client.go
+++ b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/client.go
@@ -31,6 +31,14 @@ import (

const contentTypeProto = "application/x-protobuf"

+// maxResponseBodySize is the maximum number of bytes to read from a response
+// body. It is set to 4 MiB per the OTLP specification recommendation to
+// mitigate excessive memory usage caused by a misconfigured or malicious
+// server. If exceeded, the response is treated as a not-retryable error.
+// This is a variable to allow tests to override it.
+var maxResponseBodySize int64 = 4 * 1024 * 1024
+
+
var gzPool = sync.Pool{
New: func() any {
w := gzip.NewWriter(io.Discard)
@@ -174,7 +182,11 @@ func (d *client) UploadTraces(ctx context.Context, protoSpans []*tracepb.Resourc
// Success, do not retry.
// Read the partial success message, if any.
var respData bytes.Buffer
- if _, err := io.Copy(&respData, resp.Body); err != nil {
+ if _, err := io.Copy(&respData, http.MaxBytesReader(nil, resp.Body, maxResponseBodySize)); err != nil {
+ var maxBytesErr *http.MaxBytesError
+ if errors.As(err, &maxBytesErr) {
+ return fmt.Errorf("response body too large: exceeded %d bytes", maxBytesErr.Limit)
+ }
return err
}
if respData.Len() == 0 {
@@ -205,7 +217,11 @@ func (d *client) UploadTraces(ctx context.Context, protoSpans []*tracepb.Resourc
// message to be returned. It will help in
// debugging the actual issue.
var respData bytes.Buffer
- if _, err := io.Copy(&respData, resp.Body); err != nil {
+ if _, err := io.Copy(&respData, http.MaxBytesReader(nil, resp.Body, maxResponseBodySize)); err != nil {
+ var maxBytesErr *http.MaxBytesError
+ if errors.As(err, &maxBytesErr) {
+ return fmt.Errorf("response body too large: exceeded %d bytes", maxBytesErr.Limit)
+ }
return err
}
respStr := strings.TrimSpace(respData.String())
--
2.45.4

6 changes: 5 additions & 1 deletion SPECS/azurelinux-image-tools/azurelinux-image-tools.spec
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Summary: Azure Linux Image Tools
Name: azurelinux-image-tools
Version: 1.2.0
Release: 2%{?dist}
Release: 3%{?dist}
License: MIT
URL: https://github.com/microsoft/azure-linux-image-tools/
Group: Applications/System
Expand All @@ -16,6 +16,7 @@ Source0: https://github.com/microsoft/azure-linux-image-tools/archive/ref
#
Source1: %{name}-%{version}-vendor.tar.gz
Patch0: CVE-2026-27141.patch
Patch1: CVE-2026-39882.patch
BuildRequires: golang < 1.25
BuildRequires: systemd-udev
Requires: %{name}-imagecustomizer = %{version}-%{release}
Expand Down Expand Up @@ -112,6 +113,9 @@ go test -C toolkit/tools ./...
%{_bindir}/osmodifier

%changelog
* Mon Apr 20 2026 Azure Linux Security Servicing Account <azurelinux-security@microsoft.com> - 1.2.0-3
- Patch for CVE-2026-39882

* Thu Mar 05 2026 Azure Linux Security Servicing Account <azurelinux-security@microsoft.com> - 1.2.0-2
- Patch for CVE-2026-27141

Expand Down
Loading