Brian Dantonio | 30 Jul, 2025

Can Python or Ruby Feel First-Class in the Browser?

The idea of running Python, Ruby, or Lua directly in the browser feels like something out of a dream, or a nightmare, depending on your perspective. For developers coming from a security background, this trend is both fascinating and unsettling.

We have spent decades shrinking browser attack surfaces, tightening origin policies, and sandboxing script execution. Now we are shipping entire language runtimes to the client.

That raises a simple but crucial question. Are we trading convenience for safety?

Real Appeal. Various Options.

Let’s start by acknowledging why this is even worth talking about.

Projects like Pyodide, ruby.wasm, and Fengari let developers write client-side code in languages they know and love. Scientific apps written in Python can run interactive visualizations directly in the browser, with no server round-trips. Ruby developers can prototype logic without switching to JavaScript. Educators can build zero-install notebooks for students who have never used a terminal.

You can even try Python instantly in the browser using tools like the Hackr.io Python editor, which runs client-side and requires no setup. These examples show how close we are to a truly polyglot browser.

That is powerful. In some cases, it is genuinely transformative. It also means we are pushing the browser from a controlled execution environment toward something more like a general-purpose virtual machine.

And it doesn't take much to run these.

Under the hood, most of these language ports work by compiling the language interpreter or runtime into WebAssembly (WASM). Pyodide, for example, compiles the full CPython interpreter and parts of the Python standard library into a WASM module.

Once loaded, it can evaluate Python code inside the browser, with access to in-memory filesystems, numerical libraries, and limited browser APIs through JavaScript bindings.

All of this runs inside the WASM sandbox. On paper, that sounds safe. But let us look closer.

Security: The Mirage of Containment

WebAssembly was designed with sandboxing in mind. WASM modules are memory-safe, cannot make arbitrary syscalls, and respect the same-origin policy. They also cannot access the DOM directly. That is a good starting point.

However, if you are compiling a full dynamic language runtime and shipping it to the client, you are also:

  • Increasing your attack surface by including the full standard library of that language
  • Shipping large binary payloads that may include legacy or obscure C code
  • Enabling code execution in the browser, especially if users can evaluate code dynamically

That last point is crucial. A Python or Ruby interpreter running in the browser is not more dangerous than JavaScript by default. But once it begins executing user-controlled code, you have to think about sandbox escapes, emulated object vulnerabilities, and any bugs in the C runtime now compiled to WASM.

Consider that:

  • WebAssembly offers limited visibility for debugging, which makes exploit detection harder
  • Many of these tools are maintained by small teams and lack formal audits
  • New features like threads, shared memory, and WASI file access are evolving quickly with uncertain implications

This is not alarmism. This is threat modeling.

There are some reassurances that help. But they don't solve every problem.

Elements that do mitigate risk:

  • Browser security models such as origin policies and proper use of COOP and COEP headers limit lateral movement
  • WASM’s linear memory model is safer than traditional native execution
  • Content Security Policy (CSP) headers help reduce injection risk, when configured correctly
  • Pyodide and ruby.wasm are usually built without thread support, without WASI, and with tight memory constraints

And since these runtimes operate inside the browser’s execution context, they follow the same rules as JavaScript. They are just more complex, and complexity brings risk.

What to Watch For

If you are evaluating Python or Ruby in the browser, keep an eye on:

  • Whether users can provide code to run, even indirectly
  • Runtime bundle size, since larger modules create a bigger surface for vulnerabilities
  • Whether the runtime can interact with browser APIs, either directly or through JS
  • Whether the WASM runtime is correctly sandboxed and updated regularly

And ask yourself this: how confident are you in the origin and integrity of the runtime you are shipping? Remember, this goes beyond Python projects for your portfolio. These are live, shipped products.

My Position: Cautiously Skeptical

Running Python or Ruby in the browser is not automatically unsafe. It can be very useful when the context is narrow and controlled, like in demos, offline notebooks, or teaching tools. But in production applications, especially those handling user input or sensitive data, it introduces real risks.

These runtimes do not yet feel like first-class browser citizens. That is not because they lack potential, but because the safety layers around them are still immature. The ecosystems lack formal audits, robust sandboxing guarantees, and secure-by-default APIs.

So where do we go from here?

If you plan to use these runtimes in your app, consider the following checklist:

  • Serve WASM files with proper COOP and COEP headers
  • Set up strong CSP policies to block inline scripts and reduce eval risks
  • REPLs inherently invite untrusted input execution, making them high-risk
  • Verify the source and integrity of your WASM builds
  • Minimize runtime size and feature scope to reduce attack surface
  • Monitor and log runtime behavior carefully

These tools are worth exploring. But they must be treated with the same rigor we apply to any executable environment. The future of a polyglot browser is exciting, but only if we can build it without opening new holes in the web’s already fragile security story.

By Brian Dantonio

Brian Dantonio (he/him) is a news reporter covering tech, accounting, and finance. His work has appeared on hackr.io, Spreadsheet Point, and elsewhere.

View all post by the author

Disclosure: Hackr.io is supported by its audience. When you purchase through links on our site, we may earn an affiliate commission.

In this article

Learn More