Conversation
Hooks received the same headers map used to build the request, including the full `Authorization: Bearer <api key>` value. A hook that logs or exports its event would leak the key. Hooks now get their own copy of the headers with the API key redacted to its last four characters (e.g. `Bearer ****WXYZ`). Keys of 8 characters or fewer are fully masked. The outbound request still sends the full key. Fixes SEC-786. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Fixes SEC-786 (pentest finding "API Key Forwarded to Request-Hook Handlers", Medium).
Requestor.httpRequestbuilt the hook headers withgenerateHeaders(client.getApiKey())and passed them to bothRequestHookResponsesandResponseHookResponses, so every hook receivedAuthorization: Bearer <full api key>. A hook that logs or exports its event (a common use for debugging, tracing, or APM) would write the full key to logs or a third-party platform.Changes:
generateHookHeadersbuilds the hook headers map and replaces theAuthorizationvalue withBearer ****WXYZ(last four characters only). This keeps enough auth context to tell keys apart in logs without exposing the credential.Bearer ****), since showing four characters would reveal half or more of the key. Real EasyPost keys are much longer, so this only affects unusual or test keys.createEasyPostConnectionand the App Engine path still build their own headers with the full key. The hook map was already a separate instance from the one used on the connection; it's now also redacted.headersJavadoc on both hook classes. TheResponseHookResponsesdoc said "headers of the response", but these are the request headers.Next Release.Authorizationis the only sensitive header the SDK sets, so no other headers needed redacting.Testing
New tests in
HookTestsend a request through a mockedHttpsURLConnection(viaEasyPost._vcrUrlFunction, the same approach as #382) and capture what both hooks receive:testHooksReceiveRedactedApiKey: both hooks seeBearer ****WXYZ, no header value contains the full key, andMockito.verifyconfirms the real connection was sentBearer <full key>.testHooksFullyRedactShortApiKey: an 8-character key is fully masked in both hooks and still sent in full on the wire.The existing VCR hook tests are unchanged. An
@AfterEachresets_vcrUrlFunctionso the mock doesn't leak into other tests.Notes for merging:
Next ReleaseinCHANGELOG.md, so whichever lands second will have a one-line conflict to resolve. The code changes touch different parts ofRequestorand don't overlap.Next Releasealready contains a breaking change (addCreditCardToUserremoval). A true 8.8.1 would need a backport branch fromv8.8.0; this change applies there cleanly in concept (onlyhttpRequestand two new private helpers).Pull Request Type
Please select the option(s) that are relevant to this PR.
🤖 Generated with Claude Code