phacility/phabricator · error · PhabricatorSearchConstraintException

The "Has MFA" query constraint may only be used by administr

Error message

The "Has MFA" query constraint may only be used by administrators, to prevent attackers from using it to target weak accounts.

What it means

The People directory search engine throws PhabricatorSearchConstraintException when a non-administrator viewer applies the 'Has MFA' constraint (mfa on the query). The guard exists because filtering by MFA enrollment enumerates exactly which accounts lack MFA - a targeting primitive for attackers - so only administrators may use it. Saved-query parameters still carry the constraint, so a non-admin opening such a query triggers it immediately.

Source

Thrown at src/applications/people/query/PhabricatorPeopleSearchEngine.php:175

      $query->withIsDisabled($map['isDisabled']);
    }

    if ($map['isMailingList'] !== null) {
      $query->withIsMailingList($map['isMailingList']);
    }

    if ($map['isBot'] !== null) {
      $query->withIsSystemAgent($map['isBot']);
    }

    if ($map['needsApproval'] !== null) {
      $query->withIsApproved(!$map['needsApproval']);
    }

    if (idx($map, 'mfa') !== null) {
      $viewer = $this->requireViewer();
      if (!$viewer->getIsAdmin()) {
        throw new PhabricatorSearchConstraintException(
          pht(
            'The "Has MFA" query constraint may only be used by '.
            'administrators, to prevent attackers from using it to target '.
            'weak accounts.'));
      }

      $query->withIsEnrolledInMultiFactor($map['mfa']);
    }

    if ($map['createdStart']) {
      $query->withDateCreatedAfter($map['createdStart']);
    }

    if ($map['createdEnd']) {
      $query->withDateCreatedBefore($map['createdEnd']);
    }

    return $query;

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Run the query as an administrator - the constraint requires getIsAdmin() on the viewer
  2. Share results, not queries: export the list as admin instead of distributing the constrained query URL
  3. Remove the 'Has MFA' constraint from saved queries and dashboard panels intended for non-admin audiences

Example fix

// before: saved query visible to everyone carries mfa=0
// after: strip the constraint for shared queries, keep MFA reporting admin-only
if ($viewer->getIsAdmin()) {
  $query->withIsEnrolledInMultiFactor($map['mfa']);
}
Defensive patterns

Strategy: validation

Validate before calling

// Only apply the MFA constraint for administrators
if (idx($map, 'mfa') !== null) {
  if (!$viewer->getIsAdmin()) {
    unset($map['mfa']); // or reject the request explicitly
  } else {
    $query->withIsEnrolledInMultiFactor($map['mfa']);
  }
}

Type guard

function canUseMfaConstraint(PhabricatorUser $viewer) {
  return (bool)$viewer->getIsAdmin();
}

Prevention

When it happens

Trigger: A non-admin opens a People search URL or saved query containing `mfa=0` / `mfa=1`; a shared dashboard panel embeds an MFA-constrained user query viewed by regular users; a Conduit search built with the mfa field runs with a non-admin token.

Common situations: An admin shares a 'users without MFA' query link with a team; a dashboard panel with the constraint is visible org-wide; security-audit queries left in navigation that non-admins click.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21). Data as JSON: /api/errors/660d23e42d0db0ec. Report an issue: GitHub.