DEV Community

Cover image for GitHub - Understanding Workflow Permissions
Marcel.L
Marcel.L

Posted on • Edited on

GitHub - Understanding Workflow Permissions

Overview - Managing Permissions in GitHub Actions Workflows

In this GitHub Pro Tips post we will look at how to manage permissions in GitHub Actions workflows.

GitHub Actions is a powerful tool for automating your CI/CD pipelines/workflows. It allows you to create workflows that can be triggered by events such as a push to a repository, a pull request, or a new release. Workflows are defined in YAML files that live in the .github/workflows directory of your repository.

In terms of Continuous Integration/Continuous Deployment (CI/CD), GitHub Actions provides a robust feature set for automating, customising, and executing your software development workflows right in your repository. Today we will look at the the permissions parameter as a groundbreaking feature for constraining the permissions provided to the GitHub token.

We will also look at a few practical examples of how and when you would use this feature.

A Dive Into GitHub Workflow's 'Permissions'

Let's discuss the 'permissions' key in detail, which was officially released by GitHub in April 2021. This new feature enables more fine-grained control over the permissions given to the GITHUB_TOKEN in workflows.

This is particularly useful to maintain 'principle of least privilege' - an important security concept stating that a user should have just enough rights necessary to perform their job and nothing more. By minimising the access to resources, you can reduce the damage that could result from accidents or exploits.

The permissions key allows you to set read, write, or none to different scopes. You define permissions at the top level or per job level, giving you flexibility and granularity in terms of access control.

Here is an example of defining permissions at the root level of a workflow:



name: 'My workflow'

on: [push]

permissions:
  actions: read|write|none
  checks: read|write|none
  contents: read|write|none
  deployments: read|write|none
  id-token: read|write|none
  issues: read|write|none
  discussions: read|write|none
  packages: read|write|none
  pages: read|write|none
  pull-requests: read|write|none
  repository-projects: read|write|none
  security-events: read|write|none
  statuses: read|write|none

jobs: ...


Enter fullscreen mode Exit fullscreen mode

You can also define permissions at the job level:



jobs:
  stale:
    runs-on: ubuntu-latest

    permissions:
      actions: read|write|none
      checks: read|write|none
      contents: read|write|none
      deployments: read|write|none
      id-token: read|write|none
      issues: read|write|none
      discussions: read|write|none
      packages: read|write|none
      pages: read|write|none
      pull-requests: read|write|none
      repository-projects: read|write|none
      security-events: read|write|none
      statuses: read|write|none

    steps:
      - uses: actions/stale@v5


Enter fullscreen mode Exit fullscreen mode

If you specify the access for any of these scopes, all of those that are not specified are set to none.

You can use the following syntax to define read or write access for all of the available scopes:



permissions: read-all|write-all


Enter fullscreen mode Exit fullscreen mode

You can use the following syntax to disable permissions for all of the available scopes:



permissions: {}


Enter fullscreen mode Exit fullscreen mode

Practical Use Cases

Now that we understand how the permissions key is structured, let's move on to a few practical use cases.

Example 1: Workflows That Need Custom Permissions

In workflows where you need to increase or restrict permissions for a particular job, you can set permissions on the job level:



jobs:
  job1:
    permissions:
      contents: write
    runs-on: ubuntu-latest
    steps:
      - name: Push commit
        run: |
          echo "Hello, GitHub!" > hello.txt
          git add hello.txt
          git commit -m "Add hello.txt"
          git push


Enter fullscreen mode Exit fullscreen mode

In this example, job1 has write access to the repository contents which allows it to create a commit.


Example 2: Cases Where You Want to Limit Potential Damage

Perhaps your workflow only needs read access to the contents of your repository and should never be able to write. By setting the contents key to read or none, you can prevent potential malicious scripts or configuration errors from altering your repo:



permissions: read


Enter fullscreen mode Exit fullscreen mode

Example 3: Third-Party Action Usage

When using third-party actions in your workflow, it's a wise security practice to limit the permissions of the GITHUB_TOKEN, especially if you're not entirely sure about what the third-party action is doing.



permissions:
  actions: none
  checks: read
  contents: read


Enter fullscreen mode Exit fullscreen mode

The example above restricts the third-party actions from initiating further GitHub actions, while allowing read access to checks and contents.


Conclusion

In conclusion, the permissions parameter provides refined control over the GITHUB_TOKEN scope within GitHub Actions, introducing a new level of security and allowing developers to adhere to the principle of least privilege. With this feature, you can avoid accidental write operations, limit the potential harm from vulnerabilities, and securely use third-party actions.

I hope you have enjoyed this post and have learned something new. ❤️

Author

Like, share, follow me on: 🐙 GitHub | 🐧 X/Twitter | 👾 LinkedIn

Top comments (2)

Collapse
 
felixachen profile image
FelixAchen
  1. Clarity on Permission Levels: Emphasize the importance of clearly defining different permission levels for workflows, especially in collaborative projects. This helps maintain security and integrity in the repository. Lion567 Login
Collapse
 
pedrozebrow profile image
PedroZebrow

GitHub's guide on Workflow Permissions offers valuable insights for navigating collaborative projects efficiently and securely. Reddy Anna