Private
Public Access
1
0

feat(security): replace hardcoded admin password with in-app bootstrap (#25)
All checks were successful
CI Pipeline / Rust Format Check (push) Successful in 5s
CI Pipeline / Clippy Lints (push) Successful in 50s
CI Pipeline / Rust Unit Tests (push) Successful in 1m8s
CI Pipeline / Security Audit (push) Successful in 4s
CI Pipeline / Frontend Lint & Type Check (push) Successful in 14s
CI Pipeline / Build .deb & Release (push) Has been skipped

* feat(security): replace hardcoded admin password with in-app bootstrap (issue #8)

Replace the publicly-known Argon2id hash in 002_seed_admin.sql with a
clearly-invalid placeholder that cannot validate any password (fail-closed).

On first startup, pm-web detects the placeholder and generates a random
24-character alphanumeric password, hashes it with Argon2id, and UPDATEs
the admin row. The plaintext password is printed once to stderr (visible
in systemd journal).

This eliminates the need for a separate hash_password binary, shell
script SQL injection risk, and password leakage in shell variables.

Closes #8

* fix(security): rustfmt compliance for bootstrap function

* fix(security): add trailing commas to match arms per rustfmt
This commit is contained in:
Draco-Lunaris-Echo
2026-06-04 13:28:44 -05:00
committed by GitHub
parent fda70ecf9e
commit 80ffb6b62f
2 changed files with 109 additions and 11 deletions

View File

@ -1,12 +1,17 @@
-- Migration: 002_seed_admin
-- Description: Seed the default admin account.
--
-- Default credentials (CHANGE BEFORE PRODUCTION USE):
-- Username: admin
-- Password: ChangeMe123!
-- IMPORTANT (issue #8): The password_hash below is a PLACEHOLDER
-- that cannot validate any password. On first startup, pm-web detects
-- this placeholder and generates a random admin password, replacing
-- the hash in the database. The generated password is printed once
-- to stderr (visible in systemd journal).
--
-- The password hash below is Argon2id of "ChangeMe123!" with
-- m=65536, t=3, p=1. Replace after first login.
-- If the application never starts (e.g., manual migration only),
-- the admin account is inaccessible — this is fail-closed.
--
-- On first successful login with a real password, the admin is forced to
-- set a new password (force_password_reset = TRUE).
INSERT INTO users (
id,
@ -27,10 +32,11 @@ VALUES (
'admin@localhost',
'admin',
'local',
-- Argon2id hash of "ChangeMe123!" — REPLACE IN PRODUCTION
'$argon2id$v=19$m=65536,t=3,p=1$Kv8bkGiE81yIuXARq9fwsw$NrBRFvgL1dVsW7bEK6NxEOzIX2q1p4B0K422idAVIDQ',
FALSE, -- MFA disabled by default; admin must set up on first login
-- PLACEHOLDER Argon2id hash (issue #8). Cannot validate any password.
-- pm-web replaces this with a real hash on first startup.
'$argon2id$v=19$m=65536,t=3,p=1$AAAAAAAAAAAAAAAA$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
FALSE,
TRUE,
TRUE -- Force password reset on first login
TRUE
)
ON CONFLICT (username) DO NOTHING;