{"record":{"id":"98cda0dec86c5242","repo":"SonarSource/sonarqube","slug":"insufficient-privileges-98cda0","errorCode":null,"errorMessage":"Insufficient privileges","messagePattern":"Insufficient privileges","errorType":"exception","errorClass":"ForbiddenException","httpStatus":403,"severity":"error","filePath":"server/sonar-webserver-webapi/src/main/java/org/sonar/server/setting/ws/ValuesAction.java","lineNumber":153,"sourceCode":"      result = ImmutableSet.copyOf(keys);\n    }\n    result.forEach(SettingsWsSupport::validateKey);\n    return result;\n  }\n\n  private Optional<EntityDto> loadComponent(DbSession dbSession, ValuesRequest valuesRequest) {\n    String componentKey = valuesRequest.getComponent();\n    if (componentKey == null) {\n      return Optional.empty();\n    }\n\n    EntityDto entity = dbClient.entityDao().selectByKey(dbSession, componentKey)\n      .orElseThrow(() -> new NotFoundException(format(\"Component key '%s' not found\", componentKey)));\n\n    if (!userSession.hasEntityPermission(USER, entity) &&\n      !userSession.hasEntityPermission(ProjectPermission.SCAN, entity) &&\n      !userSession.hasPermission(GlobalPermission.SCAN)) {\n      throw insufficientPrivilegesException();\n    }\n    return Optional.of(entity);\n  }\n\n  private List<Setting> loadSettings(DbSession dbSession, Optional<EntityDto> component, Set<String> keys) {\n    // List of settings must be kept in the following orders : default -> global -> component\n    List<Setting> settings = new ArrayList<>();\n    settings.addAll(loadDefaultValues(keys));\n    settings.addAll(loadGlobalSettings(dbSession, keys));\n    component.ifPresent(c -> settings.addAll(loadComponentSettings(dbSession, c, keys)));\n    return settings.stream()\n      .filter(s -> settingsWsSupport.isVisible(s.getKey(), component))\n      .toList();\n  }\n\n  private Collection<Setting> loadComponentSettings(DbSession dbSession, EntityDto entity, Set<String> keys) {\n    return loadComponentSettings(dbSession, keys, entity.getUuid());\n  }","sourceCodeStart":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-webserver-webapi/src/main/java/org/sonar/server/setting/ws/ValuesAction.java#L135-L171","documentation":"The SonarQube Web API 'api/settings/values' component lookup rejects users who lack permission on the requested component. loadComponent resolves the component key to an entity, then requires USER (or SCAN) entity permission on that entity, or global SCAN permission. If none hold, insufficientPrivilegesException() is thrown so the API does not leak settings of projects the caller cannot see.","triggerScenarios":"Calling GET api/settings/values with a component (or componentKeys) parameter while the authenticated user has neither the USER nor SCAN permission on that project, nor the global Execute Analysis (SCAN) permission.","commonSituations":"CI tokens used to read project settings without 'Execute Analysis' permission; users browsing settings of a project they are not a member of; automation scripts reusing a user account that lost project access after permission reshuffling.","solutions":["Grant the user (or the account's group) USER or Execute Analysis (SCAN) permission on the target project: Project Settings > Permissions.","Alternatively grant the global Execute Analysis permission if the integration legitimately scans/reads all projects.","Verify you are calling with a token belonging to the intended account, not an expired or reassigned token.","If read access only is needed and cannot be granted, use an account with the required permission for the API call."],"exampleFix":"// before: call with underprivileged token\ncurl -u underprivilegedToken: http://sonar/api/settings/values?component=my_project\n\n// after: grant USER/SCAN permission on my_project to the token's user, or use an admin/scanner account\ncurl -u scannerToken: http://sonar/api/settings/values?component=my_project","handlingStrategy":"validation","validationCode":"// Java client-side pre-check: does the user hold required permission?\n// GET /api/permissions/permission_templates or simpler: probe the project\nWSResponse resp = wsClient.get(\"api/projects/search\").failIfNotOk(); // project visible only if USER permission held\n// If the target project is not in the result list for this user, skip the settings call.","typeGuard":"boolean canReadSettings(UserSession s, EntityDto e) { return s.hasEntityPermission(USER, e) || s.hasEntityPermission(ProjectPermission.SCAN, e) || s.hasPermission(GlobalPermission.SCAN); }","tryCatchPattern":null,"preventionTips":["Provision service accounts with the exact project permissions they need (USER or Execute Analysis).","Use group-based permissions so token users inherit access consistently.","Check project visibility (public/private) when expecting anonymous/low-privilege reads.","Handle 403 responses explicitly in API clients and surface a clear access-request message."],"tags":["sonarqube","webapi","authorization","permissions"],"backgroundTag":"insufficient-permissions","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"}