By default an SDK should log events and identifiers, not payloads: method, path without query secrets, status, duration and request ID. Redact credentials, tokens and personal data always, and make full request and response logging an explicit, documented opt in that warns about what it exposes.
Why SDK logging is risky
Debug logging is the first thing a developer turns on when an integration fails, and the last thing they remember to turn off. If your SDK's debug mode prints headers and bodies, production logs will eventually contain customers' API keys and their users' data.
The OWASP Logging Cheat Sheet lists data that should not be recorded directly, including access tokens, authentication passwords, session identification values (or a hash of them if needed), and sensitive personal data. MITRE describes the weakness as CWE-532, insertion of sensitive information into a log file. An SDK sits at exactly the point where those values are in memory, so it carries the responsibility to keep them out.
A default logging table
| Field | Default level | Notes |
|---|---|---|
| HTTP method and path | Info | Strip query values that look like secrets |
| Status code and duration | Info | Useful for latency and error rates |
| Request ID | Info | Lets support find the server side record |
| Retry attempt and reason | Debug | No bodies |
| Authorization and API key headers | Never | Replace with a fixed placeholder |
| Request and response bodies | Off | Opt in only, with a warning |
| User identifiers | Off | Hash or omit |
Steps to implement redaction
- Route every log line through one function in the SDK. Direct print or logger calls scattered through the code are where leaks start.
- Redact by key name before formatting. A deny list should include authorization, cookie, set-cookie, api key, token, secret, password and signature, matched case insensitively.
- Redact by value shape as a second layer where you can. Your own key format, if it has a recognisable prefix, is easy to mask.
- Truncate bodies if body logging is enabled, and replace known sensitive fields with a placeholder rather than the original value.
- Add log injection protection. The OWASP guide advises sanitising event data for carriage return, line feed and delimiter characters so attacker controlled values cannot forge log lines.
- Make the verbose mode loud. When a caller enables body logging, print one warning line at startup saying that logs may contain sensitive data.
- Test it. Feed a fake secret through headers, URL, body and error paths at the highest log level, and fail the build if the fake value appears in the captured output.
Who owns the log level
Your SDK should respect the host application's logging framework and its levels, not install its own handlers or write files on its own. Writing to a file the SDK chose is a surprise, and a surprise file is an unmanaged place where secrets can sit. Use the standard logger of the language, name it after the package, and leave sinks to the application.
Document it
Publish a short page that lists what the SDK logs at each level and what it redacts. Security reviewers on the customer side ask for exactly this, and it lets them approve the SDK without reading the source. When the logged fields change, put a note in the changelog.
Quick check
Is redacting only the Authorization header enough?
No. API keys can also arrive in custom headers, query strings, cookies and bodies. Redact by key name across all of them and test with fake secrets.
Should debug logging include bodies?
Not unless the caller turns that on deliberately. Even then, truncate and mask known sensitive fields.
Safeguard's SBOM and dependency scanning can tell you which logging and HTTP libraries your SDK ships with, and its policies and gates can enforce rules in pull requests. There is a free scan to try.
Sources
Last reviewed: 19 October 2026.