Docs · Deploy
Security model
Watchpost sits where infrastructure visibility, credentials, human response, and AI meet. Its threat model begins before the first collector is accepted, and every control on this page states its safe failure mode.
Two security domains
Watchpost user authentication and Watchpost Agent local authentication are separate security domains. They share a password derivation but never share identities, sessions, or authority.
Central server accounts with viewer, operator, and administrator roles. Sessions are server-side and cookie-based; every API path enforces role and CSRF.
Loopback-local admin, technician, and viewer roles that remain manageable while Watchpost is unreachable. Local administration has its own session, Origin, and CSRF controls.
Authentication and sessions
- First administrator: created only while no users exist. Setup and sign-in are mutually exclusive in the UI, and concurrent setup has a single-winner database invariant.
- Ordinary login: by email and password; identities are normalized so case differences cannot collide or create duplicates.
- Password policy: a minimum of seven characters; password hashing uses a salted, deliberately expensive versioned PBKDF2-HMAC-SHA256 derivation with bounded input handling, shared by the central server and the agent.
- Sessions: created on login, carried in HttpOnly, SameSite cookies, and invalidated by logout or administrative session revocation.
- Origin and CSRF: both applications validate Origin and CSRF for authenticated state changes. Central Watchpost uses its original Host and does not use forwarded client-IP or scheme headers for authorization. Watchpost Agent considers forwarded host, scheme, and client-address headers only when the direct peer belongs to
WATCHPOST_AGENT_TRUSTED_PROXIES. - Agent local roles: where implemented, local admin, technician, and viewer roles gate the agent's loopback surface; remote exposure of agent administration is an explicit advanced mode.
- Session invalidation and restart: expired sessions are always pruned; a password rotation revokes every other session for that account. Agent local state survives restart and remains guarded by its local accounts.
- Rate limiting and lockout: repeated failed logins are throttled to slow credential probing; the exact bound is enforced in the application service, not in the client.
Keep these distinct: a user session, a pairing request, an agent credential, a bootstrap token, and an installation identity are different authorities and are never interchangeable.
First-administrator bootstrap token
Dangerous remote first-administrator setup requires explicit operator authorization. The gate is enforced automatically whenever the listener is not loopback or whenever a token is supplied through an environment variable or token file. Loopback-only first setup may proceed under its documented local trust model unless the operator supplies a token, which forces the requirement even on loopback. On the agent, WATCHPOST_AGENT_EXPOSE only permits a non-loopback bind; it does not by itself enable the token gate on a loopback listener, so a loopback-behind-proxy deployment must supply a token explicitly.
Explicit reverse-proxy trust
Forwarded headers are not authority. Central Watchpost does not implement a trusted-proxy resolver: it does not use forwarded client-IP or scheme headers for authorization, and there is no WATCHPOST_TRUSTED_PROXIES setting. Its proxy boundary is loopback binding, TLS termination at the proxy, original-Host preservation, --secure-cookies, and firewall or network policy.
Watchpost Agent remote administration implements the explicit forwarded-header resolver. Proxy trust is configured with explicit proxy IP/CIDR networks (WATCHPOST_AGENT_TRUSTED_PROXIES), and the direct peer must belong to a configured trusted-proxy network before forwarded host, protocol, or client-address headers are considered. Forwarded headers from any other peer are ignored or rejected according to the request.
- Agent trusted-proxy configuration is separate from client allow/deny networks.
WATCHPOST_AGENT_ALLOW_CIDRS/WATCHPOST_AGENT_DENY_CIDRSrestrict the verified client address after the trusted-proxy chain; when a CIDR policy is active, an unresolvable client address fails closed. - Operators must configure the actual proxy-to-agent network, not arbitrary public client ranges. Overly broad trusted-proxy CIDRs weaken spoofing protections.
- HTTPS termination and secure-cookie behaviour must remain consistent: use
--secure-cookiesorWATCHPOST_AGENT_SECURE_COOKIES=1when HTTPS terminates at the proxy. - Direct internet exposure without a reviewed proxy/TLS/network configuration is not endorsed. Loopback binding is the documented recovery path.
Correct examples are on the dedicated proxy pages: Caddy HTTPS and nginx HTTPS, including the agent remote-administration configuration and the distinction between a same-machine and a remote-machine reverse proxy.
Audit guarantees and safe failure
Watchpost records security-sensitive state changes with two precise guarantees.
Persistent mutations - configuration, accounts, pairing, rotation, password changes, and audit-carrying changes - commit the state mutation and its attributed audit record atomically:
Ephemeral in-memory sessions - login, logout, and administrative session revocation - cannot share a state save with their audit row, so the attributed audit event is durably persisted before the in-memory session mutation:
Safe failures:
- a failed login audit persistence creates no session;
- a failed logout audit persistence leaves the server-side session valid and returns an error;
- a failed administrative revocation audit persistence leaves targeted sessions valid and returns an error;
- successful login, logout, and revocation each emit one correctly attributed audit event.
If logout failure still clears the browser cookie, be precise about what that means: the client may lose its local cookie while the server-side session remains valid until it expires or is successfully revoked. That session is not destroyed. This ordering is safer than silently changing authority without a durable audit trail, but it is not a claim that every possible operational event is audit-covered.
Capabilities
Viewer, operator, and administrator roles are enforced by the server on every API path. Administrators manage accounts through the Users view: create users, change roles, reset passwords and revoke sessions. Any user can rotate their own password from the Account view, which revokes every other session for that account. The post owner field is metadata; evidence is not owner-isolated. Hiding a button is usability, not authorization. Permission-denied responses are rendered as deliberate UI states rather than unexplained empty panels.
Central checks and SNMP targets may deliberately monitor internal addresses, which is a core Watchpost feature. Operators can optionally restrict targets with CIDR allow/deny lists and denied ports; the policy is applied at schedule creation and again at run time against the resolved address, so a hostname that rebinds to a denied network is refused rather than probed. On-demand checks are rate-limited and audited.
Secrets
Collector, SNMP, notification, peer, and model credentials require narrow use, redaction, rotation, and exclusion from diagnostics and model context. Pairing and collector secrets are displayed once. Passwords are never returned by profile or status APIs.
Prompt injection
Monitored text is untrusted. A log line requesting shell access has no authority. Investigation tools accept server-defined typed inputs and return only citations that the server can verify.
Typed operations
Privileged operations require a registered type, validated parameters, actor capability, post scope, idempotency key, audit record, optional independent approval, atomic execution claim, and verification result. Arbitrary model-authored shell execution is outside the design. Every registered action executes a real operation and records its verification outcome - rerunning a check records the observed ok, failure and latency; silencing a route records disabled. No registered action is a no-op. Read capability never grants write authority, and no write operation travels through a generic untyped command path.
Industrial systems
Watchpost is not an industrial safety or control system. PLC writes and building-control commands remain future research requiring a separate threat model. They must not replace interlocks, certified safety systems, or deterministic control.
See Verification and hardening for what has been exercised, and Current limitations for what has not.
See the application repository's SECURITY.md. Do not include real credentials, sensitive telemetry, or exploitable production details in a public issue.