Coinbase Wallet Chrome Extension Basic Security Analysis

My Approach
As usual, Burpsuite is installed, with Portswigger’s certificate inserted in Chrome’s cert repo. We then set Chrome to use Burpsuite’s listening port as a proxy. The extension is then downloaded from the Chrome Extension store.
I will simply use the wallet to create a new seed phrase, connect the wallet to staking.synthetix.io
, then uninstall the extension. No funds will be added, no KYC completed, etc. This obviously leaves out the vast majority of functionality, and data collection, of the wallet.
Coinbase Crypto Wallet

This is my first time noticing a ‘privacy’ tab that Chrome lists per extension. As you can see, Coinbase both collects and sells your data.
I’d like to start off by noting that unlike MetaMask for example, I was not prompted to give Coinbase permission to use my data. You are simply forced to check the box agreeing to both their terms and conditions, and their privacy policy.

This POST
request to sessions.coinbase.com
sends data to Coinbase’s Bugsnag instance. Bugsnag seems to be comparable to Sentry, both are used for telemetry/data collection. Note the ‘id
‘ field with value already assigned.
Beginning the process of creating a new seed phrase, a request to api.wallet.coinbase.com/rpc/v2/CreateNonce
is sent. This Coinbase wallet API endpoint responds with a ‘nonce’ value.

Continuing, there is a POST request to api.wallet.coinbase.com/rpc/v2/createUser
containing this nonce, my newly created wallet address, and some other data that y’all blockchain experts may be able to elaborate on.

The server returns a ‘token
‘ value and a ‘refreshToken
‘ value.
The next page requested that I create an account, which I declined. The following request was generated and sent to api.wallet.coinbase.com/rpc/v2/getUserProfile

Most of the values returned by the server are ‘null
‘, except for the ‘id
‘ and ‘username
‘ fields, which were still assigned.

We see a request to api.wallet.coinbase.com/rpc/v2/refreshAccessToken
, with the ‘refreshToken
‘ being sent in the POST
body. The server replies with a fresh set of tokens. Now the wallet creation is complete.

Above is a large chunk of data being sent to dp.coinbase.com/amp
, including operating system and browser information. We also see numerous fields named ‘event_type
‘, with the highlighted example being ‘onboarding.password_step.success
‘. You are being closely tracked, with no option to decline.

The above ‘metrics
‘ are sent to dp.coinbase.com/metrics
.
What happens when we connect the wallet to staking.synthetix.io
?

Of course, Coinbase collects this info with a request containing the field “dappUrl
” and value “staking.synthetix.io
” as shown on the pane to the right side.

Above is an interesting PUT request being used to send your ‘userId
‘ to Coinbase’s Userleap instance. Searching for information about Userleap instantly reveals that they are a user tracking service. As shown above, Coinbase uses a variety of methods to track your usage of the extension, and you have no control over how they use your data.
Offense
The below request is sent to api.wallet.coinbase.com/rpc/v2/getFeatureFlags
very quickly after the extension is installed.

The highlighted text shows that ‘experimentation
‘ and ‘experimentation_v2
‘ are set to false, while ‘experimentation_v3
‘ is set to true. ‘v2’ likely refers to the API version as shown throughout this post. A few lines below shows a field, “gasless_purchase
“, which is set to false.
Could it be possible that by intercepting that response, and setting it to true, you could somehow convince Coinbase to subsidize your gas fees? I did not test this, but it may be considered in-scope of Coinbase’s bug bounty program if y’all want to try for yourself.
We see a request to api.coinbase.com/v3/coinbase.experiment.ExperimentService/ListSplitTestGroups
. I could not find any public information about this seemingly undocumented API.

A GET request was used to send a small chunk of base64 encoded text. See what it decodes to on the right side of the above image. The highlighted portion containing ‘is_employee:false
‘ is extremely interesting. What if we switch that value to true?

When we tell the server that we are an ‘employee
‘ of some sort, we are clearly sent a different set of experiment test groups from the server.
Also worth considering is the field ‘subject_type
‘ field. Testing the server reveals that valid ‘subject_type
‘ values are 1-3. I sent every combination of ‘subject_field
‘ with “is_employee
” set to both true and false. This provoked varying responses from the server.
This is just about as far as I went. Any enterprising hunter has quite a bit of attack surface to look at here.