Skip to content

GitHub Actions Permission Denied Fix

DodaTech Updated 2026-06-24 2 min read

In this tutorial, you'll learn about GitHub Actions Permission Denied Fix. We cover key concepts, practical examples, and best practices.

Your GitHub Actions workflow fails with permission denied when pushing to a branch, creating releases, or accessing cloud resources — the default GITHUB_TOKEN has limited permissions.

The Problem

# WRONG — default token without explicit permissions
name: Deploy
on: [push]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: gh release create v1.0.0 --title "Release v1.0.0"
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
! Created tag 'v1.0.0' on origin
HTTP 403: Resource protected by organization-level permission policy

The default GITHUB_TOKEN has read-only permissions for most resources by default. Creating releases, pushing to protected branches, and deleting artifacts need explicit write permissions.

Step-by-Step Fix

1. Set permissions at the workflow level

name: Deploy
on: [push]

permissions:
  contents: write
  pull-requests: write
  deployments: write

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: gh release create v1.0.0 --title "Release v1.0.0"
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

2. Use granular permissions on specific jobs

jobs:
  release:
    runs-on: ubuntu-latest
    permissions:
      contents: write
      packages: write
    steps:
      - uses: actions/checkout@v4
      - run: gh release create v1.0.0
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

3. Use OIDC for cloud provider access

jobs:
  deploy-aws:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read
    steps:
      - uses: actions/checkout@v4
      - uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789012:role/deploy-role
          aws-region: us-east-1
      - run: aws s3 sync ./dist s3://my-bucket

4. Use a personal access token for cross-repo access

- run: gh repo create my-org/new-repo --private
  env:
    GH_TOKEN: ${{ secrets.MY_PAT }}

Expected output:

✓ Created release v1.0.0
✓ Deployed to S3 successfully

Prevention Tips

  • Set permissions: at the top of every workflow
  • Use the principle of least privilege per job
  • Enable OIDC for cloud provider authentication
  • Use a PAT for cross-repository operations
  • Review Settings > Actions > General for org-level defaults

Common Mistakes with actions permission

  1. Overlapping type class instances that cause GHC to reject the program with ambiguous dispatch errors
  2. Non-exhaustive pattern matches that compile with warnings then crash at runtime
  3. Misunderstanding that String is [Char] with poor performance for large text operations

These mistakes appear frequently in real-world GITHUB code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.

Practice Exercise

Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.

This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.

FAQ

### Why does GITHUB_TOKEN get a 403 error?

The default GITHUB_TOKEN is created with minimal permissions. You must explicitly grant permissions in your workflow YAML. The token also cannot bypass branch protection rules or required reviewers. For bypassing protections, use a PAT from a user with admin access.

What permissions does GITHUB_TOKEN need for common operations?

contents: write for pushing commits and creating releases. pull-requests: write for creating/merging PRs. packages: write for publishing to GitHub Packages. deployments: write for creating deployments. id-token: write for OIDC authentication.

Can I use GITHUB_TOKEN across multiple repositories?

No. GITHUB_TOKEN is scoped to the single repository where the workflow runs. For cross-repository access, use a personal access token (PAT) stored as a secret, or use a GitHub App installation token.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro