Skip to content

[Vulnerability] parse-community/parse-server: MFA Token Replay #420

@github-actions

Description

@github-actions

Potential Security Vulnerability Detected

Repository: parse-community/parse-server
Commit: 725be0d
Author: Manuel
Date: 2026-04-26T02:10:27Z

Commit Message

fix: MFA SMS one-time password accepted twice under concurrent login ([GHSA-jpq4-7fmq-q5fj](https://github.com/parse-community/parse-server/security/advisories/GHSA-jpq4-7fmq-q5fj)) (#10448)

Pull Request

PR: #10448 - fix: MFA SMS one-time password accepted twice under concurrent login (GHSA-jpq4-7fmq-q5fj)
Labels: state:released-alpha

Description:

Issue

MFA SMS one-time password accepted twice under concurrent login ([GHSA-jpq4-7fmq-q5fj](GHSA-jpq4-7fmq-q5fj))

Tasks

  • Add tests
  • Add changes
  • Add security check
  • Add benchmark

Analysis

Vulnerability Type: MFA Token Replay
Severity: High

Description

Before this patch, an SMS Multi-Factor Authentication (MFA) one-time password (OTP) could be accepted multiple times if concurrent login requests using the same OTP were processed simultaneously. This allowed replaying the same MFA token to authenticate multiple sessions, effectively bypassing the single-use design of OTP tokens. The patch introduces optimistic locking on the authData update, preventing concurrent token reuse by ensuring only the first request consuming the MFA token succeeds while others fail.

Affected Code

          if (user.authData) {
            for (const provider of Object.keys(validatedAuthData)) {
              const original = user.authData[provider];
              if (original && typeof original === 'object') {
                for (const [field, value] of Object.entries(original)) {
                  if (
                    Array.isArray(value) &&
                    JSON.stringify(value) !== JSON.stringify(validatedAuthData[provider]?.[field])
                  ) {
                    query[`authData.${provider}.${field}`] = value;
                  }
                }
              }
            }
          }

Proof of Concept

1. Enable SMS MFA for a user 'smsmfauser'.
2. Trigger a login request that generates an SMS OTP.
3. Concurrently send multiple login POST requests to `/login` endpoint with the same username, password, and *identical* OTP in the authData.

Expected behavior before patch:
- Multiple requests succeed because the same OTP is accepted multiple times.

Expected behavior after patch:
- Exactly one request succeeds.
- All other concurrent requests with the same OTP fail with an OBJECT_NOT_FOUND or equivalent error, preventing replay of OTP tokens.

Example requests (pseudocode):

const otp = '123456'; // The issued one-time password

Promise.all(Array(10).fill().map(() => 
  fetch('http://localhost:8378/1/login', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ username: 'smsmfauser', password: 'password123', authData: { mfa: { token: otp } } })
  })
)).then(results => console.log(results));

Before patch: all 10 requests resolve successfully.
After patch: only 1 request resolves successfully; others are rejected.

This issue was automatically created by Vulnerability Spoiler Alert.
Detected at: 2026-04-26T06:00:30.826Z

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions