summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOwen Jacobson <owen@grimoire.ca>2017-11-18 20:23:12 -0500
committerOwen Jacobson <owen@grimoire.ca>2017-11-18 20:23:12 -0500
commita7446365153e3a9bfe28d9b7129555756bdcfe3d (patch)
treee4762b0bdc8e0643839d7744e3db2aafee093636
parentb757518e116657aecb128617087b54dcad8a0f37 (diff)
Security notes
-rw-r--r--SECURITY.rst115
1 files changed, 115 insertions, 0 deletions
diff --git a/SECURITY.rst b/SECURITY.rst
new file mode 100644
index 0000000..2d450e8
--- /dev/null
+++ b/SECURITY.rst
@@ -0,0 +1,115 @@
+########
+SECURITY
+########
+
+In the README, I made this strong claim:
+
+ It provides minimal safety features, but the restricted set of builtins
+ ensures that Actinide programs cannot gain access to the outside context of
+ the program. The worst they can do is waste CPU time, fill up RAM, and
+ drain your battery.
+
+This document expands on the underlying design choices used to support that goal.
+
+**************
+Specific Goals
+**************
+
+Out of the box, an Actinide ``Session`` must not:
+
+* Read information that is not part of its top-level environment or macro
+ table, which was not passed to it as an argument to a method or constructor
+ by the enclosing program.
+
+* Write information to any location other than its top-level environment, its
+ macro table, or the return value of a method or constructor called by the
+ enclosing program.
+
+* Cause system calls that perform IO of any kind.
+
+These goals imply that any externally-visible side effects of Actinide
+evaluation are entirely the responsibility of the enclosing program. A "pure"
+Actinide environment can only convert electricity into waste heat.
+
+*****
+Types
+*****
+
+Actinide has a carefully-selected list of built-in types, none of which expose
+primitive operations that can gain filesystem access or gain access to
+information outside of the Actinide session without without outside help.
+
+Atomic values other than symbols use the least-capable Python representations
+possible:
+
+* Python ``int`` objects, used to represent Actinide integers.
+
+* Python ``decimal.Decimal`` objects, used to represent Actinide decimals.
+
+* Python ``str`` objects, used to represent Actinide strings.
+
+* Python ``bool`` objects, used to represent Actinide booleans.
+
+* The Python ``None`` constant, used to represent the empty list.
+
+The remaining built-in types are represented using classes:
+
+* Instances of the ``actinide.types.Symbol`` class, used to represent Actinide
+ symbols. This class is a wrapper around a ``str`` and provides only exactly
+ the operations needed to act like a sybmol: access to the underlying string,
+ equality, hashing, and useful Python ``__str__`` and ``__repr__``
+ implementations for debugging.
+
+* Instances of the ``actinide.types.Cons`` class, representing Lisp conses and
+ list cells. This class is a ``namedtuple`` with two fields and no additional
+ methods. (This implies that conses are immutable, unlike most lisps, but this
+ is a semantic consideration and not a security consideration.)
+
+* Instances of the ``actinide.ports.Port`` class, which wraps an arbitrary
+ ``file`` object to restrict the operations available. The only built-in
+ mechanism for creating a ``Port`` creates one which wraps a string; it is not
+ possible to open port to a file, shared memory segment, pipe, process,
+ socket, or to any other OS resource using only built-in functions and types.
+
+* Instances of the ``actinide.types.Procedure`` class, which is considerably
+ more complex than the other types. This class handles the mechanics of
+ compiling and executing procedures, and allows calling procedure bodies from
+ arbitrary Python programs.
+
+ However, ``Procedure`` delegates all of its actual operations back to the
+ Actinide runtime, and has effectively the same capabilities as a top-level
+ Session.
+
+Finally, built-in functions are represented using Python's own function and
+method handle types. The only operations exposed on these are to call them as
+Actinide functions, or to extract a string representation including their names.
+
+*********
+Functions
+*********
+
+Actinide's built-in functions have been selected and implemented for simplicity
+of analysis. Actinide avoids exposing complex operations, and _particularly_
+avoids exposing any of Python's metaprogramming tools.
+
+Actinide - intentionally - exposes considerably fewer functions than a full
+Scheme implementation. Many Scheme functions are inappropriate for Actinide's
+use cases, but furthermore, keeping the function set small makes it much easier
+to analyze the security properties of the built-in functions.
+
+No built-in function unwraps any type other than as follows:
+
+* ``(string x)`` and ``(display x)``, where ``x`` is a Symbol, unwrap the
+ string contained in the symbol object.
+
+* ``(head c)``, ``(tail c)``, and ``(uncons c)``, where ``c`` is a Cons,
+ unwraps the head, tail, or both the head and the tail of a Cons.
+
+******
+Errors
+******
+
+Actinide does not support the full Scheme exception-handling system. Instead,
+operations which produce Python exceptions cause the computation to abort at
+that point. The exception passes up through the implementation untouched,
+allowing the enclosing program to determine how to handle it.