Below is a working solution. It wraps zsh with bubblewrap and uses a combinator to inject creation of python virtual env along with activation. Virtualenv is created in tmpfs in /env dir so it does not persist after shell is closed. I used no-new-session combinator to allow fzf to do it’s TUI things to terminal.
Now the only option I’m missing it to pass all stuff from parent nix store to jail to avoid fixing myriad of issues like missing grep
EDIT: added /run/current-system/sw/bin ro-bind and added this to $PATH and now jailed shell has access to all host’s software.
It will run with nix run
so the workflow will look like this:
- clone some sus git repo like
github.com/sus-dude/free-dc-privesc-dude-i-swear - copy the flake (or gen from template)
- nix run
- pip install -r totally_legit_deps.txt
- profit
{
description = "A very basic jail flake";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
jail-nix.url = "sourcehut:~alexdavid/jail.nix";
};
outputs =
{
self,
nixpkgs,
jail-nix,
...
}@inputs:
let
user = "myuser";
system = "x86_64-linux";
pkgs = import nixpkgs { inherit system; };
jail = jail-nix.lib.init pkgs;
python3-env = pkgs.python3.withPackages (py: [
# any packages from nixox is we want them outside of venv
py.virtualenv
]);
pentest-env = pkgs.symlinkJoin {
name = "pentest-env";
paths = [
python3-env
pkgs.zsh
pkgs.zsh-completions
pkgs.openssl # hate this crap, always makes me miserable :D
pkgs.coreutils
pkgs.gcc # often needed for pip compiling
pkgs.fzf
# pkgs.eza and so one
];
};
jailed-shell = jail "zsh" "${pentest-env}/bin/zsh" [
jail.combinators.network
jail.combinators.mount-cwd
# next two entries expose all software from outside of the container
(jail.combinators.ro-bind "/run/current-system/sw/bin" "/run/current-system/sw/bin")
(jail.combinators.add-path "/run/current-system/sw/bin")
# make zsh work with my config
(jail.combinators.add-path "${pentest-env}/bin")
(jail.combinators.readonly "/home/${user}/.zsh")
(jail.combinators.readonly "/home/${user}/.zshenv")
(jail.combinators.readonly "/etc/os-release")
(jail.combinators.readonly "/usr/bin")
(jail.combinators.ro-bind "${pkgs.fzf}/share/fzf" "/usr/share/fzf")
# tmpfs for temporary virtualenv
(jail.combinators.tmpfs "/env")
# needed for fzf to work
(jail.combinators.no-new-session)
# wrapper that initializes virtualenv prior to running shell
(jail.combinators.wrap-entry (entry: ''
echo "Launching jail..."
virtualenv /env
export VIRTUAL_ENV=/env
export PATH="/env/bin:$PATH"
exec ${entry}
''))
];
in
{
apps.${system}.default = {
type = "app";
program = "${jailed-shell}/bin/zsh";
};
};
}