SonarSource/sonarqube · warning · ForbiddenException

Parameter requires Administer System permission.

Error message

Parameter  requires Administer System permission.

What it means

ForbiddenException thrown by DefaultUserController.throwForbiddenFor, invoked via throwIfValuePresent whenever a caller passes a value for a users-search query parameter (e.g. managed/excludedGroupId-style filters) that is reserved for users with Administer System permission. Non-admin callers must omit the parameter entirely.

Source

Thrown at server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/user/controller/DefaultUserController.java:85

  private void throwIfAdminOnlyParametersAreUsed(UsersSearchRestRequest usersSearchRestRequest, @Nullable String excludedGroupId) {
    if (!userSession.isSystemAdministrator()) {
      throwIfValuePresent("groupId", usersSearchRestRequest.groupId());
      throwIfValuePresent("groupId!", excludedGroupId);
      throwIfValuePresent("externalIdentity", usersSearchRestRequest.externalIdentity());
      throwIfValuePresent("sonarLintLastConnectionDateFrom", usersSearchRestRequest.sonarLintLastConnectionDateFrom());
      throwIfValuePresent("sonarLintLastConnectionDateTo", usersSearchRestRequest.sonarLintLastConnectionDateTo());
      throwIfValuePresent("sonarQubeLastConnectionDateFrom", usersSearchRestRequest.sonarQubeLastConnectionDateFrom());
      throwIfValuePresent("sonarQubeLastConnectionDateTo", usersSearchRestRequest.sonarQubeLastConnectionDateTo());
    }
  }

  private static void throwIfValuePresent(String parameter, @Nullable Object value) {
    Optional.ofNullable(value).ifPresent(v -> throwForbiddenFor(parameter));
  }

  private static void throwForbiddenFor(String parameterName) {
    throw new ForbiddenException("Parameter " + parameterName + " requires Administer System permission.");
  }

  private static UsersSearchRequest toUserSearchRequest(UsersSearchRestRequest usersSearchRestRequest, @Nullable String excludedGroupId, RestPage page) {
    return UsersSearchRequest.builder()
      .setDeactivated(Optional.ofNullable(usersSearchRestRequest.active()).map(active -> !active).orElse(false))
      .setManaged(usersSearchRestRequest.managed())
      .setQuery(usersSearchRestRequest.q())
      .setExternalLogin(usersSearchRestRequest.externalIdentity())
      .setLastConnectionDateFrom(usersSearchRestRequest.sonarQubeLastConnectionDateFrom())
      .setLastConnectionDateTo(usersSearchRestRequest.sonarQubeLastConnectionDateTo())
      .setSonarLintLastConnectionDateFrom(usersSearchRestRequest.sonarLintLastConnectionDateFrom())
      .setSonarLintLastConnectionDateTo(usersSearchRestRequest.sonarLintLastConnectionDateTo())
      .setGroupUuid(usersSearchRestRequest.groupId())
      .setExcludedGroupUuid(excludedGroupId)
      .setPage(page.pageIndex())
      .setPageSize(page.pageSize())
      .build();
  }

View on GitHub (pinned to 184c821202)

Solutions

  1. Remove the restricted parameter from the request, or send it only when the authenticated user has Administer System permission
  2. Grant Administer System to the calling account if legitimately needed
  3. Fix client code that serializes null-able params as present values

Example fix

// before
GET /api/v2/users/search?managed=false
// after
GET /api/v2/users/search   // omit restricted param unless admin
Defensive patterns

Strategy: validation

Validate before calling

// client-side: only send restricted params when caller is admin
Map<String,Object> params = new HashMap<>();
if (isAdmin && managed != null) params.put("managed", managed); // omit otherwise

Prevention

When it happens

Trigger: Calling the v2 users search endpoint while supplying a value for a restricted parameter (non-null) without holding Administer System permission.

Common situations: Scripts copying admin-only search parameters, tools that always send all query params (e.g. managed=false), service accounts lacking Administer System.

Understand the failure class

Background: "You do not have permission" / 403 Forbidden errors: authenticated but not allowed — causes and fixes across open-source libraries — this error's family across 31 libraries.

Related errors


AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09). Data as JSON: /api/errors/c619861d7c143938. Report an issue: GitHub.