Security
QUBIQ's security model rests on five ideas. Everything else follows from them.
1. Two independent identity realms
| Platform | Runtime (LiveView) | |
|---|---|---|
| Who | Engineers, integrators, administrators | Plant operators |
| Log in at | /login | /{project}/login |
| Users stored in | The QUBIQ configuration database | An external User Database, per project |
| Token secret | JWT_SECRET | LIVE_JWT_SECRET, audience liveview |
| Authorises | Every design-time and administrative action | Viewing published views, writing permitted tags |
A runtime token presented to a design-time request fails on audience, not on permission. The separation is structural, not a policy that could be misconfigured away.
→ Users and roles · LiveView authentication
2. Every action is permission-gated
There is no "authenticated therefore allowed". Every action declares the permission it requires, and the check runs server-side before any work happens.
| Action | Permission it needs |
|---|---|
| Create a connection | Create connections |
| Acknowledge an alarm | Acknowledge alarms |
| Run a pipeline once | Run pipelines |
| Clear the system log | Clear system logs |
| Change who can do what | Manage permissions |
Permissions are grouped so that reading, changing and administering are separable — View the namespace is not Bind a tag to a protocol, and View the audit journal is not Manage the audit journal.
→ Permissions · Full reference
3. Secrets are encrypted and never returned
- The configuration database is encrypted at rest, with a key bound to the machine it runs on:
sealed by Windows DPAPI, or by systemd-creds or the macOS Keychain where those are available.
Changed in 1.0.4 The key is random and pinned to the installation rather than
derived from
ENCRYPTION_KEY, so editing.envcan no longer take it away — and it can be escrowed under a written-down recovery key, because a changed service account should not be a data-loss event. - Connection credentials are encrypted a second time before being written into rows.
- Secrets are never sent to the browser. Edit forms show presence flags (
has_credentials,has_auth_key) so you can see a secret is set without it leaving the server. - Protocol workers do not read the database; they request a resolved connection over the internal bus.
JWT_SECRETandENCRYPTION_KEYare required with no insecure defaults. Absent or malformed, startup fails.
4. The audit journal is outside QUBIQ
Security-relevant actions are written to an external SQL database (Postgres, MySQL or SQL Server) — deliberately never the app's own database, so a compromise of QUBIQ cannot rewrite its own history.
Records are chained with a hash chain, so tampering is detectable: altering or removing a row breaks every subsequent link.
The journal aligns with IEC 62443-3-3 requirements for auditable events, authoritative timestamps and audit-record integrity.
5. Writes to plant are gated twice
A tag write from a screen passes two independent server-side checks:
- The tag must be writable.
- The operator's level must meet the tag's write level (0–3).
Both are enforced in the server's write gate. Hiding a button is a usability choice, never the control.
Hardening a deployment
Network
- Terminate TLS, at QUBIQ (
TLS_ENABLED,TLS_CERT_FILE,TLS_KEY_FILE) or at a proxy. - Set
QUBIQ_COOKIE_SECURE=truewhen serving over HTTPS. - Set
ALLOWED_ORIGINSto your real origins; do not leave it permissive. - Set
TRUSTED_PROXIESso client IPs are attributed correctly in the audit journal. - Expose only what is needed: 8182 for the interface, 8183 for telemetry, 8090 only if you publish REST endpoints. Bind 8091 to loopback.
- Keep device networks (OPC-UA, Modbus, cameras) on segments only QUBIQ can reach.
Accounts
- Create the super admin at first-run setup immediately. The wizard is one-shot: deleting the user table does not reopen it.
- Give people the narrowest role that lets them work; do not share the super admin.
- Know the recovery path before you need it —
qubiq admin reset-passwordat the server console. → Console recovery - Reserve super-admin-only permissions — Manage permissions, Manage the audit journal, Manage backups, Manage LiveView sign-in, Manage AI settings — for administrators.
- Configure login lockout:
LOGIN_MAX_ATTEMPTS,LOGIN_WINDOW,LOGIN_LOCKOUT.
Integrations
- Give each consumer its own API key with the narrowest scopes.
- Keep REST routes fail-closed; a public route must be a deliberate choice.
- Add IP allow-lists and rate limits on published endpoints.
- Give database connections least-privilege accounts, and a separate read-only credential for the AI assistant.
Data
- Point the audit journal at an external database before go-live.
- Take passphrase-encrypted backups — only those carry connection secrets.
- Store
.envseparately from the data directory. LosingENCRYPTION_KEYmakes connection secrets unrecoverable. - Run
qubiq db-key createon the day you install, and keep the printed code off the machine. It is the only way back into the configuration database if this machine's key store becomes unreadable. New in 1.0.4
Threat notes
| Concern | Mitigation |
|---|---|
| Stolen operator token used against design-time actions | Separate realms and token audiences |
| Credential exfiltration through the interface | Secrets are never serialised to clients |
| Tampering with the audit trail | External store plus a hash chain |
| Unauthorised plant writes | Writable flag plus write level, server-enforced |
| Malicious pipeline or script | Capability scopes; Manage the script sandbox restricted to administrators |
| Backup leaking plant access | Unencrypted backups deliberately exclude secrets |
| A cloned VM corrupting history | Physical store ownership |
| Brute-force login | Attempt limits and lockout |
| A stolen session outliving a password change | A password change revokes every token issued before it |
| Somebody minting themselves a super admin by emptying the user table | First-run setup is one-shot, recorded in two places |
| A quiet console password reset | Audited, and surfaced as an undismissable seven-day notice |
| A changed service account orphaning the database key | The key is re-sealed on boot, and escrowed under a recovery key |
In this section
| Page | Contents |
|---|---|
| Users and roles | Accounts, the four roles, defaults |
| Permissions | How permission checks work and how to customise them |
| API keys | Credentials for machine access |
| LiveView authentication | Runtime identity, roles and write levels |
| Audit journal | The tamper-evident security record |
| Console recovery | Recovering a lost administrator password or database key |