{"record":{"id":"c619861d7c143938","repo":"SonarSource/sonarqube","slug":"parameter-requires-administer-system-permission","errorCode":null,"errorMessage":"Parameter  requires Administer System permission.","messagePattern":"Parameter  requires Administer System permission\\.","errorType":"http","errorClass":"ForbiddenException","httpStatus":403,"severity":"warning","filePath":"server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/user/controller/DefaultUserController.java","lineNumber":85,"sourceCode":"\n  private void throwIfAdminOnlyParametersAreUsed(UsersSearchRestRequest usersSearchRestRequest, @Nullable String excludedGroupId) {\n    if (!userSession.isSystemAdministrator()) {\n      throwIfValuePresent(\"groupId\", usersSearchRestRequest.groupId());\n      throwIfValuePresent(\"groupId!\", excludedGroupId);\n      throwIfValuePresent(\"externalIdentity\", usersSearchRestRequest.externalIdentity());\n      throwIfValuePresent(\"sonarLintLastConnectionDateFrom\", usersSearchRestRequest.sonarLintLastConnectionDateFrom());\n      throwIfValuePresent(\"sonarLintLastConnectionDateTo\", usersSearchRestRequest.sonarLintLastConnectionDateTo());\n      throwIfValuePresent(\"sonarQubeLastConnectionDateFrom\", usersSearchRestRequest.sonarQubeLastConnectionDateFrom());\n      throwIfValuePresent(\"sonarQubeLastConnectionDateTo\", usersSearchRestRequest.sonarQubeLastConnectionDateTo());\n    }\n  }\n\n  private static void throwIfValuePresent(String parameter, @Nullable Object value) {\n    Optional.ofNullable(value).ifPresent(v -> throwForbiddenFor(parameter));\n  }\n\n  private static void throwForbiddenFor(String parameterName) {\n    throw new ForbiddenException(\"Parameter \" + parameterName + \" requires Administer System permission.\");\n  }\n\n  private static UsersSearchRequest toUserSearchRequest(UsersSearchRestRequest usersSearchRestRequest, @Nullable String excludedGroupId, RestPage page) {\n    return UsersSearchRequest.builder()\n      .setDeactivated(Optional.ofNullable(usersSearchRestRequest.active()).map(active -> !active).orElse(false))\n      .setManaged(usersSearchRestRequest.managed())\n      .setQuery(usersSearchRestRequest.q())\n      .setExternalLogin(usersSearchRestRequest.externalIdentity())\n      .setLastConnectionDateFrom(usersSearchRestRequest.sonarQubeLastConnectionDateFrom())\n      .setLastConnectionDateTo(usersSearchRestRequest.sonarQubeLastConnectionDateTo())\n      .setSonarLintLastConnectionDateFrom(usersSearchRestRequest.sonarLintLastConnectionDateFrom())\n      .setSonarLintLastConnectionDateTo(usersSearchRestRequest.sonarLintLastConnectionDateTo())\n      .setGroupUuid(usersSearchRestRequest.groupId())\n      .setExcludedGroupUuid(excludedGroupId)\n      .setPage(page.pageIndex())\n      .setPageSize(page.pageSize())\n      .build();\n  }","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/user/controller/DefaultUserController.java#L67-L103","documentation":"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.","triggerScenarios":"Calling the v2 users search endpoint while supplying a value for a restricted parameter (non-null) without holding Administer System permission.","commonSituations":"Scripts copying admin-only search parameters, tools that always send all query params (e.g. managed=false), service accounts lacking Administer System.","solutions":["Remove the restricted parameter from the request, or send it only when the authenticated user has Administer System permission","Grant Administer System to the calling account if legitimately needed","Fix client code that serializes null-able params as present values"],"exampleFix":"// before\nGET /api/v2/users/search?managed=false\n// after\nGET /api/v2/users/search   // omit restricted param unless admin","handlingStrategy":"validation","validationCode":"// client-side: only send restricted params when caller is admin\nMap<String,Object> params = new HashMap<>();\nif (isAdmin && managed != null) params.put(\"managed\", managed); // omit otherwise","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Omit optional restricted query params entirely for non-admin callers","Don't serialize null-able filters as explicit values","Grant Administer System only where genuinely required"],"tags":["java","authorization","api-parameters"],"backgroundTag":"insufficient-permissions","analyzedSha":"184c821202192afc1c599fc912d0889b69fffa53","analyzedAt":"2026-09-09T12:23:51.573Z","contentChangedAt":"2026-09-09T12:23:51.573Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}