From 06504e37668315c9c916fe2b614c253c2e79fcbb Mon Sep 17 00:00:00 2001 From: Francisc Balint <7178547+franciscbalint@users.noreply.github.com> Date: Thu, 20 Aug 2026 00:41:24 +0400 Subject: [PATCH] Redact API keys from exception messages. Strip secrets from UrlCalled and payloads before they land in ZbException text. --- README.md | 7 +++++++ src/zbutility.pas | 13 +++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d71b193..7dd90cf 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,12 @@ # Zero bounce API - pascal SDK + +## Security + +- Keep API keys on a trusted server. Do not embed them in mobile apps or browser JavaScript that untrusted users can inspect. +- Custom API base URLs (when supported) must use `https://`. Do not pass end-user-controlled hosts into those settings. +- Request URLs include `api_key` as a query parameter (ZeroBounce API contract). Do not log full request URLs or enable payload debug logging in production. + This library is a wrapper for the ZeroBounce API v2. For more information about the API, visit https://www.zerobounce.net/docs/. diff --git a/src/zbutility.pas b/src/zbutility.pas index 39a0701..19d17c8 100644 --- a/src/zbutility.pas +++ b/src/zbutility.pas @@ -76,6 +76,7 @@ TZbRequestResponse = record procedure ZBInitialize(ApiKey: string); overload; procedure ZBInitialize(ApiKey: string; ApiBaseURL: ZbApiURL); overload; function EncodeParam(param: String): String; + function RedactSecrets(const S: string): string; function ZBGetRequest(url: String): TZbRequestResponse; // performs a POST request with a raw JSON body function ZBPostRequest(url: String; JsonParam: String): TZbRequestResponse; overload; @@ -92,9 +93,9 @@ implementation begin Payload := response.Payload; StatusCode := response.StatusCode; - NewMessage := Concat(AMessage, sLineBreak, 'Url:', sLineBreak, response.UrlCalled); + NewMessage := Concat(AMessage, sLineBreak, 'Url:', sLineBreak, RedactSecrets(response.UrlCalled)); NewMessage := Concat(NewMessage, sLineBreak, 'Status code: ', format('%d', [StatusCode])); - NewMessage := Concat(NewMessage, sLineBreak, 'Payload:', sLineBreak, Payload); + NewMessage := Concat(NewMessage, sLineBreak, 'Payload:', sLineBreak, RedactSecrets(Payload)); Create(NewMessage); end; @@ -139,6 +140,14 @@ implementation {$ENDIF} end; + function RedactSecrets(const S: string): string; + begin + if ZbApiKey <> '' then + Result := StringReplace(S, ZbApiKey, 'REDACTED', [rfReplaceAll]) + else + Result := S; + end; + function ZBGetRequest(url: String): TZbRequestResponse; var {$IFDEF FPC}