Repository navigation
Conversation
RpcServer held a request's signature as a plain string, in `headers` and in `authorization`, and RpcServer.post reports every coded error, provider failures included. Sentry's SDK sends every frame's local variables, and Sentry's SDK configuration turns off the scrubber, so each such report carried the signature next to the body it signs. A signature has no timestamp or nonce, so that pair can be replayed. The server now takes Authorization out of the headers on entry, in any case, and holds it as an scm.Secret. verify_get and verify_post take a Secret and still accept a plain string. RpcApiClient.request holds its signature as a Secret and reveals it only in the call to the session. ResourceServiceUnavailable no longer chains the connection error, whose frames in the session and in requests hold the header. A raw requests error still carries it in those frames, which this library can't mask.
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.
When the RPC server reports an error, the report can carry the request's signature (
Authorization: rpcsignature rpc0:...). Sentry's SDK sends the local variables of every frame in the traceback, Sentry's SDK configuration turns off the scrubber, andRpcServerholds the signature as a plain string, inheadersand inauthorization.RpcServer.postreports every coded error, including a provider failure such as GitHub being down, so each of those reports has the signature right next todata, the body it signs. #162 and #167 did the same masking for the signing secrets, the git grant and the provider token.Why it matters
A signature has no timestamp or nonce. The POST signature covers only the body, not
X-Organization-Id,X-Repository-IdorX-Credentials-Set. So anyone who reads a body and its signature in an error report can replay that request whenever they like, with other values in those headers. Changing the protocol would touch Sentry and Seer, so it's a separate decision and not part of this PR.Approach
RpcServer.getandRpcServer.posttakeAuthorizationout ofheadersas soon as they're called, the wayGitServer.handledoes with the git grant. They keep it as anscm.Secret, which shows as[Filtered].verify_getandverify_postaccept aSecretand reveal it only inline, inside the comparison. They still accept a plain string, so this doesn't break callers.RpcApiClient.requestkeeps its signature as aSecretfor the whole retry loop and reveals it only inside the call to the session. When retries on connection errors run out, theResourceServiceUnavailableit raises no longer chains the connection error (from None, asGitRelaydoes). The detail message still names that error. A chained exception is reported with its own frames, and the session's and requests' frames hold the header.Two behavior changes:
authorizationheader in any case. Before, a lowercase one got a 400. Django'srequest.headersalready givesAuthorization, so Sentry's endpoint sees no change.ResourceServiceUnavailable.__cause__is nowNone.What this doesn't cover
RpcApiClient's docstring says so. The same goes forfetch_repositoryandRequestsSession.get. MaskingRequestsSession's own frames would mean changing theSessionprotocol, which is a breaking change, and it wouldn't help: the frame right below, inrequests.api.request, holds the same headers.Tests
TestKeptOutOfErrorReportsintest_rpc_server.py: a provider failure thatpostreports, withAuthorizationand withauthorization, and a raw failure fromget.TestKeptOutOfErrorReportsintest_rpc_client.py: retries exhausted on a connection error.Each test failed before this change.
reported_localintests/unit/error_reports.pyis the same as in #167, so whichever PR lands second merges without a conflict.