Skip to content

Security & trust

Paranoid, on purpose

A control panel is the keys to your server. Here is exactly how HipnoType protects them — and where its trust boundaries sit.

Authentication

Argon2id password hashing, enforced policy, brute-force lockout, forced first-login change, TOTP 2FA with recovery codes, server-side revocable sessions, three roles (admin / developer / viewer) checked on every API call.

Secrets at rest

Cloudflare tokens, 2FA secrets and site basic-auth passwords are AES-256-GCM encrypted with a per-install key. The browser only ever sees fingerprints.

Audit hash chain

Every meaningful action is appended to a hash-chained log — modifying any entry breaks the chain and is detectable in the UI and via the API.

Network posture

Zero inbound ports by default. The panel connects out to the relay; unknown access tokens get a byte-identical 404 with normalised latency, per-IP rate limits and bans.

Terminal safety

Single-use 30-second tickets (never long-lived WS tokens), admin/developer only, idle and hard session caps, and terminal content is never logged.

Self-hardening

Hardened systemd unit (no root, restricted capabilities), 60-second firewall rollback window, and honest status when a capability is missing instead of silent degradation.

The relay trust position

In the default setup your browser's TLS connection terminates at the HipnoType relay before being forwarded to your VPS over the outbound tunnel. That is the same trust position as a CDN or Cloudflare Tunnel — the relay can technically observe traffic, and it stores only hashes of your credentials (the implementation is public in the repository). If that position is not acceptable for your threat model, you have two honest options:

  • Direct mode — the panel serves its own ACME certificate on port 443 at a domain you control; the relay leaves your traffic path entirely.
  • Self-hosted relay — the relay is open source with a one-command deploy pack; run it on infrastructure you control.

Read the full trust model →

Reporting a vulnerability

Found something? Open a private security advisory — never a public issue — and we will respond within 72 hours. Fixes ship to the stable channel first.

Browser

open function(){throw Error("Attempted to call REPO_URL() from the server but REPO_URL is on the client. It's not possible to invoke a client function from the server, it can only be rendered as a Component or passed to props of a Client Component.")}/security/advisories/new

Please include reproduction steps, affected versions and impact. We credit reporters in the changelog unless you prefer to stay anonymous.