Skip to content

v0.15.22

Choose a tag to compare

@github-actions github-actions released this 21 Jun 08:51
· 37 commits to main since this release
45a17e9

InnerWarden 0.15.22

Fixed

  • innerwarden upgrade is now watchdog-aware — paid Active-Defence hosts upgrade with one command. On a host running the innerwarden-watchdog supervisor the agent is a watchdog-SPAWNED child and innerwarden-agent.service is disabled (its unit file still exists). The old upgrade flow saw the disabled-but-present unit and ran systemctl restart innerwarden-agent, which both spawned a SECOND agent alongside the watchdog's child (duplicate-instance flood) and failed to refresh the running child's binary (the watchdog kept the old one) — so watchdog hosts needed a manual stop-watchdog/swap/start-watchdog dance. upgrade now detects an active watchdog and, instead of touching the agent unit, restarts innerwarden-watchdog (tearing down its cgroup — watchdog + child agent — and respawning the agent on the freshly-swapped binary); it never systemctl start innerwarden-agent on a watchdog host. Non-watchdog hosts are unchanged. The restart policy is a pure, unit-tested planner.

Security

  • Discovery-tactic free-pass no longer granted on a parent name alone; reverse-shell detection survives fork() (evasion audit E3 + E4). Two more confirmed evasions from the adversarial detector audit, both detection-only. (E3) The exec_context classifier granted OpInteractive — the free-pass that silences the entire Discovery tactic (discovery_burst / discovery_anomaly / nmap_scan) — to any uid>999 process whose parent comm was a shell name (bash/zsh/sh/…). That name is forgeable (prctl(PR_SET_NAME)) and even a real bash -c spawned by cron/systemd/an implant matches it, so an implant parented by a shell ran recon invisibly (re-opening the spec-050 gap). OpInteractive now additionally requires a real controlling terminal: the execve emitter records the parent's tty_nr from /proc/<ppid>/stat as has_tty, and the classifier only grants the free-pass when a tty is present — an interactive ssh shell owns a pts, an implant/reverse-shell/daemon-spawned shell does not. A missing has_tty (non-eBPF sources) defaults to "surface it". (E4) The eBPF reverse-shell sequence (network.outbound_connect + process.fd_redirect onto stdio) was correlated strictly per-PID, so a reverse shell that connect()s in the parent then fork()s and dup2()s the socket in the child (classic socat / python: fork; child dup2+exec) never matched — the connect was under the parent pid, the redirect under the child. The fd_redirect event now carries the parent pid (resolved for stdio dups only) and the detector correlates over the process's own ring UNION its parent's, so the forked reverse shell fires Critical; a child redirect whose parent never connected still does not fire. New unit anchors pin every case. No generic signal relaxed; both make a specific evasion harder. Detector count unchanged (82).

Install / upgrade (Linux, toolchain-free, signed binaries)

curl -fsSL https://innerwarden.com/install | sudo bash
# already installed:  sudo innerwarden upgrade --yes

Every binary below is signed (Ed25519 + Sigstore bundle). Docs: https://github.com/InnerWarden/innerwarden/wiki · Site: https://www.innerwarden.com

What's Changed

  • security(sensor): discovery TTY gate + reverse-shell fork correlation (audit E3/E4) by @maiconburn in #1088
  • fix(ctl): make innerwarden upgrade watchdog-aware (one-command upgrade on prod) by @maiconburn in #1089
  • release: 0.15.22 by @maiconburn in #1090

Full Changelog: v0.15.21...v0.15.22