ASVS V6.2.3 requires that password change functionality asks for the user's current password and the new one. It is a Level 1 requirement.
This is the control that protects a signed in session from being turned into a permanent takeover. It is a small form field with a large effect.
Why it matters
A stolen session cookie, an unlocked laptop or a malicious browser extension gives an attacker a signed in browser. If the change form accepts only a new password, that attacker can take over the account permanently. Asking for the current password forces them to know something a session alone does not provide.
Session theft is common: cross site scripting, malware, a shared computer. If your change form accepts only a new password, the attacker needs only a moment to move from temporary access to permanent ownership. The requirement for the current password adds a barrier that a stolen cookie does not satisfy.
It also protects against walk up attacks. A coworker who borrows an unlocked laptop should not be able to take over a banking or admin account in thirty seconds.
How to implement it
Verify the current password server side before touching the stored hash, and rate limit the endpoint like a login.
app.post("/account/password", requireSession, rateLimit, async (req, res) => {
const { current, next } = req.body;
if (typeof current !== "string" || typeof next !== "string") return res.sendStatus(400);
const ok = await argon2.verify(req.user.hash, current);
if (!ok) return res.status(403).json({ error: "Current password is incorrect" });
const problem = checkPolicy(next);
if (problem) return res.status(422).json({ error: problem });
await saveHash(req.user.id, await argon2.hash(next));
await revokeOtherSessions(req.user.id, req.sessionId);
res.sendStatus(204);
});
Pair the check with these safeguards. Rate limit the endpoint so it cannot be used to guess the current password. Require re authentication for step up actions in the same way, such as changing the email address or turning off MFA. After success, revoke all other sessions, rotate the current session identifier, and send a notice to the user, which also supports V6.3.7.
How to test it
Send the change request with the current password missing, empty and wrong. Each must fail with no change to the stored hash. Then repeat the wrong guess many times and confirm throttling kicks in.
Common mistakes
-
Checking the current password in the browser only.
-
Skipping the check for accounts that signed in recently.
-
Leaving the endpoint without a rate limit, which makes it a password oracle.
-
Treating a password reset link as proof, then allowing the change without the old password while logged in.
-
Returning different error text for a wrong current password and a weak new one in a way that leaks which field failed to attackers.
Quick check
Does a valid session replace the current password check?
No. The session proves a browser was signed in, not that the person at the keyboard is the owner.