⚠️ Security — action required (added 2026-08-17)
Self-hosted operators running any version before
0.69.0should 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.pkgas 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_connectionsschema/migrations, a web customer switcher, and a mobile approval card. M365 tools are only advertised whenDELEGANT_BASE_URLis configured (#991). - linux/arm64 agent binaries.
linux/arm64is now a first-class agent build target end-to-end — release build, signed manifest, server registration, and download — fixing asyscall.Dup2compile blocker on arm64 and adding the target to the build matrix andbinarySync(#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, andsystem.rebootRequiredas EXISTS subqueries, reworkssoftware.installed/notInstalledto query the populatedsoftware_inventorytable (fixing a latent broken software-filter), and adds backing partial indexes (#968, #1012). - Declarative
deviceArgsAI-tool gate. AI tools now declare their device-id input props andexecuteToolruns the org+siteverifyDeviceAccesscheck 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_dumpbackups are now AES256 gpg-encrypted before leaving the host whenOFFSITE_BACKUP_GPG_PASSPHRASEis set;restore-test.shdecrypts 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
buildOrgExportZipemits a ZIP scoped to one org only andcascadeDeleteOrgwipes that org's rows while leaving others intact, both verified against the RLS-enforcedbreeze_apppool (#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
procoutputpackage 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 toU+FFFD(#1033). - Forced agent re-enrollment in place. The enroll client now presents its stored device token via the
x-agent-reenrollment-tokenheader, so a--forcere-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
StatusStartingstate immediately after logging init (before wedge-prone steps like mTLS renewal), so a wedged-but-alive agent isn't falsely reported asprocess_goneand 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.exeat 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
missingtombstones. A sharedOUTSTANDING_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_statsheartbeats), soidleTimeoutMinutesfires for unattended viewers; session teardown no longer clobbers terminalfailedrows; 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, capsmatchesregex patterns at 250 chars, and makesPOST /filters/previewreturn 400 (not 500) on invalid fields/operators (#1044, #1054). - Cross-org device dispatch via incident AI tools (CRITICAL). The
execute_containmentandcollect_evidenceAI incident tools dispatched commands to an attacker-supplieddeviceIdafter validating only the incident's org, allowing actions and evidence collection on any device in any org;deviceIdnow routes through the org-scopedverifyDeviceAccessgate 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/canAccessSiteare now threaded throughAuthContext,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)afterrequireScope(#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-userallowedSiteIdson site CRUD/list and group bulk-add, and extended the RLS-coverage contract test to catch FK-child tables (#1016, #1027). script_execution_batchesorg_id denormalization (CRITICAL RLS regression). Running a built-in/system script on 2+ devices failed because the nested-EXISTS-through-scriptsRLS policy doesn't evaluate under postgres.js bound params; fixed by denormalizingorg_idonto 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.
/enrollnow rejects re-enrollment of aquarantineddevice with403 device_quarantined(audited) even with a valid existing-device token, closing a path where a quarantined device could silently flip itself back toonline; recovery remains exclusively via the admin/approveendpoint (GHSA-276w-8c3g-5pv9, #1011). - Agent telemetry ingest requires the agent role. A new
requireAgentRoleguard (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
.pkgagainst the Ed25519-signed release manifest (SHA-256) before runninginstalleras root, failing closed to verified-binary replacement when no signed checksum is available (GHSA-7m9m-6m4w-244h, #1010). - Agent update-channel hardening. Gated
dev_updatebehind a default-offallow_dev_updateflag (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.
SetSecretAndPersistnow writes viaatomicWriteFileat 0600 (was a 0644 temp file), andSetAndPersistmigrates/nils legacy inline secrets before writingagent.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.
resolveMcpExecutionOrgIdenforcescanAccessOrg()instead of trusting a client-suppliedarguments.orgId, preventing audit-log/ledger mis-attribution by partner-scoped OAuth callers (#1015);getPartnerScopePolicynow 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_desktopwith 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/meat 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
safeRelativePathshared validator is applied at theinAppSenderwrite/storage layer so a hostileuser_notifications.linkcan never be persisted (#1038), complemented by client-side redirect/href defense-in-depth:navigateToroutes throughgetSafeNext(same-origin only), aDOCS_BASE_URL-prefixed iframe-src guard onhelpStore.open, and a newgetSafeExternalHrefscheme guard (#1018).
Full Changelog: v0.68.2...v0.69.0