SSH (bash) plugin
The SSH (bash) plugin lets a Vaubaan Gateway mission use SSH (bash) without handing the agent a credential. Shell commands on a host over SSH — inspection on a read allow-list, writes priced by class (destructive, package, service, sudo), lines that cannot be classified priced as all of them.
- Version:
2.0.0(package@vaubaan/plugin-ssh) - Status: stable
- Health: not enough reports yet — what this means
- Source: plugins/ssh, catalog risk-catalog.yaml version 4 of 2026-10-14
- How to connect an account: Connect SSH (bash)
- How it is modelled: handbook
One account is one host reached over SSH with a key pair generated by this gateway and a pinned host key; that host is its single resource, labelled dev, staging or prod by its owner. The one tool runs a shell command line: inspection commands are reads, everything else is a write, and destructive commands, package changes, service control and sudo are permissions of their own.
Permissions
Each permission is a named risk of the plugin's catalog: a mission holds an explicit list of them, never "all". The severity is computed from the permission's six axes (undo, blast radius, data, cost, visible to, lasts); nothing is decided from it.
| Permission | What it allows | Severity | Why it is a risk |
|---|---|---|---|
ssh.exec-read | Run a whitelisted read-only command | low | Inspection commands recognised by the read allow-list (`journalctl`, `cat`, `ls`, `tail`, `head`, `grep`, `pgrep`, `ps`, `docker ps/inspect/logs`, `systemctl status`, `df`, `free`, `uptime`, `who`, `ss -tlnp`, `md5sum`, `stat`) with their known read-only options, alone or piped together. No mutation. Logs and files may still contain secrets, which is why `exec-read-secret-files` exists next to it. |
ssh.exec-read-secret-files | Read a credential-bearing file | low | The read allow-list accepts `cat <path>` without filtering the path, so `cat /etc/shadow`, `cat /root/.env` or `stat /home/<u>/.ssh/id_ed25519` are reads. The classifier recognises credential-bearing paths however they are spelled (`.ssh/…`, `.env`, private keys, `/etc/shadow`, `/root`, raw devices), and paths it cannot see (an expansion, `..`, a recursive `grep`, `docker inspect`, a line it cannot classify), and emits an extra slice, so a mission must hold this permission on top of `exec-read` to read them. Exfiltration of host credentials ; refused by every preset but `operator`, where it asks first. |
ssh.exec-write | Run an arbitrary shell command | medium (high on prod; only for dev, staging, prod) | Any simple command outside the read allow-list and any output redirection. File edits, builds, git operations, process launches, scripts : the program may do whatever its user can. A line the classifier cannot see through (command substitution, inline code, another host or container) needs this permission and every class permission below. On a `dev` or `staging` host the blast radius is the host ; on `prod` a write can shift the security posture or cause downtime, hence the override. |
ssh.exec-destructive | Destructive command (recursive delete, disk, reboot) | high (only for dev, staging, prod) | `rm` with `-r` or `-f`, `mkfs`, `dd`, `shred`, `wipefs`, partitioning tools, `reboot` / `shutdown`, `userdel`, firewall flushes, Docker prunes. Irreversible at the host level ; emitted together with `exec-write`. Presets make it ask first outside `dev`. |
ssh.exec-package-install | Install, remove or upgrade packages | medium (only for dev, staging, prod) | System package managers (`apt`, `dpkg`, `yum`, `dnf`, `zypper`, `apk`, `pacman`, `snap`, `brew`, `flatpak`, `rpm`) in a mutating mode, global `npm` / `pnpm` / `yarn` installs, `pipx`. Changes what runs on the host for every service ; supply-chain exposure. Emitted together with `exec-write`. |
ssh.exec-service-control | Start, stop or restart a service or process | medium (only for dev, staging, prod) | `systemctl` lifecycle verbs, `service <x> restart`, Docker and Compose lifecycle, `pm2`, `supervisorctl`, `nginx -s`, `kill` / `pkill`. Availability impact, reversible by starting again. Emitted together with `exec-write`. A developer preset allows it on `dev` and asks first on `staging`. |
ssh.exec-sudo | Privilege escalation (sudo, su, doas) | high (only for dev, staging, prod) | A non-whitelisted command run through `sudo`, `su`, `doas` or `pkexec`. Whatever the inner command does, it does as another user, usually root. Emitted together with `exec-write` and the inner command's classes. Inspection verbs the whitelist already admits under `sudo` (`sudo journalctl`, `sudo systemctl status`, `sudo ss -tlnp`) stay reads. |
ssh.uncategorized-write | Uncategorized SSH write | medium (the catch-all: touched only by a call no other permission covers) | Catch-all for writes without a dedicated entry. Every write of the single `ssh__exec` tool is covered by `exec-write` ; this entry exists for tools added later (an `ssh__sftp_put`, say) and is never referenced by a preset. |
Presets
A preset pre-fills the permissions of a mission for one account, with a limit per period, a rate and whether each permission runs freely or asks the mission creator first. The person creating the mission adjusts it; the mission stores the explicit list.
Read-only
read-only — Inspect a host — logs, processes, disk, services, files outside credential paths. No write.
| Permission | What it allows | Limit per period | Rate | Runs |
|---|---|---|---|---|
ssh.exec-read | Run a whitelisted read-only command | 2000 | 60 per minute | runs freely |
Developer
developer — One mission per code project — reads everywhere, file and process operations on dev and staging hosts, service restarts on dev; nothing destructive, no packages, no sudo, no prod.
| Permission | What it allows | Limit per period | Rate | Runs |
|---|---|---|---|---|
ssh.exec-read | Run a whitelisted read-only command | 5000 | 120 per minute | runs freely |
ssh[dev].exec-write | 1000 | 30 per minute | runs freely | |
ssh[staging].exec-write | 500 | 20 per minute | runs freely | |
ssh[dev].exec-service-control | 200 | 10 per minute | runs freely | |
ssh[staging].exec-service-control | 50 | 5 per minute | ask me first |
Operator
operator — Everything on every labelled host; credential-file reads, destructive commands, package changes, service control and sudo asking first outside dev; every prod write asking first.
| Permission | What it allows | Limit per period | Rate | Runs |
|---|---|---|---|---|
ssh.exec-read | Run a whitelisted read-only command | 10000 | 120 per minute | runs freely |
ssh.exec-read-secret-files | Read a credential-bearing file | 50 | 5 per minute | ask me first |
ssh[dev].exec-write | 2000 | 30 per minute | runs freely | |
ssh[staging].exec-write | 1000 | 30 per minute | runs freely | |
ssh[prod].exec-write | 200 | 10 per minute | ask me first | |
ssh[dev].exec-destructive | 100 | 10 per minute | runs freely | |
ssh[staging].exec-destructive | 20 | 5 per minute | ask me first | |
ssh[prod].exec-destructive | 10 | 2 per minute | ask me first | |
ssh[dev].exec-package-install | 100 | 10 per minute | runs freely | |
ssh[staging].exec-package-install | 20 | 5 per minute | ask me first | |
ssh[prod].exec-package-install | 10 | 2 per minute | ask me first | |
ssh[dev].exec-service-control | 500 | 20 per minute | runs freely | |
ssh[staging].exec-service-control | 100 | 10 per minute | ask me first | |
ssh[prod].exec-service-control | 20 | 5 per minute | ask me first | |
ssh[dev].exec-sudo | 200 | 20 per minute | runs freely | |
ssh[staging].exec-sudo | 50 | 5 per minute | ask me first | |
ssh[prod].exec-sudo | 20 | 2 per minute | ask me first |
Tools
| Tool | What it does |
|---|---|
ssh__exec | Run a shell command on a host |
Health
Health: not enough reports yet. A plugin version is deemed validated by the community with at least 200 reports and 90 % of them successful, over the last 90 days, as reported by the instances whose operators turned community telemetry on. It is a community signal, not a security guarantee.