Commit Graph

1418 Commits

Author SHA1 Message Date
rcourtman 563f4893fb test: guard ai settings endpoints by scope 2026-02-04 10:39:28 +00:00
rcourtman 86b75c9e7c test: enforce monitoring:write for metadata mutations 2026-02-04 10:38:48 +00:00
rcourtman 9409969ddd test: require monitoring:read for core data endpoints 2026-02-04 10:37:53 +00:00
rcourtman 8ed47b8971 test: enforce agent scope checks 2026-02-04 10:37:06 +00:00
rcourtman 37f909c6dd test: guard discovery endpoints by scope 2026-02-04 10:35:43 +00:00
rcourtman ad21be68f3 test: enforce settings:write for config node mutations 2026-02-04 10:34:41 +00:00
rcourtman ead8eb7087 test: require ai:execute scope on more ai endpoints 2026-02-04 10:33:53 +00:00
rcourtman c68e386d01 test: cover ai patrol and run-command scopes 2026-02-04 10:32:05 +00:00
rcourtman b9eee668e5 test: expand security regression coverage 2026-02-04 10:28:41 +00:00
rcourtman 5c1487e406 feat: add resource picker and multi-resource report generation
Replace manual resource ID entry with a searchable, filterable resource
picker that uses live WebSocket state. Support selecting multiple
resources (up to 50) for combined fleet reports.

Multi-resource PDFs include a cover page, fleet summary table with
aggregate health status, and condensed per-resource detail pages with
overlaid CPU/memory charts. Multi-resource CSVs include a summary
section followed by interleaved time-series data with resource columns.

New POST /api/admin/reports/generate-multi endpoint handles multi-resource
requests while the existing single-resource GET endpoint remains unchanged.

