github LanternOps/breeze v0.69.0

latest releases: v0.125.0, v0.124.0, v0.123.0...
5 months ago

⚠️ Security — action required (added 2026-08-17)

Self-hosted operators running any version before 0.69.0 should upgrade immediately.
Two High-severity vulnerabilities were fixed in this release. Advisories were published after the
fact; this notice was added retroactively so operators who reach these notes at upgrade time see it.

  • GHSA-7m9m-6m4w-244h —
    the macOS agent auto-updater ran the downloaded .pkg as root without verifying it against the
    Ed25519-signed release manifest
    . An attacker able to tamper with the package in transit (TLS/DNS
    MITM, poisoned release asset, or compromised CDN edge) could achieve arbitrary code execution as
    root
    on macOS agents with auto-update enabled. Windows and Linux were not affected.
    If you cannot upgrade immediately: disable auto-update on macOS agents.
  • GHSA-276w-8c3g-5pv9 —
    a quarantined device could clear its own containment by re-enrolling, resuming heartbeat,
    command execution and remote desktop with no administrator approval. Exploitation requires the
    device's own agent token — i.e. the credential quarantine exists to contain.

Watch future advisories: Watch → Custom → Security alerts on this repo. Breeze does not phone
home, so repo notifications and these release notes are the only ways we can reach you.

Added

  • Microsoft 365 helpdesk AI agent (Delegant-backed). Five M365 admin tools with tiered RBAC, per-action approvals, customer-tenant scoping, and audit correlation; adds delegant_m365_connections schema/migrations, a web customer switcher, and a mobile approval card. M365 tools are only advertised when DELEGANT_BASE_URL is configured (#991).
  • linux/arm64 agent binaries. linux/arm64 is now a first-class agent build target end-to-end — release build, signed manifest, server registration, and download — fixing a syscall.Dup2 compile blocker on arm64 and adding the target to the build matrix and binarySync (#1057).
  • Per-user column visibility and reordering on the Devices list. 9 default-visible togglable columns plus 9 off-by-default (Last User, Uptime, OS Build, Architecture, Enrolled Date, CPU, RAM, Disk, Tags), persisted per-browser in localStorage (#737).
  • Device-filter engine for the chip bar. Adds virtual boolean fields patches.pending, alerts.critical, and system.rebootRequired as EXISTS subqueries, reworks software.installed/notInstalled to query the populated software_inventory table (fixing a latent broken software-filter), and adds backing partial indexes (#968, #1012).
  • Declarative deviceArgs AI-tool gate. AI tools now declare their device-id input props and executeTool runs the org+site verifyDeviceAccess check before the handler, applied to all 75 device-arg tools across 31 files with a contract-test ratchet preventing recurrence (#1049).

Improved

  • Off-region backups are gpg-encrypted. Off-region pg_dump backups are now AES256 gpg-encrypted before leaving the host when OFFSITE_BACKUP_GPG_PASSPHRASE is set; restore-test.sh decrypts before restore. Adds a remote Prometheus scrape example config and planning docs (#1008).
  • Tenant export + erasure round-trip integration coverage. A real-DB integration test proves buildOrgExportZip emits a ZIP scoped to one org only and cascadeDeleteOrg wipes that org's rows while leaving others intact, both verified against the RLS-enforced breeze_app pool (#1007).

Fixed

  • Graceful API shutdown drains in-flight requests first. Shutdown now marks the server unhealthy, closes the listener, and waits a bounded grace period (SHUTDOWN_DRAIN_MS, default 5s) before tearing down workers/Redis/DB — preventing heartbeat 500s that could wedge agents offline during an API restart (#1055).
  • Terminal/process output mojibake. A new procoutput package forces a UTF-8 locale at the source (ApplyEnv), transcodes Windows code-page bytes at runtime, and base64-encodes terminal payloads (capability-negotiated for deploy-order safety) so non-UTF-8 bytes survive JSON transport (#976). A follow-up holds incomplete trailing UTF-8 byte sequences across 4096-byte read-chunk boundaries so multibyte characters split across reads no longer decode to U+FFFD (#1033).
  • Forced agent re-enrollment in place. The enroll client now presents its stored device token via the x-agent-reenrollment-token header, so a --force re-enroll on an already-enrolled device (after rename/re-image) re-enrolls in place instead of failing with a 409 hostname collision (#1028, #1032).
  • Stale-PID watchdog false positives. The agent writes its live PID with a new StatusStarting state immediately after logging init (before wedge-prone steps like mTLS renewal), so a wedged-but-alive agent isn't falsely reported as process_gone and recovery force-kills the correct live PID (#1029, #1031).
  • Self-heal missing breeze-user-helper.exe on Windows. The agent reconciles a missing or zero-length breeze-user-helper.exe at startup/heartbeat (throttled 30 min, decoupled from upgrades) via atomic staging + rename, fixing fleet-wide black-screen/0-fps remote desktop on agents that never received the helper binary; persistent fetch failures escalate WARN→ERROR (#1003).
  • Assist-IPC Helper path allowlist. Corrected the assist-IPC binary-hash allowlist to include the Helper's real Windows install path (C:\Program Files\Breeze Helper\breeze-helper.exe) plus agent-dir sibling and legacy paths; previously the mismatch left the IPC token-delivery path dead on Windows (#1001).
  • Reject software version pin on non-Windows endpoints. Pinning a software version now returns 422 on non-Windows endpoints, where the agent silently ignored the pin and upgraded to latest — a no-op that could violate a compliance hold (#993, #1006).
  • Patch compliance no longer counts missing tombstones. A shared OUTSTANDING_DEVICE_PATCH_STATUSES = ['pending'] constant drives compliance counts/compliancePercent/severity summaries and the patch-approval evaluator, so a fully-patched device no longer falsely shows hundreds of outstanding patches and tombstoned patches aren't selected for install (#1005).
  • Remote-desktop idle watchdog and teardown. The idle watchdog now resets only on actual mouse/keyboard input (not viewer_stats heartbeats), so idleTimeoutMinutes fires for unattended viewers; session teardown no longer clobbers terminal failed rows; and direct-mode session lifetimes are clamped (idle ≤1440m, max ≤168h) on the console path (#1040).

Security

  • Device-filter input hardening. Escapes user-supplied SQL LIKE wildcards (%/_/\) on contains/startsWith/endsWith operators, caps matches regex patterns at 250 chars, and makes POST /filters/preview return 400 (not 500) on invalid fields/operators (#1044, #1054).
  • Cross-org device dispatch via incident AI tools (CRITICAL). The execute_containment and collect_evidence AI incident tools dispatched commands to an attacker-supplied deviceId after validating only the incident's org, allowing actions and evidence collection on any device in any org; deviceId now routes through the org-scoped verifyDeviceAccess gate before dispatch (#1048).
  • Site-scope the AI-agent tool layer. The AI-agent/MCP tool layer previously enforced only the org axis, letting site-restricted users run scripts or remote actions on out-of-scope devices via AI chat/MCP; allowedSiteIds/canAccessSite are now threaded through AuthContext, verifyDeviceAccess, and the MCP API-key path (#1047).
  • Site-scope device-data reads and mutations (RBAC baseline). Site-scoped 8 high-severity device mutations (provision, discovery link/delete, networkBaselines, remote session disconnect/offer, script cancel, software remediate) (#1041), 44 device-data read handlers across backup/mobile/monitoring/reports/software/remote/groups/compliance/events (#1042), and device reads plus browser-policy mutations across browserSecurity/sentinelOne/peripheralControl/huntress/dnsSecurity/analytics (#1036). Eleven dead site-scope read gates were also made live by adding requirePermission(DEVICES_READ) after requireScope (#1056).
  • Multi-tenant isolation and authz hardening (4 HIGH, 3 MED, 1 LOW). Added RLS to seven FK-child tables (automation_runs, ai_messages, ai_tool_executions, script_execution_batches, others), enforced per-user allowedSiteIds on site CRUD/list and group bulk-add, and extended the RLS-coverage contract test to catch FK-child tables (#1016, #1027).
  • script_execution_batches org_id denormalization (CRITICAL RLS regression). Running a built-in/system script on 2+ devices failed because the nested-EXISTS-through-scripts RLS policy doesn't evaluate under postgres.js bound params; fixed by denormalizing org_id onto the table with a new column, index, and backfill migration (#1026).
  • Agent credentials gated on tenant status. Agent REST auth, agent WS auth, and enrollment now gate on active tenant status (403 tenant_inactive), and revocation severs the fleet — so suspending or deleting a tenant stops its agents and blocks re-enrollment. All gates fail closed (#1024).
  • Refuse re-enrollment of quarantined devices. /enroll now rejects re-enrollment of a quarantined device with 403 device_quarantined (audited) even with a valid existing-device token, closing a path where a quarantined device could silently flip itself back to online; recovery remains exclusively via the admin /approve endpoint (GHSA-276w-8c3g-5pv9, #1011).
  • Agent telemetry ingest requires the agent role. A new requireAgentRole guard (403 for non-agent credentials) gates the inventory, state, sessions, and elevationRequests ingest routes, so a watchdog-role token can no longer write device telemetry (#1021).
  • macOS update .pkg verified against signed manifest. The macOS auto-updater verifies the downloaded .pkg against the Ed25519-signed release manifest (SHA-256) before running installer as root, failing closed to verified-binary replacement when no signed checksum is available (GHSA-7m9m-6m4w-244h, #1010).
  • Agent update-channel hardening. Gated dev_update behind a default-off allow_dev_update flag (production agents reject it) and made server-directed auto-update monotonic so it refuses downgrades to older signed builds (#1014).
  • Agent config plaintext-secret exposure windows closed. SetSecretAndPersist now writes via atomicWriteFile at 0600 (was a 0644 temp file), and SetAndPersist migrates/nils legacy inline secrets before writing agent.yaml, so plaintext is never serialized to the 0644 file (#1017).
  • Third-party integration egress hardened against SSRF. Outbound calls to Huntress, SentinelOne, DNS providers, and M365/Delegant now route through the DNS-pinned, redirect-refusing safeFetch, re-assert host allowlists on the final URL, and close two information-reflection channels (#1025).
  • MCP/OAuth tenant-attribution and scope hardening. resolveMcpExecutionOrgId enforces canAccessOrg() instead of trusting a client-supplied arguments.orgId, preventing audit-log/ledger mis-attribution by partner-scoped OAuth callers (#1015); getPartnerScopePolicy now fails closed (empty scope cap) on a DB error during token minting instead of granting all scopes (#1022).
  • WebRTC remote-desktop session hardening. Policy is re-checked at offer time, the server can send stop_desktop with agent idle/max-duration watchdogs, live sessions tear down on user/partner suspend, viewer revocation is rechecked in the WS ping loop, sessions cannot resurrect, viewer-token TTL is single-sourced, clipboard policy is per-direction (host→viewer off by default on hosted), and clipboard/filedrop transfers are audited (#1020, #1034).
  • SOC2 audit + step-up hardening. Added audit-log coverage for previously unaudited state changes (PATCH /users/me at partner scope, sensitive-data status flips, automation policy activate/deactivate) and MFA step-up on partner unsuspend, third-party-catalog mutations, and email change to prevent account takeover (#1019).
  • Notification-link same-origin guards. A new safeRelativePath shared validator is applied at the inAppSender write/storage layer so a hostile user_notifications.link can never be persisted (#1038), complemented by client-side redirect/href defense-in-depth: navigateTo routes through getSafeNext (same-origin only), a DOCS_BASE_URL-prefixed iframe-src guard on helpStore.open, and a new getSafeExternalHref scheme guard (#1018).

Full Changelog: v0.68.2...v0.69.0

Don't miss a new breeze release

NewReleases is sending notifications on new releases.