Change-password ignores the current password

Table of Contents

This page is a capture in the inbox bucket of the product backlog — a pre-sprint idea, not yet pulled into a sprint as a story.

1. What

iam.v1.accounts.change-password accepts a current_password field and never reads it. The handler validates the bearer token, takes the account from the token's subject, and calls change_password(account_id, req->new_password). Anyone holding a live token for an account can set a new password without knowing the old one.

2. Why

Found on 2026-09-23 while documenting Journey: Protect my account. The journey's step is "prove you are still you, then choose a new password"; the server's step is "present a token, then choose a new password".

Evidence:

  • projects/ores.iam/api/include/ores.iam.api/messaging/account_operations_protocol.hpp declares current_password on the request, at lines 201 and 322.
  • current_password appears nowhere else in any .hpp or .cpp under projects/ores.iam/, so nothing reads it.
  • projects/ores.iam/core/include/ores.iam.core/messaging/account_operations_handler.hpp:432-476 is the handler: decode, extract the bearer token, validate it, derive account_id from claims_result->subject, then call svc.change_password(account_id, req->new_password).

A password change is the standard recovery step after a token is suspected stolen, so the one operation a victim would reach for is the one an attacker can also use.

Two secondary defects sit beside it, both found by the same journey:

  1. iam.v1.accounts.reset-password over NATS calls change_password rather than setting password_reset_required, while the HTTP route does set it. The two surfaces disagree about what a reset means.
  2. password_reset_required has no NATS subject that sets it, so a client cannot force a change at the next sign-in.

The fix is to verify current_password in the handler before the service call, and to fail closed when the field is absent. Decide at the same time whether an administrator reset should clear it, so the two reset surfaces agree.

3. References

  • projects/ores.iam/api/include/ores.iam.api/messaging/account_operations_protocol.hpp — the unused request field.
  • projects/ores.iam/core/include/ores.iam.core/messaging/account_operations_handler.hpp — the handler that ignores it.

4. See also

Emacs 29.3 (Org mode 9.6.15)