Skip to content

Repository files navigation

envblock

Protect sensitive environment variables on Linux using eBPF.

envblock is a companion to dirblock. While dirblock protects files, envblock protects the environment variables that many 2026 supply-chain attacks (Axios, Trivy/TeamPCP, Bitwarden CLI, Shai-Hulud variants, etc.) aggressively steal.

Why envblock exists

Developer, admin, and CI/CD workflows still pass a lot of authority through environment variables: cloud keys, GitHub tokens, npm tokens, Vault tokens, kube credentials, AI provider keys, Terraform variables, deployment credentials, and more.

The risky process is often not the trusted top-level tool. It is what that tool spawns: hooks, plugins, package scripts, interpreters, shell snippets, test runners, linters, build steps, credential helpers, postinstall scripts, and CI job steps.

envblock limits that ambient inheritance. A process may carry a secret only when the target executable is trusted to receive it and the checked caller chain is trusted to carry it. That lets a developer shell, admin terminal, or CI job keep powerful variables available for known tools without automatically handing them to every descendant process.

The goal is not to hide secrets from the user. It is to stop ambient credentials from becoming ambient authority for every subprocess.

Scope

envblock protects exported environment variables as they cross execve into child processes. It does not manage where secrets come from: .env files, direnv, CI variable stores, Vault, cloud secret managers, encrypted files, and language libraries are all outside its source-of-secret model.

That boundary is still useful for CI/CD. Once a runner, shell, or deploy job has received secrets as environment variables, envblock can reduce RCE blast radius by poisoning those values for unapproved child executables.

Features

  • Runs on execve — poisons sensitive variables before they are passed to the new process.
  • Configurable munging patterns (e.g. keep AKIA prefix on AWS keys, then fill the rest with garbage).
  • Sends random printable junk by default so stolen credentials look real but are useless.
  • Reuses the same ancestry/profile concept as dirblock.
  • Very low overhead.

Requirements

envblock needs a Linux kernel with BTF available at /sys/kernel/btf/vmlinux, plus a toolchain capable of building BPF CO-RE programs and a libbpf-linked userspace loader.

Tested build/load environments:

  • Arch Linux, kernel 6.19.12-arch1-1
  • Arch Linux, kernel 7.0.3-arch1-1
  • Ubuntu 22.04.5 LTS, kernel 6.8.0-111-generic with libbpf 1.4.0 installed under /usr/local
  • Ubuntu 24.04.4 LTS, kernel 6.8.0-111-generic

See UBUNTU_NOTES.md for detailed Ubuntu 22.04/24.04 setup, including the libbpf ABI mismatch on 22.04 and how to work around it.

Arch Linux:

sudo pacman -S --needed bpf clang llvm libbpf elfutils zlib pkgconf base-devel

Ubuntu 24.04:

sudo apt update
sudo apt install -y \
  clang llvm linux-tools-common linux-tools-$(uname -r) \
  libbpf-dev libelf-dev zlib1g-dev pkg-config build-essential

On Ubuntu, if bpftool is not on PATH, run make with the kernel tools directory first:

PATH="/usr/lib/linux-tools/$(uname -r):$PATH" make

Quick Start

Source install

envblock is installed by hand so every privileged step is explicit: you clone and review the source, build it, and grant capabilities yourself.

Build and test from the repository root:

git clone https://github.com/roku-oss/envblock
cd envblock
make
sudo setcap cap_bpf,cap_perfmon,cap_sys_admin,cap_sys_ptrace+eip ./envblock
make test
./envblock --config ./config/envblock.toml

Re-run setcap after every rebuild because linking replaces ./envblock and clears file capabilities. make test checks for required capabilities and prints the setcap command if they are missing. The checked-in sample config starts in dry_run mode.

When you are ready to daily-drive envblock, install the binary, starter config, and wrappers into your user environment:

make install
make install-wrappers \
  WRAPPER_DIR="$HOME/.local/share/envblock/wrappers" \
  WRAPPED_TOOLS="aws kubectl k9s gh git glab npm node terraform docker podman codex claude vault"
sudo setcap cap_bpf,cap_perfmon,cap_sys_admin,cap_sys_ptrace+eip "$HOME/.local/bin/envblock"
export PATH="$HOME/.local/share/envblock/wrappers:$HOME/.local/bin:$PATH"
envblock

