Skip to content

Security: Bp7-dev/warden

Security

SECURITY.md

Security Policy

Overview

WARDEN is a local Windows desktop application. All data stays on-device by default. The only exceptions are the optional AI assistant modes:

  • Local mode (default) — runs against a local Ollama model; nothing leaves the machine.
  • Cloud mode (opt-in) — uses the Anthropic API with a user-supplied key, gated behind an explicit informed-consent modal and marked in the UI with a persistent banner while active. Consent is revocable at any time.

Supported Versions

Version Supported
Latest Yes

This project is pre-release. Only the current master branch is supported.

Reporting a Vulnerability

If you have access to this repository and discover a security issue, open a private GitHub Security Advisory or contact the repository owner directly.

Please include:

  • A clear description of the vulnerability
  • Steps to reproduce
  • Potential impact assessment
  • Any suggested mitigations

Response time is best-effort; critical issues are prioritized.

Scope

In scope:

  • Rust backend (Tauri commands, port scanner, database layer)
  • Frontend React/TypeScript components
  • Tauri configuration and capability profile
  • Local data persistence (SQLite, DPAPI-encrypted blobs)
  • Optional AI assistant data handling

Out of scope:

  • The host Windows OS or kernel
  • Third-party dependencies not under this project's control
  • Attacks requiring physical access or kernel-level compromise

Security Architecture

Full details are in docs/ARCHITECTURE.md.

Summary:

  • Data collection via netstat2 + sysinfo in Rust — no shell commands for core telemetry
  • Local SQLite database; snapshot blobs encrypted at rest with Windows DPAPI
  • Tauri IPC with tightened CSP; no external origins
  • Process name sanitization at both backend ingestion and frontend render
  • Cloud AI assistant gated behind explicit informed-consent modal; consent is revocable

Audit History

