{"record":{"id":"8a4888c3e1a09b64","repo":"SonarSource/sonarqube","slug":"parameter-s-requires-administer-system-permission","errorCode":null,"errorMessage":"parameter %s requires Administer System permission.","messagePattern":"parameter (.+?) requires Administer System permission\\.","errorType":"exception","errorClass":"ServerException","httpStatus":403,"severity":"error","filePath":"server/sonar-webserver-webapi/src/main/java/org/sonar/server/user/ws/SearchAction.java","lineNumber":214,"sourceCode":"      .setQuery(request.param(TEXT_QUERY))\n      .setDeactivated(request.mandatoryParamAsBoolean(DEACTIVATED_PARAM))\n      .setManaged(request.paramAsBoolean(MANAGED_PARAM))\n      .setLastConnectionDateFrom(request.param(LAST_CONNECTION_DATE_FROM))\n      .setLastConnectionDateTo(request.param(LAST_CONNECTION_DATE_TO))\n      .setSonarLintLastConnectionDateFrom(request.param(SONAR_LINT_LAST_CONNECTION_DATE_FROM))\n      .setSonarLintLastConnectionDateTo(request.param(SONAR_LINT_LAST_CONNECTION_DATE_TO))\n      .setExternalLogin(request.param(EXTERNAL_IDENTITY))\n      .setPage(request.mandatoryParamAsInt(PAGE))\n      .setPageSize(pageSize)\n      .build();\n  }\n\n  private static void throwIfParameterValuePresent(Request request, String parameter) {\n    Optional.ofNullable(request.param(parameter)).ifPresent(v -> throwForbiddenFor(parameter));\n  }\n\n  private static void throwForbiddenFor(String parameterName) {\n    throw new ServerException(403, \"parameter \" + parameterName + \" requires Administer System permission.\");\n  }\n\n}\n","sourceCodeStart":196,"sourceCodeEnd":218,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-webserver-webapi/src/main/java/org/sonar/server/user/ws/SearchAction.java#L196-L218","documentation":"SonarQube's user SearchAction rejects requests that supply admin-only query parameters (e.g. q, groups in some versions) without the Administer System permission, throwing a ServerException with HTTP 403. The filter checks whether the parameter is present in the request and if so demands elevated rights regardless of the value. It exists to keep user enumeration from non-privileged users.","triggerScenarios":"GET api/users/search while including admin-restricted parameters (such as q) while authenticated as a user (or token) lacking the Administer System global permission.","commonSituations":"CI scripts using a project-analysis token instead of a global-admin token; self-service portal calling user search with filters; after downgrading an account's permissions; token belongs to a team admin not a global admin.","solutions":["Use a token belonging to an account with the Administer System global permission (generate via My Account > Security, or grant the permission in Administration > Security > Global Permissions).","Remove the restricted query parameter from the request; unfiltered search results are returned to non-admin callers.","Check which account the token maps to: GET api/authentication/validate or api/users/current, then verify its global permissions.","If users legitimately need filtered lookups, consider delegating to an admin service or an API wrapper that holds admin rights."],"exampleFix":"// before: project-scoped token calling filtered search\ncurl -u \"$PROJECT_TOKEN:\" 'https://sonar/api/users/search?q=jdoe'\n// after: admin token, or drop the restricted param\ncurl -u \"$ADMIN_TOKEN:\" 'https://sonar/api/users/search?q=jdoe'\n# or for non-admin callers:\ncurl -u \"$TOKEN:\" 'https://sonar/api/users/search'","handlingStrategy":"validation","validationCode":"const me = await fetch(`${base}/api/users/current`, {headers: auth}).then(r => r.json());\nconst isAdmin = me.permissions?.global?.includes('admin');\nif (params.q && !isAdmin) throw new Error('q parameter requires Administer System permission; drop it or use an admin token');","typeGuard":"function canFilterUsers(me) {\n  return Array.isArray(me?.permissions?.global) && me.permissions.global.includes('admin');\n}","tryCatchPattern":"try {\n  return await searchUsers(params);\n} catch (e) {\n  if (e.status === 403 && /requires Administer System permission/.test(e.message)) {\n    return searchUsers({}); // retry unfiltered\n  }\n  throw e;\n}","preventionTips":["Keep admin-only calls on admin tokens; never reuse analysis tokens","Validate current permissions with api/users/current before filtered queries","Drop restricted query parameters for non-admin callers","Centralize which token is used per API group"],"tags":["sonarqube","rest-api","permissions","http-403"],"backgroundTag":"permission-denied","analyzedSha":"184c821202192afc1c599fc912d0889b69fffa53","analyzedAt":"2026-09-09T12:23:51.573Z","contentChangedAt":"2026-09-09T12:23:51.573Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}