Skip to content

fix(auth): sync credential row on all password paths + harden security - #1106

Open
lane711 wants to merge 1 commit into
mainfrom
lane711/mark-pr-review-priorities
Open

lane711 wants to merge 1 commit into
mainfrom
lane711/mark-pr-review-priorities

Conversation

@lane711

@lane711 lane711 commented Oct 16, 2026

Copy link
Copy Markdown
Collaborator

Description

Applies security fixes from Mark's reviewed PRs (#1097, #1103, #1104, #1105, #1063, #1065, #1066, #1057) directly, resolving auth cascade failures and XSS vectors.

Changes

  • Auth credential sync: Better Auth signs in via auth_account.password, not auth_user.password_hash. All 5 password-write paths (register, accept-invitation, reset-password, admin create-user, admin edit-user) now atomically sync both via syncCredentialPassword() helper + db.batch()
  • Seed-admin hardening: /auth/seed-admin gated behind ENABLE_SEED_ADMIN="true" + non-production ENVIRONMENT check
  • Bootstrap security: verifySecurityConfig runs on every request (memoized per-isolate), not just cold boot — warm isolates and KV fast-path no longer skip the check
  • XSS prevention: escapeHtml applied to user-controlled values in media grid, media details, and content list templates
  • First-user registration: Seeds RBAC roles before assignment, rolls back user creation on failure
  • E2E test stability: 12 existing tests fixed (state cleanup, correct auth endpoints, collection names, CORS origin), 3 new tests added

Testing

Unit Tests

  • All unit tests passing (pre-existing better-auth peer dep failures only)
  • Type checking passes

E2E Tests

  • Added 114-seed-admin-env-gate.spec.ts — seed-admin env gate + sign-in
  • Added 115-admin-set-password.spec.ts — admin-created user can sign in, password change works
  • Added 116-register-credential.spec.ts — registered user can sign in immediately
  • Fixed 12 existing E2E tests for stability and correctness

Checklist

  • Code follows project conventions
  • Tests added/updated and passing
  • Type checking passes
  • No console errors or warnings
  • Documentation updated (if needed)

Generated with Claude Code in Conductor

🤖 Generated with Claude Code

Better Auth signs in against auth_account.password (provider 'credential'),
not auth_user.password_hash. Five password-write paths only updated the
legacy column, causing sign-in failures after registration, invitation
acceptance, password reset, admin create-user, and admin edit-user.

Security hardening:
- seed-admin gated behind ENABLE_SEED_ADMIN + non-production ENVIRONMENT
- verifySecurityConfig runs on EVERY request (memoized), not just cold boot
- escapeHtml applied to user-controlled template values (XSS prevention)
- register/form atomically creates auth_user + auth_account in db.batch()
- first-user registration seeds RBAC before role assignment, rolls back on failure

E2E test fixes:
- database-tools truncate test no longer wipes DB mid-suite
- CORS tests use TEST_ORIGIN instead of hardcoded localhost:8787
- settings/plugin/multi-tenant tests restore state in afterEach/afterAll
- lexical/json-viewer tests use correct collection name (blog_post)
- cache-invalidation uses correct auth endpoint and credentials
- block-stable-ids removes nonexistent import
- marketing-home skipped (tests marketing site, not CMS)

New E2E tests: seed-admin gate, admin-set-password, register-credential.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

This branch was successfully deployed

1 active deployment
internal — 2c5c3958 Deployed Oct 16, 2026 by lane711 via authorize #1612
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant