Coinbase Wallet Chrome Extension Basic Security Analysis

coinbase wallet security review

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

privacy

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.

bugsnag

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.

nonce

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.

create user

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

get user profile

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

refresh access token

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.

event tracking 1

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.

metrics 1

The above ‘metrics‘ are sent to dp.coinbase.com/metrics.

What happens when we connect the wallet to staking.synthetix.io?

dapp usage

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.

userleap

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.

featureflags

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.

experiment list employee boolean

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?

employee true subject type 2

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.

Related Articles