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.hppdeclarescurrent_passwordon the request, at lines 201 and 322.current_passwordappears nowhere else in any.hppor.cppunderprojects/ores.iam/, so nothing reads it.projects/ores.iam/core/include/ores.iam.core/messaging/account_operations_handler.hpp:432-476is the handler: decode, extract the bearer token, validate it, deriveaccount_idfromclaims_result->subject, then callsvc.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:
iam.v1.accounts.reset-passwordover NATS callschange_passwordrather than settingpassword_reset_required, while the HTTP route does set it. The two surfaces disagree about what a reset means.password_reset_requiredhas 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.