I am trying to create a programming game where user-supplied programs compete in battle simulations, to be used as a tool to teach and practice programming. (It will likely be a turn-based robot simulation, but for the purposes of this question, it could just as well have been chess or checkers.) One major component of implementing this game will be to provide a mechanism to run user-generated code against game data to determine their bot's moves.
I know that the typical advice is, "Wherever possible, don't run untrusted code," and I understand where it comes from. In my current case, though, it would be the core functionality of the app I would like to make, if at all possible. I know that I will need to take some precautions to ensure that user-supplied code does not cause damage. The ideal setup, from what I can tell, would enforce that:
- User code reads game state from STDIN
- User code writes generated move to STDOUT
- User code is isolated from the host system
- User code is isolated from each other
- User code is limited in the resources it can consume (CPU, memory, disk)
- User code cannot access the network
My use case doesn't seem unique. If anything, I would imagine any of the following types of apps have similar requirements:
- most programming games
- competitive programming online judge
- "Try X programming language"
- game AI competitions
Yet, I looked around on Google, but I couldn't find any reference implementations that seemed trustworthy. Most of the above sorts of apps are closed-source, and perhaps for good reason.
Given the requirements, I imagine I would need some sort of isolation/virtualization/containerization solution, although I am honestly not sure which one would provide the necessary guarantees.
What are current best practices around sandboxing for user-supplied code? Does anyone have some information or references to trustworthy sources?