Context
Last week, a Shopify app experienced a security incident where merchant access tokens were leaked via publicly accessible theme files. A bad actor used these exposed access tokens to initiate customer refunds.
This resulted in massive refunds to the affected merchant’s accounts. Exact numbers aren’t known.
To be clear, this only affected merchants using this app, and only a portion of those merchants whose access tokens associated with this app were scraped and abused.
What happened
The bad actor most likely used the refundCreate mutation to initiate these refunds.
This mutation creates a refund for a given order. The access token must have the order_write scope in order to execute this mutation.
The issue
Beyond the access token leakage, the problem is that the orders_write scope is far too broad. If your app simply needs to update tags or edit metafields on a given order, then it will also have potential to cause financial harm to the merchant via this scope in the wrong hands (or just accidentially).
Proposal
Please consider moving financially risky mutations to a separate access scope for the following reasons:
- Reduces risk to merchants for apps that need to update orders but NOT process refunds
- More granular scopes make it explicit that your app is performing financial operations like refunds
I understand that this will be impactful for apps that actually perform financial related actions like refunds, asking for additional scopes interrupts and disrupts merchants. However, the App Bridge has made it possible to gradually adopt additional scopes, so now it’s possible to introduce a window where merchants can opt into this scope until a future Admin API version that formally splits the concerns of order writes vs transactions writes.
The scope name is obviously just a placeholder, but the general idea would be to separate these risky operations into a different scope, separately from the general orders_write scope.