Skip to content

rti/nixwrap

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

54 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Nixwrap - Easy Application Sandboxing

A cute wrap, the mascot of Nixwrap

Nixwrap is a command line utility to easily wrap processes in a sandbox preventing them from accessing your system. Nixwrap can hinder access to environment variables, files, devices and the network. Under the hood, Nixwrap is based on Bubblewrap which in turn uses Linux Namespaces.

The goal of Nixwrap is to make sandboxing easy to use for common use cases, reducing the barrier to entry. While it will not provide perfect protection against any untrusted code, it does add protection for simple common threads.

Examples

npm install

You need to run npm install on a project, but you cannot trust all its dependencies.

To run npm install only with write access to the current working directory and network access, simply do:

wrap -n npm install

GUI Application using nix3-run

You need to run a GUI application, but you want limit access to your filesystem.

To run software using nix3-run, in this case vscodium with network and display access, without access to your home directory:

wrap -n -d -p nix run nixpkgs#vscodium

Python tool

You need to run a python script that has access to your audio hardware.

Run a python script with Pulse Audio and Pipewire access, but not sharing the current working directory:

wrap -a -p python my-tool.py

How to use

By default, Nixwrap will:

  • ✅ Prevent network access. (Use -n to allow.)
  • ✅ Prevent access to Wayland and X. (Use -d (desktop) to allow.)
  • ✅ Prevent camera access. (Use -c to allow.)
  • ✅ Prevent audio access. (Use -a to allow.)
  • ✅ Prevent DBus socket access. (Use -b to allow.)
  • ✅ Prevent access to user name information. (Use -u to allow.)
  • Allow write access to the current working directory.
  • Allow read only access to all paths in $NIX_PROFILES.
  • Allow read only access to nix store and config and bin paths.
  • Allow access to a set of common environment variables.

General syntax:

wrap [OPTIONS] -- [bwrap args] [program to wrap with args]

Options

  -w PATH  Mount PATH into sandbox in read write mode.
  -r PATH  Mount PATH into sandbox in read-only mode.
  -d       Allow Wayland display and rendering hardware access.
  -b       Allow DBus access.
  -n       Allow Network access.
  -a       Allow Audio access.
  -c       Allow Camera access.
  -u       Allow System user information access.
  -e VAR   Allow env var VAR access.
  -v       Verbose output for debugging.

Advanced Options

  -p       Do not share current working directory. By default wrap will share 
           the current working directory as a write mount and cd into it 
           before running the program. With this option, wrap will not share 
           the directory and leave the current directory untouched.
  -m       Manual unsharing. By default wrap unshares ipc, net, pid, and uts 
           and tries to unshare (continue on failues) user and cgroup 
           namespaces. With this option, wrap does not automatically unshare 
           any namespaces. Use together with bwrap --unshare-* options 
           (man bwrap(1)) to unshare manually.

Wrap binaries via Nix

Flake

Add the Nixwrap flake as an input in your flake.

{
  inputs = {
    wrap.url = "github:rti/nixwrap";
  };

  # outputs ...
}

Wrap a package

To wrap a package, use the function from inputs.wrap.lib.wrap. It takes the following arguments:

  • package The package to wrap.
  • executable The name of the executable, optional, defaults to package name.
  • wrapArgs Arguments to wrap, see above.

The function returns a new package wrapping the given package.

E.g. to wrap nodejs with access to current working directory (default) and additional network access, do:

inputs.wrap.packages.wrap {
  package = pkgs.nodejs;
  executable = "node";
  wrapArgs = "-n";
}

Flake devShell with wrapped nodejs

This example installs nodejs in a devShell, but wraps node with Nixwrap, so what it can only access the current working directory and the network.

{
  inputs.nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
  inputs.flake-utils.url = "github:numtide/flake-utils";
  inputs.wrap.url = "github:rti/nixwrap";

  outputs = { nixpkgs, wrap, ... } @inputs:
    inputs.flake-utils.lib.eachDefaultSystem (
      system:
      let
        pkgs = nixpkgs.legacyPackages.${system};
      in
      {

        devShells.default = pkgs.mkShell {
          buildInputs = [
            (wrap.lib.${system}.wrap {
              package = pkgs.nodejs;
              executable = "node";
              wrapArgs = "-n";
            })
          ];
        };
      }
    );
}

Supported platforms

Nixwrap is at the moment tested exclusively on NixOS, even though the concept should work in any distribution that ships a current kernel.

License

wrap is licensed under the MIT License. See the LICENSE file for more details.