• v0.6.0 7f62900dc0

    Traven released this 2026-10-29 02:57:07 +00:00 | 17 commits to main since this release

    Automatic security updates, file-permission and mount checks, a local dashboard, hardline fleet for auditing many servers over SSH, review dates for accepted risks, and Prometheus metrics from watch.

    Released 2026-10-29.

    Added

    • Automatic updates (phase 3): updates-unattended-installed and updates-unattended-enabled on Ubuntu/Debian (writes /etc/apt/apt.conf.d/52hardline-auto-upgrades, verified through apt-config dump); updates-dnf-automatic-installed and updates-dnf-automatic-timer on RHEL family.
    • time-synced (phase 3): timedatectl reports NTPSynchronized=yes. Report-only.
    • kernel-suid-dumpable (phase 7): sets fs.suid_dumpable = 0.
    • mounts-tmp and mounts-dev-shm (phase 7): nodev,nosuid,noexec, read from /proc/self/mounts. Report-only.
    • files-no-world-writable, files-no-stray-suid, files-no-unowned (phase 8): one bounded walk of local disk filesystems (no symlinks, no container storage or pseudo filesystems, stops at 3,000,000 entries). Report-only. files-no-unowned is a warning when users also come from LDAP/SSSD.
    • apt-config and timedatectl added to the fixed command list.
    • hardline dashboard [--out FILE]: a local, script-free status page with the report, score over time and recent watch runs.
    • hardline fleet <host>...: run on your own computer; audits each server over SSH (ssh added to the fixed command list) and writes one local page with every grade, open findings per host and failures shared across servers.
    • Dashboard: "How to fix" on every open finding (why it matters, what Hardline changes, the exact preview/commit/confirm commands, how to undo), a change timeline from history.log, and an accepted-risk register with review dates.
    • hardline accept --expires 90d|12w|YYYY-MM-DD: a review date for an accepted finding. Once it passes the finding counts again and watch reports it once. Existing entries keep working without one. An entry with expires is refused by 0.5.x, so after downgrading remove that line (or the entry) from /etc/hardline/accepted.toml.
    • watch run keeps the last 720 runs in watch-history.jsonl, rewrites dashboard.html, and writes Prometheus metrics (hardline.prom) for node_exporter's textfile collector.

    Fixed

    • watch-history.jsonl with one corrupt byte no longer wipes the whole history; only the bad line is dropped.
    • A full disk while saving history no longer stops the regression alert from watch run.
    • File-permission scan: a bind mount of a subdirectory no longer hides the rest of that filesystem; at most 1,000 sample paths per finding are kept (counts stay exact).
    • Temp files from atomic writes are per-process, so hardline dashboard and watch run can't publish each other's half-written file.
    • self-update takes the hardline lock, so no apply, rollback or watch run starts while the binary is replaced.
    • confirm commits the snapshots before it stops the revert timer, so a failure there still reverts on its own instead of leaving the change unguarded.
    • A failure recording files created by a package install, or (for unguarded phases) sealing the snapshot, now rolls the phase back instead of leaving it half-applied.
    • hardline dashboard --out FILE prints the right file name to open.
    • Webhook URLs with an IPv6 literal host and no port are accepted; malformed bracketed hosts are refused.
    • The dashboard's time formatting no longer assumes ASCII input.
    • rollback --pending and an early manual revert are recorded as "rolled back by hand", not "not confirmed in time"; the last-revert line no longer repeats its timestamp.
    • Writing a file by bare name (e.g. --out page.html) in the current directory.

    Install

    Download the archive for your CPU (x86_64 or aarch64), check it against the signed sums, and install it somewhere only root can write:

    curl -LO https://sudosecurity.org/hardline/releases/latest/hardline-x86_64-unknown-linux-gnu.tar.gz
    curl -LO https://sudosecurity.org/hardline/releases/latest/SHA256SUMS
    curl -LO https://sudosecurity.org/hardline/releases/latest/SHA256SUMS.sig
    curl -LO https://git.sudosecurity.org/sudosecurity/hardline/raw/tag/v0.6.0/release.pub
    openssl pkeyutl -verify -pubin -inkey release.pub -rawin -in SHA256SUMS -sigfile SHA256SUMS.sig
    sha256sum --ignore-missing -c SHA256SUMS
    tar -xzf hardline-x86_64-unknown-linux-gnu.tar.gz
    sudo install -o root -g root -m 755 hardline-*/hardline /usr/local/bin/hardline
    

    Already on 0.5.0 or later? sudo hardline self-update does the same checks for you.

    SHA256SUMS is signed with the Ed25519 release key in release.pub; the same key is compiled into Hardline for self-update.

    Full changelog: https://git.sudosecurity.org/sudosecurity/hardline/compare/v0.5.1...v0.6.0

    Downloads
  • v0.5.1 fba20eb0f6

    Traven released this 2026-10-28 02:19:25 +00:00 | 24 commits to main since this release

    Patch release: if an SSH reload failed and was reverted, sshd could stay stopped. The revert now restarts a failed SSH unit, and apply checks that sshd is still running after the reload. Upgrade recommended for everyone on 0.5.0.

    Released 2026-10-28.

    Fixed

    • SSH stayed down after a failed reload was reverted: a failed try-reload-or-restart leaves ssh.service failed, and the revert's own try-reload-or-restart skips failed units. The revert now resets and restarts a failed SSH unit. Apply also checks that sshd is still running 1 second after the reload, because systemd reports a SIGHUP reload done before sshd re-execs, and the re-exec can still die (seen on Debian 13 with ssh.socket and ssh.service both started).

    Install

    Prebuilt binaries are published for the latest release only. Use the latest release, or build this tag from source:

    git clone --branch v0.5.1 https://git.sudosecurity.org/sudosecurity/hardline.git && cd hardline
    cargo build --release --locked
    

    Full changelog: https://git.sudosecurity.org/sudosecurity/hardline/compare/v0.5.0...v0.5.1

    Downloads
  • v0.5.0 9a21b6a584

    Traven released this 2026-10-28 02:04:58 +00:00 | 26 commits to main since this release

    Signed self-updates, apply --all under one revert timer, accepted-risk tracking, watch alerts to Discord/Slack/ntfy/webhooks, SARIF output, eight new controls, and Ubuntu 26.04 / Debian 13 support.

    Released 2026-10-28.

    Added

    • Site: the controls page filters by search, severity, distro, profile and fix type (press / to search). Docs add an Updating section, a full table of every path Hardline writes, and signed-install steps from sudosecurity.org; the security page documents release signing and shows the public key. Landing-page numbers are now measured (median of 5 audits on 1-vCPU Ubuntu 24.04 and Rocky 9 VMs), and the binary size comes from the build.
    • hardline self-update [--check]: downloads the latest release from https://sudosecurity.org/hardline/releases/latest/, verifies the Ed25519 signature on SHA256SUMS against the release key compiled in from release.pub (OpenSSL 3 pkeyutl), checks VERSION and the bare binary against the signed sums, refuses downgrades and pending guarded changes, then replaces the binary atomically and keeps the old one at /var/lib/hardline/hardline.previous. The release workflow publishes an unsigned draft; the Ed25519 key stays root-only on the release host, which signs SHA256SUMS before the release is published (see CONTRIBUTING.md).
    • Eight new baseline controls: ssh-login-grace-time (LoginGraceTime 1-60, phase 1), aide-installed (installs AIDE, aide-common on Debian/Ubuntu so aideinit and the daily timer come with it) and aide-database (manual: build the baseline from a trusted state) in phase 4, docker-no-tcp-socket (no tcp:// Docker API without tlsverify, from daemon.json or -H flags; manual) in phase 6, and in phase 7 kernel-unprivileged-bpf-disabled (sets 2, which root can undo without a reboot), kernel-yama-ptrace-scope (sets 1), kernel-lockdown and kernel-module-sig-enforce (report-only; need a reboot).
    • hardline accept <id> --reason "...", hardline accept (list) and hardline unaccept <id>. Accepted findings keep their real status but are shown as accepted risk with who and why, are left out of the grade, the audit exit code and watch regressions, are skipped by apply, and are marked suppressed in SARIF. Stored in root-owned /etc/hardline/accepted.toml. The JSON report gains results[].accepted and score.accepted.
    • hardline watch notify set|test|remove posts watch regressions to Discord, Slack, ntfy or a generic JSON webhook. The URL is read from stdin, must be https without credentials, is saved only after a test alert succeeds, and lives in root-only /etc/hardline/notify.toml (mode 600, refused otherwise). It reaches curl through --config - and never appears in argv, logs or errors. A failed post is logged and doesn't change the run's exit code.
    • hardline apply --all previews every phase; apply --all --commit applies them in one run. Phases 3–8 commit one by one (each still has its own rollback --phase N), then SSH (1) and the firewall (2) go last under one revert timer, one boot guard and one hardline confirm from a new login. If you can't log back in, both revert together, newest first. If a later guarded phase fails, the earlier one is reverted too rather than left without a timer. pending.json gains an optional chain list; a single-phase change keeps the old shape.
    • Ubuntu 26.04 LTS and Debian 13 (trixie) are supported with the baseline profile. Both passed the VM lockout scenarios (timer revert, same-session confirm refused, new-session confirm, reboot before confirm) and every phase with a reboot. Ubuntu 26.04 ships sudo-rs and Rust coreutils by default; Hardline works with both.
    • hardline audit --sarif prints SARIF 2.1.0 for GitHub code scanning and other dashboards. Failing and warning controls become results with security-severity, STIG/CCI tags and a stable per-host fingerprint; a check that couldn't run becomes a tool notification and marks the run unsuccessful. Exit codes are unchanged.
    • Hardline pages get per-page share images (Open Graph and X cards), Twitter/X titles, and schema.org data (SoftwareApplication on /hardline/, breadcrumbs elsewhere); site/og.py renders the images.
    • New /hardline/architecture/ page, and docs for the JSON report fields, SARIF upload, watch alerting, Ansible, cloud-init and grade gates.

    Changed

    • Findings and hardline explain link to https://sudosecurity.org/hardline/controls/, the new controls reference. Links from older versions to /hardline/#id still land on the right entry.
    • site/build.py now builds every Hardline page on sudosecurity.org (overview, docs, controls, security, sample report, changelog, about) into site/pages/, and site/publish.py publishes them to Ghost.

    Install

    Prebuilt binaries are published for the latest release only. Use the latest release, or build this tag from source:

    git clone --branch v0.5.0 https://git.sudosecurity.org/sudosecurity/hardline.git && cd hardline
    cargo build --release --locked
    

    Full changelog: https://git.sudosecurity.org/sudosecurity/hardline/compare/v0.4.1...v0.5.0

    Downloads
  • v0.4.1 35e86eb769

    Traven released this 2026-10-19 04:23:47 +00:00 | 47 commits to main since this release

    Patch release: rolling back a change that installed a package no longer deletes that package's own config files (this left ufw enabled after rollback on Debian 12).

    Released 2026-10-19.

    Fixed

    • Rolling back a change that installed a package (ufw on Debian 12, firewalld on RHEL) deleted the config files that package had just created, such as /etc/ufw/ufw.conf. On Debian that made ufw disable fail, so the firewall stayed on after rollback. Files a package install creates are now recorded after the install, and rollback puts back the package's own copy.

    Install

    Prebuilt binaries are published for the latest release only. Use the latest release, or build this tag from source:

    git clone --branch v0.4.1 https://git.sudosecurity.org/sudosecurity/hardline.git && cd hardline
    cargo build --release --locked
    

    Full changelog: https://git.sudosecurity.org/sudosecurity/hardline/compare/v0.4.0...v0.4.1

    Downloads
  • v0.4.0 2303414c2e

    Traven released this 2026-10-19 04:12:06 +00:00 | 49 commits to main since this release

    A–F security grade, a self-contained HTML report, scheduled watch re-audits, hardline explain, and RHEL 9 / Rocky Linux 9 / AlmaLinux 9 support with guarded firewalld.

    Released 2026-10-19.

    Added

    • An A–F security grade, weighted by severity, in audit output and the JSON report (grade.letter, grade.percent). A failing high-severity control caps an A at B.
    • hardline report [--out FILE]: the audit as a self-contained HTML page with the grade, a "fix first" list and a link for every finding. No scripts or external requests (strict CSP), light and dark themes, works on phones and prints cleanly. --out creates a new 0600 file and never overwrites or follows an existing path.
    • hardline watch enable|disable|run|status: a systemd timer (hourly, daily or weekly, with jitter and catch-up after downtime) that re-audits and compares with the previous run. A grade drop, a newly failing control or an outside edit to a file Hardline wrote exits 1, so hardline-watch.service shows in systemctl --failed and OnFailure= hooks fire. Skips a run while a change awaits confirm or another hardline command holds the lock. Results go to /var/lib/hardline/watch.json (0600).
    • hardline explain <id> [--json]: why a control matters, exactly what it checks, what apply writes, the preflight checks, and how to undo it. Works offline and without root; an unknown id suggests close matches. The text comes from controls/guides.toml, which also builds the website, so the CLI and https://sudosecurity.org/hardline/ never disagree.
    • RHEL 9, Rocky Linux 9 and AlmaLinux 9 support for the baseline profile: dnf/rpm package handling, sshd.service, a new selinux-enforcing check in phase 3, and SELinux labels restored on every file Hardline writes. Tested on Rocky 9.8 and AlmaLinux 9.8 VMs with SELinux enforcing.
    • Guarded firewalld support on RHEL 9, Rocky Linux 9 and AlmaLinux 9: when firewalld isn't running, apply --phase 2 installs it if needed, opens SSH and every listening port in the default zone while keeping existing zone rules, validates with firewall-offline-cmd --check-config, and starts it under the confirm/revert/boot guard. Rollback restores the zone file exactly and stops firewalld again. Tested on Rocky 9 with SELinux enforcing.
    • Controls can be limited to one distro family with os = ["debian"] or os = ["rhel"].

    Fixed

    • Boot-guard reverts now also stop units the reverted change enabled; disabling alone didn't cancel a start job already queued for that boot.
    • Rollback disables units before restoring files. Before, reverting an nftables change failed with "Unit file hardline-firewall.service does not exist" because the unit file was already removed, so the boot guard reported a failed revert.
    • audit, diff, status, controls and dry-run apply exit 3 when stdout fails for a reason other than a closed pipe (for example a full disk), instead of exiting 0 with a truncated report.
    • The dpkg lock wait is one 5-minute budget for the whole package install, not 5 minutes per apt-get call.

    Install

    Prebuilt binaries are published for the latest release only. Use the latest release, or build this tag from source:

    git clone --branch v0.4.0 https://git.sudosecurity.org/sudosecurity/hardline.git && cd hardline
    cargo build --release --locked
    

    Full changelog: https://git.sudosecurity.org/sudosecurity/hardline/compare/v0.3.1...v0.4.0

    Downloads
  • v0.3.1 1fd0f19f3f

    Traven released this 2026-10-19 01:50:32 +00:00 | 56 commits to main since this release

    Patch release: no more broken-pipe panics when piping output, and package installs wait for the dpkg lock instead of failing on a fresh server.

    Released 2026-10-19.

    Fixed

    • Piping output into head (or any closed pipe) no longer crashes Hardline with a broken-pipe panic. Output errors can never stop an apply halfway.
    • Package installs wait up to 5 minutes for the dpkg lock (DPkg::Lock::Timeout=300) instead of failing while unattended-upgrades runs on a fresh server.

    Install

    Prebuilt binaries are published for the latest release only. Use the latest release, or build this tag from source:

    git clone --branch v0.3.1 https://git.sudosecurity.org/sudosecurity/hardline.git && cd hardline
    cargo build --release --locked
    

    Full changelog: https://git.sudosecurity.org/sudosecurity/hardline/compare/v0.3.0...v0.3.1

    Downloads
  • v0.3.0 f187259a26

    Traven released this 2026-10-19 01:35:38 +00:00 | 58 commits to main since this release

    Ubuntu 22.04 LTS and Debian 12 support for the baseline profile. Release binaries are now built on Ubuntu 22.04, so one binary runs on glibc 2.35 and newer.

    Released 2026-10-19.

    Added

    • Ubuntu 22.04 LTS and Debian 12 support for the baseline profile. All phases and the SSH/firewall lockout scenarios were run on VMs of each.
    • --profile stig is refused outside Ubuntu 24.04, since its IDs come from the Ubuntu 24.04 STIG.

    Changed

    • Release binaries are built on Ubuntu 22.04 so they run on glibc 2.35+ (Ubuntu 22.04, Debian 12) as well as 24.04.

    Install

    Prebuilt binaries are published for the latest release only. Use the latest release, or build this tag from source:

    git clone --branch v0.3.0 https://git.sudosecurity.org/sudosecurity/hardline.git && cd hardline
    cargo build --release --locked
    

    Full changelog: https://git.sudosecurity.org/sudosecurity/hardline/compare/v0.2.0...v0.3.0

    Downloads
  • v0.2.0 af0cd05d18

    Traven released this 2026-10-19 00:54:13 +00:00 | 60 commits to main since this release

    Adds the kernel (phase 7) and accounts (phase 8) phases: sysctl hardening, blocked kernel modules and password policy, with the DISA rules under --profile stig.

    Released 2026-10-19.

    Added

    • Phase 7, kernel: six sysctl controls (kernel.dmesg_restrict,
      net.ipv4.tcp_syncookies, kernel.randomize_va_space from the STIG;
      kernel.kptr_restrict, fs.protected_symlinks, fs.protected_hardlinks
      in baseline). Fixes go in /etc/sysctl.d/99-zz-hardline.conf;
      rollback restores the previous running values.
    • Phase 7 blocks kernel modules: usb-storage (STIG) plus dccp, rds, tipc
      (baseline) via /etc/modprobe.d/hardline.conf.
    • Phase 8, accounts: empty passwords, libpam-pwquality, and in stig the
      DISA password rules, password ages, INACTIVE=35 and sudo NOPASSWD. Config
      files are edited in place, so only the managed lines change.

    Install

    Prebuilt binaries are published for the latest release only. Use the latest release, or build this tag from source:

    git clone --branch v0.2.0 https://git.sudosecurity.org/sudosecurity/hardline.git && cd hardline
    cargo build --release --locked
    

    Full changelog: https://git.sudosecurity.org/sudosecurity/hardline/compare/v0.1.0...v0.2.0

    Downloads
  • v0.1.0 d32e712045

    Traven released this 2026-10-19 00:25:29 +00:00 | 75 commits to main since this release

    First public build. Hardline audits an Ubuntu 24.04 server against 43 controls, changes nothing without --commit, and reverts SSH and firewall changes unless you confirm from a new session.

    Released 2026-10-19.

    Added

    • audit, apply (dry run by default, --commit to write), confirm,
      rollback, diff, status and controls commands.
    • 43 controls across SSH, firewall, AppArmor, auditd, TLS and Docker, with
      baseline and stig profiles and Ubuntu 24.04 STIG/CCI references.
    • Guarded SSH and firewall changes: a revert timer plus a boot guard undo
      anything not confirmed from a new SSH session.
    • SHA-256 snapshots with mode and ownership, drift detection, and manual
      rollback that refuses to overwrite later edits without --force.
    • ufw backend, and an nftables backend that only owns table inet hardline.
    • JSON report schema version 1.
    • Project page at https://sudosecurity.org/hardline/, built from the controls
      by site/build.py. Every finding links to its section there.
    • Release archives have stable names (hardline-<target>.tar.gz), so
      releases/latest/download/ links always work.

    Install

    Prebuilt binaries are published for the latest release only. Use the latest release, or build this tag from source:

    git clone --branch v0.1.0 https://git.sudosecurity.org/sudosecurity/hardline.git && cd hardline
    cargo build --release --locked
    

    Source: https://git.sudosecurity.org/sudosecurity/hardline/src/tag/v0.1.0

    Downloads