In bug bounty hunting, we often spend a lot of time looking for complex injection flaws or deep architectural logic errors. But sometimes, the most critical vulnerabilities present themselves when an application simply breaks down and talks too much.
Recently, while testing a prominent online learning platform (let's call it target.com), I stumbled upon a vulnerability that started as a simple console error but escalated into a massive infrastructure exposure.
Here is the story of how a failed WebSocket connection leaked a real-time authentication token, and how a severe misconfiguration turned that token into a master key for the platform's backend.
The Trigger: Breaking the State
It all started while I was testing the search functionality on target.com. I like to observe how frontend applications handle unexpected or malformed inputs. I injected a basic JavaScript payload into the search filter to see if the application would reflect it or throw an interesting error: https://target.com/home/search?query=test&filter=javascript:console.log(1)
While this didn't trigger an XSS, it did something arguably more interesting: it broke the application's internal state.
With my browser's Developer Tools open, I noticed that this malformed URL caused the frontend to fail to establish a WebSocket connection with its third-party Real-Time Messaging provider (Backend-as-a-Service, or BaaS).
When the connection failed, the application loudly complained in the developer console and the network logs. Mixed in with the error text was the full WebSocket URL being attempted and right there in plaintext, sitting in the URL parameters, was an active access_token.

The Pivot: From Frontend Leak to Backend Exploit
Finding a leaked token is great, but as researchers, our next immediate question must be: "Exactly how much power does this token hold?"
In a well-architected system, a client-side token like this should be strictly scoped. Think of it like a hotel keycard: it should only give the user access to their specific room (in this case, their personal notification channel).
Instead of trying to reconnect the WebSocket in the browser, I took the leaked token and moved over to Burp Suite. I wanted to speak directly to the third-party messaging provider's REST API to see what this token was allowed to do.
Bypassing the WAF and Probing the API
My first few direct API requests were blocked. It turned out the infrastructure was sitting behind a Web Application Firewall (WAF) that was filtering out automated or non-standard REST requests.
To bypass this, I forged my requests in Burp Suite to perfectly mimic a legitimate browser session, spoofing the User-Agent, Origin, and Referer headers to match target.com.
First, I tested the token against the BaaS provider's /time endpoint to verify it was actually active:
GET /time HTTP/2 Host: [REDACTED_BAAS_API_URL] Authorization: Bearer [REDACTED_TOKEN] User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Origin: https://target.com Referer: https://target.com/ Accept: application/json, text/plain, */*
Result: HTTP/2 200 OK. The token was fully valid.

The Escalation: Unmasking the Infrastructure
Now it was time to test the access controls. I sent a request to the /channels endpoint, which is typically an administrative route used to list active communication pipelines.
GET /channels HTTP/2 Host: [REDACTED_BAAS_API_URL] Authorization: Bearer [REDACTED_TOKEN] User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Origin: https://target.com Referer: https://target.com/ Accept: application/json, text/plain, */* Connection: close
To my surprise, the server responded with a massive 200 OK.
The token wasn't scoped to my user at all. The API dumped a full JSON response containing the active internal channel IDs for the entire platform. It revealed the underlying naming conventions (e.g., [REDACTED_APP]:[REDACTED_TENANT]:****) and the live activity footprint of the application.

To confirm the severity, I hit the /stats endpoint. Once again, the token successfully authenticated and returned application-wide analytics and traffic data.
The Impact: Why This Matters
This vulnerability is a textbook case of Broken Access Control leading to severe Sensitive Information Disclosure.
Because the token lacked proper capability restrictions, it functioned as an over-privileged master key. An unauthenticated or low-privileged attacker who snagged this token could:
- Enumerate the Infrastructure: Map out all active real-time communication channels across the platform.
- Intercept Traffic: By scripting a custom WebSocket client, an attacker could potentially subscribe to these exposed channels. This could lead to the interception of administrative broadcasts, internal course updates, or even private user notifications a massive privacy breach.
The Fix: Two Critical Security Lessons
I immediately reported this issue to the vendor, outlining two required fixes to secure the infrastructure:
- Enforce the Principle of Least Privilege (Token Scoping): Client tokens must never be globally scoped. When generating authentication for third-party BaaS providers, backend servers must use capability mechanisms to restrict the token. A client should only be granted
subscribeorpublishpermissions for the exact channels associated with their user ID. Access to administrative REST endpoints like/channelsand/statsmust be explicitly denied for client-side tokens. - Prevent Token Exposure in URLs: Tokens should never be placed directly in connection URL parameters. When a connection fails, browsers will often log the full URL (including the secrets) to the console or local logs. Developers should use secure headers or secure callback methods for token exchange during WebSocket initialization.
Conclusion
This finding is a great reminder that modern applications are only as secure as their third-party integrations. What seemed like a harmless frontend connection error ended up providing a direct, unfiltered view into the platform's backend infrastructure.
Always keep an eye on your console logs when breaking an application's state you never know what secrets the app might drop when it panics!
Disclaimer: This vulnerability has been fully patched. No sensitive user data was extracted, retained, or manipulated during this authorized security research.