Erbot runs the #emacs robot. He has a jail inside him for running arbitary elisp safely.
The code is here: git:git.sv.gnu.org/erbot.git
Also on GitHub here.
The goal of this project is to take erbot's code and adapt it for general use.
It is very much a work in progress. Feel free to help out!
First load elisp-sandbox.el. It provides a number of functions that support working with Emacs Lisp code in a safe way.
The simplest function is elisp-sandbox-eval. Using it will evaluate the code in a way that prevents the code from calling any disallowed functions.
The elisp sandbox works by prefixing any symbols it receives as input before that input is evaluated. That way, the user can only access symbols that begin with that prefix. For example,
(elisp-sandbox '(setq x 100))
=>
(elisp-sandbox-unsafe-env-setq elisp-sandbox-unsafe-env-x 100)
and:
(elisp-sandbox '(defun nic-test-2 nil 100))
=>
(elisp-sandbox-unsafe-env-defun elisp-sandbox-unsafe-env-nic-test-2 nil 100)
To evaluate unsafe code:
(elisp-sandbox-eval <unsafe code here>)
Example:
(elisp-sandbox-eval '(+ 1 2))
=>
3
Any output is stored as a list of strings in the symbol:
elisp-sandbox-evaluation-output
(elisp-sandbox-eval '(message "Hello World!"))
=>
("Hello World!")
Sandbox provides a number of functions and macros that are accessible to untrusted code.
defun -- Defines a function specific to the sandbox environment.
while -- Basic looping. Has a maxium loop depth foncigurable with sandbox-while-max .
(elisp-sandbox-eval '(progn (setq counter 0 total 0) (while (< counter 10) (setq total (+ total counter)) (setq counter (+ 1 counter))) total))
=>
45
The maximum execution while depth can be configured:
(let ((sandbox-while-max 2)) (if (elisp-sandbox-eval '(ignore-errors (setq counter 0 total 0) (while (< counter 10) (setq total (+ total counter)) (setq counter (+ 1 counter))) t)) "A non-nil resuld would mean that the while finished and t was returned" "A nil result means an error happend, as expected!"))
=>
"A nil result means an error happend, as expected!"
message -- method for saving output.
The following are available as aliases of the standard functions:
setq, <, +, progn, let, ignore-errors, if
When code behaves badly, errors can be thrown. we gotta figure out how to handle these well.
- it would be nice to allow changing of prefixes, declaration with diff prefixes, and cleaning up of prefixes. That way a single process can handle different sandboxes.
- still need to figure out which additional functions need to come from erbot
- features to port funcall, apply, pi, e, emacs-version
Use the script bin/clone_erbot.sh to get a local copy of the erbot source for yourself.
Tests are written with ert.
Run the file
./test.sh
Tests can also be run interactively... TODO document this
Readme content is automatically generated from the file README-spec.el, in the same directory. Its examples are used as feature tests. Do not edit README.creole directly; instead, edit README-spec.el and regenerate README.creole.
Each feature is covered more thoroughly in the specs/ directory.