SonarSource/sonarqube · error · ForbiddenException

Insufficient privileges

Error message

Insufficient privileges

What it means

AbstractUserSession.checkPermission throws ForbiddenException when the logged-in user lacks the requested GlobalPermission. Unlike an authentication error, the user is authenticated but not authorized to perform the action.

Source

Thrown at server/sonar-webserver-auth/src/main/java/org/sonar/server/user/AbstractUserSession.java:179

  protected List<ComponentDto> doKeepAuthorizedComponents(ProjectPermission permission, Collection<ComponentDto> components) {
    boolean allowPublicComponent = ProjectPermission.PUBLIC_PERMISSIONS.contains(permission);
    return components.stream()
      .filter(c -> (allowPublicComponent && !c.isPrivate()) || hasComponentPermission(permission, c))
      .toList();
  }

  @Override
  public final UserSession checkLoggedIn() {
    if (!isLoggedIn()) {
      throw new UnauthorizedException(AUTHENTICATION_IS_REQUIRED_MESSAGE);
    }
    return this;
  }

  @Override
  public final UserSession checkPermission(GlobalPermission permission) {
    if (!hasPermission(permission)) {
      throw new ForbiddenException(INSUFFICIENT_PRIVILEGES_MESSAGE);
    }
    return this;
  }

  @Override
  public final UserSession checkComponentPermission(ProjectPermission projectPermission, ComponentDto component) {
    if (!hasComponentPermission(projectPermission, component)) {
      throw new ForbiddenException(INSUFFICIENT_PRIVILEGES_MESSAGE);
    }
    return this;
  }

  @Override
  public UserSession checkEntityPermission(ProjectPermission projectPermission, EntityDto entity) {
    if (hasEntityPermission(projectPermission, entity)) {
      return this;
    }

View on GitHub (pinned to 184c821202)

Solutions

  1. Grant the required global permission in Administration > Security > Global Permissions (directly or via group)
  2. Use a token belonging to a user/account that already holds the permission
  3. If the action is project-scoped, check whether the caller should use project permissions via checkComponentPermission instead of a global permission

Example fix

// before
userSession.checkPermission(GlobalPermission.ADMIN);
// after
if (!userSession.hasPermission(GlobalPermission.ADMIN)) {
  throw new ForbiddenException("Global 'Administer System' permission is required; grant it in Administration > Security > Global Permissions");
}
userSession.checkPermission(GlobalPermission.ADMIN);
Defensive patterns

Strategy: try-catch

Validate before calling

if (!userSession.hasPermission(GlobalPermission.ADMIN)) {
  throw new ForbiddenException("This action requires the 'Administer System' global permission");
}

Try / catch

try {
  userSession.checkPermission(GlobalPermission.ADMIN);
  // perform admin action
} catch (ForbiddenException e) {
  if (!e.getMessage().equals("Insufficient privileges")) throw e;
  // return 403 with the required permission name for the caller
}

Prevention

When it happens

Trigger: Calling checkPermission(GlobalPermission.X) (directly or via a webservice handler) when hasPermission(X) is false — user lacks the global permission such as Administer, Provision Projects, or Execute Analysis.

Common situations: Non-admin users calling admin-only APIs (api/users, api/settings); CI tokens created from a user without Execute Analysis permission; permission changes after group membership updates.

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/38232fdf2f15b6cc. Report an issue: GitHub.