The portmod sandbox allows safe access to dangerous functions such as
shutil.rmtree while still allowing pybuilds to be as pythonic as possible.
This is achieved through the use of RestrictedPython and custom import code which provides stripped-down copies of modules for use within pybuilds, using wrappers with an io guard for modules that allow access to the filesystem. Binaries are only allowed to be executed through the use of a sandbox program such as bubblewrap on Linux and sandbox-exec on OSX.
In general, the following is restricted:
- File I/O in the global scope. All file I/O must be within functions in the Mod class.
- File I/O outside the build directory in
- Network access outside
- File writes outside the build directory in all scopes
The idea is that this prevents:
- Poorly written code from accidentally performing dangerous actions such as deleting your files.
- Malicious actors from creating a seemingly benign third-party repository and causing either deliberate damage to your system or stealing your personal information when you try to install or update mods from that repository.
Additionally, the following restrictions apply to the pybuild code:
- You may only access the following modules:
typing, and the
pyclassmodule and its submodules (noting that pyclass modules are subject to the same restrictions as pybuilds). Support for other modules can be added on request.
- Use of the
str.formatfunction is banned. This is known to be unsafe and is disabled by RestrictedPython by default. It is encouraged to used f-strings instead.
- Access to attributes that begin with underscores is banned. The convention in python is that these attributes are considered hidden, and represent internal functions and variables which could change at any time. By blocking the use of them pybuilds are forced to use the more stable public module APIs. Prior to the merging of !225 this is also done for security reasons, as pybuilds only have access to "safe" functions (e.g. restricted file i/o), and access to underscored attributes would allow this to be circumvented.
- Use of the
superfunction is allowed, however note that
super().__init__(self)cannot be invoked manually due to underscored functions being banned. As such, it is automatically called in any Mod class that overrides
- Use of builtins that allow arbitrary code execution is banned. This includes
All external executable calls are sandboxed using a platform-specific sandbox command. This prevents filesystem write access outside the build directory and prevents filesystem read access until all potentially-unsafe network access has been completed (i.e. prevents a malicious pybuild from scanning your system and uploading data to a remote server).
Portmod uses Sandboxie on Windows. Please note that there are known issues with Sandboxie (see #102), however in general it appears to be working. If you encounter issues, please report them, as current tests have been done almost exclusively via the test suite.