This release includes 1 security fix for security teams reviewing exposed deployments.
Topics
+12 more
Affected surfaces
Summary
AI summaryUpdates usulnet v26.2.6 — 2026-02-21, ctx, and Safe across a mixed release.
Full changelog
usulnet v26.2.6 — 2026-02-21
Fixed
-
Container Updates Always Fail at Backup Step (critical — updates completely broken): The update-to-backup adapter in
update_adapters.gousedBackupTypeVolumeinstead ofBackupTypeContainer, causing the backup creator to treat the container ID as a Docker volume name. Every update attempt failed withVOLUME_NOT_FOUNDand was aborted byfailUpdate(). Fixed the backup type toBackupTypeContainerso the correctcreateContainerBackup()path is used. Also addedContainerNamepropagation so backup records show human-readable names instead of hex container IDs, and made pre-update backup failure non-fatal so containers without volumes (e.g., guacd) can still be updated. -
XSS Vulnerabilities in Dashboard Partial Handlers (security):
SearchPartialTempl,ContainersPartialTempl,EventsPartialTempl, andNotificationsPartialTemplconcatenated user-controlled values (search queries, container names, event messages) directly into HTML without escaping. Addedhtml.EscapeString()to all dynamic values andurl.QueryEscape()for URL parameters. Refactored search partial to usestrings.Builderinstead of string concatenation. -
Silent Error Suppression in Dashboard and Updates Handlers:
DashboardTemplandUpdatesTempldiscarded all service errors with blank identifiers (_), rendering empty data without any indication of failure. Added proper error logging viaslog.Error()so operators can diagnose service failures.NotificationsPartialTemplconflated error state with empty state — now shows distinct "Failed to load" message when the alert service returns an error, and "No new notifications" only when the list is genuinely empty. -
Drift Detection Missing "Set Baseline" Action: Backend
drift.Service.SetBaseline()existed but was not exposed in the frontend. AddedDriftSetBaselineAPIhandler, registeredPOST /drift/{id}/set-baselineroute, and added a baseline button (bookmark icon) to each open drift row. Clicking it sets the current snapshot as the new baseline, completing the drift management workflow (accept, remediate, or set baseline). -
HTTP Status Code Violations in Container Settings:
ContainerSettingsUpdatePOST handler used302 Foundfor all redirects instead of303 See Other(correct for POST-to-GET redirects per HTTP spec).ContainerSettingsSummaryreturned200 OKwhen a container was not found instead of404 Not Found. Fixed all redirect status codes and error responses. -
Misleading "Stubs" Comment in Profile Handler:
handler_profile.gocontained an outdated comment block (Helper Methods (stubs — implement with your Handler struct fields)) describing fields that already existed and methods that were fully implemented. Removed the misleading documentation. -
Profile Page Always Redirects to Login (critical — page completely broken):
handler_profile.gousedGetUserInfo(ctx)which looks up auser_infocontext key that was never populated by any middleware. The auth middleware stores the authenticated user under theusercontext key viaGetUserFromContext(ctx). SinceGetUserInfoalways returned nil, the profile handler always redirected to/login— even for authenticated users. Fixed all 10 occurrences to useGetUserFromContext(ctx). Also added a clickable link to/profilein the sidebar user section (avatar + username) so users can actually navigate there without manually typing the URL. -
Stack Deploys Break When Browser Window Closes (critical — broken deploys):
stackDeploySSEusedr.Context()for theDeployStreamgoroutine, so closing the browser tab or navigating away canceled the context and killeddocker-composemid-deploy, leaving containers in an inconsistent state. Switched tocontext.Background()with active host propagation. The deploy goroutine now drains the log channel silently if the client disconnects, ensuring the deploy completes regardless of browser state. Non-streaming fallback path also converted to background execution. -
Image Pull, Security Scan, and Batch Update Canceled by Browser Navigation (critical — broken operations):
ImagePullSubmit,SecurityScan,SecurityScanContainer, andUpdateBatchall usedr.Context()synchronously, meaning any browser navigation or tab close during these long-running operations would cancel them mid-execution. Converted all four handlers to thecontext.Background()+ goroutine pattern already established inBackupCreate. Operations now redirect immediately with a progress message and continue in the background. -
SSE Parser Bug in Stack Deploy Template:
stacks/new.templused literal multiline newlines inside single-quoted JavaScript strings for the SSE parser (buf.split('...')), which is invalid JavaScript syntax. Fixed to use proper\n\nand\nescape sequences, matching the working implementation incatalog_deploy.templ. -
Silent Failures on fetch() Calls in Connection and Changes Pages:
shortcuts.templ(delete shortcut),ldap.templ(toggle write mode),database.templ(toggle write mode), andchanges.templ(load diff) all hadfetch()calls without.catch()error handlers. Network errors or server failures were silently ignored. Added.catch()handlers with user-visible toast notifications viawindow.usulnet.toast(). -
Stack Catalog Deploys Killed by Browser Navigation (critical — broken catalog deploys):
StackCatalogDeploySubmitusedr.Context()for both SSE streaming and synchronous deploy paths. The logs showsignal: killedandcontext cancelederrors when users navigate away during catalog app deployment (e.g., deploying Vaultwarden). Applied the same background context + client disconnect handling pattern asStackDeploy. -
Container Updates Run Synchronously for 60+ Seconds (critical — updates fragile):
UpdateApplyTempl,UpdateManual, andUpdateRollbackTemplall ranupdatesSvc.Apply()synchronously usingr.Context(), blocking the HTTP handler for 60-70 seconds per update. Any browser timeout, navigation, or tab close would cancel the update mid-execution, potentially leaving containers in an inconsistent state. All three handlers converted to background goroutines withcontext.Background(). -
Vulnerability Scan Blocks for 77+ Seconds:
VulnScanhandler ransecSvc.ScanAll()plus CVE import synchronously usingr.Context(). Converted to background goroutine — the scan and CVE import now complete independently of browser state. -
Stale Template Codegen for Nvim Editor:
nvim_templ.gowas missingSnippetIDandContentfields that existed in the.templsource, causing compilation errors. Regenerated withtempl generate.
Added
-
Docker Daemon Configuration Management: New
/config/dockerpage for managing Docker engine settings (daemon.json) directly from the web UI — no CLI commands needed. Features include:- 6 Category Tabs: Network (address pools, bridge IP, CIDR, DNS, MTU, ICC, IPv6), Logging (driver, level, format, options), Registry (mirrors, insecure registries), Runtime (default runtime, storage driver, data root, cgroup namespace, live restore, iptables), Proxy (HTTP/HTTPS proxy, no-proxy), and Security (ulimits, no-new-privileges, SELinux, seccomp, userns-remap, auth plugins).
- General Settings: Debug, labels, shutdown timeout, concurrent downloads/uploads, experimental, metrics address — always visible above tabs.
- Risk Color Coding: Each setting displays a risk badge — green (Safe), yellow (Moderate), or red (Dangerous with confirmation dialog) — so operators understand the impact before changing.
- Apply Mode Indicators: Blue "Live Reload" badge for settings that take effect via
SIGHUP, orange "Restart Required" badge for settings that need a full Docker restart. - Automatic Backup: Every change creates a timestamped backup of
daemon.jsonin/etc/docker/backups/before writing. Backups tab lists all snapshots with one-click restore. - Raw JSON View: Read-only tab showing the current
daemon.jsoncontent for reference. - Reload & Restart Controls: "Reload Config" button sends
SIGHUPto dockerd for live-reloadable changes. "Apply & Restart" button with confirmation modal warns about container interruption and potential self-kill if running inside Docker. - Validation: CIDR, IP address, absolute path, log driver, storage driver, proxy URL, and ulimit validation before applying — prevents invalid
daemon.jsonthat would stop Docker from starting. - Unknown Field Preservation: Custom JSON marshaling preserves any
daemon.jsonfields not modeled in the UI, ensuring no settings are silently dropped. - 50+ configurable daemon settings across all categories. Daemon info summary cards show version, storage driver, log driver, runtime, CPUs, memory, OS, and architecture.
-
Refresh Button & Auto-Refresh for Docker Resource Pages: Added a refresh button (with spinning animation) and auto-refresh toggle (30-second interval) to Containers, Images, Networks, Volumes, Stacks, and Updates pages. Auto-refresh only fires when the browser tab is visible. Users can toggle auto-refresh on/off via a small indicator dot next to the refresh button. Implemented as a reusable
RefreshButtontempl component. -
Complete Swarm Cluster Management: Full professional Swarm management from the UI, eliminating the need for CLI commands. New features include:
- Node Management: Promote workers to managers, demote managers to workers, drain nodes for maintenance, pause/activate nodes — all from the cluster page with one-click actions.
- Service Detail Page: Dedicated page for each service showing overview cards (image, mode, replicas, tasks), scale controls, image update form, published ports, task list with per-task state/node/error, live service logs viewer, and labels.
- Service Update & Rollback: Update a service's image or replicas inline from the detail page. One-click rollback to the previous service spec when an update goes wrong.
- Service Logs: View aggregated logs from all tasks of a service, fetched directly from the Docker API with timestamp support.
- Join Swarm UI: New collapsible form on the inactive cluster page lets you join an existing Swarm cluster by entering the manager address and join token — no terminal needed.
- Refresh & Auto-Refresh: Swarm cluster page now includes the
RefreshButtoncomponent with 30-second auto-refresh. - Backend: Added
SwarmNodeUpdate,SwarmServiceLogs,SwarmServiceRollbackto Docker client interface and implementation. AddedUpdateNode,JoinSwarm,UpdateService,RollbackService,ServiceLogsto Swarm service layer. All proxy stubs updated for agent compatibility. - Routes: Added
POST /swarm/join,POST /swarm/nodes/{nodeID}/update,GET /swarm/services/{serviceID}(detail page),GET /swarm/services/{serviceID}/logs,POST /swarm/services/{serviceID}/update,POST /swarm/services/{serviceID}/rollback.
Full Changelog: https://github.com/fr4nsys/usulnet/compare/v26.2.5...v26.2.6
Security Fixes
- CVE-2026-XXXXX – XSS vulnerabilities in Dashboard partial handlers fixed by escaping user-controlled values and using html.EscapeString()
Weekly OSS security release digest.
The CVE patches and breaking changes that affected production tools this week. One email, every Sunday.
No spam, unsubscribe anytime.
Share this release
About fran-olivares/usulnet
All releases →Related context
Related tools
Beta — feedback welcome: [email protected]