VomeSync Security Audit
Generated: 2026-01-25
Scope: This audit covers the VomeSync webserver API, website UI, Redis storage,
media ingestion pipeline, Home Assistant integration, and CI test coverage in this repository.
It does not replace external penetration testing or infrastructure audits.
Contents
Summary
VomeSync’s security posture centres on strong authentication paths, server-side permission checks,
and minimising exposure of sensitive keys. Bearer keys are never stored in plaintext in Redis, logs are
redacted, and access-key toggles are constrained by server-side permissions.
- Owner writes require signed v2 requests; non-owners cannot call owner endpoints.
- Delegated access keys allow limited actions per switch and are enforced server-side.
- Images are rehosted, size-limited, and converted to WebP with SSRF protections.
System overview
- Webserver API: Express + WebSocket server with Redis-backed state and key metadata.
- Website: static UI served via Nginx, calling API/WS for switch details.
- Home Assistant integration: config flow, coordinator, switch/sensor entities.
- Storage: Redis for state + key metadata, media volume for icons/banners.
Threat model
Unauthorised toggle or privilege escalation
- Risk: A subscriber or public viewer attempts to toggle without permission.
- Mitigation: Owner-only writes require signed v2 state updates.
- Mitigation: Access-key toggles require server-side
toggle permission.
- Mitigation: HA subscriptions are read-only unless an access key is supplied.
Bearer key leakage (logs, Redis, URLs)
- Risk: API/personal/access keys leak via storage or logs.
- Mitigation: Redis stores only hashed key IDs derived via HMAC with
KEY_HASH_SECRET.
- Mitigation: Logger redacts sensitive fields and URL fragments.
- Mitigation: Legacy plaintext records are migrated on first use.
SSRF or malicious image payloads
- Risk: Image URLs target internal services or oversized inputs.
- Mitigation: URL validation blocks local hosts/private IPs and enforces redirects/timeouts.
- Mitigation: Images are size/pixel limited and converted to WebP before hosting.
Abuse or brute-force traffic
- Risk: High-volume requests or abuse of public endpoints.
- Mitigation: Rate limiting per action/identifier; optional CAPTCHA for public listings.
Reverse proxy misconfiguration
- Risk: Exposing internal ports or bypassing TLS.
- Mitigation: Recommended to expose only the proxy; API/WS ports stay internal.
- Mitigation: Production server trusts proxy headers only in production mode.
Security controls
Authentication and authorisation
- Owner state changes require signed v2 payloads at
/api/v2/switch/:uid/state.
- Replay protection uses timestamps + nonce claiming.
- Delegated access keys call
/api/v2/switch/:uid/toggle and must include toggle permission.
- HA coordinator refuses non-owner state changes; access-key toggles use the delegated endpoint.
Key handling and log redaction
- Redis stores only hashed key IDs (HMAC-SHA256) using
KEY_HASH_SECRET.
- API key listings return IDs + metadata, never plaintext keys.
- Legacy plaintext records are migrated to hashed IDs on first use.
- Server logs redact keys, tokens, cookies, and URL fragments.
Media ingestion and hosting
- External image URLs are validated and resolved before fetch.
- Private IPs/localhost are rejected to prevent SSRF.
- Images are size/pixel limited and converted to WebP before serving from
/api/media.
Abuse controls
- Rate limiting is enforced in the auth layer with per-action limits.
- hCaptcha can be enabled for public switch creation/updates.
Transport and deployment
- External TLS is expected at the reverse proxy; in-app SSL is optional.
- CORS origins are configurable; defaults to
* unless restricted.
Security tests
Webserver unit/integration tests
webserver/tests/unit/utils/redis.test.js (hashed key IDs, legacy migration)
webserver/tests/unit/utils/auth.test.js (auth + rate limit)
webserver/tests/unit/utils/redact.test.js (log redaction)
webserver/tests/integration/api.test.js (v2 access keys, public switch rules)
Website UI regression tests
webserver/tests/website/website.test.js (auth gating, toggle dialog, manage-on-website deep link)
Home Assistant integration tests
hacs-addon/tests/test_switch.py::test_switch_toggle_denied_for_non_owners
hacs-addon/tests/test_switch.py::test_switch_turn_on_with_access_key
hacs-addon/tests/test_switch.py::test_switch_created_for_subscription_with_access_key
hacs-addon/tests/test_sensor.py::test_sensor_created_from_imported_cache_for_subscriptions
hacs-addon/tests/test_sensor.py::test_sensor_skips_subscription_with_access_key
hacs-addon/tests/test_coordinator.py::test_coordinator_toggle_with_access_key_updates_subscription
hacs-addon/tests/test_coordinator.py::test_set_switch_state_denies_non_owner
hacs-addon/tests/test_coordinator.py::test_coordinator_rate_limits_toggle
End-to-end coverage
tests/e2e/test_full_flow.py (v2 flows + public discovery)
Operational guidance
Pre-beta essentials
- Set
JWT_SECRET, KEY_HASH_SECRET, and REDIS_PASSWORD to unique, strong values.
- Serve the website/API over TLS via a reverse proxy; keep Redis internal.
- Review docs/OPERATIONS.md for backup/restore and monitoring steps.
Residual risks
Key compromise
- Bearer keys grant access; protect client storage, backups, and admin access.
- Hashed IDs protect Redis at rest, but do not protect active keys in memory or clients.
Dependency and environment risks
- Security depends on third-party libraries (Node, Sharp, Redis).
- Infrastructure hardening (firewalls, TLS, secret management) remains operator responsibility.
Public listings
- Public switches are discoverable and viewable without keys; only toggling is restricted.
Recommendations
Operational improvements
- Run the test suite before releases and after infrastructure changes.
- Rotate access keys on compromise; encourage users to save and back up signing keys.
- Perform periodic restore drills for Redis + media volumes.