Scopes are effectively permissioning, or ACLs, for Taskcluster. The official definition of scopes is here. They’re essentially strings; if your set of scopes or scope patterns match the required scopes, you have the required scopes.

For example, if you have the scopes:


And the required scopes are:


Then you have the required scopes. However, if you need a-little-bit-secret/something-else, you don’t have the required scopes.


We grant scopes to clients and roles. These are defined in the ci-configuration repo; view the README.

The ci-configuration repo also contains the ci-admin management tool which we use to test, diff, and apply the configuration changes.


Roles are a way of grouping sets of scopes together. If you’re granted the assume:<role> scope, you are granted each of the scopes in that role. (See Scopes and Roles.)

Expansion of scopes in Automation#

It’s not intuitive at first which scopes are granted and which are required in automation. This is at least partially because scopes are expanded from a simple single role to a massive set. Star scopes expand to match any number of matching scopes, and each one of those allow for further expansion.

(There’s a handy tool that lets us put in a scope or scopes, then click the expand scopes button in the lower right, to list the full set of scopes granted.)

Hg Pushes#

For hg.m.o, pushes go through hooks. (see How Tasks are Triggered.) By default we’ll assume the role e.g. hook-id:hg-push/mozilla-central in this hook. The create-task scopes limit what worker pools we can create tasks for, and we can only grant scopes to tasks within the set of scopes that the hook has been granted. (If the hook has scopes ["foo", "bar"], it can schedule tasks with the scopes ["foo"], ["bar"], or ["foo", "bar"] but not ["foo", "baz"].)

The hg-push template grants the scope assume:${project_role_prefix}:branch:*, e.g.* to the build-decision task, which means the decision task can have a subset of those scopes.

The decision task itself will have the scopes defined in .taskcluster.yml, which will be a subset of the build-decision task’s scopes (or we’ll fail due to insufficient scopes).


Taskcluster-github grants these scopes to tasks depending on their Github event type.


Similar to hg pushes, cron goes through hooks (see How Tasks are Triggered). By default we’ll assume the role e.g. hook-id:project-releng/cron-task-mozilla-central in this hook.

The cron task template grants the scope assume:hook-id:${hookGroupId}/${hookId}, so the resulting build-decision task will have the same set of scopes as the hook.

The cron task itself will have the scopes defined in .taskcluster.yml, which will be a subset of the build-decision task’s scopes (or we’ll fail due to insufficient scopes).


Actions check for a special scope, assume:repo:{head_repository[8:]}:action:{actionPerm}. actionPerm falls back to generic for many actions, which means they’re all permissioned the same. An action like retrigger-decision or release-promotion will not specify generic=True, and their actionPerm will be retrigger-decision or release-promotion, respectively; this lets us grant these scopes more selectively.


We’re able to target our scope grants fairly granularly. For example, this block:

- grant:
  - project:releng:balrog:server:beta
  - project:releng:balrog:server:esr
  - project:releng:balrog:server:release
  - project:releng:beetmover:bucket:maven-production
  - project:releng:beetmover:bucket:partner
  - project:releng:beetmover:bucket:release
  - project:releng:bouncer:server:production
  - project:releng:bouncer:server:production-nazgul
  - project:releng:ship-it:server:production
  - projects:
      job: ["action:release-promotion"]
      trust_domain: gecko
      level: [3]
      alias: [mozilla-esr78, mozilla-esr91, mozilla-release, mozilla-beta]

lets us grant restricted scriptworker scopes to just the release promotion action, run on level 3 gecko repositories, as long as their aliases match one of the above. Phew! Where we run into issues is if we, say, want to run a retrigger action hook on one of those tasks. Because the retrigger action hook doesn’t match the above filter, it won’t have the scopes to create the retriggered task. (Perhaps this is all for the best, given the issues with retriggering release tasks.



Colons : are delimiters for the official platform defined scopes and scope prefixes. We also use dashes - and slashes / as word delimiters in the user-defined portions of the scope strings. (Also, periods . for index delimiters.) If you define a scope pattern with a trailing asterisk *, it’s best practice to append the asterisk after a word delimiter:


rather than:


Groups / teams#

We try to tie most user scope grants to LDAP. Grants to mozilla-group:GROUP will assign the scopes to users that belong to that MoCo ldap group. Grants to mozillians-group:GROUP will grant scopes to users that belong to that Mozillians group (

We also define ci-group roles like project:releng:ci-group:team_moco in this block.


Levels in scopes match the Firefox commit levels. Level 1 is Try and pull requests; contributors can easily get this level of access. Level 2 is projects and l10n, and isn’t used everywhere. Level 3 is release level, and requires a higher bar to gain this level of access. Ideally contributors will be able to get everything done at level 1 unless they become a trusted member of a project.

We encode levels in workerType/workerPool names, and in other scopes that should be restricted by repo and commit level. For example, the gecko-1/decision worker is the decision worker for Try. gecko-3/decision is the trusted decision worker for release trains and autoland.

Docker- and Generic-Worker scopes#

The scopes for docker- and generic-worker workers should be minimal, just enough to register as a given workerType and claim tasks from the queue. They will be granted temporary scopes for each task that they run.

Scriptworker scopes#

Scriptworker scopes are similar, but each *script will also define script-specific scopes, like project:releng:signing:format:signcode.

In addition, until we fix Issue #426 (use temp queue to download artifacts), we also need to grant private artifact scopes to the clientId as well as the task.

Restricted scopes#

We define Chain of Trust cot_restricted_scopes in scriptworker. These are scopes that can only run on specific allowlisted trees or tasks_for.