Also fixes resource ID validation regex to allow colons used in
VM/container IDs (e.g., "instance:node:vmid").
2026-02-04 10:24:23 +00:00
rcourtman dcfa8cf0ba fix: prevent false PBS backup indicators when VMIDs collide across PVE instances (#1177)
When namespace matching fails, the VMID-only fallback now checks whether
the VMID appears on multiple PVE instances. If ambiguous, the fallback
is skipped — preventing backups from being falsely attributed to the
wrong guest. Unique VMIDs still fall back as before.
2026-02-04 10:11:35 +00:00
rcourtman f60050a801 fix(security): restrict query-string token auth to WebSocket upgrades only
API tokens passed via ?token= query parameter were accepted on all HTTP
requests. This is a security concern because tokens in URLs can leak via
server logs, browser history, referrer headers, and proxy logs.

The query-string token path exists solely for WebSocket connections which
cannot set custom headers during the upgrade handshake. This change adds
an isWebSocketUpgrade check to all three query-string extraction sites
in CheckAuth and extractAndStoreAuthContext, rejecting ?token= on regular
HTTP requests while preserving WebSocket functionality.

No frontend impact — the kiosk flow stores the token in sessionStorage
then uses X-API-Token headers for all API calls.
2026-02-04 09:52:32 +00:00
rcourtman a6f2a674eb fix: resolve test failures blocking release
- KnowledgeStore: use atomic write (temp+rename) to prevent file
  corruption from concurrent async saves
- Change password tests: add auth headers since endpoint now requires
  authentication
- ClearSession test: expect 2 cookies (pulse_session + pulse_csrf)
  matching updated clearSession behavior
- API token test: update to match current behavior where query-string
  tokens are accepted (needed for WebSocket connections)
- Host agent config: allow ScopeHostManage to resolve any host, not
  just token-bound hosts
2026-02-03 23:53:54 +00:00
rcourtman 00793c7688 fix: resolve ExportConfig deadlock and update apprise test
ExportConfig held a read lock while calling LoadNodesConfig, which
could trigger a migration requiring a write lock - causing a deadlock.
Removed the redundant outer lock since each Load function manages its
own locking.

Also updated TestAppriseConfigPersistence to match the security fix
that hardcodes CLIPath to "apprise" to prevent RCE.
2026-02-03 23:35:36 +00:00
rcourtman 6059759958 feat: Add sparkline support for unified host agents on hosts page
Backend:
- Add HostData field to ChartResponse struct in types.go
- Add host data processing in /api/charts endpoint using 'host:' prefix key
- Include hosts count in debug logging for chart responses

Frontend:
- Add 'host' to MetricResourceKind type in metricsKeys.ts
- Add hostData field to ChartsResponse interface in charts.ts
- Process hostData in seedFromBackend() in metricsHistory.ts
- Pass resourceId to EnhancedCPUBar and StackedMemoryBar in HostsOverview.tsx
- Add '7d' and '30d' to TIME_RANGE_OPTIONS in metricsViewMode.ts

This enables sparkline trend visualization for unified host agents,
consistent with Proxmox guests. Data accumulates over time at 30s intervals.
2026-02-03 22:59:55 +00:00
rcourtman 7c1ebbecd5 fix(security): enhance webhook validation, enforce API scopes, and improve test coverage 2026-02-03 22:41:44 +00:00
rcourtman a3436fbde5 fix(tests): disable email in concurrency test to prevent CI timeouts
The TestNotificationManagerEmailConfigConcurrency test was causing CI
failures by triggering 1000+ email send attempts to a non-existent SMTP
server, each with retries and delays. This test verifies concurrent config
updates don't cause races, not actual email delivery. Disabling email
eliminates the network operations that were causing 60+ second test runs
and occasional CI failures.
2026-02-03 22:39:59 +00:00
rcourtman 5a990dd554 Fix sparkline data inconsistency and support 30d range 2026-02-03 22:39:50 +00:00
rcourtman 81f146dcf0 Security fixes: Prevent Apprise RCE and Webhook DNS Rebinding 2026-02-03 22:00:02 +00:00
rcourtman a9ed380718 fix(websocket): respect X-Forwarded headers in same-origin check
- Use X-Forwarded-Proto/X-Forwarded-Scheme for scheme detection
- Use X-Forwarded-Host for host matching behind reverse proxies
- Update tests with remoteAddr for CSWSH protection validation
2026-02-03 21:45:39 +00:00
rcourtman 1490a6e6e3 revert: remove dual-key license verification
Restored original license signing key from backup - key was never
compromised (private repo). Removes unnecessary dual-key complexity:

- Remove legacyPublicKey and SetLegacyPublicKey from license.go
- Simplify signature verification to single key
- Remove EmbeddedLegacyPublicKey from pubkey.go
- Remove PULSE_LICENSE_LEGACY_PUBLIC_KEY from Dockerfile and workflows
- Remove dual-key test
- Simplify mock.env
2026-02-03 21:29:21 +00:00
rcourtman f810a003eb license: add dual-key verification 2026-02-03 20:45:00 +00:00
rcourtman b7a94bad9f security: fix websocket scope and agent impersonation
1. Enforce monitoring:read scope on WebSocket upgrades
   - Prevents low-privilege tokens (e.g. host-agent:report) from accessing
     full infra state via requestData on the main WebSocket.

2. Enforce agent token binding to prevent impersonation
   - Added Metadata field to APITokenRecord to support bound_agent_id
   - Updated agentexec server to validate token-to-agent binding if present
   - Prevents agent:exec tokens from registering as arbitrary agent IDs
2026-02-03 20:40:08 +00:00
rcourtman 0dfe3d16b3 security: secure socket.io, test-notification, and stats endpoints
1. Secure /socket.io/ endpoint
   - Previously allowed unauthenticated WebSocket upgrades via transport=websocket
   - Now enforces CheckAuth() before upgrade

2. Secure /api/test-notification
   - Previously unauthenticated and allowed broadcasting to all clients
   - Now requires Admin + settings:write scope

3. Secure /simple-stats
   - Added authentication requirement (was public)
2026-02-03 20:08:16 +00:00
rcourtman dd47cbe5b4 security: fix host token binding, AI findings scope, and DLQ credential exposure
1. Host agent link/unlink/delete now require settings:write scope
   - Prevents compromised host-agent:manage tokens from manipulating
     or deleting unrelated hosts
   - Host tokens scoped to one host can no longer affect other hosts

2. AI investigation endpoints now require ai:execute scope
   - /api/ai/findings/* was only protected by RequireAuth
   - Low-privilege tokens could read investigation details and chat logs

3. Notification DLQ endpoints now require settings:read/write scope
   - DLQ entries contain notification configs (webhooks, SMTP, etc.)
   - Prevents monitoring:read tokens from reading credential data
   - DLQ retry/delete operations require settings:write
2026-02-03 19:59:46 +00:00
rcourtman fdc99418d6 security: add authentication to /api/security/apply-restart endpoint
CRITICAL FIX: This endpoint previously allowed unauthenticated users to
trigger service restarts, which is a denial-of-service vulnerability.

Now requires:
- Authentication (CheckAuth) when auth is configured
- Admin role for proxy auth users
- settings:write scope for API tokens

Initial setup (no auth configured yet) remains accessible to allow
first-time security configuration to trigger restart.
2026-02-03 19:55:29 +00:00
rcourtman 832fda6c96 security: add scope checks to alerts, AI models, patrol status/stream, and remaining AI endpoints
- /api/alerts/* now requires monitoring:read scope
- /api/ai/models now requires ai:chat scope
- /api/ai/patrol/status and /api/ai/patrol/stream now require ai:execute scope
- /api/ai/patrol/findings now requires ai:execute scope
- /api/ai/remediation/* endpoints now require ai:execute scope
- /api/ai/circuit/status now requires ai:execute scope
- /api/ai/incidents/* now requires ai:execute scope
- /api/ai/question/* now requires ai:chat scope
- /api/ai/agents now requires ai:execute scope
- /api/ai/cost/summary now requires settings:read scope
2026-02-03 19:48:43 +00:00
rcourtman c295ee277f security: add scope checks to AI endpoints and mitigate CSWSH
- AI Intelligence endpoints (/api/ai/intelligence/*, /api/ai/forecast/*,
  /api/ai/unified/findings, etc.) now require ai:execute scope to prevent
  low-privilege tokens from reading sensitive intelligence data

- AI Knowledge endpoints (/api/ai/knowledge/*) now require ai:chat scope
  to prevent arbitrary guest data access across the fleet

- AI Debug Context (/api/ai/debug/context) now requires settings:read scope
  to prevent system prompt and infrastructure details leakage

- WebSocket origin check now validates peer IP is private when allowing
  private network origins, mitigating CSWSH attacks where a malicious page
  on the same LAN tries to hijack connections using victim's session cookie
2026-02-03 19:40:46 +00:00
rcourtman 2ebe65bbc5 security: add scope checks to AI Patrol and agent profile endpoints
- AI Patrol mutation endpoints (acknowledge, dismiss, suppress, snooze, resolve,
  findings/note, suppressions/*) now require ai:execute scope to prevent
  low-privilege tokens from blinding patrol by hiding/suppressing findings

- Agent profile admin endpoints (/api/admin/profiles/*) now require
  settings:write scope to prevent low-privilege tokens from modifying
  fleet-wide agent behavior
2026-02-03 19:29:56 +00:00
rcourtman 1733bea15c feat(ui): show backup permission warnings on Backups page
When PVE backup polling detects permission errors (403/401/permission
denied), track them per instance and surface them via the scheduler
health endpoint.

The Backups page now fetches instance warnings and displays a banner
when backup permission issues are detected, telling users exactly how
to fix the problem.

Related to #1139
2026-02-03 19:27:10 +00:00
rcourtman 69e3286e5e security: fix AI OAuth scope bypass, approval replay attacks, and approval endpoint scope gating
- OAuth endpoints now require settings:write scope (not just admin)
- Approval endpoints now require ai:execute scope
- Added CommandHash to approvals for replay protection
- Approvals are now single-use (consumed on first use)
- consumeApprovalWithValidation validates command matches approval
2026-02-03 19:15:15 +00:00
rcourtman 316a56299c fix(agent): grant PVEDatastoreAdmin for backup visibility
The unified agent's Proxmox setup was missing the PVEDatastoreAdmin
permission on /storage, causing local PVE backups to not appear in
Pulse's backup overview for users who set up nodes via the agent.

The UI-generated setup script already included this permission, but
the agent path (--enable-proxmox) did not, creating an inconsistency.

Related to #1139
2026-02-03 19:11:25 +00:00
rcourtman 43c696896f security: fix high severity authz issues (AI chat, patrol autonomy, discovery, host config) 2026-02-03 19:00:56 +00:00
rcourtman 4fdc0cae64 feat(reporting): enrich metric reports with detailed resource info 2026-02-03 18:51:27 +00:00
rcourtman 225da6eb39 security: strengthen public URL capture to enforce scope and admin checks 2026-02-03 18:49:42 +00:00
rcourtman 83382ee251 security: enforce scope checks on admin diagnostics endpoint 2026-02-03 18:44:55 +00:00
rcourtman 8f92273e33 security: enforce scope checks for AI approvals and config management 2026-02-03 18:40:31 +00:00
rcourtman 60f9e6f07f security: fix multiple vulnerabilities (SAML, SSRF, Auth)
Addressed several security findings:
- SAML: Sanitized RelayState to prevent open redirects
- SAML: Fixed logout to properly invalidate server-side sessions
- Auth: Added auth, rate limiting, and logout checks to password change endpoint
- AI: Added admin/scope gating (ai:execute) for command execution
- AI: Blocked private IP ranges in fetch_url to prevent SSRF
- Config: Enforced settings:read/write scopes for export/import
- Agent: Added agent:exec scope requirement for WebSockets
2026-02-03 18:39:15 +00:00
rcourtman 442d29e9b9 feat(reporting): enhance PDF reports with Executive Summary and actionable insights
- Add professional cover page with branding and report period
- Add Executive Summary page with health status banner (HEALTHY/WARNING/CRITICAL)
- Add Quick Stats section with color-coded metrics and trend indicators
- Add Key Observations with automated analysis of CPU, memory, disk, and disk wear
- Add Recommended Actions section with prioritized, actionable items
- Add Resource Details page with hardware info, storage pools, physical disks
- Add color-coded tables for alerts, storage, and disk health
- Add performance charts with area fills and proper scaling
- Improve overall visual design with consistent color scheme
- Fix SAML session invalidation to use correct SessionStore method
2026-02-03 18:17:31 +00:00
rcourtman 2e4e7b06a8 fix(tests): update reporting handlers tests to match new signature
NewReportingHandlers now requires a MultiTenantMonitor parameter.
Pass nil since the tests don't need the monitor functionality.
2026-02-03 17:48:44 +00:00
rcourtman d716bbfdeb fix(security): add proper authorization to sensitive endpoints
- /api/agent-install-command: require admin + settings:write scope
  Previously only RequireAuth, allowing any authenticated user to mint
  high-privilege API tokens (host-agent:manage)

- /api/system/ssh-config: require settings:write scope
  Previously any authenticated token could modify ~/.ssh/config

- /api/system/verify-temperature-ssh: require settings:write scope
  Previously any authenticated token could trigger SSH connection
  attempts to arbitrary nodes (network scanning risk)

- /api/diagnostics: require admin privileges
  Previously exposed API token metadata (IDs, hints, usage mapping)
  to any authenticated token, enabling enumeration attacks
2026-02-03 17:47:40 +00:00
rcourtman 12a5a98117 fix: SSE race conditions, alert user spoofing, and security status oracle
SSE Broadcaster:
- Add per-client mutex to prevent concurrent writes to ResponseWriter
- Fix data race in cleanupLoop reading LastActive without synchronization
- Update LastActive in SendHeartbeat so clients aren't incorrectly pruned
  after 5 minutes of idle heartbeat traffic

Alert Acknowledgements:
- Extract authenticated user from X-Authenticated-User header instead of
  hardcoding 'admin' or trusting request body's User field
- Prevents audit log spoofing and ensures accurate user attribution

Security Status Endpoint:
- Remove ?token= query param validation from public /api/security/status
- Prevents endpoint from acting as a token validity oracle for attackers
- Authentication still works via session cookies and X-API-Token header
2026-02-03 17:40:58 +00:00
rcourtman beae4c860c fix: address 6 security and reliability issues
Security fixes:
- Auto-register now requires settings:write scope for API tokens
- X-Forwarded-For in auto-register only trusted from verified proxies
- Public URL capture requires authentication (no loopback bypass)
- Lockout reset now uses RequireAdmin for session users

Reliability fixes:
- Docker stop command expiration clears PendingUninstall flag
- Cancelled notifications get completed_at set and are cleaned up
2026-02-03 17:32:44 +00:00
rcourtman b2639ed5a5 Fix security vulnerabilities and critical bugs
- Fix WebSocket CORS bypass by strictly verifying origin
- Fix OIDC refresh token persistence by encrypting at rest
- Fix grouped webhook data mutation by cloning alerts
- Fix host agent uninstall authorization and config fetch logic
- Fix notification queue recovery for stuck sending items
- Fix ignored update history limit parameter
- Fix ineffective break statement in WebSocket write pump
2026-02-03 17:16:27 +00:00
rcourtman c7f4030c29 fix(monitoring): prevent memory leak from stale metrics history and rate tracker entries
MetricsHistory.Cleanup() was defined but never called, and even if called,
it only removed old data points without deleting map entries for deleted
containers/VMs. Each stale entry leaked ~224KB (7 pre-allocated slices).

Changes:
- Call metricsHistory.Cleanup() and rateTracker.Cleanup() in maintenance loop
- Delete map entries entirely when all data points have expired
- Return nil instead of empty slice in cleanupMetrics() to release backing arrays
- Add Cleanup() method to RateTracker with 24-hour stale threshold
- Add debug logging to track cleanup activity

Related to #1153
2026-02-03 17:16:06 +00:00
rcourtman f8bb14977d fix(discovery): include IPAddresses in state adapter for URL suggestion
The discovery state adapter was not copying IPAddresses from the models
when converting VM/Container state. This caused getResourceExternalIP()
to return empty strings, preventing URL suggestion from working.
2026-02-03 17:05:01 +00:00
rcourtman bd030c7c87 security: fix webhook SSRF, rate limit spoofing, metrics retention, and url poisoning
- Fix SSRF and rate limit bypass in SendEnhancedWebhook by validating the rendered URL.
- Fix rate limit spoofing in updates API by using secure IP extraction (trusted proxies).
- Fix memory leak in metrics history by correctly clearing fully stale data series.
- Fix public URL poisoning by preventing overwrites when explicitly configured.
2026-02-03 16:58:13 +00:00
rcourtman 3ea3f0f827 feat(discovery): auto-suggest web interface URLs for discovered services
Add deterministic URL suggestion based on service type and external IP:

- Add SuggestedURL field to ResourceDiscovery type (Go + TypeScript)
- Create url_suggestion.go with 60+ service defaults (Jellyfin, Plex,
  Home Assistant, Grafana, Proxmox, etc.)
- Support HTTPS services, custom paths (/web, /dashboard/, /admin)
- Fall back to discovered ports for unknown services
- Add UI in DiscoveryTab with "Use this" button to populate URL input
- Add comprehensive unit tests for URL suggestion logic

Suggestion only appears when no custom URL is saved. User clicks
"Use this" to populate the input, then "Save" to confirm.
2026-02-03 16:49:57 +00:00
rcourtman 4f40c3d751 fix: resolve critical stability and auth issues
- Fix data race in webhook notifications by removing shared state
- Fix duplicate monitors on config reload by stopping old instances
- Prevent metrics ID deletion on transient startup errors
- Support Bearer auth header for config export/import endpoints
2026-02-03 16:46:27 +00:00
rcourtman 935326ebb7 fix(api/ai): resolve critical auth, agent download, and lifecycle issues
- Fix API-only mode to accept Bearer tokens and query params
- Fix data race in API token validation using fine-grained locking
- Fix unified agent download serving wrong binary for invalid arch
- Fix AI infra discovery running when AI disabled and missing stop mechanism
2026-02-03 16:35:12 +00:00