GitXplorerGitXplorer
g

python-sandbox

public
1 stars
2 forks
0 issues

Commits

List of commits on branch master.
Unverified
b799eef439f0e447fe3dac7f576f802a35e00ad9

Add -f to force creation

committed 9 days ago
Unverified
b4e393bcb3075405a63485b899ae17fa65345bb8

Add crucial todo

committed 9 days ago
Unverified
7bc41af5822098b02496902fa2472cb3c26bfdd2

Remove too specific naming

committed 9 days ago
Unverified
cb4ef27158ec3601223737b5c564a78ff134c3df

Undo incompat. change for older firejail versions

committed 9 days ago
Unverified
374a7902085f8c4e0a7d5d0a9f768a6d356e2122

Add crucial bit of info

committed 9 days ago
Unverified
b92d8bcd64c01ee5c482ff985fe9e5d89e82627c

Document a bit more

committed 9 days ago

README

The README file for this repository.

Python Sandboxing

Do you trust whatever comes out of pip install? Do you trust nightly builds?

A single hijacked package in your dependencies can leak all your secrets (private keys, tokens, github access, emails, ...).

No? Good! Maybe this is a solution for you, then.

This project aims to provide firejail profiles for python development environments. This means that you will have an isolated shell with only selected parts, some read-only, some not at all visible, of your host filesystem.

Image of a terminal showing access of .ssh folder and no access after activation of the sandbox

This is by no means perfect but at least it is better than being at the mercy of pypi.

Requirements

  • firejail
  • python-virtualenv
  • bash or zsh
  • Linux based OS (WSL2 might work)

Installation

Very basic

This will give you the ability to create python sandboxes from a template and nothing more. No integration into your shell. This is how to do it:

$ sudo apt install firejail python-virtualenv
$ git clone git@github.com:githubnemo/python-sandbox.git
<add $PWD/python-sandbox to your PATH in .bashrc / .zshrc / ...>

This setup assumes that your python envs will live in ~/envs/<sandbox-name>.

Advanced shell integration

There are examples for ZSH and bash on how to integrate these sandboxes better into your environment. These features are showcased in the Neat Things section. I'm not confident enough in these features yet to build a script that you can simply source, sorry.

Allowing your tools inside the sandbox

The default template will never cover all your custom setup. To allow for additional tools outside of the basic template, you can add your own access configuration with a local override that works for every template.

You can place arbitrary rules in ~/.config/firejail/python-env-template.local and they are included in the environment profile.

For example, if you have a specific tool, say fzf, in a directory outside of the sandbox and your .bashrc depends on that path, you could add it there.

Example python-env-template.local file:

whitelist ${HOME}/Code/fzf
read-only ${HOME}/Code/fzf

With the above content your sandbox is now able to access ~/Code/fzf. See man firejail-profile for all possible directives.

Workflow

New python project? New sandbox.

$ mkdir ~/code/mynewproject
$ create-python-sandbox mynewproject ~/code/mynewproject

# After profile creation we can jump into the sandbox
$ firejail --profile=python-env-mynewproject --tab bash

# We can now create a virtualenv there (or use poetry, conda, ...)
$ python -m venv ~/envs/mynewproject
$ . ~/envs/mynewproject/bin/activate
$ pip install [...]

It is best to make access to the sandbox as easy as possible. At best, never leave it (launch a tmux session inside the sandbox, work in there). Second best: create an alias to quickly jump into the sandbox. See section "Common entrypoint":

$ sbox mynewproject

Neat things

Common entrypoint

I have a function definition for invoking sandboxed shells

sbox() {
    # replace "bash" with any shell you like
    firejail --profile=python-env-$1 --tab bash
}

so I can quickly jump into the sandbox using sbox myenv.

Visual hint of being inside a sandbox

To gauge if I'm in a sandbox or not the sandbox environment provides an environment variable (JAILED_ENV=<env name>) so it is easy to react on that in the shell prompt.

Example from my .bashrc:

jail=""
if [ -n "$JAILED_ENV" ]; then
    jail="(J:${JAILED_ENV})"
fi

if [ "$color_prompt" = yes ]; then
    PS1='${debian_chroot:+($debian_chroot)}${jail}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
else
    PS1='${debian_chroot:+($debian_chroot)}${jail}\u@\h:\w\$ '
fi

Entering the sandbox upon entering a directory

To enter the sandbox as soon as you're working on a project, you can configure your shell to watch for .python-sandbox files with the sandbox's name in it.

Showcase of activating the sandbox on directory change

There's an example for ZSH in examples/zsh.md, the gist is:

# Little helper to go upward the directory tree in search for a file.
# Makes sure to use the least amount of external tools for performance.
_upfind() {
    if [[ "$2" -eq 0 ]]; then
        return 1
    fi
    [[ -e "$1" ]] && echo "$1" || _upfind "../$1" "$(($2 - 1))"
}

enable_sbox_if_needed() {
    if [ -n "$JAILED_ENV" ]; then
        return
    fi

    # Look into current and upward directories for sandbox file to
    # enable sandbox upon finding it.
    sandbox_file=$(_upfind ".python-sandbox" 5)

	if [[ "$?" -eq 0 ]]; then
        export PWD_BEFORE_JAIL="$PWD"
        sbox "$(head -n1 "$sandbox_file")"
    fi
}

add-zsh-hook chpwd enable_sbox_if_needed
enable_sbox_if_needed

Caveats

My bashrc is different in the sandbox :(

Depending on your firejail version, the sandbox bashrc is sourced from /etc/skel/.bashrc. Newer versions of firejail support the keep-shell-rc configuration option. Enable it in the template to avoid this problem.

Tab completion is not working?!

Note the --tab option of firejail. Firejail disables tab completion for bash since there were vulnerabilities in the implementation before and you have to supply --tab to enable that feature explicitly.

To do

  • [ ] limit access to SSH agent from inside the sandbox
  • [ ] limit access to specific read-only tokens (e.g. hf hub)
  • [ ] make paths to tools like fzf, pyenv, conda, etc. configurable