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
- 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
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
- 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
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
- Insufficient privileges
- Insufficient privileges
- Insufficient privileges
- %s is not a valid url
- Error while executing a call to %s. Return code %s. Error me
AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09).
Data as JSON: /api/errors/c619861d7c143938.
Report an issue: GitHub.