I want to build a browser application to execute code entered by anyone and return output. For that I want to prevent him from infinity loops and system commands.
Any idea how to do that. Thanks in advance.
That’s an interesting question!
For the security part, a probably good compromise could be to run each individual stuff in a dedicated container, for which you’d choose and tune the image, so that you have a lot of control about the privileges that execution context gets. That implies your solution needs:
Since I’ve been using Hashicorp’s Nomad a lot over the last year, and although I have not used it for such goals, it does check a lot of boxes (but other tasks schedulers could probably help you a lot with that). We’re really talking about batch jobs here (CircleCI uses Nomad for their builds, if that gives you an idea of what it can do for batch jobs)
A quick idea (really written live here, without stopping to think about it, and after a drink, so you could probably have much better design if you spend more time on it ;-) would be that
Now comes the expiration problem. FOr this Nomad also offers a great way to easily solve this (again, there are many other ways, this is just an easy way to rely on what already works nicely out of the box) Nomad offers service jobs (e.g. API or workers that you want to be always up), batch jobs (you want to run it until it succeeds. If it fails, run it again, if it worked, then it’s complete, do not restart it), you also have periodic jobs (think cronjob, which you can run in a distributed fashion, controlled by a scheduler. It’s to cronjob what color tv is to b&w tv ;-) An idea could be to start 2 jobs: a batch for the execution, and a periodic job which cron expression would be to run only once. at the expiration time of your evaluation task. This is not optimal (it will often run for nothing, but it’s probably a super lightweight task), and it gives you a great isolation to make sure you have some kind of watchdog to kill the evaluation task if it goes overtime. The monitoring task would check if the evaluation job (with the ID you generated) is still running (Nomad offers both a REST API and a nice SDK, and has 3rd party libs if you prefer to use it from Python for instance), and if not, just exit and be forgotten. But if it finds the evaluation task, it will a.) tell Nomad to stop it, b.) store the timeout status in the DB to let the frontend layer that it’s not useful to keep waiting and can provide sad but meaningful feedback to the user.
And because all these evaluations are short time-lived, your db could leverage something as simple as Redis with expiring keys (or DynamoDB with TTL since you’re only interested in querying by the job IDs) which would make it very easy to keep the DB layer small and automatically clean.
As I wrote, this is just random thoughts late in the day, but that’s a really interesting challenge and many great tools could help to make it easier to solve (than how we would have attacked this problem a few years ago)
I hope these random thoughts give you some ideas and helped you
Ravi Teja Gadi
Aravind
Software Engineer At Hasura, Hashnode Alumnus
Hey, That's an interesting problem. The following is the solution that I came up with.
It is possible to control and manage all the runtime parameters of a container. You can control the amount of system resources a container takes ie the memory, network bandwidth, storage, etc.