Skip to content

fran-olivares/usulnet

v26.2.4 Security

This release includes 7 security fixes for security teams reviewing exposed deployments.

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

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

crypto_tls breaking_upgrade

Summary

AI summary

Updates usulnet v26.2.4 — 2026-02-21, SOC2/ISO27001/CIS, and eBPF-based across a mixed release.

Full changelog

usulnet v26.2.4 — 2026-02-21

Added

  • Redis TLS Encryption by Default: All Redis connections now use TLS with ECDSA P-256 self-signed certificates. The Redis container generates certificates at startup (or uses custom certs mounted at /certs-src/). Connection URL scheme changed from redis:// to rediss://. New PKI method EnsureRedisServerCert() generates and signs Redis server certificates via the internal CA. Full mTLS support available via tls_cert_file and tls_key_file config options.

  • Container Registry Browser: Full UI for browsing private and public container registries. List repositories, explore tags with digest, platform, and size details, and inspect image manifests (config, layers, OS/architecture). Supports Docker Hub, GitHub Container Registry, and any OCI-compliant private registry. New RegistryService with authentication caching, GET /registries/{id}/browse, /{id}/tags/{repo}, and /{id}/manifest/{repo}/{ref} routes. Three new template pages: browse, tags, manifest.

  • Drift Detection: Automatically detects configuration drift between the desired and actual state of running containers. Compares expected image tag, environment variables, volume mounts, port bindings, and resource limits against what is actually running. Results presented in a dedicated Drift page with per-container diff view. Backed by DriftService, migration 040_drift_detection, and DriftDetection/DriftDiff models.

  • Change Events Feed: Chronological audit trail of infrastructure changes — container start/stop/restart, image pulls, stack deploys, configuration edits, and user actions — displayed in a filterable timeline. Backed by ChangesService, migration 039_change_events, and ChangeEvent/ChangeEventStats models. Accessible at /changes.

  • Resource Cost Optimization: Analyzes container CPU and memory usage patterns and surfaces rightsizing recommendations (over-provisioned and under-provisioned containers). Calculates estimated cost impact based on resource waste. New CostOptService, migration 041_resource_optimization, ResourceRecommendation/ResourceUsageSample models, and /costopt page.

  • Session Recording & Replay: Terminal sessions (SSH, host exec, container exec) can now be recorded and replayed in-browser with full timing accuracy. Recordings are stored server-side. New RecordingService, migration 042_session_recording, session replay routes at /session-replay/{id} and /session-replay/{id}/data.

  • Calendar: Integrated operations calendar for scheduling maintenance windows, tracking SLA deadlines, and coordinating team tasks. Supports events, tasks with checklists, and notes. New CalendarService, migration 044_calendar, CalendarEvent/CalendarTask models, and a full calendar grid UI at /calendar.

  • Scheduled Jobs Management UI: Visual management page for all recurring background jobs (backup, retention, metrics collection, security scans, drift checks, SLA evaluation). View status, next run time, last result, and manually trigger jobs. Accessible at /jobs/scheduled.

  • Developer Tools Suite: 15 built-in browser-based developer utilities, accessible at /tools and individually:

    • Encoders: Base64 encode/decode, URL encode/decode, HTML entities, hex
    • Formatters: JSON pretty-print/minify, YAML↔JSON conversion
    • Generators: UUID v4/v7, random strings, secure passwords, Lorem Ipsum
    • Hash: MD5, SHA-1, SHA-256, SHA-512, bcrypt calculator
    • Network: CIDR/subnet calculator, IP geolocation lookup, DNS resolver
    • Regex: Live regex tester with match highlighting and group extraction
    • Text Diff: Side-by-side and unified diff viewer for text comparison
    • JWT: JWT decoder with header/payload/claims display and expiry validation
    • Crypto: RSA/ECDSA key pair generation, certificate info viewer
    • Token: API key generator, TOTP secret generator
    • All tools run client-side with no server round-trips
  • Enterprise Feature Previews: Eight preview pages for upcoming Enterprise tier features — OPA Policy Engine, Compliance Frameworks (SOC2/ISO27001/CIS), Image Signing & Verification, Runtime Security (eBPF-based), Custom Dashboards, Ephemeral Environments, Manifest Builder, and Git Sync — each with feature descriptions and early-access prompts.

  • About Page: Application version, build info, license edition, active feature flags, and runtime statistics accessible at /about.

  • App Catalog: 14 New One-Click Deploy Apps: The stack catalog grows from 6 to 20 apps, now organized into 7 categories. New additions:

    • Storage: Nextcloud (file sync, calendar, contacts, 300+ apps)
    • Networking: Traefik v3 (Docker service discovery, Let's Encrypt), WireGuard Easy (VPN server with web UI)
    • Communication: Mattermost (Slack-compatible team messaging)
    • Security (new category): Passbolt (E2E-encrypted team password manager, LDAP sync), Vaultwarden (Bitwarden-compatible, works with all Bitwarden clients), Authentik (enterprise SSO with OAuth2, SAML, LDAP proxy, SCIM)
    • Monitoring (new category): Uptime Kuma (uptime monitoring with status pages, 90+ notification channels), Grafana + Prometheus (metrics stack with embedded prometheus.yml via Docker Compose configs, includes node-exporter)
    • Development: Woodpecker CI (pipeline-as-code CI/CD with native Gitea OAuth2 integration)
    • Database (new category): PostgreSQL 16 + pgAdmin 4 (shared database server with web management UI)
  • Dashboard Service: New DashboardService aggregates container stats, host health, recent events, storage usage, and security scan summaries into a single optimized query for the main dashboard. Replaces multiple individual queries.

  • Nginx Reverse Proxy Backend: New services/proxy/nginx/ sub-package adds a complete Nginx proxy backend alongside the existing Caddy adapter. Includes ACME certificate management, upstream builder, and API client. The proxy service abstraction layer is refactored with backend.go and caddy_backend.go interfaces.

  • Compliance PDF Report Generator: The compliance service gains evaluator.go (CIS Docker Benchmark scoring engine) and pdf_report.go (generates downloadable audit-ready PDF reports with findings, risk ratings, and remediation steps).

  • Runbook Approvals: Multi-step runbook execution now supports approval gates. Designated approvers must sign off before the next runbook step executes. New RunbookApproval model, migration 043_runbook_approvals, and runbook_execute.go scheduler worker.

  • Automatic Deployment Worker: New auto_deploy.go scheduler worker continuously watches for GitOps sync triggers and stack update webhooks, automatically redeploying stacks when new image tags are pushed or repository changes are detected.

  • SLA Breach Worker: New sla_breach.go worker evaluates SLA thresholds against live metrics on each scheduler tick, firing notifications and creating calendar events when breach conditions are detected.

  • Webhook Dispatch Worker: New webhook_dispatch.go worker handles reliable asynchronous delivery of outbound webhooks with retry logic and delivery confirmation tracking.

  • TOTP Replay Attack Protection: Redis-backed TOTPReplayStore rejects one-time codes that have already been used within their validity window, preventing replay attacks even when the server clock is slightly ahead of the client.

  • Database Migrations 036–044: Nine new schema migrations covering agent events table (036), git sync repo full-name field (037), vulnerability remediation tracking (038), change events (039), drift detection state (040), resource usage samples and optimization recommendations (041), session recording storage (042), runbook approval gates (043), and calendar events/tasks (044).

  • WebSocket Origin Validation: Dedicated ws_origin.go module validates the Origin header on all WebSocket upgrade requests in both the web and API layers, rejecting cross-origin connections from unauthorized domains.

  • Comprehensive Test Suite: ~140 new _test.go files added across the entire codebase. Shared testutil/testutil.go helper package. Coverage now spans agent sub-packages (executor, connection, inventory), Docker SDK wrappers, all seven service layers, PostgreSQL and Redis repositories (including integration tests), API auth handlers, and web WebSocket origin logic. Integration tests for Gitea and NPM clients added with httptest mocking.

  • GitHub Actions CI Pipeline: Lint, test, security scan, build, and Docker image push workflow.

  • GoReleaser Configuration: Multi-platform release builds for Linux (amd64, arm64).

  • Pre-commit Hook: govulncheck, migration verification, and go mod tidy checks.

  • Prometheus Scrape Configuration: Templates for usulnet and agent metrics.

Changed

  • Application Initialization Refactored: Monolithic app.go (2,554 lines) decomposed into eight domain-specific initialization files — init_docker.go, init_api.go, init_auth.go, init_scheduler.go, init_server.go, init_services.go, init_web.go, and init_context.go — plus bootstrap.go, adapters.go, and commands.go. Each file has a single clear responsibility, improving readability and testability.

  • Route Permissions Hardened: SSH, RDP, and SFTP connection routes are now split into separate permission groups. Read-only operations (host:view) and mutation operations (host:update) are independently gated. SFTP write operations and SSH tunnel create/toggle/delete now require host:update; listing and viewing require only host:view.

  • Auth Rate Limiting: Login and TOTP POST endpoints are now wrapped with WebAuthRateLimit() middleware, limiting brute-force attempts per IP.

  • Request Body Limit: All authenticated routes now enforce a 10 MB maximum request body size via MaxRequestBody middleware, preventing memory exhaustion from oversized uploads to unexpected endpoints.

  • Logout CSRF Protection: POST /logout moved inside the authenticated middleware group, ensuring CSRF validation applies. The GET /logout alias is kept for plain anchor links.

  • API DTO Layer Removed: The api/dto/request and api/dto/response packages were absorbed directly into handler structs, eliminating an unnecessary indirection layer and reducing boilerplate.

  • Container Registry UI Dark Theme: Registry browse, tags, and manifest pages rewritten to use the project's dark-first Tailwind classes (bg-dark-800, divide-dark-600, hover:bg-dark-700/50) instead of the light-mode-first dark: variant pattern, matching the rest of the application.

  • Error Context Wrapping: 234 bare return err statements wrapped with contextual fmt.Errorf messages for better debugging and log traceability.

  • Configurable Paths: Hardcoded paths (/tmp/usulnet/*) moved to a configurable paths section in config.yaml.

  • PostgreSQL TLS by Default: Default PostgreSQL SSL mode changed to require. Connection enforces TLS verification.

  • Redis TLS by Default: Redis connection URL scheme changed from redis:// to rediss://. All deployment configurations (docker-compose, install script, test environment) updated with TLS-enabled Redis.

Fixed

  • Containers Not Appearing After Restart (critical): bootstrapLocalHost previously returned early if the local Docker host row already existed in the database, leaving hosts stuck in offline status after any Docker connectivity failure. Fixed with an ON CONFLICT DO UPDATE SET status = 'online' upsert that always restores online status on startup. The reconciliation worker and event watchers filter by status = 'online', so this was silently preventing all container sync.

  • Host Never Recovered from Offline: performHealthChecks correctly called SetOffline when a ping failed but never called UpdateStatus(..., "online", ...) when the ping subsequently succeeded. Hosts marked offline by a transient Docker outage stayed offline until the next restart. Fixed by adding the success branch with UpdateStatus.

  • Shortcuts Form Multiple Submission: The three icon type inputs (fa, url, emoji) sharing name="icon" were all submitted simultaneously regardless of which icon type was selected, because x-show only sets display:none without disabling form submission. Fixed by adding :disabled="iconType !== 'X'" Alpine.js bindings so only the active input is included in the form submission.

  • Ansible Inventory Routes: The /tools/ansible handler (handler_ansible.go) was fully implemented but its routes had been commented out, causing a 404 for both the sidebar navigation link and the tools list card. Routes re-registered: GET /ansible, POST /ansible/upload, POST /ansible/parse, DELETE /ansible/{id}.

  • Node Metrics "No Data Available": The metrics collector was using MetricsTypeNode to store node-level metrics but the handler was querying with a different type constant. Aligned the type constants so node Storage & Resources displays data correctly.

  • NATS "Disconnected" on About Page: The about page handler was probing NATS connectivity before the client had fully connected. Added a connection readiness check so the NATS status reflects the actual connection state.

  • Stack Deploy Log Not Streaming: Stack deployment output was buffered and only shown after completion. Fixed to stream log lines in real-time via the WebSocket connection.

  • Calendar Event Creation: Calendar service was not properly initializing the event store on first use. Fixed initialization sequence.

  • Neovim Editor Integration: The embedded Neovim terminal was not forwarding resize events, causing display corruption. Fixed WebSocket resize handler.

  • Host File Browser Auth: File browser API endpoints were accessible at operator level despite containing write operations. Elevated to admin-only consistent with the security model.

  • Forward Reference Compile Error: Fixed forward reference of trackedVulnRepo in app.go causing build failure.

  • NATS Client Never Connected: Connect() was never called after NATS client creation, leaving the messaging bus non-functional.

  • Audit Service Standalone Mode: apiHandlers.Audit was not initialized in standalone mode, causing nil pointer dereference on audit log queries.

  • Orphan Contexts in Goroutines: Fixed orphan contexts in Trivy goroutine and scheduler callbacks that could leak resources.

  • Startup Timing Race: Replaced time.After startup timing with ready channels for deterministic initialization sequencing.

  • Proxy Host ID Resolution: Fixed proxy host ID resolution to match by hashUUIDToInt instead of list index, which broke when hosts were added/removed.

  • Data Race in Audit Mock: Fixed concurrent slice access in audit service test mock.

  • Pricing Page Node Count Display: Fixed visual off-by-one where the pricing calculator showed one more node than actually purchased. The master node (always free) is now displayed separately.

Security

  • Removed hardcoded JWT secret and encryption key from versioned configuration files
  • JWT token lookup restricted to Authorization header and cookie; query-parameter tokens rejected on all API routes
  • CORS restricted to same-origin by default (was *)
  • Host terminal and file browser access elevated to admin-only (previously operator-level)
  • 10 MB upper limit on host file reads via the file browser API
  • Webhook tokens hashed with SHA-256 before database storage
  • Secure cookies enabled by default when TLS is active
  • Per-route Content Security Policy: strict policy globally, relaxed CSP only for Monaco Editor routes
  • getRealIP now uses the rightmost non-private IP from X-Forwarded-For, preventing IP spoofing via prepended addresses
  • FailedLoginAttempts field excluded from User JSON serialization
  • Encryption key validated for hex encoding (not just byte length)
  • Default PostgreSQL SSL mode changed to require
  • Redis TLS encryption enabled by default with ECDSA P-256 self-signed certificates
  • JetStream stream size limits added (MaxBytes/MaxMsgs) to prevent unbounded disk growth
  • TOTP replay attack protection via Redis-backed used-code store
  • WebSocket upgrade requests now validated against allowed origin list

Full Changelog: https://github.com/fr4nsys/usulnet/compare/v26.2.3...v26.2.4

Breaking Changes

  • Redis connection URL scheme changed from redis:// to rediss:// (TLS enforced by default).
  • Connection string defaults updated to require TLS for PostgreSQL and Redis.

Security Fixes

  • Removed hardcoded JWT secret and encryption key from versioned configuration files.
  • JWT token lookup restricted to Authorization header and cookie; query‑parameter tokens rejected on all API routes.
  • CORS now defaults to same‑origin (was *).
  • Host terminal and file browser access elevated to admin‑only.
  • Webhook tokens hashed with SHA‑256 before database storage.
  • Secure cookies enabled by default when TLS is active.
  • WebSocket upgrade requests validated against allowed origin list.

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]