# Understanding the Jenkins Security Permission Model: PermissionGroup, Permission, and PermissionScope

> Master the Jenkins security permission model. Learn how Permission, PermissionGroup, and PermissionScope manage access control effectively. Secure your Jenkins instance today.

- Repository: [Jenkins/jenkins](https://github.com/jenkinsci/jenkins)
- Tags: deep-dive
- Published: 2026-07-28

---

**The Jenkins security permission model organizes access control through three hierarchical concepts: Permission represents individual security privileges, PermissionGroup collects related permissions under an owner class, and PermissionScope defines the model objects (Jenkins instance, items, runs) where permissions can be configured.**

The Jenkins security permission model provides a granular, extensible framework for access control that plugin developers use to define and enforce authorization rules. Implemented in the `jenkinsci/jenkins` repository, this model centers on the relationship between `PermissionGroup`, `Permission`, and `PermissionScope` classes in `core/src/main/java/hudson/security/` to create a hierarchical security structure that scales from the global Jenkins instance down to individual build runs.

## Core Components of the Jenkins Security Architecture

### Permission: The Atomic Security Privilege

A **Permission** in Jenkins represents a single, discrete security privilege such as *Read*, *Configure*, or *Delete*. Defined in [`core/src/main/java/hudson/security/Permission.java`](https://github.com/jenkinsci/jenkins/blob/main/core/src/main/java/hudson/security/Permission.java), each permission is uniquely identified by its owner class and name combination.

The `Permission` constructor signature reveals the model's sophistication:

```java
public Permission(@NonNull PermissionGroup group,
                  @NonNull String name,
                  @CheckForNull Localizable description,
                  @CheckForNull Permission impliedBy,
                  boolean enable,
                  @NonNull PermissionScope[] scopes)

```

Key parameters include:

- **group** – The `PermissionGroup` that owns this permission
- **name** – A Java-identifier-compatible string (e.g., `"Read"`, `"Configure"`)
- **impliedBy** – An optional broader permission that implicitly grants this one, forming a permission hierarchy (see lines 88-96 in [`Permission.java`](https://github.com/jenkinsci/jenkins/blob/main/Permission.java))
- **scopes** – An array of `PermissionScope` values defining where this permission can be configured
- **enabled** – A toggle controlling visibility in the permission matrix

All permissions register themselves in a global list (`ALL`) and can be retrieved via `Permission.fromId(String)`.

### PermissionGroup: Logical Containers for Related Permissions

**PermissionGroup**, defined in [`core/src/main/java/hudson/security/PermissionGroup.java`](https://github.com/jenkinsci/jenkins/blob/main/core/src/main/java/hudson/security/PermissionGroup.java), serves as the registration point and container for permissions belonging to the same owner class. When a permission is instantiated, it automatically adds itself to its group's internal `SortedSet` (line 99) and to the global registry (`PERMISSIONS`).

Key behaviors of `PermissionGroup` include:

- **Iteration** – The class implements `Iterable<Permission>`, allowing enumeration of all permissions within a group
- **Lookup** – The `find(String name)` method retrieves permissions by simple name
- **Containment checking** – `hasPermissionContainedBy(PermissionScope)` determines whether any permission in the group applies to a specific scope

Permission groups maintain a specific sort order: Hudson/Jenkins core groups appear first based on a *compare order* value, followed by plugin groups sorted by fully-qualified owner class name (lines 31-40).

### PermissionScope: Defining Configuration Boundaries

**PermissionScope**, implemented in [`core/src/main/java/hudson/security/PermissionScope.java`](https://github.com/jenkinsci/jenkins/blob/main/core/src/main/java/hudson/security/PermissionScope.java), abstracts the model object a permission acts upon and determines where administrators can configure that permission. Each scope contains:

- **modelClass** – The concrete `ModelObject` subclass (e.g., `Jenkins.class`, `Item.class`)
- **containers** – Broader scopes that contain this one, enabling implicit configuration at higher levels (lines 66-72)

The built-in scopes defined in lines 94-116 include:

- `JENKINS` – The top-level Jenkins instance
- `ITEM_GROUP` – Containers such as folders and projects
- `ITEM` – Individual jobs and configuration items
- `RUN` – Individual build runs
- `COMPUTER` – Agent nodes and build machines

The `isContainedBy(PermissionScope)` method recursively checks containment relationships, ensuring that a scope always contains itself (lines 80-86). This allows permissions scoped to `ITEM` to be configured at the `ITEM_GROUP` or `JENKINS` level through scope inheritance.

## How the Three Components Interact

When defining a new permission, developers follow a standard pattern that demonstrates the interplay between these classes:

```java
class MyFeature {
    private static final PermissionGroup PERMISSIONS = 
        new PermissionGroup(MyFeature.class, Messages._MyFeature_Permissions_Title());

    public static final Permission DO_SOMETHING = 
        new Permission(PERMISSIONS, "DoSomething",
                       Messages._MyFeature_DoSomething_Description(),
                       Permission.READ,   // impliedBy hierarchy
                       true,
                       new PermissionScope[]{PermissionScope.ITEM});
}

```

In this pattern:

1. The **PermissionGroup** registers the owner class (`MyFeature.class`) and provides the UI title
2. The **Permission** adds itself to the group and the global registry while specifying `Permission.READ` as its implied parent
3. The **PermissionScope** (`ITEM`) restricts configuration to individual items, though administrators may also set it at `ITEM_GROUP` or `JENKINS` levels due to scope containment

During authorization checks, Jenkins evaluates whether a user holds the required permission directly or through the `impliedBy` chain, and whether the current context matches the permission's declared scopes.

## Implementing Custom Permissions in Jenkins Plugins

### Creating a Permission Group and Permission

Plugin developers typically define permissions as static fields within their plugin class:

```java
// In src/main/java/com/example/MyPlugin.java
public class MyPlugin {
    // Register a group for this plugin's permissions
    private static final PermissionGroup PERMISSIONS =
        new PermissionGroup(MyPlugin.class, Messages._MyPlugin_Permissions_Title());

    // Permission scoped to ItemGroup level (folders, projects)
    public static final Permission CREATE_JOB = new Permission(
        PERMISSIONS,
        "CreateJob",
        Messages._MyPlugin_CreateJob_Description(),
        Permission.READ,          // inherits generic read privilege
        true,
        new PermissionScope[]{PermissionScope.ITEM_GROUP});
}

```

### Checking Permissions at Runtime

To enforce security checks in your plugin code:

```java
// Inside a job configuration page or management link
if (Jenkins.get().hasPermission(MyPlugin.CREATE_JOB)) {
    // Render UI elements allowing job creation
}

```

### Enumerating Permissions Programmatically

To inspect all permissions within a specific group:

```java
PermissionGroup pg = PermissionGroup.get(MyPlugin.class);
for (Permission p : pg.getPermissions()) {
    System.out.println(p.getId() + " enabled: " + p.getEnabled());
}

```

## Summary

- **Permission** represents atomic security privileges with unique IDs, descriptions, and optional implied-by hierarchies defined in [`core/src/main/java/hudson/security/Permission.java`](https://github.com/jenkinsci/jenkins/blob/main/core/src/main/java/hudson/security/Permission.java).
- **PermissionGroup** organizes related permissions by owner class, implements `Iterable<Permission>` for enumeration, and maintains registration in [`core/src/main/java/hudson/security/PermissionGroup.java`](https://github.com/jenkinsci/jenkins/blob/main/core/src/main/java/hudson/security/PermissionGroup.java).
- **PermissionScope** defines configuration boundaries through model objects (Jenkins, Item, Run, Computer) with recursive containment logic in [`core/src/main/java/hudson/security/PermissionScope.java`](https://github.com/jenkinsci/jenkins/blob/main/core/src/main/java/hudson/security/PermissionScope.java).
- The three components work together to create a hierarchical security model where permissions can be configured at broader scopes and inherited at narrower ones.
- Plugin developers use static initialization patterns to register custom permissions that integrate with Jenkins' matrix-based authorization strategies.

## Frequently Asked Questions

### What is the difference between Permission and PermissionGroup in Jenkins?

A **Permission** represents a single security privilege like "Read" or "Configure," while a **PermissionGroup** acts as a container that collects all permissions belonging to the same owner class. According to the Jenkins source code in [`PermissionGroup.java`](https://github.com/jenkinsci/jenkins/blob/main/PermissionGroup.java), when a permission is constructed, it automatically registers itself with its group, which then maintains a sorted set of all related permissions and provides iteration and lookup capabilities.

### How does PermissionScope determine where a permission can be configured?

**PermissionScope** defines the model object level—such as `JENKINS`, `ITEM`, or `RUN`—where a permission is applicable. As implemented in [`core/src/main/java/hudson/security/PermissionScope.java`](https://github.com/jenkinsci/jenkins/blob/main/core/src/main/java/hudson/security/PermissionScope.java), scopes form a containment hierarchy where broader scopes (like `ITEM_GROUP`) contain narrower ones (like `ITEM`). The `isContainedBy()` method recursively checks these relationships, allowing permissions scoped to items to be configured at the Jenkins global level because `JENKINS` contains `ITEM` through the intermediate `ITEM_GROUP` scope.

### What is the purpose of the impliedBy parameter in the Permission constructor?

The **impliedBy** parameter creates a permission hierarchy where holding a broader permission automatically grants implied narrower permissions. For example, if a user has `Permission.ADMINISTER`, they implicitly hold all other permissions that specify `ADMINISTER` as their `impliedBy` value. This mechanism, visible in lines 88-96 of [`Permission.java`](https://github.com/jenkinsci/jenkins/blob/main/Permission.java), reduces administrative overhead by allowing high-level roles to automatically inherit granular privileges without explicit configuration.

### How do I check if a user has a specific permission in a Jenkins plugin?

Use the `hasPermission(Permission)` method available on `Jenkins` instances or model objects. For example, `Jenkins.get().hasPermission(MyPlugin.CREATE_JOB)` verifies that the current security context possesses the required permission. This check evaluates both direct permission grants and the `impliedBy` hierarchy, returning true if the user holds the specific permission or any permission that implies it according to the security realm configuration.