Red-team findings register (audit #1)

Fourteen findings (F1–F14) were raised. Closed items are implemented and regression-tested; open items have a concrete plan in the audit register.

Closed:

  • F2 (CRIT) Per-socket keying — port rows now key on (local_port, protocol, pid, remote_addr, remote_port); multi-PID / multi-remote situations no longer collapse.
  • F3 (CRIT) ETW-unavailable coverage — emits a HIGH self_integrity alert when ETW is expected but not running.
  • F4 (HIGH) Relative ETW event-rate drop — rolling-sample detector fires when the trailing-3-sample rate drops below 20% of baseline median, catching partial kernel-stream tampering below the absolute-silence threshold.
  • F7 (HIGH) Lineage-aware baseline reset — on identity rotation (different exe_path or different parent once learned), first_seen and occurrence_count reset so the newcomer cannot inherit the prior binary's established trust.
  • F8 (HIGH) Rapid-warmup anomaly — learned_baseline fires RAPID WARMUP when a novel signal crosses its occurrence cap in under 10 minutes.
  • F9 (HIGH) Per-severity alert budgets — independent 30/hour budgets per severity so a MEDIUM flood cannot squeeze out CRITICAL.
  • F10 (MED) Exact-match name attribution — .exe entries in the known-app list require exact match, eliminating substring trust inheritance from renamed binaries.
  • F12 (MED) Persistence scanner expansion — added Winlogon hooks, AppInit_DLLs, IFEO debugger hijacks, and scheduled-task XML enumeration. A single normalize_target_path() helper expands env vars and kernel-namespace prefixes before scoring so risky-location heuristics match consistently.

Carried forward (tracked in audit register):

  • F1 (event-driven network telemetry)
  • F5 (low-and-slow beacon detectors)
  • F6 (per-tenant destination novelty)
  • F11 (single-symptom injection via ETW-TI)
  • F12a (WMI event-subscription enumeration — deferred to avoid pulling WMI/COM surface into the scanner)
  • F13 (signed append-only event ledger)
  • F14 (full-pipeline replay harness)

Tuning passes (audits #2 through #6)

Five subsequent audits recalibrated scoring against more specific user profiles. Summary only; the audit register keeps full per-item detail.

Audit #2 — Consumer machine. Seven soft-signal dampeners to reduce false positives on normal consumer desktops (Discord / Chrome / VS Code / Steam). Hard attack primitives (LOLBin cmdline, hidden process, DLL sideload, impersonation) were left untouched.

  • Novelty bundle cap at +12 unless a hard primitive is also present
  • Known-provider beacon weight reduced +20 → +8, gated on a BEACONING CONFIRMED marker (≥6 intervals observed)
  • Rapid-warmup scoring gated behind context; indicator still emits for visibility
  • Identity-drift weight scaled by destination class (KP +2, UNRESOLVED +3, UNKNOWN +10, SUSPICIOUS reputation +15)
  • New UNRESOLVED destination class separating "reverse DNS failed" from "resolved but unrecognized"
  • User-hive HKCU\...\RunOnce first-sight freshness dampened until the entry is observed across 2+ scan cycles
  • PATH UNKNOWN (first sight) neutral indicator distinct from the seen-then-missing PATH UNAVAILABLE

Audit #3 — Installer hell. Three shipped, two declined to preserve commodity-malware detection.

  • New in_installer_context() helper gates on ancestry walk (msiexec / winget / TrustedInstaller / SetupHost / DISM / AppInstaller / Steam / EpicGamesLauncher / Update.exe) and a valid Authenticode chain on the child. When true, risky-path dampens +10 → +4, first-observation dropper bonus → 0, and "bad parent + new outbound" → 0.
  • Suspicious-chain weight +25 → +8 for signed children spawned through an installer host (covers winget/scoop/msiexec-via-powershell dev flows).
  • Four built-in replay scenarios lock the behavior in: installer_discord_setup, installer_chrome_in_temp, installer_vscode_via_winget, installer_steam_unsigned_helper.

Audit #4 — Lazy-attacker coverage. Counterweight to #2 and #3: would a basic attacker evade detection by staying boring?

  • UNKNOWN-reputation processes on non-privileged ports now default to MEDIUM risk (was LOW).
  • New low-signal scoring rule: +12 when UNSIGNED + UNKNOWN reputation + OUTBOUND + destination in {UNKNOWN, UNRESOLVED}.
  • ETW-off compensation: when the collector is unavailable (unprivileged install, wedged provider), every port is tagged REDUCED TELEMETRY and unsigned outbound gets a conservative +5 to compensate for missing cmdline/sideload signals.
  • low_signal_custom_rat replay scenario asserts WATCH minimum on a custom unsigned RAT with no behavioral primitives.

Audit #5 — Developer machine. Two shipped, three deferred as features, one declined.

  • Dev-context LOLBin split: msbuild.exe and msiexec.exe moved to LOLBIN_DEV_CONTEXT_PROCESSES. Network activity emits an indicator but does not force SUSPICIOUS+HIGH; scoring adds +20 only when destination is UNKNOWN/UNRESOLVED. Hard LOLBins (certutil / mshta / wscript / bitsadmin / regsvr32 / etc.) unchanged. dev_msbuild_nuget_restore scenario locks the calm outcome.
  • Extended KNOWN_APPS and KNOWN_PROVIDERS with developer-ecosystem entries: pwsh, pip/poetry/uv, go/gofmt, mvn/gradle/sbt, ruby/gem, nuget, jetbrains IDEs, docker tooling; PyPI, crates.io, Go proxy, Maven Central, NuGet, Docker Hub, GHCR, Quay, JetBrains, VS Code CDN endpoints.

Audit #6 — Readiness review. Most items were already implemented or are UX work rather than scoring. One tuning item real:

  • Beacon detector range widened (2..=3600)(2..=7200) seconds to catch 1–2 hour cadence patterns common in low-volume implants.

Hardening pass (audit #7)

Two items from the "ready for real-world use" review:

  • Scan-thread panic isolation. Each scan iteration runs inside std::panic::catch_unwind. On recovery, a CRITICAL scan_panic alert is emitted with a 1-hour dedup window; monitoring continues on the next interval. Previously a panic would have silently killed the polling thread and left the UI showing stale data.
  • max_verdict assertions on replay. The Assertion schema gained an optional max_verdict ceiling. All eight negative-control scenarios now carry max_verdict: "CLEAN" (or "WATCH" on the vscode-winget first-install case). A scoring regression that silently promotes benign software above its ceiling now fails CI instead of passing the old min_verdict: "CLEAN" check (which any verdict satisfied).

Deferred work (tracked)

These items are real but need design before code; they don't block daily use.

  • WMI event-subscription persistence enumeration (F12a / audit #4 #4) — needs either the wmi crate or manual COM FFI; dependency decision first.
  • Startup .lnk target resolution (audit #4 #5) — needs IShellLink via COM or a minimal MS-SHLLINK binary parser.
  • Per-tuple alert cooldown / noise-budget layer (audit #5 #5 / audit #6 #1) — design work on top of the existing severity-budget and incident-grouping mechanisms.
  • Cumulative-trend scoring across N windows (audit #6 #6) — needs persistent cross-scan state.
  • Frontend polish: inline threshold context on verdicts, persistent degraded-telemetry banner, per-item action buttons. All product/UX work.
  • Developer Mode + Trusted Dev Paths (audit #5 #1 + #2) — user-opt-in feature, not a tuning tweak.

There aren't any published security advisories