# Security Policy ## Supported versions drivestage is pre-1.0 software. Only the most recent minor release line receives security fixes. | Version | Supported | Notes | |---------|--------------------|--------------------------------------| | 0.2.x | :white_check_mark: | Current release line | | 0.1.x | :x: | EOL — upgrade to 0.2.x | | < 0.1 | :x: | Never released | When 0.4.0 ships, 0.2.x will move to a 30-day security-only window before EOL. --- ## Reporting a vulnerability **Do not open a public GitHub issue for security vulnerabilities.** Email vulnerability reports to **[security@dcos.net](mailto:security@dcos.net)**. Please include: 1. A description of the issue and its impact. 2. The exact `blkstage.sh` subcommand(s) or GUI flow involved. 3. Reproduction steps (commands, ISO filenames, device path). 4. The output of `blkstage.sh --version`. 5. Your distro, kernel, and (if relevant) Rust toolchain version. 6. Any suggested remediation. You will receive an acknowledgement within **5 business days**. If you do not, follow up — the maintainer may be offline. ### Coordinated disclosure We follow a **90-day coordinated disclosure** timeline: | Day | Action | |------|-------------------------------------------------------------------| | 0 | Reporter emails `security@dcos.net` | | ≤ 5 | Maintainer acknowledges receipt | | ≤ 14 | Maintainer triages and assigns a severity (see below) | | ≤ 30 | Maintainer proposes a fix or mitigation; reporter reviews | | ≤ 60 | Fix lands on a maintenance branch and a patch release is cut | | ≤ 90 | Public advisory published (CVE requested if eligible) | If a fix is delayed, the reporter is kept informed at each milestone. Reporters who wish to extend the 90-day window are encouraged to ask — extensions are granted in good faith. ### Severity We use [CVSS v3.1](https://www.first.org/cvss/calculator/3.1). Examples relevant to this project: | Severity | Example | |-----------|----------------------------------------------------------------------------------| | Critical | Script wipes the OS disk on a non-USB device under any input | | High | Sudo password leaks to disk, logs, or another process | | Medium | A distro-detection false negative causes the wrong kernel args on a known ISO | | Low | Cosmetic information leak (e.g. device serial printed to stdout) | --- ## Threat model drivestage is a **disk-destroying, privilege-elevating** tool. Treat it with the same caution as `dd`, `mkfs`, or `parted`. The realistic threats are: 1. **Wrong-device wipe.** The user runs `setup` against a path that turns out to be the OS disk, an LVM member, or a LUKS-backed device. Data loss is total and unrecoverable. 2. **Credential exposure.** The GUI captures the user's sudo password to run the engine. A leak (logs, core dump, swap, /proc//environ) discloses it to other local users or to anyone with later physical access. 3. **Tampered config file.** `blkstage.sh` sources an optional `CONF_FILE` (`/etc/drivestage.conf`). A world-writable or non-root-owned conf file is a local privilege escalation vector — any user could plant shell that runs as root on the next invocation. 4. **Concurrent invocation.** Two `setup` or `deploy` runs racing on the same device produce a corrupted partition table or half-written GRUB image. 5. **Hostile ISO payloads.** The tool copies ISO files verbatim. It does not inspect ISO contents. Booting a malicious ISO is the user's responsibility — but the tool must not silently boot a different ISO than the one the user selected. 6. **CI/supply-chain.** A compromised dependency in `Cargo.lock` could ship malicious code into the GUI binary. The tool is **not** designed to defend against an attacker with write access to the drivestage installation itself (`/usr/local/bin/drivestage`, `/usr/local/lib/drivestage/`, or the git checkout). At that point the attacker already has the privileges the tool runs with. --- ## Security measures in place The following mitigations are present in 0.2.x. Each is documented in [`CHANGELOG.md`](./CHANGELOG.md) and tested where feasible. ### Disk safety - **`guard_root_disk`** refuses to operate on the device hosting `/`. It walks the `lsblk PKNAME` chain so it also catches the OS disk when root sits on LVM, LUKS, or mdadm. A second check blocks any device whose `PKNAME` chain mentions `crypt`, `lvm`, `md`, or `dm-`. - **Typed confirmation.** `setup` requires the user to type the device name verbatim before any destructive operation begins. - **Recursive unmount.** `unmount_all` uses `umount -R` so nested mounts under `/mnt/drivestage/*` are cleaned up before re-partitioning. - **Free-space check.** `deploy_payload` verifies sufficient free space on the payloads partition before invoking `rsync`. - **Cleanup trap.** A trap on `EXIT`/`INT`/`TERM` calls `unmount_all` so a Ctrl-C mid-deploy doesn't leave partitions mounted and confusingly writable. ### Credential handling - **`Zeroizing`** wraps the sudo password in the GUI (`core/sudo.rs`). The string is zeroized on drop — never written to logs, never serialized, never sent across an IPC channel that persists. - **`flock`-based single-instance lock.** Concurrent invocations are refused with an explicit error rather than racing on shared state. - **No password on the command line.** The script never accepts a password as an argument or environment variable; the GUI passes it through `sudo -S`'s stdin only. ### Configuration file safety - **`CONF_FILE` ownership and mode validation.** Before sourcing `/etc/drivestage.conf`, the script verifies: - Owner is `root:root`. - Mode is `0644` or stricter (no group/other write). - File is a regular file (not a symlink, FIFO, or device node). Failure aborts before sourcing. ### Build & supply chain - **Pinned `Cargo.lock`.** The lockfile is committed; CI runs `--locked` for test/build/clippy. A `cargo update` is a deliberate, reviewable change. - **Dependabot** opens PRs for cargo + GitHub Actions dependency updates on a weekly cadence (see [`.github/dependabot.yml`](./.github/dependabot.yml)). - **CI gate.** Every push and PR runs `fmt`, `clippy -D warnings`, `test`, `build --release`, `shellcheck`, `bash-tests`, and MSRV check on Rust 1.75 and stable (see [`.github/workflows/ci.yml`](./.github/workflows/ci.yml)). --- ## Hardening recommendations for users - Install the script to a root-owned, mode-0755 location (`/usr/local/bin/drivestage`). - If you use `/etc/drivestage.conf`, `chown root:root` it and `chmod 0644` it. The script will refuse to source it otherwise. - Run the GUI as your normal user, not as root. The GUI escalates via `sudo` only when needed; running it as root skips the privilege boundary. - Verify the device path with `lsblk` before each `setup`. The script's `guard_root_disk` catches the OS disk — it does **not** catch a second data disk you care about. - Don't leave a drivestage stick plugged into a multi-user host. The payloads partition is world-readable ext4 by default. --- ## Contact - **Security reports:** [security@dcos.net](mailto:security@dcos.net) - **General issues:** [GitHub Issues](https://git.dcos.net/dcosnet/DriveStage/issues) - **Maintainer:** Jeremy Anderson — [dcos.net](https://dcos.net)