Spaces:
Runtime error
security: reject known-insecure default passwords during admin seeding (#123)
Browse filesThe admin seeding function previously fell back to password 'admin' when
AUTH_PASS was unset, and accepted any value from .env.example including
the documented default 'change-me-on-first-login'. This meant a user who
copied .env.example without changing the password (or forgot to set
AUTH_PASS entirely) would have an instance running with publicly known
credentials.
The seeding function now:
- Skips seeding entirely if AUTH_PASS is not set (instead of defaulting
to 'admin')
- Checks AUTH_PASS against a blocklist of known insecure values
(admin, password, change-me-on-first-login, changeme, testpass123)
- Logs a clear warning explaining what to do in both cases
Existing instances that already have users in the database are not
affected — the seeding function only runs when the users table is empty.
Signed-off-by: Mark Liu <mark@prove.com.au>
- src/lib/db.ts +29 -1
|
@@ -73,6 +73,16 @@ function initializeSchema() {
|
|
| 73 |
|
| 74 |
interface CountRow { count: number }
|
| 75 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
function seedAdminUserFromEnv(dbConn: Database.Database): void {
|
| 77 |
// Skip seeding during `next build` — env vars may not be available yet
|
| 78 |
if (process.env.NEXT_PHASE === 'phase-production-build') return
|
|
@@ -81,7 +91,25 @@ function seedAdminUserFromEnv(dbConn: Database.Database): void {
|
|
| 81 |
if (count > 0) return
|
| 82 |
|
| 83 |
const username = process.env.AUTH_USER || 'admin'
|
| 84 |
-
const password = process.env.AUTH_PASS
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 85 |
const displayName = username.charAt(0).toUpperCase() + username.slice(1)
|
| 86 |
|
| 87 |
dbConn.prepare(`
|
|
|
|
| 73 |
|
| 74 |
interface CountRow { count: number }
|
| 75 |
|
| 76 |
+
// Known-insecure passwords that should never be used in production.
|
| 77 |
+
// Includes the .env.example default and common placeholder values.
|
| 78 |
+
const INSECURE_PASSWORDS = new Set([
|
| 79 |
+
'admin',
|
| 80 |
+
'password',
|
| 81 |
+
'change-me-on-first-login',
|
| 82 |
+
'changeme',
|
| 83 |
+
'testpass123',
|
| 84 |
+
])
|
| 85 |
+
|
| 86 |
function seedAdminUserFromEnv(dbConn: Database.Database): void {
|
| 87 |
// Skip seeding during `next build` — env vars may not be available yet
|
| 88 |
if (process.env.NEXT_PHASE === 'phase-production-build') return
|
|
|
|
| 91 |
if (count > 0) return
|
| 92 |
|
| 93 |
const username = process.env.AUTH_USER || 'admin'
|
| 94 |
+
const password = process.env.AUTH_PASS
|
| 95 |
+
|
| 96 |
+
if (!password) {
|
| 97 |
+
logger.warn(
|
| 98 |
+
'AUTH_PASS is not set — skipping admin user seeding. ' +
|
| 99 |
+
'Set AUTH_PASS in your .env file to create the initial admin account.'
|
| 100 |
+
)
|
| 101 |
+
return
|
| 102 |
+
}
|
| 103 |
+
|
| 104 |
+
if (INSECURE_PASSWORDS.has(password)) {
|
| 105 |
+
logger.warn(
|
| 106 |
+
`AUTH_PASS matches a known insecure default ("${password}"). ` +
|
| 107 |
+
'Please set a strong, unique password in your .env file. ' +
|
| 108 |
+
'Skipping admin user seeding until credentials are changed.'
|
| 109 |
+
)
|
| 110 |
+
return
|
| 111 |
+
}
|
| 112 |
+
|
| 113 |
const displayName = username.charAt(0).toUpperCase() + username.slice(1)
|
| 114 |
|
| 115 |
dbConn.prepare(`
|