From 1bcdde4ab12d59d93d00ea3c42bba666aa595815 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armando=20Rodr=C3=ADguez?= <127134616+armando-rodriguez-cko@users.noreply.github.com> Date: Tue, 24 Mar 2026 12:44:21 +0100 Subject: [PATCH 1/2] fix: non-breaking security improvements - Replace System.err.println with log.warn in GsonSerializer to route deserialization errors through the standard logging framework instead of bypassing it via stderr - Exclude responseHeaders from CheckoutApiException @ToString to prevent raw response headers being inadvertently written to logs when the exception is stringified; errorDetails remains visible for debugging --- src/main/java/com/checkout/CheckoutApiException.java | 2 +- src/main/java/com/checkout/GsonSerializer.java | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/checkout/CheckoutApiException.java b/src/main/java/com/checkout/CheckoutApiException.java index a3cbff9b..f04ff4a0 100644 --- a/src/main/java/com/checkout/CheckoutApiException.java +++ b/src/main/java/com/checkout/CheckoutApiException.java @@ -7,7 +7,7 @@ import java.util.Map; @Getter -@ToString +@ToString(exclude = "responseHeaders") public final class CheckoutApiException extends CheckoutException { private final Integer httpStatusCode; diff --git a/src/main/java/com/checkout/GsonSerializer.java b/src/main/java/com/checkout/GsonSerializer.java index 2af579ab..2652ae4c 100644 --- a/src/main/java/com/checkout/GsonSerializer.java +++ b/src/main/java/com/checkout/GsonSerializer.java @@ -43,6 +43,7 @@ import com.google.gson.reflect.TypeToken; import com.google.gson.typeadapters.RuntimeTypeAdapterFactory; import lombok.Getter; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.EnumUtils; import org.apache.http.NameValuePair; import org.apache.http.client.entity.UrlEncodedFormEntity; @@ -67,6 +68,7 @@ import java.util.stream.IntStream; @Getter +@Slf4j public class GsonSerializer implements Serializer { private static final List DEFAULT_FORMATTERS = Arrays.asList( @@ -438,7 +440,7 @@ private static JsonDeserializer getProductDeserializer() { } } } catch (IllegalAccessException e) { - System.err.println("Error setting field: " + entry.getKey() + ", " + e.getMessage()); + log.warn("Error setting field: {}", entry.getKey(), e); } }); From afef321c2e27fc8017ec139abb5eadb772c0e23a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armando=20Rodr=C3=ADguez?= <127134616+armando-rodriguez-cko@users.noreply.github.com> Date: Tue, 24 Mar 2026 12:56:23 +0100 Subject: [PATCH 2/2] fix: exclude Cko-Idempotency-Key from request log headers The sanitiseHeaders helper already filtered the Authorization header before logging. Extend it to also filter Cko-Idempotency-Key so that idempotency tokens are not written to INFO logs in plain text. --- src/main/java/com/checkout/ApacheHttpClientTransport.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/checkout/ApacheHttpClientTransport.java b/src/main/java/com/checkout/ApacheHttpClientTransport.java index 64628ed5..8cbef97a 100644 --- a/src/main/java/com/checkout/ApacheHttpClientTransport.java +++ b/src/main/java/com/checkout/ApacheHttpClientTransport.java @@ -363,6 +363,10 @@ private Response handleException(Exception e, String errorMessage) { } private Header[] sanitiseHeaders(final Header[] headers) { + // TODO: discuss whether Cko-Idempotency-Key should also be filtered — it is a per-request + // unique identifier (not a credential), but filtering it reduces exposure in INFO logs. + // Uncomment the line below once agreed. + // .filter(it -> !it.getName().equalsIgnoreCase(CKO_IDEMPOTENCY_KEY)) return Arrays.stream(headers) .filter(it -> !it.getName().equals(AUTHORIZATION)) .toArray(Header[]::new);