Default admin password yields a fully privileged API token before it is changed #2

Closed
opened 2026-08-31 18:55:30 -05:00 by Ghost · 1 comment

Severity

Medium

What's going on

The built-in admin accepts the well-known default password password until a new password is stored. Login still returns a fully privileged JWT even when mustChangePassword is true. That flag is advisory; /api/proxy-hosts and the rest of the mutating admin API accept the token immediately.

The admin UI/API also listens on all interfaces (empty host / 0.0.0.0 with DISABLE_IPV6=1). The sample compose file publishes host port 81 to the container.

Practical impact

On first boot (or any install that has not yet changed the password), anyone who can hit the published admin port can log in with password and reconfigure the reverse proxy. PROXY_MODE=development skips even the UI hint.

This is separate from the JWT signing-secret issue: after the password is changed, default-password login stops working, but a well-known JWT secret would still be an issue until that is fixed.

Fix

  • Treat an unset admin password as a bootstrap lock: only /api/login and /api/users/me/password should succeed with the bootstrap token until a non-default password is stored.
  • Keep the admin listener off the public internet (bind loopback or put it behind an already-authenticated reverse proxy / firewall). Do not publish :81 on an untrusted network before the password is changed.
  • Consider refusing to start in non-development mode until the password has been changed, or requiring ADMIN_PASSWORD from the environment on first boot.

Not sending a code PR for this one; the JWT secret fix is the higher-leverage change and this needs a small product/API decision so tests that use the default password keep working in development.

## Severity Medium ## What's going on The built-in admin accepts the well-known default password `password` until a new password is stored. Login still returns a **fully privileged** JWT even when `mustChangePassword` is true. That flag is advisory; `/api/proxy-hosts` and the rest of the mutating admin API accept the token immediately. The admin UI/API also listens on all interfaces (empty host / `0.0.0.0` with `DISABLE_IPV6=1`). The sample compose file publishes host port 81 to the container. ## Practical impact On first boot (or any install that has not yet changed the password), anyone who can hit the published admin port can log in with `password` and reconfigure the reverse proxy. `PROXY_MODE=development` skips even the UI hint. This is separate from the JWT signing-secret issue: after the password is changed, default-password login stops working, but a well-known JWT secret would still be an issue until that is fixed. ## Fix - Treat an unset admin password as a bootstrap lock: only `/api/login` and `/api/users/me/password` should succeed with the bootstrap token until a non-default password is stored. - Keep the admin listener off the public internet (bind loopback or put it behind an already-authenticated reverse proxy / firewall). Do not publish `:81` on an untrusted network before the password is changed. - Consider refusing to start in non-development mode until the password has been changed, or requiring `ADMIN_PASSWORD` from the environment on first boot. Not sending a code PR for this one; the JWT secret fix is the higher-leverage change and this needs a small product/API decision so tests that use the default password keep working in development.

Triaged as medium. Default password still yields a full admin JWT; mustChangePassword is advisory. Separate from #1 (now fixed by #3). Next: bootstrap lock until password is changed, do not publish :81 on untrusted nets. Needs a small API/test decision so I am not stuffing it into #3. Leaving open.

Triaged as medium. Default password still yields a full admin JWT; mustChangePassword is advisory. Separate from #1 (now fixed by #3). Next: bootstrap lock until password is changed, do not publish :81 on untrusted nets. Needs a small API/test decision so I am not stuffing it into #3. Leaving open.
Ghost closed this issue 2026-08-31 22:57:37 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: s1d3sw1ped/helix-proxy#2