InnerWarden/innerwarden
Local safety layer for AI agents that use the terminal. Screens risky commands and MCP/tool calls, watches Linux activity with eBPF, blocks dangerous behavior, and keeps audit trails local. Open source, self-hosted, dry-run by default.
✨ Added
- The agent-guard command inspector now flags attempts to disable InnerWarden itself (in-path self-protection). The `check-command` brain (`POST /api/agent/check-command`, the MCP `innerwarden_check_command` tool, and the `agent proxy` guard) previously scored commands like `systemctl stop innerwarden-*`, `pkill -f innerwarden`, `innerwarden uninstall`, and `rm`/`truncate` of InnerWarden's own binaries, config, data, or pinned eBPF objects as `allow` / risk 0 - so an AI coding agent wired through the in-path guardrail could be talked into turning the monitor off without the guard objecting. A new `security_tooling_tamper` signal (score 60 -> `deny`) in `crates/agent-guard` (`threats::check_security_tamper` + `SECURITY_TAMPER_INDICATORS` / `INNERWARDEN_SELF_PATHS`) now denies InnerWarden self-disable/removal plus the universal defense-evasion verbs (`systemctl stop auditd`, `setenforce 0`, `auditctl -e 0`, disabling AppArmor; MITRE T1562/T1489). File removal requires a destructive verb AND an InnerWarden path, so status reads and restarts (`innerwarden get status`, `systemctl status`/`restart innerwarden-agent`, grepping a config under `/etc/innerwarden`) are NOT flagged. Closes the command-layer half of the self-tamper gap surfaced by the 2026-06-27 AI-coding-agent guardrail evaluation (the kernel-side `mitre_hunt` uid-0 self-stop carve-out is tracked separately). New unit tests pin deny on the tamper set, deny on the host-monitor set, and allow on the benign reads/restart.
- `innerwarden agent install-hook` wires the in-path command guard into Claude Code (enforcing, not advisory). `agent mcp-serve` and `POST /api/agent/check-command` are advisory - a coding agent running its raw shell tool never asks. The new command writes a fail-closed guard script plus a PreToolUse `Bash` hook into the agent's `settings.json` (`~/.claude/settings.json` by default; `--settings`/`--url`/`--block-review` override), so every shell command the agent proposes is POSTed to the loopback `check-command` brain and blocked (exit 2) before it runs when the verdict is `deny` (or `review` with `--block-review`), failing CLOSED if the agent is unreachable. The settings merge is idempotent and preserves existing keys/hooks. Currently supports Claude Code. Unit-tested: the JSON merge (empty / idempotent / preserves existing / repairs a non-object root) and the generated script (deny-only vs block-review, the check-command call, fail-closed on error).
🐛 Fixed
- The admin-action audit log was stamped with local time, drifting off the UTC date scheme. `append_admin_action` named `admin-actions-<date>.jsonl` from `chrono::Local::now()`, while every other date-stamped file InnerWarden writes (`events-`/`incidents-`/`decisions-*.jsonl`) and the reader (`today_date_string`) use UTC. In a non-UTC timezone straddling midnight (e.g. UK/BST after 00:00 local, still the previous UTC day) the audit entry landed on a different date than the rest of the system, splitting the day's audit trail and breaking the reader plus the `cmd_tune` audit test on that boundary. Now UTC, consistent with the rest of the date-stamped files.
- The correlation-chain block path bypassed the cloud safelist and banned Canonical on Hetzner (cloud-FP sweep follow-up). Two sibling response paths gate a candidate IP against the cloud/CDN safelist before escalating: the repeat-offender path and the completed-correlation-chain path. The repeat-offender path was switched from `identify_provider` (a first-octet heuristic that only knows a handful of broad ranges) to `cloud_safelist::safelist_label` (the real CIDR walk) on 2026-05-08, but the chain path was missed and still used the heuristic. Result: the `Data Exfiltration (eBPF Sequence)` chain (CL-008-class) banned Canonical `185.125.190.49` (apt/livepatch) on Hetzner, because `185.125.188.0/22` is in the safelist's CIDR table but the first-octet heuristic does not know `185.x`. Both paths now route through one shared `safelisted_provider` helper (a thin wrapper over `safelist_label`), so the gate cannot drift between them again. Anti-evasion preserved: the safelist is the existing CIDR table (no new IP hardcoded), and a real attacker IP outside every safelist range (`203.0.113.45`, `45.148.10.121`) is still blockable by both paths. A new `#[tokio::test]` drives both async paths end-to-end with a CIDR-only safelisted IP and asserts each purges it from reputation state instead of escalating.
- ---
📦 Install / upgrade (Linux, toolchain-free, signed binaries)
- ```bash
- curl -fsSL https://innerwarden.com/install | sudo bash
- ```
- Every binary below is signed (Ed25519 + Sigstore bundle). Docs: <https://github.com/InnerWarden/innerwarden/wiki> · Site: <https://www.innerwarden.com>
📋 What's Changed
- fix(agent): correlation-chain block path bypassed cloud_safelist (banned Canonical) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1125
- docs(changelog): record #1125 correlation-chain safelist-bypass under Unreleased by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1126
- feat(agent-guard): deny commands that disable InnerWarden itself by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1127
- fix(core): stamp admin-action audit filename in UTC, not local time by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1128
- feat(ctl): innerwarden agent install-hook — enforce the guard in Claude Code by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1129
- release: 0.15.30 — AI-agent guardrail self-protection + audit UTC fix by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1132
- Full Changelog: https://github.com/InnerWarden/innerwarden/compare/v0.15.29...v0.15.30
🐛 Fixed
- execve events never carried the parent PID in-kernel, leaving the fileless-systemd false-positive gate (0.15.28) inert in production. The 0.15.28 post-deploy re-audit found `fileless:systemd` still firing on Azure. Root cause: the eBPF execve handler hardcoded `event.ppid = 0`, so every execve `ppid` came from a userspace `/proc/<pid>/status` fallback. That works for long-lived processes (it is why `connect` events have a parent) but misses short-lived ones, notably systemd's sealed-executor `fexecve` of `/proc/self/fd/N` whose `/proc` entry is gone before the ring reader can read it (the audit measured `ppid=0` on 4995/5000 execve events). Because the 0.15.28 fileless-systemd parent-lineage gate needs the parent, it almost never engaged in prod. The fix reads `task_struct->real_parent->tgid` in-kernel at execve, mirroring the Execution Gate's `BPRM_OFFSETS` pattern: a new `TASK_OFFSETS` map (`real_parent` + `tgid` byte offsets) is populated by the userspace loader from kernel BTF (`member_offset`), and the handler does two bounded `bpf_probe_read_kernel` hops. If BTF is unavailable the offsets stay 0, the handler returns 0, and the `/proc` fallback applies unchanged (it never reads a guessed offset). Validated live on a 6.x x86_64 kernel: the verifier accepts the program, the offsets resolve from BTF, and a `comm=systemd` `fexecve` of `/proc/self/fd/N` now reports `ppid=1`, so the gate resolves `/proc/1/exe` to systemd and suppresses the false positive. aarch64 offsets are BTF-resolved identically.
- ---
📦 Install / upgrade (Linux, toolchain-free, signed binaries)
- ```bash
- curl -fsSL https://innerwarden.com/install | sudo bash
- ```
- Every binary below is signed (Ed25519 + Sigstore bundle). Docs: <https://github.com/InnerWarden/innerwarden/wiki> · Site: <https://www.innerwarden.com>
📋 What's Changed
- fix(sensor): capture execve parent PID in-kernel so the fileless-systemd gate works by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1123
- release: 0.15.29 (eBPF execve parent-PID capture) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1124
- Full Changelog: https://github.com/InnerWarden/innerwarden/compare/v0.15.28...v0.15.29
🐛 Fixed
- `fileless:systemd` flooded Critical on every unit start (Azure: 1206 Critical/week, all `comm=systemd`). systemd v254+ copies `systemd-executor` into a sealed memfd and `fexecve`s it via `/proc/self/fd/N` at the start of every unit, which the fileless detector read as in-memory malware execution. The exec event carries no `exe_path`, so the fix resolves the launching process's parent via `/proc/<ppid>/exe` (the kernel symlink, which `prctl(PR_SET_NAME)`/`argv[0]` cannot forge) and suppresses only the self-fd `fexecve` form launched by a systemd manager. Anti-evasion preserved: `/memfd:`, `/dev/fd/`, `(deleted)`, `/proc/<other-pid>/fd/`, and any non-systemd parent (a shell/dropper running `exec /proc/self/fd/N`) still fire; an unresolvable parent fails safe to firing; the memfd payload is still caught at creation by `kernel_promote`.
- Cloud guest agents tripped C2 / flood / IMDS-SSRF detectors, auto-blocking the platform control plane. A cloud VM's management agents (Azure WALinuxAgent, AWS SSM agent / cloud-init, GCP guest agent, OCI cloud agent) poll the platform control plane (WireServer, IMDS) often enough to look like C2 beaconing, connection floods, and IMDS access by an unexpected process. On Azure this fed a cross-layer correlation that auto-blocked the WireServer management IP `168.63.129.16` six times (a block that can sever the VM from its management plane), and produced 869 IMDS needs-review incidents. New `crates/sensor/src/cloud_platform.rs` (a crate-root helper, not a detector) recognises the platform's agents by non-forgeable process identity: the cloud is auto-detected from DMI/SMBIOS (firmware strings, not anything userspace can forge); a compiled agent is matched by its real `/proc/<pid>/exe`; an interpreter agent (`python3 /usr/sbin/waagent`, `cloud-init`) is trusted only when its script argument is a known agent path that exists on disk as a root-owned file under a trusted system directory; and extension-handler children (relative script path) are matched by walking up to four parent hops to the real agent. `is_guest_agent(pid, uid)` is gated on a recognised cloud VM AND `uid 0`, and is used downgrade-only in `c2_callback`, `outbound_anomaly`, and `imds_ssrf` (the interpreter case its exe-prefix list missed). Anti-evasion (tested): an `argv` that merely names a guest-agent path without the file being root-owned, a trusted interpreter running a `/tmp` script, an untrusted interpreter, a planted look-alike path, on-prem Hyper-V (not Azure), bare metal, a non-root process, and a webserver runtime hitting IMDS all still fire. The WireServer actor was the Azure guest agent (`python3 -u /usr/sbin/waagent`), not the co-located AI agent.
- `dns_tunneling` flagged Azure platform service DNS as high-entropy tunneling (Azure: 667/667 false positives). The host resolving Azure Storage / SQL / Service Bus / Key Vault FQDNs (`<resource>.blob.core.windows.net`, `<vault>.vault.azure.net`) tripped the Shannon-entropy heuristic on the random-looking resource name. The existing `DNS_ALLOWED_DOMAINS` allowlist (already covering provider-controlled zones like `oraclevcn.com`, `internal.cloudapp.net`, `azure.com`, `amazonaws.com`, `googleapis.com`) was simply missing the Azure service zones; `windows.net` and `azure.net` are added. This is a domain allowlist, not an IP one: Microsoft controls these zones and does not delegate arbitrary subdomains, so a DNS tunnel cannot be built under them. Anti-evasion preserved: the dot-boundary match means `evil-windows.net` is not trusted, and tunneling through an attacker-controlled zone still fires.
- ---
📦 Install / upgrade (Linux, toolchain-free, signed binaries)
- ```bash
- curl -fsSL https://innerwarden.com/install | sudo bash
- ```
- Every binary below is signed (Ed25519 + Sigstore bundle). Docs: <https://github.com/InnerWarden/innerwarden/wiki> · Site: <https://www.innerwarden.com>
📋 What's Changed
- fix(sensor): suppress fileless FP from systemd sealed-executor unit launch by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1119
- fix(sensor): cloud-platform guest-agent provenance (non-IP) for WireServer/IMDS FPs by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1120
- fix(sensor): allowlist Azure platform service DNS zones (windows.net, azure.net) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1121
- release: 0.15.28 (Azure cloud-platform false-positive sweep) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1122
- Full Changelog: https://github.com/InnerWarden/innerwarden/compare/v0.15.27...v0.15.28
🐛 Fixed
- `memfd_create` fileless-execution false positives on legitimate tools (prod 7-day audit). The `kernel:memfd_fileless` detector fired 17 High incidents in a week on benign memfd users: `fwupdmgr` (firmware updater), systemd's `(sd-executor)`, and `tokio-rt-worker` (a generic Rust async-runtime thread name: InnerWarden's own agent and any other Rust service). The first two are added to the curated `comm` allowlist, but the Rust-runtime case is fixed the non-forgeable way, not by allowlisting a generic thread name (which any Rust payload could wear): a new third FP layer clears a memfd only when the creating process's kernel-captured exe path (`details.exe_path`, the `execve` filename) lives under a package-managed system directory (`path_trust::is_trusted_system_path`, the single source of truth now shared with `host_drift`). Anti-evasion preserved: a payload running from `/tmp`, with a deleted backing file (`(deleted)`), or memfd-backed exec is explicitly NOT trusted and still promotes, and the `fexecve`-from-memfd follow-up stays in the recommended checks. New tests pin the FP fixes AND the evasion cases (untrusted/deleted/`memfd:` exe paths still fire), plus a cross-test that `host_drift` and `kernel_promote` agree on what "trusted" means.
- Cloud-range safelist could free-pass an AbuseIPDB-confirmed attacker (Context Gate blind spot). The 7-day audit found the Warden classifier `ignore`-ing IPs marked `safelist=Google Cloud, abuseipdb=100`: a cloud-range safelist was burying a community-confirmed attacker, exactly the free pass an attacker buys by renting cloud. The deterministic Context Gate now reads the existing `ip_reputation` (AbuseIPDB) and, escalate-only (identical shape to the DShield signal), refuses to passively close (dismiss/ignore) an incident whose IP scores `>= 90/100`, and blocks the provenance-driven benign-dismiss for such IPs. It can only ever raise a weak passive close to a surface (Monitor / RequestConfirmation), never relax an enforcement verdict, so a noisy shared-cloud IP at this score is at worst Monitored, never auto-blocked. The high floor avoids flooding the operator on borderline scores. New tests pin: confirmed-attacker passive close is surfaced, an enforcement verdict is left intact, a below-floor score is unchanged, the provenance self-dismiss is refused for a confirmed attacker, and the no-reputation path is unchanged.
- `innerwarden upgrade` now arch-smoke-tests a new binary before swapping it in. sha256 + signature prove the downloaded bytes are authentic but NOT that they execute on this host's CPU; installing an x86_64 build on the aarch64 prod box took it down on 2026-06-10. The upgrader now stages each verified binary into the install directory (a package-trusted path, so the host's own `host_drift` detector does not flag the check the way a `/tmp` exec would, which is what produced the self-inflicted Critical `host_drift` incidents seen in the audit during the manual aarch64 deploy ritual) and runs `--version`. It hard-fails and keeps the existing binary only when the binary cannot execute (spawn failure / killed by signal, the wrong-CPU-arch / corruption case); a clean non-zero exit or a cosmetic version-string mismatch is a soft warning that proceeds, so upgrades never break on anything but a genuinely non-runnable asset. This retires the manual "`file` + `./bin --version` in /tmp before swap" procedure by doing it in-product. The smoke-test verdict logic is a pure, fully unit-tested function.
- ---
📦 Install / upgrade (Linux, toolchain-free, signed binaries)
- ```bash
- curl -fsSL https://innerwarden.com/install | sudo bash
- ```
- Every binary below is signed (Ed25519 + Sigstore bundle). Docs: <https://github.com/InnerWarden/innerwarden/wiki> · Site: <https://www.innerwarden.com>
📋 What's Changed
- fix: prod-audit fixes (memfd FP, AbuseIPDB cloud-safelist blind spot, upgrade arch smoke-test) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1117
- release: 0.15.27 by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1118
- Full Changelog: https://github.com/InnerWarden/innerwarden/compare/v0.15.26...v0.15.27
📋 Changed
- DShield (SANS ISC) reputation is now a real decision signal on the Warden classifier path, not just LLM context. DShield enrichment already attached the community's global attack history to attacker profiles and fed the LLM prompt, but the on-device Warden classifier and its deterministic Context Gate ignored it. The gate now reads a structured `ip_dshield_attacker` signal (`DshieldReputation::is_known_attacker`: ISC reports > 0 or active threat-feed membership) and, escalate-only, (1) refuses to passively close (dismiss/ignore) an incident from a DShield-confirmed global attacker, surfacing it instead, and (2) blocks the provenance-driven benign-dismiss for such IPs. It can only ever raise a weak verdict, never relax an enforcement action. The trained classifier's text input is intentionally not changed (novel input is out-of-distribution; enriching the model input is the separate re-distill path), so the model's behaviour is unchanged; DShield acts deterministically in the gate that wraps it. New unit tests pin: a confirmed attacker's confident dismiss is surfaced, an enforcement verdict is left intact, and a non-DShield low-severity dismiss is unchanged.
🐛 Fixed
- Installer no longer sends the telemetry ping from CI / automation. Installer smoke-tests run on ephemeral CI runners (GitHub Actions and friends), each a fresh machine-id from a US x86_64 box, so every run was writing an `install` row into the opt-out install telemetry, inflating the install count with non-users (most of a given window's "installs" were our own CI). `install.sh` now detects a CI environment (`CI=true/1`, or any of `GITHUB_ACTIONS`/`GITLAB_CI`/`JENKINS_URL`/`BUILDKITE`/`CIRCLECI`/`TF_BUILD`/`TEAMCITY_VERSION`/`DRONE`) and skips the ping (logging that it did). The install itself still runs and is still verified in CI; only the ping is suppressed, so the telemetry reflects real installs. `CI=false` (some dev shells) is correctly treated as not-CI.
- ---
📦 Install / upgrade (Linux, toolchain-free, signed binaries)
- ```bash
- curl -fsSL https://innerwarden.com/install | sudo bash
- ```
- Every binary below is signed (Ed25519 + Sigstore bundle). Docs: <https://github.com/InnerWarden/innerwarden/wiki> · Site: <https://www.innerwarden.com>
📋 What's Changed
- fix(install): skip telemetry ping in CI / automation by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1114
- feat(agent): DShield reputation as a decision signal in the Context Gate by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1115
- release: 0.15.26 by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1116
- Full Changelog: https://github.com/InnerWarden/innerwarden/compare/v0.15.25...v0.15.26
🔒 Security
- `quinn-proto` 0.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 unrelated `tract-onnx` 0.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).
- `memmap2` 0.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 the `local-classifier` feature. Lockfile-only; `cargo deny check` is clean (advisories/bans/licenses/sources all ok).
- `rustls` 0.23.40 → 0.23.41 and `bytes` 1.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`/`apt` maintainer scripts, `certbot` renewals, 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 map `EXEC_GATE_SCOPE` (`/sys/fs/bpf/innerwarden/exec_gate_scope`, cgroup id → 1) holds the agent's cgroup id(s); the gate consults `LSM_POLICY` key 4: when `1`, `try_exec_gate` fires only for tasks whose current cgroup id is in `EXEC_GATE_SCOPE` and allows every other exec. Key 4 absent/0 = host-wide, the original behaviour, so this is opt-in with no regression. The scope map is `repin_preserving` so 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 paid `config-sign` tooling populates the scope and flips key 4. Verifier-cheap: one map read plus, when scoped, one `bpf_get_current_cgroup_id` lookup, 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. New `tunnel_iface` collector (collector #31) watches `/sys/class/net` for a *new* tun/WireGuard interface appearing at runtime and classifies by the kernel-set TYPE (`uevent: DEVTYPE=wireguard` or the `tun_flags` attribute), not the name — so a renamed mesh-VPN binary is still caught, because the tunnel still has to create a `tun`/`wg` interface to route traffic. Interfaces present at startup are baselined (the operator's own VPN), so only a tunnel that comes up *later* fires. The `c2_web_tunnel` detector 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 by `DEVTYPE` even under a non-tunnel name, TUN caught by `tun_flags`, plain interfaces ignored, and the High `mesh_vpn_iface` incident. 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, so `innerwarden playbook test --url https://127.0.0.1:8787 …` failed with `invalid peer certificate: UnknownIssuer` and the command could not reach its own agent. The new `--insecure` flag 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.md` shows how to drive the existing
- `GET /api/agent/security-context` (threat assessment) and
- `POST /api/agent/check-command` (safety validation) endpoints from an [n8n](https://n8n.io/)
- workflow: HTTP Request node configuration for each endpoint, the request/response shapes
- + 5 more
🐛 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.0` on 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-zero `would_change_action`" data its own promotion gate requires. Root cause: its useful benign-suppression bands gate on `first_seen_age_days >= 7`, but it read `first_seen` from 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_profile` now 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 to `enforce`. 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 Critical `ebpf_reverse_shell` incidents 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 comm `innerwarden-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 by `is_verified_infra_process` — i.e. the comm matches `innerwarden*` AND `/proc/<pid>/exe` resolves to a real system path. No blind spot: a process that merely sets `comm=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)
- ```bash
- curl -fsSL https://innerwarden.com/install | sudo bash
- ```
- Every 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 https://github.com/InnerWarden/innerwarden/pull/1097
- feat(sensor): detect mesh/overlay-VPN persistence (tailscale/zerotier/netbird/nebula) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1098
- test(sensor): cover journald collector command and cursor branches by @GordonYuanyc in https://github.com/InnerWarden/innerwarden/pull/1096
- docs(readme): clarity pass for the top screen (virality + comprehension) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1099
- docs(readme): remove the inline demo video embed by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1100
- docs(readme): drop deprecated fail2ban-integration from modules + scan by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1105
- build(deps): bump rustls 0.23.41 + bytes 1.12.0 (unified) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1104
- build(deps): bump quinn-proto 0.11.15 (fixes RUSTSEC-2026-0185) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1107
- + 7 more
✨ New Contributors
- @GordonYuanyc made their first contribution in https://github.com/InnerWarden/innerwarden/pull/1096
- @Posterfo made their first contribution in https://github.com/InnerWarden/innerwarden/pull/1106
- Full Changelog: https://github.com/InnerWarden/innerwarden/compare/v0.15.24...v0.15.25
🔒 Security
- spec-081 managed-agent coexistence now works when InnerWarden runs non-root and the agent runs as another user (live FP fix, found 2026-06-21). A co-located AI agent (OpenClaw) doing a routine task — read its own `/home/lab/.env`, then call its own Azure-OpenAI endpoint — was flagged CRITICAL data-exfiltration and the endpoint was auto-blocked, breaking the agent. Root cause: the managed-agent verifier (`evaluate_managed_agent_downgrade` → `decide`) fail-closed on two facts a non-root IW agent (`innerwarden` uid) cannot obtain about a process owned by a different user (`lab`): (1) `readlink /proc/<pid>/exe` is EACCES cross-uid → `exe_path` None → the interpreter-root gate blocked; (2) `ProtectHome=yes` on the agent unit hid `/home`, so the own-config `stat` for the file-owner uid returned None → the own-config gate blocked. Both made spec-081 silently never downgrade for a cross-user agent, even one correctly registered with a matching cmdline fingerprint. Fixes: (a) code — when `/proc/exe` is unreadable the interpreter-root check falls back to `argv[0]`, safe because the exact registered cmdline-fingerprint match already pins identity (an untrusted `argv[0]` like `/tmp/node` still blocks); (b) ops — the example agent unit sets `ProtectHome=read-only` (so the verifier can read /home to confirm the agent's own config) with an optional `CAP_SYS_PTRACE` for strict `/proc/exe` verification. No blind spot: a foreign-secret read (`/etc/shadow`, another user's `~/.ssh`), an unregistered/fingerprint-mismatched process, or a known-bad destination still forces the block. New regression tests pin the cross-uid downgrade + the untrusted-argv0 block.
- ---
📦 Install / upgrade (Linux, toolchain-free, signed binaries)
- ```bash
- curl -fsSL https://innerwarden.com/install | sudo bash
- ```
- Every binary below is signed (Ed25519 + Sigstore bundle). Docs: <https://github.com/InnerWarden/innerwarden/wiki> · Site: <https://www.innerwarden.com>
📋 What's Changed
- security(agent): fix spec-081 managed-agent coexistence for cross-uid / non-root IW by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1094
- release: 0.15.24 by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1095
- Full Changelog: https://github.com/InnerWarden/innerwarden/compare/v0.15.23...v0.15.24
🐛 Fixed
- `innerwarden upgrade` now retries transient asset/sidecar download failures. Right after a release, GitHub's asset CDN intermittently fails individual binary or sidecar (`.sha256`/`.sig`) downloads while it propagates the new release. The old code aborted on the first such failure, which made `upgrade` brittle in exactly that window — deploying 0.15.22, two consecutive runs on one box each failed on a *different* sidecar before a manual `curl --retry` deploy succeeded. The binary download and both sidecar fetches now retry (4 attempts, 3s apart); a binary retry re-creates the destination so a partial download is never kept. Retry policy is a pure, unit-tested helper.
- ---
📦 Install / upgrade (Linux, toolchain-free, signed binaries)
- ```bash
- curl -fsSL https://innerwarden.com/install | sudo bash
- ```
- Every binary below is signed (Ed25519 + Sigstore bundle). Docs: <https://github.com/InnerWarden/innerwarden/wiki> · Site: <https://www.innerwarden.com>
📋 What's Changed
- ci: auto-announce releases to your own channels on publish by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1091
- fix(ctl): retry transient asset/sidecar downloads in innerwarden upgrade by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1092
- release: 0.15.23 by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1093
- Full Changelog: https://github.com/InnerWarden/innerwarden/compare/v0.15.22...v0.15.23
🐛 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)
- ```bash
- curl -fsSL https://innerwarden.com/install | sudo bash
- ```
- 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 https://github.com/InnerWarden/innerwarden/pull/1088
- fix(ctl): make innerwarden upgrade watchdog-aware (one-command upgrade on prod) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1089
- release: 0.15.22 by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1090
- Full Changelog: https://github.com/InnerWarden/innerwarden/compare/v0.15.21...v0.15.22
📋 What's Changed
- feat(live-feed): specific sanitized titles for the genericized detectors by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1080
- feat(allowlist): config-driven self_infra_ips to keep own boxes out of the feeds by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1081
- fix(guardrail): close the FP and miss found by the guardrail benchmark by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1082
- fix(sensor): catch crontab reinstall + world-writable chmod (atomic-bench findings) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1083
- security(sensor-ebpf): surface credential reads dropped by the openat allowlist (atomic-bench) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1084
- security(sensor): close io_uring comm-spoof + SUID fixed-scope evasions (audit E5/E6) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1085
- security(sensor-ebpf): close credential-read + IMDS forgeable-comm evasions (audit E1/P1) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1086
- release: 0.15.21 by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1087
- + 1 more
📋 What's Changed
- build(deps): bump tract-onnx from 0.22.2 to 0.22.3 in the cargo group across 1 directory by @dependabot[bot] in https://github.com/InnerWarden/innerwarden/pull/1076
- feat(docs): agent-native install/operate guide (spec 082 phase 1) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1077
- feat(ctl): innerwarden agent mcp-serve, an MCP server over the loopback brain (spec 082 phase 2A) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1078
- release: 0.15.20 by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1079
- Full Changelog: https://github.com/InnerWarden/innerwarden/compare/v0.15.19...v0.15.20
📋 What's Changed
- feat(agent-guard): auto-register + prune co-located agents (spec-081 survives restarts) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1064
- fix(spec-081): own-config gate on the kernel-block path (close LPE divergence) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1065
- fix(notifications): Telegram alerts + action reports name the server by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1066
- fix(scenario-qa): wait for incident count to quiesce (stop the 02-coordinated flake) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1067
- fix(ctl): de-flake serve_drives_the_proxy_over_pipes (cat block-buffering) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1068
- fix(replay-qa): quiesce-wait the sensor on event count before SIGINT by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1069
- fix(telegram): record FP on quick-ignore + usage for bare /enable /disable by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1070
- feat(telegram): actuate guardian mode from the phone (/mode, 2FA-gated) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1071
- + 5 more
📋 What's Changed
- feat(notify): burst summary names the server + explains the attack by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1061
- feat(briefing): accurate, explained daily report in InnerWarden's voice by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1062
- release: 0.15.18 by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1063
- Full Changelog: https://github.com/InnerWarden/innerwarden/compare/v0.15.17...v0.15.18
📋 What's Changed
- fix(agent): managed-agent verifier resolves a real agent-connect-registered agent by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1059
- release: 0.15.17 by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1060
- Full Changelog: https://github.com/InnerWarden/innerwarden/compare/v0.15.16...v0.15.17
📋 What's Changed
- ci(release): stop macOS thread-cap flake blocking the binary publish by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1056
- feat(agent): spec 081 — stop severing a co-located IW-managed AI agent (no-hole) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1057
- release: 0.15.16 by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1058
- Full Changelog: https://github.com/InnerWarden/innerwarden/compare/v0.15.15...v0.15.16
📋 What's Changed
- ci(release): fix macOS release thread exhaustion (raise ulimit -u, not -n) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1051
- feat(agent): DNS Guard intel bridge — export malicious-domain intel to the denylist by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1052
- feat(agent): ingest DNS Guard block events as incidents — close the visible loop by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1053
- fix(agent): DNS Guard export cleans hosts-file feed entries (field-found) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1054
- release: 0.15.15 by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1055
- Full Changelog: https://github.com/InnerWarden/innerwarden/compare/v0.15.14...v0.15.15
📋 What's Changed
- fix(sensor): exfil detector no longer flags source/node_modules files by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1019
- fix(agent): stop notifying dismissed/ignored incidents by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1020
- refactor(agent): unified chat-channel registry (spec 078 P1) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1021
- refactor(agent): action reports + summaries via chat-channel registry (spec 078 P2) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1022
- feat(agent): Discord notification channel (spec 078 P3) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1028
- feat(ctl,agent): notify discord command + dashboard card (spec 078 P3b) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1029
- build(deps): batch dependency updates (chrono, regex, russh, tower-http) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1030
- feat(ctl): Discord in the setup wizard (spec 078 P3c) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1031
- + 18 more
📋 What's Changed
- ci: pin actions/checkout SHA (#190/#191) + fix macOS release test flake by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1006
- ctl test/UX: de-flake agent_proxy pipe test + silence macOS-xattr tar noise on model extract by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1007
- fix(ctl): make Azure OpenAI configurable + visible to doctor by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1008
- feat(harden): deeper kernel + MAC checks, cloud-aware FP reduction by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1009
- fix(agent-guard): detect interpreter-launched AI agents via cmdline by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1010
- feat(mesh): resilient init + one-command connect by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1011
- fix(test): de-flake MCP-proxy pipe tests by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1012
- fix(dashboard): Telegram+Slack is multi-channel, not an overlap warning by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1013
- + 5 more
📋 What's Changed
- feat(telemetry): opt-out install ping + ping on upgrade by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/996
- docs(changelog): record the opt-out telemetry change (#996) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/997
- ci(release): fix macOS binary signing (LibreSSL has no pkeyutl -rawin) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/998
- feat(agent): operator "Trust IP" monitor-only allowlist by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/999
- feat(dashboard): Trust IP button on the case view by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1000
- feat(exec-gate): observe mode (spec 077 P2) — safe onboarding without brick by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1001
- Execution Gate: operator Trust Exec (2FA) + allow_exec rule visibility (spec 077 P3/P4) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1002
- Truthful containment: re-verify already-blocked needs_review cases (live firewall) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/1003
- + 3 more
📋 What's Changed
- feat(agent): block-enforcement reconciler + truthful dashboard (spec 076 phase 2) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/986
- Operator case actions + truthful containment for already-blocked threats by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/987
- Fix DShield enrichment: parse bare-integer `as` field by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/988
- Input-robustness hardening (DShield bug class) across enrichment clients by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/989
- Cap the MCP proxy line reader (OOM/DoS) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/990
- Fix install-ping: follow the apex->www redirect (-L + www host) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/991
- Fix systemd_persistence FPs: is-enabled query + bare daemon-reload by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/992
- feat(sensor): Execution Gate eBPF primitive — allowlist pre-authorization LSM, ships inert by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/993
- + 3 more
📋 What's Changed
- feat(agent): Explained Alerts — detector catalog + why-this-matters in alerts (spec 075) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/983
- test(agent): anchor ss dump parsers by @Photon101 in https://github.com/InnerWarden/innerwarden/pull/982
- fix(agent): verify live firewall rule before skipping a re-block — close free-pass hole (spec 076) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/984
- chore(release): 0.15.10 — block live-verify fix (spec 076) + Explained Alerts (spec 075) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/985
✨ New Contributors
- @Photon101 made their first contribution in https://github.com/InnerWarden/innerwarden/pull/982
- Full Changelog: https://github.com/InnerWarden/innerwarden/compare/v0.15.9...v0.15.10
📋 What's Changed
- feat(sensor): audit-state poll detector — catch audit disable by any method (spec 074) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/980
- chore(release): 0.15.9 — audit-state poll detector (spec 074) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/981
- Full Changelog: https://github.com/InnerWarden/innerwarden/compare/v0.15.8...v0.15.9
📋 What's Changed
- fix(agent-guard): embed ATR rules so they actually load in prod by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/956
- docs(agent-guard): honest capability claims + count anchors by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/957
- feat(agent-guard): export ATR rules-loaded gauge to /metrics by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/958
- feat(agent-guard): MCP proxy foundation — JSON-RPC envelope + framing by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/959
- feat(agent-guard): MCP proxy pure message router by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/960
- feat(agent-guard): MCP proxy enforcement layer (advisory default) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/961
- feat(agent-guard): MCP proxy transport + enforcement (single-task loop) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/962
- feat(ctl): innerwarden agent proxy — run the MCP inspecting proxy by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/963
- + 17 more
📋 What's Changed
- docs: update README + handbook for 0.15.6 (spec 070 privilege provenance) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/953
- sensor-ebpf: emit setns for call_usermodehelper helpers (close LPE blind spot) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/954
- release: 0.15.7 by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/955
- Full Changelog: https://github.com/InnerWarden/innerwarden/compare/v0.15.6...v0.15.7
📋 What's Changed
- fix(062): orphan-recovery routes High/Critical orphans to needs_review (closes the Autonomy Gap) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/947
- fix(sensor): container_mount_escape skips kernel threads + arg-less mounts (prod FP) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/948
- fix(sensor): calibrate 3 detector FPs from routine system activity (kernel update, pkg cleanup, shell history) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/949
- feat(sensor): privilege-provenance + untrusted-root-execution detection (spec 070) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/950
- harden(sensor): route namespace pivots to the priority event lane by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/951
- release: 0.15.6 by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/952
- Full Changelog: https://github.com/InnerWarden/innerwarden/compare/v0.15.5...v0.15.6
📋 What's Changed
- fix(ctl): drain full request in one-shot test server (macOS CI flake) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/929
- fix(agent): hydrate block_ip decisions across the UTC midnight boundary by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/930
- feat(sensor): promote killing a security tool to a defense-evasion incident (spec 069 #2 leftover) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/941
- refactor(ebpf): remove 20 orphan syscall tracepoint handlers superseded by kprobes (spec 069 #7) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/942
- chore: demote per-event log to trace + batch 10 Dependabot bumps by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/943
- fix(killchain): stop DATA_EXFIL false positives from world-readable file reads by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/944
- fix(ebpf): tighten kernel kill-chain sensitive-read to genuine /etc secrets by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/945
- release: 0.15.5 by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/946
- + 1 more
📋 What's Changed
- fix(release): per-arch eBPF object — aarch64 syscall-arg capture (0.15.4) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/928
- Full Changelog: https://github.com/InnerWarden/innerwarden/compare/v0.15.3...v0.15.4
📋 What's Changed
- fix(sensor): pt_regs self-check false positive on aarch64 + release 0.15.3 by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/927
- Full Changelog: https://github.com/InnerWarden/innerwarden/compare/v0.15.2...v0.15.3
📋 What's Changed
- refactor(agent): split knowledge_graph/detectors.rs into family submodules (spec 068 Tier 1) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/916
- refactor(agent): split config.rs into per-section submodules (spec 068 Tier 1) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/917
- fix(sensor-ebpf): attach sched_process_exit via raw_tracepoint (spec 069 kernel 7.0) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/918
- fix(sensor-ebpf): kernel 7.0 syscall arg capture via kprobe-on-wrapper (spec 069 Phase 2) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/919
- feat(sensor): multi-lane event channels — stop silent drops under load (spec 069 #1) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/920
- feat(sensor): promote orphan kernel-syscall events to incidents — layered FP (spec 069 #2) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/921
- build(sensor): re-embed eBPF object via OUT_DIR + rerun-if-changed (spec 069 #3) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/922
- refactor(sensor-ebpf): remove dead spec-053 tail-call dispatcher (spec 069 #5) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/923
- + 4 more
📋 What's Changed
- fix(telegram): inbound auth + richer needs_review card + working debrief block (spec 067 Phase 1) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/907
- feat(ai): DShield into decide() LLM prompt (spec 067 Phase 2a) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/908
- feat(ai): host posture into decide() LLM prompt (spec 067 Phase 2b) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/909
- feat(ai): prior operator decisions into decide() prompt (spec 067 Phase 2c) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/910
- feat(telegram): /ask + free-text deep-dive explains the decision for a named IP (spec 067 Phase 3) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/911
- feat(telegram): live server pulse in chat context (spec 067 Phase 4) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/912
- feat(telegram): baseline-normal in the live server pulse (spec 067 Phase 4b) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/913
- feat(telegram): answer-style guide makes chat reply like a resident (spec 067 Phase 5) by @maiconburn in https://github.com/InnerWarden/innerwarden/pull/914
- + 2 more
