[00.00_r1gor]
[00.00_bugbounty]
r1gor

all write-ups

$1,499/month plan for free, on a HIPAA platform

Target is a healthcare automation platform. Clinics wire it up to their EHR, lab, scheduling, billing. Workflows shuffle PHI between systems. The pricing page goes Starter $149, Professional $399, Scale Up $1,499, Enterprise "talk to sales".

I wanted Scale Up. I did not want to pay $1,499.

the bug

The billing surface is a Hasura GraphQL endpoint. After signing up I grabbed a Hasura JWT from the session token endpoint and hit the schema.

query {
  pricingTable {
    name
    productId
    isSelectable
    price { id unit_amount interval }
  }
}

Every plan came back with isSelectable: true and a Stripe price id sitting next to it. Including Scale Up.

mutation {
  selectPlan(priceId: "price_1OjeucIwl3CYZ39AhhJbbFmZ") {
    name
    status
    trialEnd
    currentPeriodEnd
    requiresPaymentInfo
    price { unit_amount interval }
  }
}

response, http 200:

{
  "name": "Scale Up Plan",
  "status": "trialing",
  "trialEnd": "2026-05-21T16:08:55.000Z",
  "requiresPaymentInfo": true,
  "price": { "unit_amount": 149900, "interval": "month" }
}

read it twice. same json object. server says requiresPaymentInfo: true and in the same breath sets the plan to trialing and hands me a 28 day expiry. the field exists. somebody wrote it. it just is not wired to the gate.

confirming the entitlements

query {
  entitlements {
    plan { name status }
    quotas {
      runs { limit count }
      workflows { limit count }
    }
  }
}
{
  "plan": { "name": "Scale Up Plan", "status": "trialing" },
  "quotas": {
    "runs":      { "limit": 24000, "count": 0 },
    "workflows": { "limit": 15,    "count": 0 }
  }
}

24,000 workflow runs a month. 15 concurrent workflows. Scale Up features unlocked. No credit card on file. No billing address. No Stripe customer. The trial badge in the UI is the only thing distinguishing this from a paying tenant.

the bonus round

There is a separate extendTrial mutation. First call returns true. Subsequent calls rate limit with "Trial extension limit reached". So the trial is renewable once, then you burn the account and sign up again. New email, new tenant, another 28 days of $1,499 a month.

Enterprise is properly blocked. selectPlan with the Enterprise price id returns "Enterprise plan cannot be selected". So the gate exists in the resolver. It just covers exactly one plan out of four.

Starter ($149) and Professional ($399) bypass the same way.

why it works

The pricing table flags every paid plan isSelectable: true whether the caller has a payment method or not. selectPlan reads isSelectable and the explicit Enterprise denylist, then provisions the trial. Stripe customer creation, payment method check, billing guard - all of that lives downstream of the entitlement update. The entitlement is granted before the payment surface is even consulted.

The fix is the boring one. selectPlan should refuse to grant any paid trial without a Stripe payment method on file, or a sales-led override flag. Trust the field that already exists in the response, requiresPaymentInfo. The server is telling itself the answer in the same payload it ignores.

scale

  • $1,499/month plan, free, instant
  • 24,000 workflow runs per cycle, on a HIPAA platform
  • repeatable per email address, per tenant, indefinitely
  • enterprise gate exists, three other paid tiers go around it

The healthcare angle is what makes this more than a billing bug. Every workflow run on Scale Up can move PHI between connected systems. A free tenant gets 24,000 of those a month. Whatever the abuse case is, you scale it on someone else's compliance bill.

reported.

when a server returns its own gate next to its own decision, read both. the response is sometimes confessing.