Search code examples
npmgithub-actionsgithub-package-registrygithub-packages

How to solve "Permission permission_denied: read_package" in a GitHub Actions workflow targeting the GitHub packages registry?


Given two private organization repositories using the GitHub npm registry where one of them is a published library and the other one tries to install it.

The application project is using this .npmrc file

@company:registry=https://npm.pkg.github.com
registry=https://registry.npmjs.org

and this workflow:

name: Workflow

# trigger

jobs:
  workflow:
    runs-on: ubuntu-latest

    steps:
      # ...

      - name: Setup npm login
        run: npm config set //npm.pkg.github.com/:_authToken=${{ secrets.GITHUB_TOKEN }}

      - name: Install dependencies
        run: npm install

      # ...

The workflow fails during the install step

npm error code E403
npm error 403 403 Forbidden - GET https://npm.pkg.github.com/@company%2fpackage - Permission permission_denied: read_package
npm error 403 In most cases, you or one of your dependencies are requesting
npm error 403 a package version that is forbidden by your security policy, or
npm error 403 on a server you do not have access to.
npm error A complete log of this run can be found in: /home/runner/.npm/_logs/2024-09-17T20_37_08_095Z-debug-0.log
Error: Process completed with exit code 1.

so I thought the workflow needs more permissions (GITHUB_TOKEN is not enough). Based on this article I added the following lines between the on and jobs field (workflow wide):

permissions:
  packages: read

Unfortunately the workflow fails again but this time during checkout:

Run actions/checkout@v4
Syncing repository: company/project
Getting Git version info
Temporarily overriding HOME='/home/runner/work/_temp/18cb3ff1-5e12-4eb8-a214-df2dc107f875' before making global git config changes
Adding repository directory to the temporary git global config as a safe directory
/usr/bin/git config --global --add safe.directory /home/runner/work/project/project
Deleting the contents of '/home/runner/work/project/project'
Initializing the repository
  /usr/bin/git init /home/runner/work/project/project
  hint: Using 'master' as the name for the initial branch. This default branch name
  hint: is subject to change. To configure the initial branch name to use in all
  hint: of your new repositories, which will suppress this warning, call:
  hint:
  hint:     git config --global init.defaultBranch <name>
  hint:
  hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
  hint: 'development'. The just-created branch can be renamed via this command:
  hint:
  hint:     git branch -m <name>
  Initialized empty Git repository in /home/runner/work/project/project/.git/
  /usr/bin/git remote add origin https://github.com/company/project
Disabling automatic garbage collection
Setting up auth
Fetching the repository
  /usr/bin/git -c protocol.version=2 fetch --prune --no-recurse-submodules origin +refs/heads/*:refs/remotes/origin/* +refs/tags/*:refs/tags/*
  remote: Repository not found.
  Error: fatal: repository 'https://github.com/company/project/' not found
  The process '/usr/bin/git' failed with exit code 128
  Waiting 15 seconds before trying again
  /usr/bin/git -c protocol.version=2 fetch --prune --no-recurse-submodules origin +refs/heads/*:refs/remotes/origin/* +refs/tags/*:refs/tags/*
  remote: Repository not found.
  Error: fatal: repository 'https://github.com/company/project/' not found
  The process '/usr/bin/git' failed with exit code 128
  Waiting 13 seconds before trying again
  /usr/bin/git -c protocol.version=2 fetch --prune --no-recurse-submodules origin +refs/heads/*:refs/remotes/origin/* +refs/tags/*:refs/tags/*
  remote: Repository not found.
  Error: fatal: repository 'https://github.com/company/project/' not found
  Error: The process '/usr/bin/git' failed with exit code 128

So I also tried every permission with write and now I'm getting the first mentioned error again. Does someone know how to fix this?


Solution

  • GITHUB_TOKEN is scoped to the current repo only. It can read/write packages from/to current repo only.

    When you set workflow permissions as

    permissions:
      packages: read
    

    you actually reduced GITHUB_TOKEN permissions. Specifically you lost:

      contents: read
    

    In order to read a package from a private repo that is different from the repo where your workflow is running, you need to use a token that has access to that repo with read:packages scope. If you are a member of that repo, you can use your Personal Access Token (it needs read:packages scope). Otherwise, you need a bot/service account token - PAT token from a bot user that is a member of that repo.