Sandboxed Escaping

Discovering the issue

While working on a security review for a popular application, I ran into something that felt a little off. The app had a sandbox user meant for testing and development, so people could try things out without putting real user data at risk. At least, that was the intention.

Before going further, a quick note. Since work with this client is still active, all values and examples here are replaced with stand-in data to protect the real environment.

As I spent more time with the app, I found a path that allowed these restricted sandbox accounts to interact with information related to real users on another connected platform. It was not something you would find by accident. It took some patience and a fair bit of curiosity to piece together. Once it clicked, it became clear that the isolation was not as strong as it first appeared.

How the pieces started to fit

In theory, sandbox users should live in their own world. They are not supposed to see or touch anything that belongs to real users. That is the entire point of having a separate environment. While I was testing different endpoints though, I started to notice behavior that did not match that expectation. Even though I was using a sandbox account, the responses hinted that the account was being exposed to media from a connected sister application. That raised the question of what else this token could reach across that boundary.

Step 1: Capturing the token

I began by logging in with a sandbox account while intercepting traffic through Burp Suite. This gave me a session token that the platform used to identify the account and decide what it should be able to do.

GET /account/verify?info=&options=1&token=ABC[REDACTED] HTTP/2
Host: api.exampleplatform.com
User-Agent: Mozilla/5.0

The response confirmed that the token belonged to my sandbox user, which matched what I expected at this stage.

Step 2: Probing endpoints

The next step was to see how far that token could go. I started calling other endpoints that were tied to the surrounding environment. At first, everything lined up with the documented permissions for the sandbox account. Many requests were rejected with clear messages that the request was not supported or did not have the right level of access.

{
  "issue": {
    "details": "Unsupported. Invalid request or insufficient permissions.",
    "status": 400
  }
}

That was the expected behavior, and if things had stopped there, the story would have ended. But once I pointed the same token at endpoints that belonged to the sister application, things changed.

GET /user-profile/67890?info=&options=1&token=ABC[REDACTED] HTTP/2
Host: api.sisterplatform.com
User-Agent: Mozilla/5.0

This time, the response did not contain an error. Instead, it returned structured data about a real user on the sister platform, including metadata and references to their media and activity.

Realizing the connection to the sister app

What made this more serious is that the sister platform is a production system with a real and active user base. Many people have accounts on both platforms. Under the hood, the two applications share some of the same API logic. Because of that, the sandbox token I captured could successfully reach endpoints in the sister environment.

This meant that a sandbox account, which should have been limited to a safe and contained space, could access profiles and activity information associated with real users on the sister platform. In the right conditions, it might even be possible to send interactions on their behalf. At that point, the sandbox felt less like a safe test space and more like an unexpected doorway.

Where things went wrong

  1. Shared API logic. Both environments relied on overlapping API components. That shared logic did not fully separate requests from the sandbox and the sister platform.
  2. Session tokens used across environments. The same session token format appeared to be valid on both sides. The token for the sandbox user was not strictly limited to the sandbox rules.
  3. Missing context checks. The sister platform did not consistently verify that the incoming token belonged to a user in its own environment. Instead, it accepted the token and proceeded with the request.

Strengthening the separation

Closing thoughts

This experience was a helpful reminder that details around environment design are easy to overlook. It is not always the obvious access control checks that cause trouble. Sometimes it is the quiet reuse of a token format or shared logic between applications that opens the door.

In the end, testing like this is not about pointing fingers. It is about finding the gaps that are hard to see from the inside, so that teams can close them and keep users safer. Each issue like this is an opportunity to learn and to improve how we think about separation, trust, and access in complex ecosystems.

Powered by Buttondown.