Skip to content

About access control

Dependency-Track uses a role-based access control model built around permissions, teams, and users. Permissions can be assigned to teams or directly to users.

Effective permissions

A user's effective permissions are the union of their direct permissions and the permissions of every team they belong to. Permissions are never intersected or downgraded by team membership.

Users

Four types of users exist:

Type Description
Managed User A local account created and managed within Dependency-Track.
LDAP User Authenticated via an external LDAP directory. See Configuring LDAP.
OIDC User Authenticated via an OpenID Connect identity provider. See Configuring OIDC.
Service Account A non-human account for automation. Authenticates with its own API keys, or through workload identity federation. Available in 5.2.0 and later. See Service accounts.

All user types share the same permission model. The authentication mechanism determines how the system verifies a user's identity, not what they can access.

Service accounts

Available in 5.2.0 and later

Earlier versions support only team API keys for automation.

A service account is the identity of a CI pipeline, scanner, script, or other automated tool. Like any other user, it holds permissions directly or through team membership, and appears in team member lists.

A service account can't log in. It authenticates in one of two ways:

  • Workload identity federation. The workload exchanges a short-lived token issued by its own platform, such as GitHub Actions, GitLab CI, Kubernetes, or SPIFFE, for a session of the service account. See About workload identity federation.
  • API keys that the service account owns. Each request made with such a key acts as the service account.

Either way, audit records show the service account's username. Suspending a service account stops all its API keys and blocks new token exchanges, until you lift the suspension. It also ends sessions created through federation at once. Deleting the account also deletes its API keys and its workload identity bindings.

Service account usernames always start with svc:, for example svc:ci-pipeline. No other user can have a username with that prefix. This prevents a service account from taking a username that an LDAP or OIDC user would receive on first login.

Managing service accounts requires the ACCESS_MANAGEMENT permission.

Compared to team API keys, service accounts:

  • Give each automated tool a distinct identity, even when tools share a team.
  • Take permissions directly, so narrowing one tool's permissions doesn't need a dedicated team.
  • Support suspension, which blocks access without deleting API keys.
  • Can authenticate without any stored credential, through workload identity federation.

The intended path for automation

Service accounts combined with workload identity federation are the strategic replacement for teams that exist only to hold a long-lived API key. Team API keys remain supported. Start new integrations on service accounts.

Teams

A team is a named collection of users and API keys. Teams hold permissions, which makes it straightforward to manage access for groups of people (for example, Security Engineers, Developers, CI/CD Pipelines) or automated systems.

A user can belong to more than one team and inherits the union of all permissions from every team they are a member of. Permissions can also be assigned directly to a user. Those permissions add to whatever the user inherits from their teams.

Prefer team-based assignment as the default. Use direct user permissions sparingly, for exceptions that don't justify a dedicated team.

Team API keys belong to a team and carry the same permissions as that team. They authenticate automated access (CI/CD pipelines, integrations) without associating requests with a specific identity. In 5.2.0 and later, service accounts supersede them: they carry their own identity and permissions, and can authenticate without a stored credential at all.

Deleting a team also deletes its API keys and any project access assignments made through it. It keeps projects, user accounts, and API keys owned by service accounts, but users lose the permissions they had inherited from the deleted team.

Portfolio access control

By default, every principal with VIEW_PORTFOLIO can see every project. Portfolio Access Control (PAC) restricts that visibility so a team can only act on the projects explicitly assigned to it. The per-project list of assigned teams is the project's Access Control List (ACL).

With PAC enabled, ACL membership gates every operation on a project: viewing, BOM upload, editing, deletion, and vulnerability triage. The portfolio permissions (VIEW_PORTFOLIO, PORTFOLIO_MANAGEMENT_UPDATE, and so on) become necessary but not sufficient: a principal must hold the relevant permission and belong to a team on the project's ACL.

Enable PAC in Administration > Access Management > Portfolio Access Control.

Enabling PAC affects existing projects

