# Unauthenticated access to Checkout Blocks employee-only endpoints exposed merchant metadata

Next.js data-route URL bypassed edge auth on checkout-blocks.shopifyapps.com, exposing 201k merchant install records and feature flags to anonymous users.

- Payout: $3,100
- Severity: medium
- Program: Shopify
- Found by: cafecito
- Disclosed: 2026-11-03
- Write-up quality: 8/10
- Original: https://hackerone.com/reports/3954327
- Library page: https://bugbountylibrary.com/r/h1%3A3954327
- Tags: area:web domain:web impact:data-leak impact:integrity kind:bounty platform:hackerone sev:medium tech:nextjs technique:recon technique:source-review vuln:access-control vuln:auth-bypass vuln:info-disclosure

**Target:** Next.js app on checkout-blocks.shopifyapps.com internal staff API routes
**Root cause:** Employee-only routes were protected only by an edge rule matching URL prefix /internal; Next.js also serves the same route code at /_next/data/<buildId>/<route>.json, which the rule did not match and which lacked in-route session checks.
**Steps:**
1. Request `/api/internal/shops` unauthenticated -> 302 to minerva.shopifycloud.com employee login (gate works).
2. Read buildId from public `/login` page.
3. Request `/_next/data/<buildId>/api/internal/shops.json` with no cookie/authorization -> 200 JSON.
4. Confirm not catch-all: `/_next/data/NOPE/...` -> 404; `/_next/data/<buildId>/api/admin/...` -> 302 login (route checks own session).
5. Paginate to page 40298 of 40304, retrieving shop domains, internal shop ids, install dates and feature flags.
**How found:** Noticed staff pages redirect to employee SSO, recognized the app is Next.js, and hypothesized the framework's parallel /_next/data/<buildId>/<route>.json URL would not match the edge prefix rule but would reach the same handler; buildId was leaked on the public /login page.
**Exploitation:** Anonymous internet user reads buildId from /login, then hits /_next/data/<buildId>/api/internal/*.json to page through the full merchant install list (201,520 records) including staging stores and enabled feature flags; team review found the same bypass allowed toggling Checkout Blocks features for stores.
**Escalation:** Beyond read-only metadata, internal review found the bypass also permitted enabling/disabling Checkout Blocks features on arbitrary stores.
**Insight:** On Next.js targets, any edge/WAF rule keyed on a path prefix can be bypassed via the framework's /_next/data/<buildId>/<route>.json twin URL; grab buildId from public pages and test a route known to self-check session as a control to prove it's a bypass, not a public endpoint.

## Proof of concept (copied exactly from the original report)

**PoC script bypassing auth via Next.js data route**

```
Run the attached `poc.sh`. No arguments, no credentials.

1 normal  /api/internal/shops      -> 302  https://minerva.shopifycloud.com/auth/minerva?...
2 bypass  /_next/data/ID/..shops   -> 200  628 bytes  application/json
3 ghost   /_next/data/NOPE/..      -> 404  (expect 404)
4 control /_next/data/ID/..admin   -> 302  .../login  (expect 302 login)
5 last page  -> {'total': 201520, 'pages': 40304, 'current': 40298} | shops returned: 5
```

