Skip to content

fran-olivares/usulnet

v26.2.6 Security

This release includes 1 security fix for security teams reviewing exposed deployments.

✓ No known CVEs patched
Read the diff → Tool health → What is this tool? →
This release patches 1 known CVE

Topics

agplv3 docker docker-deployment docker-management docker-management-tool docker-manager
+12 more
docker-swarm docker-ui go goland moby postgresql self-hosted swarm templ ui usulnet webui

Affected surfaces

auth rce_ssrf

Summary

AI summary

Updates 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.go used BackupTypeVolume instead of BackupTypeContainer, causing the backup creator to treat the container ID as a Docker volume name. Every update attempt failed with VOLUME_NOT_FOUND and was aborted by failUpdate(). Fixed the backup type to BackupTypeContainer so the correct createContainerBackup() path is used. Also added ContainerName propagation 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, and NotificationsPartialTempl concatenated user-controlled values (search queries, container names, event messages) directly into HTML without escaping. Added html.EscapeString() to all dynamic values and url.QueryEscape() for URL parameters. Refactored search partial to use strings.Builder instead of string concatenation.

  • Silent Error Suppression in Dashboard and Updates Handlers: DashboardTempl and UpdatesTempl discarded all service errors with blank identifiers (_), rendering empty data without any indication of failure. Added proper error logging via slog.Error() so operators can diagnose service failures. NotificationsPartialTempl conflated 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. Added DriftSetBaselineAPI handler, registered POST /drift/{id}/set-baseline route, 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: ContainerSettingsUpdate POST handler used 302 Found for all redirects instead of 303 See Other (correct for POST-to-GET redirects per HTTP spec). ContainerSettingsSummary returned 200 OK when a container was not found instead of 404 Not Found. Fixed all redirect status codes and error responses.

  • Misleading "Stubs" Comment in Profile Handler: handler_profile.go contained 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.go used GetUserInfo(ctx) which looks up a user_info context key that was never populated by any middleware. The auth middleware stores the authenticated user under the user context key via GetUserFromContext(ctx). Since GetUserInfo always returned nil, the profile handler always redirected to /login — even for authenticated users. Fixed all 10 occurrences to use GetUserFromContext(ctx). Also added a clickable link to /profile in 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): stackDeploySSE used r.Context() for the DeployStream goroutine, so closing the browser tab or navigating away canceled the context and killed docker-compose mid-deploy, leaving containers in an inconsistent state. Switched to context.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, and UpdateBatch all used r.Context() synchronously, meaning any browser navigation or tab close during these long-running operations would cancel them mid-execution. Converted all four handlers to the context.Background() + goroutine pattern already established in BackupCreate. Operations now redirect immediately with a progress message and continue in the background.

  • SSE Parser Bug in Stack Deploy Template: stacks/new.templ used literal multiline newlines inside single-quoted JavaScript strings for the SSE parser (buf.split('...')), which is invalid JavaScript syntax. Fixed to use proper \n\n and \n escape sequences, matching the working implementation in catalog_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), and changes.templ (load diff) all had fetch() calls without .catch() error handlers. Network errors or server failures were silently ignored. Added .catch() handlers with user-visible toast notifications via window.usulnet.toast().

  • Stack Catalog Deploys Killed by Browser Navigation (critical — broken catalog deploys): StackCatalogDeploySubmit used r.Context() for both SSE streaming and synchronous deploy paths. The logs show signal: killed and context canceled errors when users navigate away during catalog app deployment (e.g., deploying Vaultwarden). Applied the same background context + client disconnect handling pattern as StackDeploy.

  • Container Updates Run Synchronously for 60+ Seconds (critical — updates fragile): UpdateApplyTempl, UpdateManual, and UpdateRollbackTempl all ran updatesSvc.Apply() synchronously using r.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 with context.Background().

  • Vulnerability Scan Blocks for 77+ Seconds: VulnScan handler ran secSvc.ScanAll() plus CVE import synchronously using r.Context(). Converted to background goroutine — the scan and CVE import now complete independently of browser state.

  • Stale Template Codegen for Nvim Editor: nvim_templ.go was missing SnippetID and Content fields that existed in the .templ source, causing compilation errors. Regenerated with templ generate.

Added

  • Docker Daemon Configuration Management: New /config/docker page 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.json in /etc/docker/backups/ before writing. Backups tab lists all snapshots with one-click restore.
    • Raw JSON View: Read-only tab showing the current daemon.json content for reference.
    • Reload & Restart Controls: "Reload Config" button sends SIGHUP to 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.json that would stop Docker from starting.
    • Unknown Field Preservation: Custom JSON marshaling preserves any daemon.json fields 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 RefreshButton templ 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 RefreshButton component with 30-second auto-refresh.
    • Backend: Added SwarmNodeUpdate, SwarmServiceLogs, SwarmServiceRollback to Docker client interface and implementation. Added UpdateNode, JoinSwarm, UpdateService, RollbackService, ServiceLogs to 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

Track fran-olivares/usulnet

Get notified when new releases ship.

Sign up free

About fran-olivares/usulnet

All releases →

Related context

Beta — feedback welcome: [email protected]