293 lines
8.4 KiB
Rust
293 lines
8.4 KiB
Rust
use std::fs;
|
|
use std::path::{Path, PathBuf};
|
|
|
|
use crate::SandboxError;
|
|
|
|
pub struct PathContext {
|
|
pub home: String,
|
|
pub run_user: String,
|
|
}
|
|
|
|
pub struct BlacklistOverlays {
|
|
pub tmpfs_dirs: Vec<PathBuf>,
|
|
pub null_bind_files: Vec<PathBuf>,
|
|
}
|
|
|
|
pub fn resolve_overlays(ctx: &PathContext) -> Result<BlacklistOverlays, SandboxError> {
|
|
let mut tmpfs_dirs: Vec<PathBuf> = Vec::new();
|
|
let mut null_bind_files: Vec<PathBuf> = Vec::new();
|
|
|
|
for raw in SENSITIVE_PATHS {
|
|
let expanded = expand_path(raw, ctx);
|
|
let mut paths = expand_glob(&expanded)?;
|
|
paths.sort_by_key(|p| !p.is_dir());
|
|
for path in paths {
|
|
match classify_path(&path) {
|
|
PathKind::Dir(path) => {
|
|
if !tmpfs_dirs.contains(&path) {
|
|
tmpfs_dirs.push(path);
|
|
}
|
|
}
|
|
PathKind::File(path) => {
|
|
if !is_under_tmpfs_dir(&path, &tmpfs_dirs) && !null_bind_files.contains(&path) {
|
|
null_bind_files.push(path);
|
|
}
|
|
}
|
|
PathKind::Missing => {}
|
|
}
|
|
}
|
|
}
|
|
|
|
Ok(BlacklistOverlays {
|
|
tmpfs_dirs,
|
|
null_bind_files,
|
|
})
|
|
}
|
|
|
|
pub fn resolve_path_context() -> Result<PathContext, SandboxError> {
|
|
let home = crate::require_home()?;
|
|
let run_user = crate::require_run_user()?;
|
|
Ok(PathContext { home, run_user })
|
|
}
|
|
|
|
enum PathKind {
|
|
Dir(PathBuf),
|
|
File(PathBuf),
|
|
Missing,
|
|
}
|
|
|
|
fn classify_path(path: &Path) -> PathKind {
|
|
match fs::canonicalize(path) {
|
|
Ok(path) if path.is_dir() => PathKind::Dir(path),
|
|
Ok(path) => PathKind::File(path),
|
|
Err(_) => PathKind::Missing,
|
|
}
|
|
}
|
|
|
|
fn expand_path(raw: &str, ctx: &PathContext) -> String {
|
|
let s = raw
|
|
.replace("${HOME}", &ctx.home)
|
|
.replace("${RUNUSER}", &ctx.run_user);
|
|
let s = if let Some(rest) = s.strip_prefix('~') {
|
|
format!("{}{rest}", ctx.home)
|
|
} else {
|
|
s
|
|
};
|
|
assert!(
|
|
!s.contains("${"),
|
|
"unexpanded variable in SENSITIVE_PATHS entry: {raw}"
|
|
);
|
|
s
|
|
}
|
|
|
|
fn expand_glob(pattern: &str) -> Result<Vec<PathBuf>, SandboxError> {
|
|
let entries = glob::glob(pattern)?;
|
|
Ok(entries.filter_map(|r| r.ok()).collect())
|
|
}
|
|
|
|
fn is_under_tmpfs_dir(path: &Path, tmpfs_dirs: &[PathBuf]) -> bool {
|
|
tmpfs_dirs.iter().any(|dir| path.starts_with(dir))
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Curated sensitive paths from firejail disable-common.inc + disable-programs.inc.
|
|
// Goal: protect secrets, credentials, and session tokens from agentic access.
|
|
// ---------------------------------------------------------------------------
|
|
|
|
const SENSITIVE_PATHS: &[&str] = &[
|
|
// -- history files (can leak passwords/tokens typed on command line) --
|
|
"${HOME}/.*_history",
|
|
"${HOME}/.*_history_*",
|
|
"${HOME}/.histfile",
|
|
"${HOME}/.history",
|
|
"${HOME}/.python-history",
|
|
"${HOME}/.pythonhist",
|
|
"${HOME}/.viminfo",
|
|
"${HOME}/.lesshst",
|
|
"${HOME}/.local/share/fish/fish_history",
|
|
"${HOME}/.config/nushell/history.txt",
|
|
// -- /tmp leaks --
|
|
"/tmp/xauth*",
|
|
"/tmp/konsole-*.history",
|
|
// -- clipboard managers (may contain copied passwords) --
|
|
"${HOME}/.cache/greenclip*",
|
|
"${HOME}/.kde/share/apps/klipper",
|
|
"${HOME}/.kde4/share/apps/klipper",
|
|
"${HOME}/.local/share/klipper",
|
|
"/tmp/clipmenu*",
|
|
// -- SSH and remote access --
|
|
"${HOME}/.ssh",
|
|
"${HOME}/.rhosts",
|
|
"${HOME}/.shosts",
|
|
"/etc/hosts.equiv",
|
|
"/etc/ssh",
|
|
// -- GPG --
|
|
"${HOME}/.gnupg",
|
|
// -- git credentials --
|
|
"${HOME}/.git-credentials",
|
|
"${HOME}/.git-credential-cache",
|
|
"${HOME}/.config/hub",
|
|
"${HOME}/.config/gh",
|
|
// -- general credentials and secrets --
|
|
"${HOME}/.netrc",
|
|
"${HOME}/.cargo/credentials",
|
|
"${HOME}/.cargo/credentials.toml",
|
|
"${HOME}/.fetchmailrc",
|
|
"${HOME}/.msmtprc",
|
|
"${HOME}/.smbcredentials",
|
|
"${HOME}/.davfs2/secrets",
|
|
"${HOME}/.config/msmtp",
|
|
"${HOME}/.config/keybase",
|
|
"${HOME}/.minisign",
|
|
"${HOME}/.caff",
|
|
"${HOME}/.password-store",
|
|
// -- cloud provider credentials --
|
|
"${HOME}/.aws",
|
|
"${HOME}/.boto",
|
|
"${HOME}/.config/gcloud",
|
|
"${HOME}/.kube",
|
|
"${HOME}/.passwd-s3fs",
|
|
"${HOME}/.s3cmd",
|
|
"/etc/boto.cfg",
|
|
// -- keyrings and wallets --
|
|
"${HOME}/.gnome2/keyrings",
|
|
"${HOME}/.local/share/keyrings",
|
|
"${HOME}/.local/share/kwalletd",
|
|
"${HOME}/.kde/share/apps/kwallet",
|
|
"${HOME}/.kde4/share/apps/kwallet",
|
|
// -- certificates and PKI --
|
|
"${HOME}/.pki",
|
|
"${HOME}/.cert",
|
|
"${HOME}/.local/share/pki",
|
|
"${HOME}/.local/share/plasma-vault",
|
|
"${HOME}/.vaults",
|
|
// -- KeePass databases --
|
|
"${HOME}/*.kdb",
|
|
"${HOME}/*.kdbx",
|
|
// -- encryption --
|
|
"${HOME}/.ecryptfs",
|
|
"${HOME}/.fscrypt",
|
|
"${HOME}/.Private",
|
|
"${HOME}/Private",
|
|
"/.fscrypt",
|
|
"/home/.ecryptfs",
|
|
"/home/.fscrypt",
|
|
"/crypto_keyfile.bin",
|
|
// -- system auth files --
|
|
"/etc/shadow",
|
|
"/etc/shadow+",
|
|
"/etc/shadow-",
|
|
"/etc/gshadow",
|
|
"/etc/gshadow+",
|
|
"/etc/gshadow-",
|
|
"/etc/passwd+",
|
|
"/etc/passwd-",
|
|
"/etc/group+",
|
|
"/etc/group-",
|
|
"/etc/sudo*.conf",
|
|
"/etc/sudoers*",
|
|
"/etc/doas.conf",
|
|
"/etc/davfs2/secrets",
|
|
"/etc/msmtprc",
|
|
// -- session directory and sockets (lateral movement vectors) --
|
|
"/tmp/ssh-*",
|
|
"/tmp/tmux-*",
|
|
"${RUNUSER}",
|
|
// -- mail (sensitive content) --
|
|
"${HOME}/.Mail",
|
|
"${HOME}/.mail",
|
|
"${HOME}/Mail",
|
|
"${HOME}/mail",
|
|
"${HOME}/postponed",
|
|
"${HOME}/sent",
|
|
"${HOME}/.mutt",
|
|
"${HOME}/.muttrc",
|
|
// -- password managers --
|
|
"${HOME}/.keepass",
|
|
"${HOME}/.keepassx",
|
|
"${HOME}/.keepassxc",
|
|
"${HOME}/.config/KeePass",
|
|
"${HOME}/.config/KeePassXCrc",
|
|
"${HOME}/.config/keepassxc",
|
|
"${HOME}/.cache/keepassxc",
|
|
"${HOME}/.local/share/KeePass",
|
|
"${HOME}/.config/1Password",
|
|
"${HOME}/.config/Bitwarden",
|
|
"${HOME}/.config/Enpass",
|
|
"${HOME}/.cache/Enpass",
|
|
"${HOME}/.local/share/Enpass",
|
|
"${HOME}/.lastpass",
|
|
"${HOME}/.config/Authenticator",
|
|
"${HOME}/.cache/Authenticator",
|
|
// -- browser profiles (saved passwords, cookies, session tokens) --
|
|
"${HOME}/.mozilla",
|
|
"${HOME}/.cache/mozilla",
|
|
"${HOME}/.config/mozilla",
|
|
"${HOME}/.config/google-chrome",
|
|
"${HOME}/.cache/google-chrome",
|
|
"${HOME}/.config/chromium",
|
|
"${HOME}/.cache/chromium",
|
|
"${HOME}/.config/BraveSoftware",
|
|
"${HOME}/.cache/BraveSoftware",
|
|
"${HOME}/.config/microsoft-edge",
|
|
"${HOME}/.cache/microsoft-edge",
|
|
"${HOME}/.config/vivaldi",
|
|
"${HOME}/.cache/vivaldi",
|
|
"${HOME}/.config/opera",
|
|
"${HOME}/.cache/opera",
|
|
"${HOME}/.librewolf",
|
|
"${HOME}/.cache/librewolf",
|
|
"${HOME}/.config/qutebrowser",
|
|
"${HOME}/.cache/qutebrowser",
|
|
"${HOME}/.local/opt/tor-browser",
|
|
"${HOME}/.tor-browser*",
|
|
"${HOME}/.cache/torbrowser",
|
|
"${HOME}/.config/torbrowser",
|
|
// -- cryptocurrency wallets --
|
|
"${HOME}/.*coin",
|
|
"${HOME}/.bitcoin",
|
|
"${HOME}/.electrum*",
|
|
"${HOME}/.ethereum",
|
|
"${HOME}/Monero/wallets",
|
|
"${HOME}/wallet.dat",
|
|
// -- nyx (tor controller) --
|
|
"${HOME}/.nyx",
|
|
// -- D-Bus sockets (can execute commands via systemd) --
|
|
"/run/dbus",
|
|
"/var/run/dbus",
|
|
// -- input devices (keylogging via evdev) --
|
|
"/dev/input/",
|
|
// -- X11 / Wayland sockets (keystroke injection, screen capture) --
|
|
"/tmp/.X11-unix",
|
|
"/tmp/.ICE-unix",
|
|
"/tmp/.XIM-unix",
|
|
"${RUNUSER}/wayland-*",
|
|
"${RUNUSER}/X11-display",
|
|
// -- container/VM runtime sockets (sandbox escape vectors) --
|
|
"/var/run/docker.sock",
|
|
"${RUNUSER}/docker.sock",
|
|
"${RUNUSER}/podman/podman.sock",
|
|
"/var/run/podman/podman.sock",
|
|
"${RUNUSER}/containers/",
|
|
"${RUNUSER}/crun",
|
|
"${RUNUSER}/libpod",
|
|
"${RUNUSER}/runc",
|
|
"${RUNUSER}/toolbox",
|
|
"/var/run/libvirt/libvirt-sock",
|
|
"/var/run/libvirt/libvirt-sock-ro",
|
|
"${RUNUSER}/libvirt/libvirt-sock",
|
|
// -- package manager sockets (can install/run arbitrary code) --
|
|
"${RUNUSER}/snapd-session-agent.socket",
|
|
"${RUNUSER}/.flatpak*",
|
|
"${RUNUSER}/.dbus-proxy",
|
|
// -- window manager IPC (allows arbitrary shell execution) --
|
|
"/tmp/i3-*/ipc-socket.*",
|
|
"${RUNUSER}/i3/ipc-socket.*",
|
|
"/tmp/sway-ipc.*",
|
|
"${RUNUSER}/sway-ipc.*",
|
|
// -- database sockets (data access) --
|
|
"/var/run/mysqld/mysqld.sock",
|
|
"/var/run/mysql/mysqld.sock",
|
|
"/tmp/.s.PGSQL.*",
|
|
];
|