Skip to content

Security: initial password creation on passwordless accounts lacks step-up and session handling (SUF-02) #328

Description

@devondragon

Summary

POST /user/setPassword (adding an initial password to a passwordless / passkey-only account) requires only an authenticated session. It performs no step-up (fresh WebAuthn assertion or recent-auth proof), and it does not invalidate or rotate sessions after the credential is added.

Severity: Medium (requires a pre-existing authenticated session; additive-only; documented limitation)

Affected code

  • src/main/java/com/digitalsanctuary/spring/user/api/UserAPI.javasetPassword (~488/511) only null-checks the principal.
  • src/main/java/com/digitalsanctuary/spring/user/service/UserService.javasetInitialPassword (~837), persistInitialPassword (~873): no session invalidation.

Details

The endpoint is correctly guarded to initial password onlyhasPassword() is checked at both the API and service layers, so it cannot overwrite an existing credential, and the account's existing passkey remains valid. However, on a passwordless account there is no way to prove the caller is the legitimate owner beyond "the session is authenticated," and no step-up primitive exists in the library yet. This is acknowledged in the endpoint Javadoc and MIGRATION.md.

Impact

A caller who already controls an authenticated session on a passwordless account can add a durable password credential (additive persistence; reversible via the email reset flow). This is a persistence concern, not privilege escalation or lockout.

Recommended fix

  • Implement a WebAuthn step-up assertion bound to user, session, action (set-password), RP ID, origin, challenge, and short expiry, and require it here.
  • Until step-up exists, consider disabling this endpoint by default or requiring a consumer-provided step-up service.
  • Note: simply invalidating other sessions after the change would evict the legitimate user (default keeps the current session), not the attacker — step-up is the real remedy.
  • Add endpoint-level tests for the auth/step-up/session behavior of /user/setPassword (currently only service-level coverage exists).

Identified during a code-first security assessment of the current main branch.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingsecurity

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions