Skip to content

fix: mint a per-deploy HyperDX session secret - #204

Merged
catinspace-au merged 3 commits into
mainfrom
fix/hyperdx-session-secret
Oct 6, 2026
Merged

catinspace-au merged 3 commits into
mainfrom
fix/hyperdx-session-secret

Conversation

@catinspace-au

@catinspace-au catinspace-au commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Two HyperDX keys nothing in this repo set.

HyperDX falls back to a session secret published in upstream's source when EXPRESS_SESSION_SECRET is unset (packages/api/src/config.ts:16 in our fork, upstream 2.40.0), so every compose deployment signed HyperDX sessions with the same public key. And without TOKEN_ENCRYPTION_KEY it stores third-party tokens (Slack bot tokens, OAuth tokens) in plain text.

  • make init mints both with the other generated secrets, topped up into an existing .env that predates them, never overwritten on a re-run.
    • HYPERDX_EXPRESS_SESSION_SECRET: 48 alphanumeric chars.
    • HYPERDX_TOKEN_ENCRYPTION_KEY: 64 hex chars (32 bytes), the format the fork parses (packages/api/src/utils/tokenEncryption.ts:150).
  • Compose passes them to the hyperdx container as EXPRESS_SESSION_SECRET and TOKEN_ENCRYPTION_KEY.
  • Neither is a ${VAR:?}. Compose interpolates every service before profiles filter, so a :? would break make down for anyone not running HyperDX.
    • The session key falls back to the same sentinel NEXTAUTH_SECRET uses.
    • The token key falls back to EMPTY, never a sentinel: HyperDX refuses to start on a malformed key (tokenEncryption.ts:259 -> server.ts:92 -> index.ts:38-44 exits), and empty reads as encryption off.
    • make post fails while either is at its fallback (WEAK_SECRET_DEFAULTS, scoped to the hyperdx service).
  • .env.example, README and docs list both among the generated secrets.

Tests: test_hyperdx.py checks compose reads each minted key, the fallback compose runs on is exactly what make post refuses, the minted token key is 64 hex chars that decode to 32 bytes, and a .env that predates either key gets one on re-init and keeps it.

The pinned HyperDX image (v0.2.7) reads EXPRESS_SESSION_SECRET today. It predates tokenEncryption.ts, so TOKEN_ENCRYPTION_KEY takes effect from the first fork release that carries it.

The Kubernetes half is hyperi-io/dfe-infra#530. Profile projection here goes green once #205 is in.

Done when CI is green and a fresh make init leaves both keys live in .env.

HyperDX signs its session cookie with a key published in upstream's source whenever EXPRESS_SESSION_SECRET is unset, and nothing here set it. So every compose deployment shared one key anyone can read.

make init now mints HYPERDX_EXPRESS_SESSION_SECRET with the other generated secrets: 48 alphanumeric chars, topped up into an existing .env that predates it, never overwritten on a re-run. Compose hands it to the hyperdx container as EXPRESS_SESSION_SECRET.

Same shape as NEXTAUTH_SECRET, not a :? hard-fail. Compose interpolates every service before profiles filter, so a :? would break make down for anyone not running HyperDX. The sentinel default is what make post fails on instead.
catinspace-au and others added 2 commits October 6, 2026 11:28
HyperDX stores third-party tokens (Slack bot tokens, OAuth tokens) in plain text unless TOKEN_ENCRYPTION_KEY is set, and nothing here set it. make init now mints HYPERDX_TOKEN_ENCRYPTION_KEY and compose hands it to the hyperdx container.

The format is the one the fork parses (packages/api/src/utils/tokenEncryption.ts:150): 64 hex chars, 32 bytes. HyperDX refuses to start on a malformed key, so the compose fallback is empty, which reads as encryption off, never a sentinel. make post fails while it is empty.

The README and docs now list both HyperDX keys among the generated secrets.
@catinspace-au
catinspace-au merged commit f940665 into main Oct 6, 2026
7 checks passed
@catinspace-au
catinspace-au deleted the fix/hyperdx-session-secret branch October 6, 2026 00:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant