New collection API bug: Any app can push products to an app-owned source that it does not own

Description

Using the now legacy mutation collectionAddProductsV2 any app can push product to a source it does not own.

Steps to reproduce

  1. Create an app owned source from app A and link it to a collection
mutation CollectionConditionsSourceCreate($input: CollectionCreateConditionsSourceInput!) {
          collectionConditionsSourceCreate(input: $input) {
            source { id }
            userErrors { field message }
          }
        }
{
        input: {
          title: "title",
          description: "description",
          targetType: "PRODUCTS",
          inclusion: {
            matchType: "ANY",
            conditions: [
              {
                productTag: {
                  relation: "TAGGED_WITH",
                  values: [
                    "some-tag",
                  ],
                  matchType: "ANY",
                },
              },
            ],
          },
        },
      }

Important: This app-owned source belongs to App A and has id gid://shopify/CollectionConditionsSource/1234 and it is attached to collection `gid://shopify/CollectionConditionsSource/5678`

  1. Try to add a product to the source from App B using the new source-based API
mutation CollectionConditionsSourceUpdate($input: CollectionUpdateConditionsSourceInput!) {
  collectionConditionsSourceUpdate(input: $input) {
    source { id }
    userErrors { field message }
  }
}
{
      "input": {
        "id": "gid://shopify/CollectionConditionsSource/1234",
        "inclusion": {
          "selectionsToAdd": [{ "productId": "gid://shopify/Product/9999"}]
        }
      }
    }

As expected it returns error Source is not owned by this app

  1. Now try to push the same product to a collection that uses the source 1234 using the legacy API. From App B run this query:
mutation collectionAddProductsV2($id: ID!, $productIds: [ID!]!) {
          collectionAddProductsV2(id: $id, productIds: $productIds) {
            job {
              done
              id
            }
            userErrors {
              field
              message
            }
          }
}
{
      "id": "gid://shopify/Collection/5678",
      "productIds": ["gid://shopify/Product/9999"]
    }

It added a product to the source. In other terms App B was able to add a product to a source that belongs to App A despite not being allowed to do so.

Expected

The mutation collectionAddProductsV2 should not let an app pushing products to an app-owned source that it does not own.

@Wes-Dev-Shopify @diana_cheptene @Liam-Shopify

Hey @Soufiane_Ghzal - thanks for flagging this.

After further investigation, we’ve confirmed that the issue reported here has been fixed.

For future reports that may involve a sensitive matter such as an app being able to affect the functionality of another app, please report them through Shopify’s Bug Bounty Program: HackerOne, rather than sharing the details in a forum post.

Thanks again and I hope this helps!