{"record":{"id":"7a6cd27a687b2db7","repo":"coleam00/Archon","slug":"better-auth-secret-must-be-at-least-string-min-b","errorCode":null,"errorMessage":"BETTER_AUTH_SECRET must be at least ${String(MIN_BETTER_AUTH_SECRET_LENGTH)} characters when web auth is enabled. Generate one with: openssl rand -base64 32","messagePattern":"BETTER_AUTH_SECRET must be at least (.+?) characters when web auth is enabled\\. Generate one with: openssl rand -base64 32","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"packages/server/src/auth/config.ts","lineNumber":39,"sourceCode":"/**\n * Web auth is active only when a Postgres connection AND a signing secret are\n * configured. SQLite installs (no DATABASE_URL) are always opted out.\n */\nexport function isWebAuthEnabled(env: NodeJS.ProcessEnv = process.env): boolean {\n  return Boolean(env.DATABASE_URL && env.BETTER_AUTH_SECRET);\n}\n\n/**\n * Fail fast at server boot: when web auth is enabled, the signing secret must be\n * long enough to be a real secret. A short/placeholder secret would let an\n * attacker forge sessions, so we throw with an actionable hint rather than\n * silently mounting auth on a weak key.\n */\nexport function assertWebAuthAtBoot(env: NodeJS.ProcessEnv = process.env): void {\n  if (!isWebAuthEnabled(env)) return;\n  const secret = env.BETTER_AUTH_SECRET ?? '';\n  if (secret.length < MIN_BETTER_AUTH_SECRET_LENGTH) {\n    throw new Error(\n      `BETTER_AUTH_SECRET must be at least ${String(MIN_BETTER_AUTH_SECRET_LENGTH)} characters ` +\n        'when web auth is enabled. Generate one with: openssl rand -base64 32'\n    );\n  }\n}\n\n/**\n * Parse the signup allowlist from `ARCHON_AUTH_ALLOWED_EMAILS` (comma-separated,\n * lowercased, trimmed, blanks dropped). An empty/unset list does NOT mean open\n * signup — see `getSignupMode` (empty defaults to `disabled` unless\n * `ARCHON_AUTH_OPEN_SIGNUP=true`).\n */\nexport function parseAllowedEmails(env: NodeJS.ProcessEnv = process.env): string[] {\n  return (env.ARCHON_AUTH_ALLOWED_EMAILS ?? '')\n    .split(',')\n    .map(e => e.trim().toLowerCase())\n    .filter(Boolean);\n}","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/coleam00/Archon/blob/0773b9745896ef0612e709c80845a0f7db315b19/packages/server/src/auth/config.ts#L21-L57","documentation":"assertWebAuthAtBoot runs during startServer and refuses to boot with web authentication enabled but a BETTER_AUTH_SECRET shorter than the minimum length (MIN_BETTER_AUTH_SECRET_LENGTH). Better Auth signs session tokens with this secret; a weak/guessable key would let attackers forge sessions, so the server fails fast with remediation instructions instead of silently mounting auth on a weak key.","triggerScenarios":"startServer() → assertWebAuthAtBoot() with web auth enabled (per isWebAuthEnabled) and env.BETTER_AUTH_SECRET unset (treated as '') or shorter than the minimum length.","commonSituations":"Forgetting to set BETTER_AUTH_SECRET in a fresh deployment/.env; placeholder values like 'changeme' or 'secret'; a truncated secret from copy-paste; enabling web auth via a flag without adding the secret env var.","solutions":["Generate a strong secret with `openssl rand -base64 32` and set it as BETTER_AUTH_SECRET in the server environment/.env","Verify the full secret was pasted (no truncation/whitespace) and its length meets the minimum","If web auth is not needed, disable it so the check is skipped"],"exampleFix":"// before (.env)\nBETTER_AUTH_SECRET=changeme\n// after\n# openssl rand -base64 32\nBETTER_AUTH_SECRET=kJ8fQ2mN7xR4vT9wLpZ3aB6cD1eF0gH5iJ2kL3mN4oP5qR6sT7uV8wX9yZ0aB1c=","handlingStrategy":"validation","validationCode":"const MIN = 32; // match MIN_BETTER_AUTH_SECRET_LENGTH\nconst secret = process.env.BETTER_AUTH_SECRET ?? '';\nif (secret.length < MIN) {\n  throw new Error(`BETTER_AUTH_SECRET must be >= ${MIN} chars: openssl rand -base64 32`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await startServer();\n} catch (err) {\n  if (String(err.message).includes('BETTER_AUTH_SECRET')) {\n    console.error('Set a strong BETTER_AUTH_SECRET before enabling web auth.');\n  }\n  throw err;\n}","preventionTips":["Generate the secret at deploy time with `openssl rand -base64 32`; never commit it","Use a deploy checklist that pairs enabling web auth with provisioning the secret","Detect placeholder values ('changeme', 'secret') in config linting"],"tags":["security","auth","environment","boot"],"backgroundTag":"weak-or-missing-auth-secret","analyzedSha":"0773b9745896ef0612e709c80845a0f7db315b19","analyzedAt":"2026-09-01T02:28:07.064Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}