Skip to main content

STALLYONS TECHNOLOGIES

Innovating the future of digital with AI, design, and technology. From AI to Web — Stallyons transforms your ideas into digital reality. Building smarter digital experiences through AI, innovation, and technology. Innovating the future of digital with AI, design, and technology. From AI to Web — Stallyons transforms your ideas into digital reality. Building smarter digital experiences through AI, innovation, and technology.
EN
background

Blog

RocketChat: QA of
an HTML and JS Sandbox

RocketChat QA of an HTML and JS Sandbox

Letting users post HTML and JavaScript into a chat channel is either a great feature or a security incident waiting to happen, depending entirely on whether the sandbox around it holds. This RocketChat deployment made that bet on purpose: channels can render user-supplied HTML and JavaScript so messages carry rich content like interactive charts and custom widgets. The feature that makes the platform special is also its biggest risk, so the testing had to prove the sandbox contains that content on every client before anyone could trust it. This is the story of that quality assurance work.

RocketChat here is a cross-platform communication and collaboration platform on Web, iOS and Android, deployed and then extended with an unusual capability: channels render user-supplied HTML and JavaScript, sandboxed in an iframe on the web and in WebView components on mobile so that content cannot do harm. Around that headline feature sit the ordinary but essential parts of a chat platform, real-time messaging, access and authentication, the user, channel and message APIs, and rate-limiting.

Put simply, the defining tension is that executing HTML and JavaScript from messages is both the point and the peril. So security testing sits at the centre of the work: the sandbox is attacked directly to prove it contains malicious scripts and cannot be used to escape, steal tokens or reach other channels. Everything else is verified around that core.

The Starting Point: A Feature That Is Also the Risk

A chat platform that deliberately runs user HTML and JavaScript, across three clients and in real time, concentrates risk in a few sharp places. Six problems set the testing agenda:

  • Channels run user HTML and JavaScript. Arbitrary content is rendered, so the sandbox had to be proven to contain it and block cross-site scripting, not merely assumed to.
  • The sandbox has to hold on every platform. Content renders in a web iframe and in mobile WebViews, so containment had to be verified on Web, iOS and Android, not just one.
  • Real-time messaging has to stay reliable. Messages flow over WebSockets, so delivery, ordering and reconnection had to hold up under many users and channels.
  • Access has to be enforced. Roles, private channels, JWTs and OAuth logins all gate what a user can see and do, so the access boundary had to be tested rather than trusted.
  • The APIs have to be correct. Users, channels and messages have full CRUD, with cascade deletions, edit-and-delete-own rules and pagination, all of which had to behave correctly.
  • Abuse has to be limited. Rate-limiting protects the APIs, so it had to be tested to confirm it throttles abuse without blocking normal use.

The QA Approach: Attack the Sandbox First

The sandbox was treated as the top priority and attacked head-on. Using a library of cross-site-scripting and injection payloads, the tests confirm that content rendered in a channel stays inside its sandbox: scripts cannot break out of the iframe or WebView, read or steal JWTs, call the APIs as the user, or reach other channels. The same attacks are then run against the web iframe and the iOS and Android WebViews, because a cross-platform app is exactly where containment is most likely to differ from one client to the next.

Each attack follows a fixed procedure, and the test asserts the outcome at each point in it:

  1. A cross-site-scripting or injection payload is crafted to attempt an escape.
  2. It is posted into a channel as ordinary user content.
  3. The content renders in the sandbox, the web iframe or a mobile WebView.
  4. The test asserts the script cannot escape, steal a JWT, call the APIs as the user, or reach another channel.
  5. The same payload is re-run on Web, iOS and Android to prove containment holds everywhere it renders.

On that foundation the rest of the platform is verified. The WebSocket layer is tested for delivery, ordering, reconnection and behaviour under concurrency, so real-time messaging stays reliable. Role-based access, JWTs and OAuth logins are tested so roles and private-channel memberships are enforced. Because the sandbox first has to hold in the browser, where the content renders inside an iframe, this work sits close to our web development practice, where an embedded frame running untrusted scripts is a security surface, not just a view.

Technical Architecture of the Test Suite

