‼️ Disclaimer: I've changed specific details about the application in this write-up for confidentiality. Even the screenshots shown are from a different, similar application that doesn't have a bug bounty program — they're only used for illustration. Also, all API endpoints mentioned have been altered to avoid revealing the actual program.
The Program
Alright so I'm looking at this organization's application: A management platform. The ecosystem consists of a main web interface at app.target.com for user onboarding and a GraphQL API endpoint hosted at app.target.com/api/v1/graphql. While mapping out the application's functionality, I noticed it also allows inviting other users and there's a page for user management where roles can be assigned and what not.
My testing methodology always begins by establishing a baseline for expected behavior. By using the application as intended, creating an account, verifying the email, and logging in, I can map out what a successful response looks like. I observed that the application issues a JWT for session management immediately after both email verification and standard authentication.
The Vulnerability
Initially, this was straight forward. After creating an account, I was hit with a 'Verify Your Account' wall. Without that activation link, there was no obvious path to the dashboard. I attempted several forced browsing techniques to bypass the requirement, but the server consistently redirected me back to the verification notice. At this stage, no session JWT had been issued, confirming that the application was correctly withholding authentication until the account was activated.

But looking through burp's HTTP History tab, I noticed 3 GraphQL requests go through when this page loaded up for the first time. In contrast, when you do a fresh login with the newly created account, you get redirected to the same verification page. However, these 3 GraphQL requests do not happen.

These are easy to miss as a lot of GraphQL analytic operations are being sent during this time. Reviewing the first of the 3, I noticed it was a query operation to retrieve the signed-up user's profile information. The second one retrieved my workspace info and the last retrieved my role information. In these 3 requests, there was a custom header named X-Target-Env-Access-Blobwhich contained a key. Removing this gave me a 401 error.
This is another method I used to Bypass Rate Limit using some special headers in the request.
The Exploit
Using the account I created earlier to understand the flow, I performed a few authenticated operations, including inviting another user to my workspace. This GraphQL mutation takes a workspace ID and the invitee's email. I copied the mutation into Burp Suite's Repeater, grabbed my workspace ID from the second background request I found earlier, and added the email address I wanted to invite.
{
"query": "mutation InviteUserToWorkspace($input: InviteUserInput!) {
inviteUser(input: $input) {
success
message
invitation {
id
email
role
status
}
}
}",
"variables": {
"input": {
"workspaceId": "ws_attackers_worspace_UUID",
"email": "another-user@tinopreter.com",
"role": "MEMBER"
}
}
}I sent this and I got an invite link in my inbox. This means, even though my request does not have a valid JWT Authorization, the key in the X-Target-Env-Access-Blobheader provided me with an authenticated session to use the application through the APIs, without verifying my account.
Decompile Android APK to learn how to Abuse Notification Logic for exploit.
Impact of this Email Verification Bypass
As an attacker, you could sign up using any organization's email and take full control of the resulting workspace through the API. From there, you could create tasks and invite legitimate staff to join fraudulent projects. You could even invite your own external email addresses, assign yourself administrative privileges, and operate right alongside unsuspecting employees.
Initial Payment
I was paid $500 for this finding. I expected more but yeah.

But I wasn't done yet.

First Escalation: Session Persistence ($150)
When you create an account with your victim's email and get stuck at the verify email page, you can manage your workspace through the APIs.
The Invite Flow
When you create an account, a workspace is automatically generated under your name. However, if a workspace admin is invited to join another user's workspace and accepts that invitation, they immediately lose access to their own workspace and become a member of the new one.
When the victim (whose email we used to create the account) is invited to a legitimate workspace and accepts, they are prompted to set a new password. This immediately invalidates the password the attacker set during the initial account creation. Ideally, the workspace the attacker was operating under also gets abandoned. Once the victim sets their own password, the attacker's unauthorized access is effectively cut off.
BUT, the access granted by those 3 GraphQL requests is never invalidated after the password change. We can now see the new workspace data the victim has access to.
Even after a new password is set and the initial workspace we controlled becomes invalid, the session remains persistent. I submitted this in a new report, but it was downgraded to Low severity due to specific attack constraints. I ultimately agreed with the assessment and was awarded a $150 bounty.

Second Escalation: Account Linking ($200)
I don't want to make this write-up too long. This particular escalation was very interesting, so I will create a separate post for it and update this one with the link once it's live.
In summary, I identified an improper OAuth implementation where combining session persistence with the email verification bypass allowed for unauthorized account access. The security team determined that this finding shared the same root cause as the initial verification bypass, which acted as the anchor for most of these attacks. They downgraded the severity accordingly and awarded a $200 bounty.

Final Argument: Getting Paid the Remains ($650)
The fact that they all have the same root cause tied to the email verification bypass aside, the impact of this bypass extends far more than my initial report indicated. I reopened the bypass report and argued my point.

They agreed and upgraded the original email verification bypass from Medium to High. Since I had already been paid $850, they issued the remaining $650 to meet the $1,500 total that a High-severity finding deserves.

At times all it takes is taking some time away from the keyboard and coming back with new ideas. Communication is also very key.
At times all it takes is Changing the wording in an API's path to retrieve ALL user PII.
Hey …bye

Thanks for reading this, if you have any questions, you can DM me on X @tinopreter. Connect with me on LinkedIn Clement Osei-Somuah.