v0.15.25
InnerWarden 0.15.25
Security
quinn-proto0.11.14 → 0.11.15 (RUSTSEC-2026-0185). Fixes a remote memory-exhaustion advisory (unbounded out-of-order stream reassembly) in the transitive QUIC dependency. The unrelatedtract-onnx0.22 → 0.23 bump was deliberately NOT taken (breaks the build + would need inference-parity revalidation of the Local Warden classifier for zero security benefit).memmap20.9.10 → 0.9.11 (RUSTSEC-2026-0186). Clears an "unchecked pointer offset" unsoundness advisory (published 2026-06-20) in a transitive mmap dependency that only enters the tree with thelocal-classifierfeature. Lockfile-only;cargo deny checkis clean (advisories/bans/licenses/sources all ok).rustls0.23.40 → 0.23.41 andbytes1.11.1 → 1.12.0. Routine backward-compatible dependency maintenance.
Added
- Execution Gate can now enforce around just the AI agent (agent-scoped mode, spec 083 eBPF primitive). The Execution Gate is a path-exact allowlist enforced in the kernel; host-wide it fits a locked-down appliance, but a general-purpose server constantly execs legitimate new/transient binaries (
dpkg/aptmaintainer scripts,certbotrenewals, dynamic container workloads), so a host-wide allowlist would block them. New opt-in cgroup scoping lets the gate enforce solely inside the AI agent's process tree and allow everything else unconditionally — "zero-trust for the agent" without touching the rest of the machine. New pinned mapEXEC_GATE_SCOPE(/sys/fs/bpf/innerwarden/exec_gate_scope, cgroup id → 1) holds the agent's cgroup id(s); the gate consultsLSM_POLICYkey 4: when1,try_exec_gatefires only for tasks whose current cgroup id is inEXEC_GATE_SCOPEand allows every other exec. Key 4 absent/0 = host-wide, the original behaviour, so this is opt-in with no regression. The scope map isrepin_preservingso it survives sensor restart; empty-while-scoped is fail-open (the gate never fires), so a wipe is not a brick. Free + INERT in the OSS sensor (key 4 unset); the paidconfig-signtooling populates the scope and flips key 4. Verifier-cheap: one map read plus, when scoped, onebpf_get_current_cgroup_idlookup, both patterns already used in the gate hook. eBPF program count unchanged (a new map, not a new program). - Mesh-VPN persistence detection is now rename-proof (behavioural TUN/WireGuard signal). The previous exec-name detector (
tailscale/zerotier/…) could be evaded by renaming the binary. Newtunnel_ifacecollector (collector #31) watches/sys/class/netfor a new tun/WireGuard interface appearing at runtime and classifies by the kernel-set TYPE (uevent: DEVTYPE=wireguardor thetun_flagsattribute), not the name — so a renamed mesh-VPN binary is still caught, because the tunnel still has to create atun/wginterface to route traffic. Interfaces present at startup are baselined (the operator's own VPN), so only a tunnel that comes up later fires. Thec2_web_tunneldetector promotes the event to a High, allowlistable ([detectors.c2_web_tunnel]) incident with the same dual-use framing ("legitimate if you started a VPN — allowlist it; if not, it is attacker persistence", T1572/T1219). On by default (AlwaysOnCollectorConfig), 30s poll, deduped on the 600s cooldown. New unit tests pin: WireGuard caught byDEVTYPEeven under a non-tunnel name, TUN caught bytun_flags, plain interfaces ignored, and the Highmesh_vpn_ifaceincident. Closes the rename-evasion follow-up tracked when the exec-name detector shipped. innerwarden playbook test --insecure. The agent dashboard serves HTTPS with a self-signed certificate, soinnerwarden playbook test --url https://127.0.0.1:8787 …failed withinvalid peer certificate: UnknownIssuerand the command could not reach its own agent. The new--insecureflag skips TLS verification for the self-signed cert (documented as not-for-untrusted-networks), so the dry-run playbook test works against the live HTTPS dashboard. Unit-tested for both the verifying and insecure agent-construction paths.- n8n integration recipe for the Agent Guard API (docs). New
docs/integration-recipes/n8n-agent-guard.mdshows how to drive the existing
GET /api/agent/security-context(threat assessment) and
POST /api/agent/check-command(safety validation) endpoints from an n8n
workflow: HTTP Request node configuration for each endpoint, the request/response shapes
and recommendation thresholds (allow/review/deny), and a complete importable
workflow JSON that halts automatically when the server threat level is elevated or a
command is denied. Documentation-only — no code or behaviour change. Closes the n8n gap
noted alongside the existing OpenClaw guide; linked fromintegrations/README.md. - Mesh / overlay-VPN remote-access tools are now detected as a persistence channel (Tailscale, ZeroTier, NetBird, Nebula). Closes a real gap: an attacker who lands on a host can install a mesh VPN (
tailscale/tailscaled,zerotier-one/zerotier-cli,netbird,nebula) and SSH back in over the encrypted, NAT-traversing tunnel — stable persistent access that looks like ordinary infrastructure (T1572 protocol tunneling / T1219 remote-access software). Ngrok/Cloudflare/bore/frp/chisel were already covered byc2_web_tunnel; the mesh-VPN family was not. The detector now fires on exec of a known mesh-VPN binary. UX-safe by design because these tools are commonly legitimate: fired at High (not Critical, unlike the C2 tunnels) so it never auto-blocks on its own, exec-only (no coordination-DNS matching, which would be noisy on hosts that legitimately run a mesh VPN), deduped on a 600s cooldown, and allowlistable via[detectors.c2_web_tunnel]; the incident text says plainly "LEGITIMATE if you use it for admin access — allowlist it; if you did NOT install it, it is a common attacker-persistence channel." Anti-gap, honestly scoped: the match is on the exact argv0 basename, so a renamed mesh-VPN binary evades exec-name detection — that limitation is documented in the detector and tracked as a behavioural TUN/WireGuard follow-up (the tunnel still has to create atun/wginterface, which is the rename-proof signal). New unit tests pin: mesh binaries fire High with sub_kindmesh_vpn, the existing tunnel binaries stay Critical, substring/unrelated binaries stay quiet, and repeat execs are deduped. Detector count unchanged (82 — extends the existingc2_web_tunnel).
Fixed
- KG decide-modifier (spec 043) is no longer inert — it now measures entity tenure with a clock that survives restarts. The Knowledge-Graph confidence modifier was sitting at
modifier_raw=0.0on essentially every incident in production, so it never did its job (suppressing false positives on long-tenured benign IPs) and could never accumulate the "non-zerowould_change_action" data its own promotion gate requires. Root cause: its useful benign-suppression bands gate onfirst_seen_age_days >= 7, but it readfirst_seenfrom the in-memory KG IP node, which is rebuilt from a dated, daily graph snapshot and effectively resets across days/restarts — so the age gate was unreachable. Fix:merge_persisted_profilenow overlays the persisted attacker-intel profile (loaded from redb on boot, carrying the true first sighting + composite risk) onto the KG features, taking the OLDER age and HIGHER risk. This makes the age-gated benign bands reachable for genuinely long-lived IPs and keeps the repeat-offender band honest, with no detection weakening (the merge only lengthens tenure / raises risk, never the reverse). Still shadow mode by default — it now produces real signal to validate before any operator flips it toenforce. New unit tests pin the unlock and the never-weakens invariant. - InnerWarden no longer flags its OWN egress as a reverse shell (self-FP). The eBPF reverse-shell sequence detector (
network.outbound_connect+process.fd_redirect/dup2 within a window, per PID) fired Criticalebpf_reverse_shellincidents on the agent's and CLI's own legitimate outbound connections — Telegram notifications (149.154.166.x), the dashboard API, threat-feed polling — because the agent connects out and dup2's fds in the same process. Observed as ~126 Critical self-flags in 30 minutes on a test box (source comminnerwarden-age/innerwarden); pure noise (it did not auto-block) but it spammed incidents and polluted measurements. Now the sequence detector skips a verified InnerWarden self-process, gated byis_verified_infra_process— i.e. the comm matchesinnerwarden*AND/proc/<pid>/exeresolves to a real system path. No blind spot: a process that merely setscomm=innerwarden-*but whose exe is/tmp(or anywhere non-system) still fires. Verified via the reliable connect-time comm, so skipping the connect also prevents a later corrupted-comm fd_redirect from firing. Regression tests pin both the self-skip and the forged-comm-still-fires case.
Install / upgrade (Linux, toolchain-free, signed binaries)
curl -fsSL https://innerwarden.com/install | sudo bash
# already installed: sudo innerwarden upgrade --yesEvery binary below is signed (Ed25519 + Sigstore bundle). Docs: https://github.com/InnerWarden/innerwarden/wiki · Site: https://www.innerwarden.com
What's Changed
- fix(sensor): stop InnerWarden flagging its own egress as a reverse shell by @maiconburn in #1097
- feat(sensor): detect mesh/overlay-VPN persistence (tailscale/zerotier/netbird/nebula) by @maiconburn in #1098
- test(sensor): cover journald collector command and cursor branches by @GordonYuanyc in #1096
- docs(readme): clarity pass for the top screen (virality + comprehension) by @maiconburn in #1099
- docs(readme): remove the inline demo video embed by @maiconburn in #1100
- docs(readme): drop deprecated fail2ban-integration from modules + scan by @maiconburn in #1105
- build(deps): bump rustls 0.23.41 + bytes 1.12.0 (unified) by @maiconburn in #1104
- build(deps): bump quinn-proto 0.11.15 (fixes RUSTSEC-2026-0185) by @maiconburn in #1107
- docs: add n8n integration recipe for Agent Guard API by @Posterfo in #1106
- feat(ctl): playbook test --insecure for the self-signed dashboard by @maiconburn in #1109
- feat(sensor): rename-proof mesh-VPN detection (tunnel-interface monitor) by @maiconburn in #1110
- fix(agent): KG decide-modifier reads persisted tenure (spec 043, un-inert) by @maiconburn in #1111
- docs(readme): dedupe the middle (Watches/Detects walls) by @maiconburn in #1112
- feat(sensor): agent-scoped Execution Gate (spec 083, eBPF primitive) by @maiconburn in #1113
- release: 0.15.25 by @maiconburn in #1108
New Contributors
- @GordonYuanyc made their first contribution in #1096
- @Posterfo made their first contribution in #1106
Full Changelog: v0.15.24...v0.15.25