The legacy cleanup section in TEMPERATURE_MONITORING.md only covered 1 of the
5 systemd units and referenced an outdated binary path. Users following these
docs still had the selfheal timer running, generating recurring TASK ERROR
entries in the Proxmox task log.
Updated with the complete set of units, correct file paths, and a note that
upgrading the Pulse container does not remove the sensor proxy from the host.
Added a sensor proxy removal section to UPGRADE_v5.md so users see the warning
during upgrade.
Related to #817
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").
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.
Add three layers of secret leak prevention:
1. .gitleaks.toml — config extending the default ruleset (~150 rules for
AWS, GCP, Stripe, OpenAI, private keys, JWTs, etc.) with allowlists
tuned to suppress false positives from test fixtures and docs.
2. .husky/pre-commit — enhanced with gitleaks protect --staged (graceful
skip if not installed), sensitive file type blocking (.pem, .key, .enc,
id_rsa, etc.), and broadened fallback patterns covering AWS, OpenAI,
GCP, and private key headers alongside existing Stripe checks.
3. .github/workflows/build-and-test.yml — new secret-scan CI job using
gitleaks-action that runs in parallel with build on every push/PR,
serving as the last gate if someone bypasses local hooks.
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.
The previous fix (cf52b5f5) only updated NodeSummaryTable. Guest rows,
Docker hosts, storage, and backup views still used hardcoded 0 decimals,
showing "1 GB/2 GB" instead of "1.50 GB/2.00 GB" for small values.
Related to #1116
- 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
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.
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.
The DiscoveryTab component for Docker containers/services and Kubernetes pods
was not receiving the customUrl and onCustomUrlChange props, causing saved
URLs to be lost when the drawer was reopened.
Changes:
- Add guest metadata management to DockerUnifiedTable (fetches on mount,
caches, listens for external changes)
- Pass customUrl and onCustomUrlChange props to DiscoveryTab in
DockerContainerRow and DockerServiceRow
- Add guest metadata management to KubernetesClusters component
- Update PodRow to receive and pass metadata props to DiscoveryTab
The fix ensures that when users click 'Use this' on a suggested URL and save,
the URL persists correctly across Docker containers, Swarm services, and K8s pods.
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.
- 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
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
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
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
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.
- 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
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