Existing projects keep their data but start with no team assignments. Until an administrator (or a principal with PORTFOLIO_ACCESS_CONTROL_BYPASS) assigns at least one team to each project, those projects become invisible to all non-administrator users. Plan the assignment rollout before enabling PAC on a production instance.

PAC is most useful in multi-tenant scenarios where different teams should not see each other's projects. For single-team or open environments, PAC adds management overhead without security benefit.

How PAC interacts with permissions

Permissions and ACLs are orthogonal:

  • Permissions define what a principal can do, such as uploading BOMs, editing projects, or triaging vulnerabilities. They are global to the principal. The model has no per-project permissions.
  • ACLs define which projects a principal can do it on. They gate both reads and writes, but do not change which capabilities the principal holds.

To act on a project, a principal needs both the relevant permission and ACL access to that project. A user with PORTFOLIO_MANAGEMENT_UPDATE can edit every project they have ACL access to, and none of the ones they don't. Removing a team from a project's ACL revokes that team's access to the project but leaves the team's permissions unchanged elsewhere.

Pattern: separating permission teams from access teams

Because permissions and ACLs compose independently, a useful pattern is to split teams by role:

  • Permission teams carry capabilities (VIEW_PORTFOLIO, VULNERABILITY_ANALYSIS, and so on) but are not assigned to any project.
  • Access teams hold no permissions but are assigned to a subset of projects.

A user joins one team of each kind. Their effective rights are the union of all their teams' permissions, scoped to the union of all their teams' ACL grants. This emulates per-project permissions without the model having to support them directly.

For an organization with a Front Office and a Back Office portfolio:

flowchart LR
    Alice(["Alice<br/>Developer, Front Office"])
    Bob(["Bob<br/>Developer, Back Office"])
    Carol(["Carol<br/>Auditor, Front + Back Office"])

    subgraph Permission teams
        Devs["<b>Developers</b><br/>VIEW_PORTFOLIO<br/>VIEW_VULNERABILITY"]
        Auditors["<b>Auditors</b><br/>VIEW_PORTFOLIO<br/>VIEW_VULNERABILITY<br/>VULNERABILITY_ANALYSIS"]
    end

    subgraph Access teams
        FO["<b>Front Office</b><br/>(no permissions)"]
        BO["<b>Back Office</b><br/>(no permissions)"]
    end

    FP[("Front Office<br/>projects")]
    BP[("Back Office<br/>projects")]

    Alice --> Devs
    Alice --> FO
    Bob --> Devs
    Bob --> BO
    Carol --> Auditors
    Carol --> FO
    Carol --> BO

    FO -. ACL .-> FP
    BO -. ACL .-> BP

Resulting effective access:

User Can view Can triage vulnerabilities on
Alice Front Office projects none
Bob Back Office projects none
Carol Front Office and Back Office projects both portfolios

Adding a new domain becomes a single new access team and its ACL assignments. Granting an existing user analyst rights on that domain is a team membership change, not a per-project edit.

Inheritance through the project hierarchy

ACL grants are inherited down the project hierarchy. Granting a team access to a parent project grants access to every descendant, current and future. Assigning teams at the top of a project tree is usually preferable to assigning them on every leaf.

Bypassing PAC

The PORTFOLIO_ACCESS_CONTROL_BYPASS permission exempts a principal from PAC entirely: they see every project as if PAC were disabled. Reserve it for administrators and trusted automation that legitimately needs to operate across the full portfolio.

Project creation under PAC

When a team API key or a service account creates a project (for example, via BOM upload with PROJECT_CREATION_UPLOAD), Dependency-Track adds its first team in alphabetical order to the new project's ACL. A service account that belongs to no team adds no team to the ACL.

When a user creates a project, they must designate an owning team from those they belong to. The chosen team is added to the new project's ACL. A project created with no team assignment is invisible to everyone except administrators and holders of PORTFOLIO_ACCESS_CONTROL_BYPASS until one is assigned.

Further reading