July 30, 2026
From a Duplicate to a Bounty: How Digging Deeper Led to a More Impactful Business Logic…
While testing a subscription system, I discovered two business logic vulnerabilities related to the Business trial workflow. The first…
By Mahmoudelsadany
3 min read
While testing a subscription system, I discovered two business logic vulnerabilities related to the Business trial workflow. The first issue turned out to be a duplicate, but instead of moving on, I continued investigating the same functionality. That decision led me to discover a second, more impactful vulnerability that was accepted and rewarded.
One of the biggest lessons I learned from this experience was simple:
A duplicate report doesn't always mean the end of your research. Sometimes it's just the beginning.
1. Unlimited Business Trial Reactivation
Overview
The application offered a 14-day Business trial for each workspace. Users on the Free plan were limited to a single workspace, and each workspace was expected to be eligible for the trial only once.
While exploring the trial functionality, I identified the endpoint responsible for activating the Business trial.
POST /api/v1/workspaces/trialPOST /api/v1/workspaces/trialAfter my initial 14-day trial expired, I simply repeated the same request using the same workspace_id.
Unexpectedly, the server responded with HTTP 200 OK and returned a brand-new Stripe Checkout URL.
{
"checkout_session_url": "https://checkout.stripe.com/..."
}{
"checkout_session_url": "https://checkout.stripe.com/..."
}Completing the checkout activated another 14-day Business trial for the same workspace.
Root Cause
The application failed to permanently mark a workspace as having already consumed its Business trial.
Once the previous trial expired, the backend allowed the same workspace to request another trial indefinitely.
Impact
Any user could repeatedly reactivate the Business trial and continue using premium Business features without ever purchasing a subscription.
Unfortunately, this issue had already been reported and was marked as a duplicate.
At this point, I could have stopped testing. Instead, I decided to continue exploring the same endpoint because I felt there was still something interesting happening behind the scenes.
That decision eventually led to a completely different vulnerability.
2. Trial Stacking via Multiple Checkout Sessions
Observation
POST /api/v1/workspaces/trialPOST /api/v1/workspaces/trialI noticed that every request generated a completely new Stripe Checkout session.
For example:
- First request → Checkout URL A
- Second request → Checkout URL B
- Third request → Checkout URL C
Each request returned a unique checkout URL.
After activating the trial, attempting to generate another checkout session normally resulted in a response indicating that the workspace was already subscribed.
That made me ask myself a simple question:
What would happen if I generated multiple checkout sessions before completing any of them? Would they all remain valid?
If every checkout session remained valid independently, perhaps they could all be completed even after the first subscription had already been activated.
Testing
To verify this idea, I performed the following steps:
- Generated multiple trial checkout sessions.
- Saved every Stripe Checkout URL.
- Activated the trial using the first checkout session.
- Returned to one of the previously generated checkout URLs.
- Completed the checkout process again.
To my surprise, the server accepted both subscriptions independently.
Initially, nothing seemed unusual.
The application still displayed a normal 14-day Business trial, so I assumed the second activation had no effect.
I cancelled the subscription and waited for the trial to expire.
Unexpected Behavior
After the trial period ended, something unexpected happened.
The application displayed messages indicating that the Business plan had expired and prompted me to upgrade.
However, the workspace was never actually downgraded.
Although the interface claimed that the subscription had expired, I still had full access to Business features.
For example:
- Trial started: December 19
- Expected expiration: January 2
- Several days later, Business features were still accessible.
At this point, it became clear that the subscription state had become inconsistent.
The frontend considered the subscription expired, while the backend continued treating the workspace as an active subscriber.
After reviewing the API response, I confirmed that the subscription status was marked as expired, yet premium Pro features were still available.
The screenshot below demonstrates this inconsistency between the subscription status returned by the API and the privileges granted to the account.
Extending the Research
Since the issue appeared to affect the trial workflow rather than only the Business plan, I decided to test another subscription tier.
The application also offered a 7-day Pro trial.
Using the same technique, I generated multiple checkout sessions before completing any of them.
The result was identical.
After the trial officially expired, the application indicated that the Pro subscription had ended and the account should have been downgraded.
However, premium Pro features remained fully accessible.
This confirmed that the vulnerability affected the application's subscription lifecycle rather than a single trial implementation.
Root Cause
The application generated multiple valid Stripe Checkout sessions for the same workspace without invalidating previously generated sessions.
Each checkout session could independently activate a trial, resulting in overlapping subscription states that were never properly synchronized.
As a result, premium access could persist even after the trial had officially expired.
Lessons Learned
This was one of the most valuable lessons I've learned since starting my bug bounty journey.
I didn't discover the second vulnerability by switching to another feature or testing a different part of the application. Instead, I stayed focused on the same endpoint and kept asking simple questions about how it behaved.
If you're just getting started with bug bounty hunting, don't be discouraged by duplicate reports. Take the time to understand how a feature works, question every assumption, and explore edge cases. Persistence and curiosity often lead to discoveries that are far more impactful than your initial finding.
Thank you for reading.