Skip to content

v0.6.1 — Security release

Choose a tag to compare

@anshu8858 anshu8858 released this 20 Sep 19:44
· 18 commits to main since this release
e36dda8

Security release. Upgrading is recommended for all deployments.

Several endpoints were missing authorization checks, several request fields that reach shell commands on managed hosts were unvalidated, and several defaults were permissive. This release fixes all of them.

No API or database schema changes — but some deployments need configuration changes. See Action required below.

A GitHub Security Advisory with full detail will follow shortly.

Authorization

Endpoints that were reachable by any authenticated user — including a viewer — now require an appropriate role:

  • GET /servers/:id/auto-update — executes a shell script on the managed host over SSH
  • POST /ssh-keys/test-server/:id — an online SSH credential test
  • GET /ssh-keys — host key listing
  • GET /servers/:id/alert-channels — notification configuration
  • All six SSL mutations (scan, per-domain scan, create, update, delete, restore)

Global vault unlock and lock now require admin-level vault permissions. They were gated on the server-update permission, which an editor holds, despite being documented as admin-only. Persisting the vault passphrase to .env requires a separate permission and is now recorded in the audit log.

Input validation

Request fields interpolated into shell commands are now strictly validated and shell-escaped:

  • ATOP time windows are pinned to HH:MM[:SS], enforced in the shared schema and re-checked at the point of interpolation
  • OS user shells, home directories and group names are validated and escaped
  • Sudoers command entries are allowlisted to absolute command paths with plain arguments
  • Sudoers rules are written from a base64 payload via mktemp and install(1) instead of an echo redirect, removing both shell expansion and a predictable-filename race

Two related bugs fixed along the way: install -o root -g root replaces mv + chmod, which previously left sudoers.d files owned by the SSH user — files sudo silently ignores. And a custom sudo grant with an empty command list used to fall back to ALL, silently granting unrestricted passwordless root; it is now rejected.

Defaults

  • TRUSTED_ORIGINS falls back to WEB_ORIGIN instead of *. The wildcard remains available as an explicit opt-in and logs a warning at boot.
  • The Secure cookie flag is set whenever BETTER_AUTH_URL or WEB_ORIGIN is https, rather than being inferred from BETTER_AUTH_URL alone.
  • Self-registration is disabled unless ALLOW_SELF_SIGNUP=true.
  • The "persist passphrase to .env" checkbox defaults to off. The write is now atomic, mode 0600, and anchored to the exact variable so it no longer rewrites commented-out or similarly-named lines.

Audit coverage

Added entries for fifteen mutations that were previously unrecorded: SSH key add/remove, SSH connectivity tests, API key issue/revoke, access-request deletion, remote auto-update changes, storage recalculation, all SSL mutations, and all four inventory export endpoints.

Documentation accuracy

The credential vault was described as zero-knowledge with client-side WebCrypto encryption in fourteen places across the README, user guide, security policy and product portal. No client-side cryptography exists. The vault is server-side envelope encryption (PBKDF2 → KEK → DEK, AES-256-GCM): the passphrase is sent to the server on unlock, and opting in to auto-unlock writes it to .env. All affected copy now describes the actual design.

Run RackMap behind TLS.

Also corrected: SSH_ENABLED was documented as an RCE kill-switch. It gates only the browser terminal — metrics, discovery, log viewing, ATOP and OS user management still execute commands over SSH when it is false. And SSH_HOST_POLICY is declared but never read; it is now marked as not implemented. Real host-key verification is next.

Action required on upgrade

  1. TRUSTED_ORIGINS no longer defaults to *. If you reach RackMap at a hostname or IP that differs from WEB_ORIGIN, sign-in will be rejected. Set it explicitly:
    TRUSTED_ORIGINS=https://rackmap.example.com,http://10.0.0.5:8080
    
    TRUSTED_ORIGINS=* restores the old behaviour and logs a warning.
  2. ALLOW_SELF_SIGNUP defaults to false. The registration form and the checkout sign-up step are hidden. Set it to true to restore self-registration.
  3. Custom sudo permissions with an empty command list are rejected. Supply explicit absolute command paths, or choose the full-access option deliberately.

Upgrading

git pull
docker compose up -d --build

Verification

pnpm build, pnpm -r typecheck and pnpm test all pass. Test count goes from 35 to 150: the new suites assert that an unauthenticated caller and a viewer are both rejected on every newly guarded route, and that hostile values are rejected on every field that reaches a shell.

Still open

  • Host-key verification is not implemented — hostVerifier currently accepts any key. Planned for the next release.
  • 27 Dependabot alerts (8 high) remain on the default branch.

Full changelog: https://github.com/deziss/rackmap/blob/v0.6.1/CHANGELOG.md