Skip to content

    Back to articles

    6 min read

    Give alert triage its own token permissions

    Separate reading alerts from shipping software

    A workflow that classifies Dependabot alerts should not need the authority of a workflow that publishes a package. I would make the alert workflow’s permission explicit, then keep it separate from build and release jobs. GitHub’s early September 2026 Actions update added a read-only vulnerability-alerts permission for GITHUB_TOKEN (GitHub’s early September 2026 Actions update). That gives alert triage a narrower option than granting broader repository permissions just to retrieve vulnerability data.

    The design principle is straightforward: give a task the access its purpose requires, not the access a neighboring task happens to need. A triage workflow needs to read alert details. A publishing workflow may need to write packages. Combining those responsibilities means the token for one job can carry permissions that have nothing to do with the other job’s work.

    This is a boundary I would express in the workflow file, not leave to a convention about which steps are “supposed” to use a token. GitHub documents that actions may access GITHUB_TOKEN through the github.token context even when the workflow does not explicitly pass it to them, so limiting permissions matters even when a token is not an obvious action input (GitHub’s guidance on using GITHUB_TOKEN).

    Grant only the permission the job needs

    A small manually triggered workflow makes the permission boundary visible. It lists alerts through GitHub CLI; the token is supplied to the CLI through its supported GH_TOKEN environment variable.

    name: Triage Dependabot alerts
    
    on:
      workflow_dispatch:
    
    jobs:
      triage:
        runs-on: ubuntu-latest
        permissions:
          vulnerability-alerts: read
        steps:
          - name: List Dependabot alerts
            env:
              GH_TOKEN: ${{ github.token }}
            run: gh api --paginate "repos/${GITHUB_REPOSITORY}/dependabot/alerts"

    The important line is not the API command; it is the permission declaration next to the job that uses it. GitHub’s workflow syntax says vulnerability-alerts: read permits listing Dependabot alerts, and supports only read and none for this permission—not write (GitHub’s workflow syntax for vulnerability-alerts). Since the permission is scoped to the job, it describes what this job needs rather than silently extending a broad workflow-level grant to unrelated jobs.

    There is a useful consequence to declaring permissions explicitly: GitHub documents that when you specify individual permissions, unspecified permissions are set to none (GitHub’s workflow syntax for token permissions). In this example, the triage job does not need repository contents, package publishing, or deployment permissions. If I later add a step that genuinely needs another capability, I must add that permission deliberately. That makes a change in authority visible in review alongside the code that requires it.

    The example is intentionally read-only. Listing alerts is a useful starting point for triage, but it does not claim to close alerts, create issues, or notify another system. Those are different actions and may require different permissions. I would add them only after deciding what the workflow should change and identifying the narrowest permission for that change. The Dependabot alerts REST API documentation distinguishes listing alerts from updating an alert and describes the permissions required for those API operations.

    Keep triage apart from build and release authority

    I would not add alert triage as another step inside a release workflow simply because that workflow already has a token. A release pipeline has a different job: it may build artifacts, publish packages, or deploy software. Reading a vulnerability alert and publishing an artifact are separate capabilities. Keeping them in separate workflows lets each declare a permission set tied to its purpose.

    That separation is not a claim that every shared workflow is unsafe. It is a design choice about blast radius and review. If a triage action or its script behaves unexpectedly, a read-only alert token is a more limited authority than a token that can also publish or modify repository contents. If a release step needs write access, I would grant that access to the release job that needs it—not to a general-purpose workflow that happens to contain alert handling too.

    This is also why I prefer permissions close to the job rather than relying on a repository-wide default to communicate intent. GitHub allows permissions at workflow or job level, and recommends granting the minimum access required (GitHub’s GITHUB_TOKEN permission guidance). A job-level declaration gives reviewers a compact answer to “what can this part of the pipeline do?” It also gives a reusable pipeline a clearer contract: the caller can see which jobs read security alerts and which jobs need authority to ship software.

    Treat the permission as part of the workflow contract

    Adding vulnerability-alerts: read does not by itself make a workflow safe. The workflow still runs code and actions, and the token is available to steps that can access the GitHub context. I would keep the job’s steps focused, avoid checking out repository code if the task does not need it, and review any third-party action as code that runs within the job’s permission boundary. GitHub’s security guidance recommends limiting GITHUB_TOKEN permissions and notes that actions can access the token through the context (GitHub’s secure use reference).

    I would also keep the meaning of “triage” narrow. If triage means read, classify, and produce a report, then read-only access is an appropriate boundary. If it also means editing issues or closing alerts, that is a new requirement, not a reason to give the workflow broad permissions pre-emptively. I would split the read and write steps into separate jobs where practical, and give the write job only the additional permission its output requires.

    For teams using reusable pipelines across many repositories, this permission is especially useful as an explicit interface. The reusable workflow can state that the alert-reading job needs vulnerability-alerts: read; repository owners can review that request without granting the same authority to every build or deployment job. The point is not to make permissions complicated. It is to stop unrelated capabilities from accumulating in one token because the pipeline grew one step at a time.

    I would give alert triage its own read-only token permission and keep it out of the path that builds, publishes, or deploys software. The smaller permission is not just a safer setting; it is a clearer description of the job.

    Drafted with AI assistance, reviewed and edited by Ali.