The strategy tests the RocketChat clients and their HTML and JavaScript rendering, real-time and data layers at API, security, integration, real-time and cross-platform levels, with a payload-driven attack on the sandbox at its heart, all automated in continuous integration. The pieces worth calling out:

  • Security testing of the sandbox. Because channels render user HTML and JavaScript, the sandbox is attacked with cross-site-scripting and injection payloads to confirm scripts stay contained and cannot escape, steal JWTs or reach other channels, the single most important test for this platform.
  • Cross-platform containment. The same attacks run against the web iframe and the iOS and Android WebViews, so the sandbox is proven to hold consistently everywhere the content renders.
  • Access and authentication. Role-based access, JWTs and OAuth logins are tested so roles and private-channel memberships are enforced and only the right users reach the right channels and actions.
  • Real-time messaging. The WebSocket layer is tested for delivery, ordering, reconnection and behaviour under concurrency, so live messaging stays reliable across many users and channels.
  • APIs and data. The user, channel and message APIs are tested for correct CRUD, cascade deletions, edit-and-delete-own rules and pagination, so the data stays consistent.
  • Abuse prevention and automation. Rate-limiting and authentication boundaries are tested to throttle abuse, and the whole suite runs in CI on every change so security regressions are caught before release.

Proving a platform this security-sensitive, where the headline feature is also the attack surface, is the kind of work our software QA and testing team leads with security tests rather than bolts them on at the end.

Challenges Solved

Containing the HTML and JavaScript came down to attacking the sandbox directly with cross-site-scripting and injection payloads until it was proven to hold, with no escape and no token theft. Holding that containment on every platform meant running the same attacks against the web iframe and both mobile WebViews, so behaviour could not quietly diverge on one client. Keeping real-time messaging reliable meant testing WebSocket delivery, ordering and reconnection under concurrency. Enforcing access meant role, JWT, OAuth and private-channel membership tests, so only the right users reached the right places. Verifying the APIs meant CRUD, cascade-delete, edit-and-delete-own and pagination tests. And limiting abuse meant rate-limit and authentication-boundary tests.

The through-line was leading with security and automating it, so the most dangerous kind of regression, a hole in the sandbox, is caught immediately rather than discovered in production. Real-time collaboration platforms like this are common across SaaS and startups, where a product’s most distinctive feature is often its riskiest and has to be proven safe before it ships.

The Result

The sandbox is proven to hold on every client, the messaging is reliable in real time, the access is enforced, and the APIs behave correctly, all verified repeatably and automatically. Because the riskiest feature is proven safe and the rest is thoroughly checked, the platform can be shipped and changed with confidence, and a security regression is caught in CI on the change that introduces it rather than in the wild.

If you are shipping a platform whose best feature is also its biggest risk, you can bring on dedicated developers who have security-tested exactly this kind of system, or tell us what you are building and we will map out how to prove it safe before it goes live.

Frequently Asked Questions

How do you test a sandbox that runs user HTML and JavaScript?

By attacking it directly. A library of cross-site-scripting and injection payloads is posted into channels, and the tests confirm the content stays inside its sandbox and cannot escape, steal JWTs, call the APIs as the user, or reach other channels. The sandbox is proven to contain the content rather than assumed to.

Why run the same attacks on Web, iOS and Android?

Because the content renders in a web iframe and in mobile WebViews, and a cross-platform app is exactly where behaviour can diverge. Running the same payloads against all three clients proves containment holds consistently everywhere the content renders, not just on the one platform that happened to be tested.

How is real-time messaging tested?

The WebSocket layer is tested for delivery, ordering, reconnection and behaviour under concurrency, so live messaging stays reliable when many users and channels are active at once, rather than only when a single conversation is open.

How is access controlled and verified?

Role-based access, JWTs and OAuth logins are tested so roles and private-channel memberships are enforced, and only the right users reach the right channels and actions. The access boundary is tested rather than trusted.

Are the APIs and rate-limiting covered too?

Yes. The user, channel and message APIs are tested for correct CRUD, cascade deletions, edit-and-delete-own rules and pagination, and rate-limiting is tested to confirm it throttles abuse without blocking normal use. The whole suite runs in CI on every change so regressions in any of these layers are caught before release.

Leave a Reply