make install installs envblock to ~/.local/bin/envblock and installs config/envblock.toml to ~/.config/envblock/envblock.toml, replacing any existing user config.

Put the wrapper directory before ~/.local/bin and before any real tools it wraps. In shell startup files, place the wrapper PATH line after other tools that prepend to PATH so they do not move ahead of envblock wrappers later.

Need Help?

If you are using an AI coding assistant to build, test, tune, or configure envblock, start with this prompt:

Read AI_HELPER.md and use it to help me set up envblock on this machine.

Configuration

Start from config/envblock.toml, then copy or adapt it to:

~/.config/envblock/envblock.toml

Key sections:

  • [profiles] — reusable executable groups for entry and chain roles
  • [env] sensitive — exact variable names to protect
  • [env.munging] — how to mangle each variable (highly recommended)
  • [env.entry] — which targets may directly receive each real value
  • [env.chain] — which callers/ancestors may carry each real value

See CONFIGURING.md for the policy model and worked configuration examples, and WRAPPERS.md for wrapper setup.

How it works

  1. At startup, userspace reads the config, precomputes sensitive VAR= lookups, and stats role-configured executables into (mount_id, inode) identities with entry and chain bitmasks.
  2. On execve/execveat, eBPF stashes envp, then evaluates policy from fexit/do_open_execat after the kernel has opened the target executable.
  3. For sensitive variables, eBPF requires the target executable to be trusted under [env.entry] and every checked caller/ancestor executable to be trusted under [env.chain].
  4. If not allowed, it preserves any configured literal prefix and overwrites the rest with random printable characters before the child receives the environment.

This makes stolen environment variables much less useful to attackers while keeping most legitimate workflows working.

See ARCHITECTURE.md for the full picture, with diagrams, including how wrappers fit in for script- and runtime-backed tools.

Executable Trust And Reloads

Allowlisted executable paths are trusted by the file identity that exists when envblock starts or reloads, not by path string alone. For example, if ~/.local/bin/myApp is allowlisted, envblock.cpp resolves and stats that path and sends its inode identity to BPF.

If that binary is later overwritten, whether by a normal update or a malicious replacement, the new file gets a different inode. The running BPF policy will not automatically trust it. That is intentional: replacement breaks trust until the user explicitly reloads or restarts envblock.

To intentionally accept updated allowlisted executables:

kill -HUP <envblock-pid>

For the recommended dry-run rollout, run envblock in a tmux session with dry_run = true, watch the would-poison logs, update the config as needed, and reload only when you intentionally accept the executable set.

Trusted Tool Wrappers

Install standard per-user wrappers:

make install-wrappers \
  WRAPPER_DIR="$HOME/.local/share/envblock/wrappers" \
  WRAPPED_TOOLS="aws kubectl k9s gh git glab npm node terraform docker podman codex claude vault"

make install-wrappers installs a wrapper only for tools that resolve to interpreted scripts. ELF binaries are skipped (they can be trusted directly) and names not found in PATH are skipped, so hosts without terraform or podman do not get confusing dead wrappers.

Append this near the end of ~/.bashrc, after other tools that prepend to PATH:

# set PATH so it includes envblock wrappers
if [ -d "$HOME/.local/share/envblock/wrappers" ] ; then
    PATH="$HOME/.local/share/envblock/wrappers:$PATH"
fi

For setup, policy examples, and custom wrapper creation, see WRAPPERS.md. Administrators rolling wrappers out across users or CI should also read ADMIN_GUIDE.md.

Administration

This README describes the single-user workflow. For multi-user hosts, containers, and CI/CD runners, see ADMIN_GUIDE.md.

Building

Requires:

  • clang + LLVM (for BPF)
  • libbpf-dev
  • bpftool
  • Kernel with BTF (/sys/kernel/btf/vmlinux)
make

See ARCHITECTURE.md for how envblock works conceptually, and CONTRIBUTING.md for BPF map layout and development workflow.

Status

This is currently an experimental companion to dirblock. See test_results.md for current validation coverage and eBPF.md for verifier limits and tuning guidance.

Contributions and ideas welcome (especially around ancestry integration and config generation).

License

Apache-2.0. See LICENSE.

About

No description, website, or topics provided.

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages