Skip to content

wyeworks/elixir_console

Repository files navigation

Build Status


Elixir Web Console

The Elixir Web Console is a virtual place where people can try the Elixir language without the need to leave the browser or installing it on their computers. While this is a project in its early stages, we hope this is a contribution to the effort to promote the language, providing a convenient way to assess the capabilities of this technology. We would love to hear ideas about how to extend this project to serve this purpose better (see the Contributing section).

This project is inspired in existing playground sites from distinct communities, such as SwiftPlayground and Rust Playground, yet, it is unique because it aims to mimic the Elixir interactive shell (iEX).

Features

  • Bindings are persisted through the current session. Users can assign values to variables. They will remain visible at the side of the screen.
  • Pressing the Tab key displays a list of suggestions based on what the user is currently typing in the command input. If only one option is available, the word is autocompleted. It will help to discover modules and public functions. Existing binding names are also taken into account to form the list of suggestions.
  • The console presents the history of executed commands and results. The sidebar will display the documentation of Elixir functions when the user clicks on them.
  • There is easy access to already-executed commands pressing Up and Down keys when the focus is in the command input.

Elixir Web Console

Where my Elixir code is executed?

Unlike other playground projects, it does not rely on spawning sandbox nodes or additional servers to run the code. The Elixir application that is also serving the web page is also responsible for executing the user code.

Of course, there are plenty of security considerations related to the execution of untrusted code. However, we came up with a solution that allows us to execute them directly on our Elixir backend (see next section).

The system executes every submitted command in the context of a dedicated process. Note that subsequent invocations to self() will return the same PID value. Since this is an isolated process, the executed code should not interfere with the LiveView channel or any other process in the system.

How much Elixir can I run in the web console?

As you might guess, not all Elixir code coming from unknown people on the internet is safe to execute in our online console. The system checks the code before running it. Code relying on certain parts of the language will cause an error message explaining the limitations to the user.

Elixir safe modules and Kernel functions

The console has a whitelist that includes modules and functions of Elixir considered safe to execute. The system will inform about this limitation when users attempt to use disallowed stuff, such as modules providing access to the file system, the network, and the operating system, among others.

Moreover, the mentioned whitelist does exclude the metaprogramming functionality of Elixir. The functions Kernel.apply/2 and Kernel.apply/3 are also out of the whitelist to prevent the indirect invocation of not-secure functions.

The AST of the user code is verified before its actual execution, checking if the function invocations are not dangerous. However, some cases are impossible to detect by only inspecting at the code. For this reason, a layer of runtime validations exists as well, providing an additional way to detect non-secure invocations that only happens when the user code computes the callee at runtime. Both approaches have some overlap, and the design of the solution has room for improvement, so we expect to work on having a more refined solution shortly.

Processes

The console currently does not allow the usage of the module Process and other parts of Elixir related to processes. Existing resource usage limitations (see next section) would be much harder to enforce if users were permitted to spawn processes. Similarly, the functions send and receive are restricted to avoid integrity and security problems.

This limitation does not make us happy because it would be valuable to let people play with processes within our interactive shell. We are currently thinking about manners to include those modules and functions within the whitelist. Extra precaution is needed to implement it due to possible security implications.

The problem with atoms

It represents a tricky issue for our web console because in Elixir/Erlang atoms are never garbage collected. Therefore, each atom created by users code will be added to the global list of existing atoms. It means that, eventually, the maximum number of atoms will be reached, causing a server crash.

We consider this issue is not an impediment to have the server operating, at least for now. In case of a crash due to the overflow of atoms, Heroku will automatically restart the application.

When the server is restarted, any existing sessions are lost. Of course, it would be problematic if it happens often. We are monitoring the server to diagnose the relevance of this issue better. Hopefully, it will require some server restart from time to time, and we have some ideas to automate it in the future.

To mitigate this problem, the function String.to_atom/1 is not available in the console limiting the creation of a large number of atoms programmatically.

We are confident that the number of created atoms will grow relatively slow, giving us time to restore the server if this is ever needed.

Other limitations

The execution of code in this console is limited by the backend logic in additional ways in an attempt to preserve the server health and being able to attend a more significant number of users.

Each submitted command should run in a limited number of seconds; otherwise, a timeout error is returned. Moreover, the execution of the piece of code must respect a memory usage limit.

The length of the command itself (the number of characters) is limited as well. This restriction exists due to security and resource-saving reasons.

Roadmap

While a refined ongoing plan does not exist yet, the following is a list of possible improvements.

  • Add the ability to write multiline code.
  • Extract the Elixir Sandbox functionality to a package.
  • Allow spawning a limited amount of processes.
  • Try to permit the definition of modules and structs.
  • Implement sandboxed versions of individual restricted modules and functions (for example, a fake implementation of the filesystem functions).
  • Provide controlled access to additional concurrency-related functionality (send/receive, Agent, GenServer), if possible.
  • Overcome the problem with atoms (we are working on a prototype to confirm if this is feasible).

About this project

This project was initially implemented to participate in the Phoenix Phrenzy contest. It is an example of the capabilities of Phoenix and LiveView.

Beyond its primary purpose, this is a research initiative. We are exploring the implications of executing untrusted Elixir code in a sandboxed manner. In particular, we want to solve it without using extra infrastructure, being as accessible and easy to use as possible. We have plans to create a package that includes the sandbox functionality. This package would enable the usage of Elixir as a scripting language (although we are not sure if this is a good idea).

Special Thanks

The authors of the project are Noelia, Ignacio, Javier, and Jorge. Special thanks to WyeWorks for providing working hours to dedicate to this project.

We also want to publicly thanks Marcelo Dominguez, Allen Madsen, Gabriel Roldán, Luis Ferreira, and Ben Hu for testing the console and reporting several security issues.

Contributing

Please feel free to open issues or pull requests. Both things will help us to extend and improve the Elixir Web Console 🎉 We know that security vulnerabilities probably exist due to the nature of the technical challenge. If you have found a security issue, please send us a note privately at elixir-console-security@wyeworks.com.

Runing tests

$ mix test

To run feature tests Wallaby requires you to have Chrome or Chromedriver in your PATH.

Headful mode:

$ HEADLESS=false mix test

License

Elixir Web Console is released under the MIT License.