Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dependabot triggered Actions cant access secrets or use a writable token #3253

Closed
WtfJoke opened this issue Mar 10, 2021 · 167 comments
Closed

Dependabot triggered Actions cant access secrets or use a writable token #3253

WtfJoke opened this issue Mar 10, 2021 · 167 comments
Labels
T: bug 🐞 Something isn't working

Comments

@WtfJoke
Copy link

WtfJoke commented Mar 10, 2021

Moderator note: If you're here because your Dependabot triggered actions are broken, read our updated docs or jump to #3253 (comment) for a FAQ

Package manager/ecosystem
npm

Manifest contents prior to update

Updated dependency

What you expected to see, versus what you actually saw
Since ~08.03.21 our dependabot pull requests fail, because they cant access the npm private registry anymore.
We figured out, the reason is because dependabot cant read secrets anymore (see https://github.com/github/docs/pull/4397/files).

When we rerun the pull requests they succeed as the used GITHUB_TOKEN has permission to read the secret.

Is there a solution or workaround in place?

Images of the diff or a link to the PR, issue or logs

https://github.com/github/docs/pull/4397/files

@WtfJoke WtfJoke added the T: bug 🐞 Something isn't working label Mar 10, 2021
@mdreizin
Copy link

I can confirm that. Now Dependabot can't read secrets anymore at all.

@mdreizin
Copy link

Any secrets are not available for Dependabot.

@mdreizin
Copy link

Can't share links to private repos, but here is a couple of public ones:

mdreizin/chrome-bookmarks-alfred-workflow#96
mdreizin/gatsby-plugin-robots-txt#418

@mdreizin
Copy link

mdreizin commented Mar 10, 2021

I contacted yesterday support team and they denied that issue and refused to fix.

Could you please fix it as soon as possible, because many users are affected including paid ones?

@mercuriete
Copy link

mercuriete commented Mar 10, 2021

the team support answer me with this:

We recently made changes to dependabot which means they will receive a read-only GITHUB_TOKEN and will not have access to any secrets available in the repository.

https://github.blog/changelog/2021-02-19-github-actions-workflows-triggered-by-dependabot-prs-will-run-with-read-only-permissions/

So it is not a bug its a feature.

My use case is I am auto merging branches after a CI passes using this action:
https://github.com/ahmadnassri/action-dependabot-auto-merge

and now my workflow is totally broken.

Please add automerge to dependabot.

Thanks.

@mercuriete
Copy link

I am trying to fix the problem using a workaround:
https://docs.github.com/en/actions/reference/events-that-trigger-workflows#pull_request_target

it is mention in that post but I think with pull_request_target the tokens are insecure to forks. So I am only using that workaround to private repositories.

@derTobsch
Copy link

@mercuriete
Copy link

mercuriete commented Mar 10, 2021

yeah, I can confirm that moving from

on: pull_request
to
on: pull_request_target

fix the problem

but you need to read the docs first -> https://securitylab.github.com/research/github-actions-preventing-pwn-requests

the main problem as a CI developer is that if you make a change on the pipeline you can't see the change until is in the base branch which is difficult for CI developing.

I hope it helps someone.

EDIT: It only work with GITHUB_TOKEN if you need personal access token it won't work :(

@mdreizin
Copy link

Recommended solution by using pull_request_target only for GITHUB_TOKEN and the rest secrets will be empty:

https://github.com/mdreizin/gatsby-plugin-robots-txt/blob/master/.github/workflows/dev.yml#L6
https://github.com/mdreizin/gatsby-plugin-robots-txt/pull/400/checks?check_run_id=2077439179

@derTobsch
Copy link

see
https://github.community/t/dependabot-prs-and-workflow-secrets/163269 and
https://github.community/t/dependabot-doesnt-see-github-actions-secrets/167104

@jasperroel
Copy link

jasperroel commented Mar 11, 2021

I'm running into the same issue. Steps taken so far (since https://github.blog/changelog/2021-02-19-github-actions-workflows-triggered-by-dependabot-prs-will-run-with-read-only-permissions/ mentions that switching to pull_request_target should grant access to repository secrets again).

Unfortunately, even these steps seem to only switch the GITHUB_TOKEN to a write, but I still do not see any of the other expected secrets.

1 Update pull_request to pull_request_target

Change

on:
  pull_request:
    branches:
      - develop

to

on:
  pull_request_target:
    branches:
      - develop

2 Limit to dependabot

Added if: github.actor == 'dependabot[bot]' so that the jobs with secrets only run for Dependabot

3 Modify the checkout to still grab the head checkout

Change:

      - name: Checkout
        uses: actions/checkout@v2.3.4

to

      - name: Checkout
        uses: actions/checkout@v2.3.4
        with:
          ref: ${{ github.event.pull_request.head.sha }}

As other mentioned that seems to switch the ${{ secrets.GITHUB_TOKEN }} from a read-only to a write token, but other secrets remain unaccessible.

For example:

      - name: Automerge Dependabot
        uses: actions/github-script@v3
        with:
          github-token: ${{ secrets.PAT_PUSH_TOKEN }}
          script: |
            const output = `@dependabot squash and merge`;

            github.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: output
            })

fails with a

Error: Input required and not supplied: github-token
    at getInput (/home/runner/work/_actions/actions/github-script/v3/dist/index.js:1452:15)
Error: Unhandled error: Error: Input required and not supplied: github-token

@mercuriete
Copy link

mercuriete commented Mar 11, 2021

people from this issue might want to subscribe to this issue:
#2268

we all are facing the same issue.

BTW, I tested the alternative
on: workflow_run:
suggested here: https://securitylab.github.com/research/github-actions-preventing-pwn-requests

and again it work for github_token but not for secrets (at least for me)
with that alternative the secrets are all empty.

@mercuriete
Copy link

mercuriete commented Mar 11, 2021

I will try to move from dependabot to renovate to asset the feasibility of the migration.
right now dependabot is broken for enterprise users that make use of GitHub packages to upload/download to/from npm private registries and a lot of enterprise use cases.
(AWS deployments are broken as well when the job is triggered by dependabot)

renovate: https://www.whitesourcesoftware.com/free-developer-tools/renovate

@mdreizin
Copy link

@mercuriete The biggest issue with on: workflow_run is missing ability to fail the whole pipeline, because they run in different context.

For instance, you have ci workflow and cd one which depends on ci via on: workflow_run (which needs access to your secrets) you won't see if cd fails or not without visiting ie https://github.com/dependabot/dependabot-core/actions to see actual status.

@mdreizin
Copy link

@mercuriete I am also considering migrating to renovate bot.

The funny thing: all PRs created by dependabot on that repo also fail https://github.com/dependabot/dependabot-core/pulls?q=is%3Aopen+is%3Apr+label%3Adependencies :)

The support team still has not provided any ways how to get rid of that issue.

@mdreizin
Copy link

Maybe anybody from Dependabot team could provide a solution to fix missing secrets on PR created by dependabot?

@mercuriete
Copy link

hahaha
it seems dependabot is eating its own dog food https://es.wikipedia.org/wiki/Dogfooding

https://github.com/dependabot/dependabot-core/pull/3258/checks?check_run_id=2083846045

I'm glad they are facing the same issue because they have to fix it by themselves.

@mdreizin
Copy link

@asciimike
Copy link
Contributor

asciimike commented Mar 11, 2021

Hey folks, Dependabot PM here.

First off, apologies for the quick change and continued brokenness 😞 .

What changed?

The specific change is twofold, in that during pull_request triggered workflows:

  • your GITHUB_TOKEN is read-only
  • secrets can't be accessed

Additionally, a bug was introduced where pull_request_target also had these properties, which made the migration process worse. This was fixed at ~2300 UTC on March 11th, so pull_request_target should be working for those of you trying to use it.

Why was this change made?

This change was made in response to reported vulnerabilities in these types of workflows, and we felt that it critical to ensure our developers were protected before they were publicly disclosed.

Specifically, a malicious dependency could execute code to exfiltrate secrets or perform something other malicious action in the repo (deleting files, etc.).

By making secrets unavailable and tokens read only, this prevents a compromised dependency from being able to exfiltrate those secrets or perform any malicious write actions.

How do I fix a broken workflow?

As per the advice in https://securitylab.github.com/research/github-actions-preventing-pwn-requests, you can either use pull_request_target or create two workflows, one untrusted that generates whatever artifacts, and one trusted that does the push of the changes.

Taking a simple example:

### .github/workflows/dependabot_automerge.yml
### This workflow now has no secrets and a read-only token
name: Dependabot Workflow
on:
  pull_request

jobs:
  do-stuff:
    runs-on: ubuntu-latest
    if: ${{ github.actor == 'dependabot[bot]' }}
    steps:
      - uses: actions/checkout

Either use pull_request_target:

### .github/workflows/dependabot_automerge.yml
### As of 2300 UTC on 11 March, this workflow has secrets and a read-write token
name: Dependabot Workflow
on:
  pull_request_target

jobs:
  do-stuff:
    runs-on: ubuntu-latest
    if: ${{ github.actor == 'dependabot[bot]' }}
    steps:
      - uses: actions/checkout
        with:
          ref: ${{ github.event.pull_request.head.sha }}
          github-token: ${{ secrets.GITHUB_TOKEN }}

Or make it two workflows:

### .github/workflows/dependabot_pr.yml
### This workflow doesn't have access to secrets and has a read-only token
name: Dependabot PR Check
on:
  pull_request

jobs:
  check-dependabot:
    runs-on: ubuntu-latest
    if: ${{ github.actor == 'dependabot[bot]' }}
    steps:
      - run: echo "PR created by Dependabot"

Which triggers:

### .github/workflows/dependabot_automerge.yml
### This workflow has access to secrets and a read-write token
name: Dependabot Automerge
on:
  workflow_run:
    workflows: ["Dependabot PR Check"]
    types: 
      - completed

jobs:
  do-stuff:
    runs-on: ubuntu-latest
    if: ${{ github.event.workflow_run.conclusion == 'success' }}
    steps:
      - uses: actions/checkout
        with:
          ref: ${{ github.event.pull_request.head.sha }}
          github-token: ${{ secrets.GITHUB_TOKEN }}

Again, I'm really sorry for the churn and brokenness here, but hopefully this should get folks moving in the right direction 🙇🏻

@asciimike
Copy link
Contributor

asciimike commented Mar 11, 2021

Re: @mercuriete's

I will try to move from dependabot to renovate to asset the feasibility of the migration.
right now dependabot is broken for enterprise users that make use of GitHub packages to upload/download to/from npm private registries and a lot of enterprise use cases.
(AWS deployments are broken as well when the job is triggered by dependabot)

renovate: https://www.whitesourcesoftware.com/free-developer-tools/renovate

Private registry support is coming out shortly, so stay tuned and follow this issue and the changelog.

@derTobsch
Copy link

derTobsch commented Mar 12, 2021

Hey folks, Dependabot PM here.

First off, apologies for the quick change and continued brokenness disappointed .

What changed?

The specific change is twofold, in that during pull_request triggered workflows:

* your `GITHUB_TOKEN` is read-only

* `secrets` can't be accessed

Additionally, a bug was introduced where pull_request_target also had these properties, which made the migration process worse. This was fixed at ~2300 UTC on March 11th, so pull_request_target should be working for those of you trying to use it.

Why was this change made?

This change was made in response to reported vulnerabilities in these types of workflows, and we felt that it critical to ensure our developers were protected before they were publicly disclosed.

Specifically, a malicious dependency could execute code to exfiltrate secrets or perform something other malicious action in the repo (deleting files, etc.).

By making secrets unavailable and tokens read only, this prevents a compromised dependency from being able to exfiltrate those secrets or perform any malicious write actions.

How do I fix a broken workflow?

As per the advice in https://securitylab.github.com/research/github-actions-preventing-pwn-requests, you can either use pull_request_target or create two workflows, one untrusted that generates whatever artifacts, and one trusted that does the push of the changes.

Taking a simple example:

### .github/workflows/dependabot_automerge.yml
### This workflow now has no secrets and a read-only token
name: Dependabot Automerge
on:
  pull_request

jobs:
  automerge:
    runs-on: ubuntu-latest
    if: ${{ github.actor == 'dependabot[bot]' }}
    steps:
      - uses: ...

Either use pull_request_target:

### .github/workflows/dependabot_automerge.yml
### As of 2300 UTC on 11 March, this workflow has secrets and a read-write token
name: Dependabot Automerge
on:
  pull_request_target

jobs:
  automerge:
    runs-on: ubuntu-latest
    if: ${{ github.actor == 'dependabot[bot]' }}
    steps:
      - uses: ...
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}

Or make it two workflows:

### .github/workflows/dependabot_pr.yml
### This workflow doesn't have access to secrets and has a read-only token
name: Dependabot PR Check
on:
  pull_request

jobs:
  check_dependabot:
    runs-on: ubuntu-latest
    if: ${{ github.actor == 'dependabot[bot]' }}
    steps:
      - run: echo "PR created by Dependabot"

Which triggers:

### .github/workflows/dependabot_automerge.yml
### This workflow has access to secrets and a read-write token
name: Dependabot Automerge
on:
  workflow_run:
    workflows: ["Dependabot PR Check"]
    types: 
      - completed

jobs:
  automerge:
    runs-on: ubuntu-latest
    if: ${{ github.event.workflow_run.conclusion == 'success' }}
    steps:
      - uses: ...

Again, I'm really sorry for the churn and brokenness here, but hopefully this should get folks moving in the right direction 🙇🏻

Hey @asciimike,

I already tried that but without success. The workflows that that get triggered via workflow_run has no access to the secrets see https://github.com/synyx/urlaubsverwaltung/runs/2093235834?check_suite_focus=true - are my workflows and trigger correct?

What I did with a little more details:

name: Urlaubsverwaltung CI

on:
  schedule:
    - cron: "2 4 * * *"
  push:
    branches:
      - master
      - v3.x
  pull_request:
  workflow_dispatch:

jobs:
  build:
    name: build and analyse
    runs-on: ubuntu-20.04
    steps:
      - name: Checkout repository
        uses: actions/checkout@v2
        ...
      - name: Build
        run: ./mvnw --batch-mode -Pcoverage clean verify
...

and this triggeres the workflow https://github.com/synyx/urlaubsverwaltung/blob/master/.github/workflows/update-assets-manifest.yml e.g. with

name: Update assets-manifest

on:
  workflow_run:
    workflows: [ "Urlaubsverwaltung CI" ]
    branches: [ "dependabot/npm_and_yarn/**" ]
    types:
      - completed
  workflow_dispatch:

jobs:
  build:
    runs-on: ubuntu-20.04
    if: ${{ github.event.workflow_run.conclusion == 'success' }}
    steps:
      - name: Checkout repository
        uses: actions/checkout@v2
        with:
          persist-credentials: false
     ...
      - name: Assets-Manifest push
        uses: ad-m/github-push-action@v0.6.0
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          branch: ${{ github.ref }}

but now the github token does not have the permission to push to this branch.

@mercuriete
Copy link

same here, I tried yesterday both cases and even though github_token was present, secrets are not available making all normal use cases unusable.

use cases broken:
1- yarn install where you are pulling packages from private registry (npm)
2- docker login/docker pull from images from private registry
3- send reports to sonarqube.io

everything that involves a personal access token.

Please give us a working example of private registries making use a PAT.

thanks

@asciimike
Copy link
Contributor

asciimike commented Mar 12, 2021

@derTobsch: I just set up a workflow run triggered by a Dependabot PR and I'm seeing the same behavior 😞

It seems like the answer is "workflow_run inherits the secrets and token from the previous PR" (the docs seem to indicate this, though the actions team indicated that it should have the secrets and a write token). The answer is to use pull_request_target (which I have confirmed has a read-write token), though at that point, there's no reason to use the second workflow (and indeed, my testing shows that the workflow_run runs as read-only without secrets, so you can't use it!).

@mercuriete: 1 and 2 will be solved more elegantly via github/roadmap#67, which is imminent. 3 will have to use pull_request_target or wait for the change as above.

@asciimike
Copy link
Contributor

I have confirmed that workflow_run now works as expected, with the workflow now able to access secrets and a read-write GITHUB_TOKEN. I believe this is now back to a place where folks should be able to fix themselves in a fairly straightforward way.

@essenmitsosse
Copy link

Secrets in Dependabot PRs are considered a security risk, since an updated dependency could introduce malicious code, that could steal secrets — as far as I understand the basis for this issue.

Switching to pull_request_target or workflow_run allows the PR to read those secrets, but doesn't this just open up the security issue again?

As far as I understand, all this would mean, that there is no secure way to use Dependabot on a repository that for example needs an NPM token to install a private dependency. But technical that would also mean that on such a repo, I would have to manually check every dependency update for malicious code — which seems completely unfeasable.

Am I missing something here or is this the situation we're in?

@ahmadnassri
Copy link

I'm seeing an issue where after instructing dependabot to merge using @dependabot merge secrets are still inaccessible on main branch on push workflows.

if I re-run the workflow manually through the UI, it completes successfully.

this seems like a bug, contacting github support is not useful, as they keep referring back to the article announcing the change, and this thread ...

the issue has nothing to do with dependabot itself running, but seemingly somebody at github did something along the lines of if commit.author === dependabot && event !== pull_request_target => NO SECRETS

here are a couple of examples:

https://github.com/ahmadnassri/node-oas-request/runs/2687844031?check_suite_focus=true
https://github.com/ahmadnassri/node-nightwatch-accessibility/runs/2687397030?check_suite_focus=true

@ahmadnassri
Copy link

RE using workflow_run as some folks pointed out in the thread to address the issue after @dependabot merge it wouldn't address the issue, as the subsequent triggered push event on main branch will still fail.

@emilgoldsmith
Copy link

emilgoldsmith commented May 28, 2021 via email

@ahmadnassri
Copy link

ahmadnassri commented May 28, 2021

Are you sure that workflow_run wouldn't work? Did you try?

I don't need to try it to know it wont work ... since it's a different context altogether.

the comment / command @dependabot merge triggers a merge ... the issue happens on push event AFTER dependabot merges the commit. (so dependabot itself is not doing anything here, this is generic github push event)

even if I type it up manually by hand in the comments, the result will be the same.

look at the commit itself: ahmadnassri/node-oas-request@1917083

when it's coming from dependabot as the author, that's when it loses access to secrets.

image

@emilgoldsmith
Copy link

emilgoldsmith commented May 28, 2021 via email

@ahmadnassri
Copy link

well, I'll give it a try, but if that DOES work, it seems the dependabot team has some fixing to do cuz it doesn't make sense to block push on master from getting secrets, just because the author is dependabot

@asciimike
Copy link
Contributor

it doesn't make sense to block push on master from getting secrets, just because the author is dependabot

The reason push is blocked is the same reason pull_request is blocked: malicious package code could be executed during this event.

@moroine
Copy link

moroine commented May 31, 2021

it doesn't make sense to block push on master from getting secrets, just because the author is dependabot

The reason push is blocked is the same reason pull_request is blocked: malicious package code could be executed during this event.

yeah, but we don't care at this point. If malicious code reach master, accessing github action secret it's not the worst case scenario, we should worry about the production code then. But if we trigger manually it works so in this case the malicious code would still have access to it.

@emilgoldsmith
Copy link

emilgoldsmith commented May 31, 2021 via email

@essenmitsosse
Copy link

@moroine @emilgoldsmith That was also my thought. Seems more like security theatre to me, then actually thread prevention.

Making it really hard for people to use a tool, isn't the same as preventing a foot gun. And while there is a way you could argue why these changes are helping, there are also a lot of arguments for why they barely do, while they force everyone — no matter if they are in the line of danger or not — to run circles around a very specific edge case, that could still occur.

The real problem here are projects, that leak unnecessary secrets to their merge steps, which could better be stopped by educating people and forcing them to actively approve those decisions, than by just making the workflow more complicated. And es stated above: making merging harder is next to pointless, because the malicious code could execute 2 minutes afterwards when the next pull request ist merged.

On the one hand you treat devs like children, who need their toy taken away. On the other hand you force them to implement a very complicated, brittle and most importantly: hard to to understand* workflow, that basically makes this tool close to unusable, while introducing a lot of noise into a process that is supposed to keep your head clear.

Im pretty sure this change will do more damage, by making people stop regular updates, than it will prevent by stopping any real world attack scenarios. Also if these changes make people stop using Dependabot and update their dependencies by hand, no one will have gained anything.

*tests are run from the branch that is merged into, not the commit that is merged. Which is super counter-intuitive, and now every user of dependabot needs to understand this.

@BorntraegerMarc
Copy link

As a company with private repositories and disallowed forking I just want to have an option to let dependabot read all secrets in all workflows.

I don't want any workflow or process change. Seems to be as well that this particular case wouldn't be affected by potential security vulnerabilities (as described above)

@mattvb91
Copy link

As a company with private repositories and disallowed forking I just want to have an option to let dependabot read all secrets in all workflows.

I don't want any workflow or process change. Seems to be as well that this particular case wouldn't be affected by potential security vulnerabilities (as described above)

This would completely fix the issue if they just allowed us to run it as normal with a checkbox "allow potential sec issues". The most annoying part of this issue is the fact that this change does nothing to fix it, it just makes it more difficult for maintainers. The security threat is still the same

@mattvb91
Copy link

Im pretty sure this change will do more damage, by making people stop regular updates, than it will prevent by stopping any real world attack scenarios. Also if these changes make people stop using Dependabot and update their dependencies by hand, no one will have gained anything.

This is exactly what has happened in our case. We just stopped updating dependancies because of this which introduces more potential for issues than there was in the first place

@mercuriete
Copy link

mercuriete commented May 31, 2021

@mattvb91 @BorntraegerMarc @essenmitsosse
First of all, I don't want to spam because nobody is paying me, it is just a personal opinion.
Second, I am not recommending this due to security concerns that we know we have.
Third, I want that dependabot will become a better tool in the long run so don't take this post as hostile because I really love dependabot.

I just drop dependabot on all organizations managed by me and I started to use renovatebot.
I kept dependabot for CVE security PR and I handle it manually.

you can try renovatebot by dropping this file on the root of the project for example:

renovate.json

{
  "extends": [
    "config:base"
  ],
  "schedule": ["after 7pm and before 7am"],
  "prConcurrentLimit": 2,
  "packageRules": [
    {
      "matchUpdateTypes": ["minor", "patch", "pin", "digest"],
      "automerge": true
    },
    {
      "matchDepTypes": ["devDependencies"],
      "automerge": true
    },
    {
      "matchPackageNames": ["aws-sdk"],
      "extends": ["schedule:monthly"]
    }
  ]
}

This example is for a Nodejs project with automerge of patch version bumps on dependencies
and automerge major versions on devDependencies.

you need to install the application using the marketplace first:
https://github.com/marketplace/renovate

Remember this approach will have the security concern that dependabot has but It can be useful for some people with some use cases.

I am not recommending using this alternative, I am just telling what I use meanwhile waiting for dependabot implementing a user-friendly solution.

Thanks and I hope this helps someone.

@thuringia

This comment has been minimized.

@Fryie
Copy link

Fryie commented May 31, 2021

I agree that the design of this is broken, especially in the way that understanding what is happening here, and why, is very difficult for people who have not been following this thread closely (witness the number of misunderstandings that still keep coming up around this issue). If you have a workflow that needs access to secrets, and it runs but without having access to those secrets, it can lead to errors that are extremely hard to understand.

I think a much better solution to this whole issue would be the following:

  • By default, workflows only ever run for branches and PRs coming from the same repository
  • There is a section in the workflow definition where specific forks and external apps, such as dependabot, can be explicitly allowed for that particular workflow definition
  • Whenever a workflow runs, it has access to the full set of permissions, because we can assume that it has been explicitly trusted
  • If somebody makes a PR from an external fork and the workflow run is blocked, there should be an option for the maintainer to run the workflow manually after inspecting the changes
  • For OSS projects with many forks, there could be an option to just allow all forks (which is opt-in). The documentation could add explicit caveats that this is only safe if no secrets are being used in the workflow.

This has the following benefits:

  • It disables the attack vector of "malicious PR from an unknown fork that grabs secrets" by default
  • Maintainers can explicitly declare trust in particular forks and/or apps, so that their previous workflows can be re-enabled without much effort
  • When trust has not been declared, the workflow will simply not run, which is much easier to understand and debug (especially if GitHub can show an appropriate warning message) than having a workflow that runs but unexpectedly fails because of a missing secret
  • All of this behaviour is easy to explain in a blog post whenever people wonder "why did this dependabot PR not run?". Just instruct people to add allow: dependabot to their workflow or something.
  • It uses a "secure by default" approach while allowing developers to be adults about the kinds of risks that they're exposing themselves to

@mpdude
Copy link

mpdude commented May 31, 2021

What would be the „right“ way to create a merge request yourself in a pull_request_target workflow?

@WtfJoke
Copy link
Author

WtfJoke commented May 31, 2021

* allowing use of Dependabot's secrets (instead of Actions)

@asciimike sorry for mentioning you again... is there a feature request somewhere about that so that I can give it a thumbs up?

We havent made any changes yet (as I havent digged up the best approach yet, we simply rerun all dependabot prs atm manually). Since we have only one secret (the read only artifactory token), which is needed to install dependencies.

PS: Dependabot private registry updates works great, however

@moroine

This comment has been minimized.

@mgrip
Copy link

mgrip commented Jun 1, 2021

bumping because this thread is so hard to follow - anyone who ran into issues switching to GitHub native dependabot because your workflows need to access to GitHub secrets or auto merging, @Kocal's post is super helpful+clear, and did the trick for me

https://hugo.alliau.me/2021/05/04/migration-to-github-native-dependabot-solutions-for-auto-merge-and-action-secrets/

@asciimike
Copy link
Contributor

asciimike commented Jun 1, 2021

Here is what I hope is a definitive FAQ related to this change. Docs have been published and will be updated, but I'll leave this thread up for the foreseeable future in case it's still helpful.

TL;DR: See "GitHub Actions: Workflows triggered by Dependabot PRs will run with read-only permissions" and "Keeping your GitHub Actions and workflows secure: Preventing pwn requests".

What and why

What changed?

For GitHub Actions workflows initiated by Dependabot (github.actor == "dependabot[bot]") using the pull_request, pull_request_review, pull_request_review_comment, and push events:

  • your GITHUB_TOKEN is read-only
  • secrets are inaccessible

Why was this change made?

This change was made in response to reported vulnerabilities in these types of workflows, and we felt that it critical to ensure our developers were protected before they were publicly disclosed.

Specifically, a malicious dependency could execute code to exfiltrate secrets or perform something other malicious action in the repo (deleting files, etc.).

By making secrets unavailable and tokens read only, this prevents a compromised dependency from being able to exfiltrate those secrets or perform any malicious write actions.

Is this actually a problem?

Yes. Attacks like eslint-scope, which included a malicious postinstall script, could end up exfiltrating credentials.

Doesn't Dependabot not run postinstall scripts to prevent this?

Yes, though the ability to prevent this type of arbitrary execution doesn't exist for all ecosystems. This prevents exfiltration by not having secrets present in the first place (and downscoping tokens to reduce the risk).

Why wasn't I informed of this change?

GitHub's current deprecation notification process is to publish a post to the GitHub Changelog (replicated to Twitter), rather than send individual notifications to users.

How do I fix my workflows?

How do I fix a broken pull_request workflow?

As per the advice in "Keeping your GitHub Actions and workflows secure: Preventing pwn requests", you can either use pull_request_target or create two workflows, one untrusted that generates whatever artifacts, and one trusted that does the push of the changes.

Taking a simple example:

### .github/workflows/dependabot_automerge.yml
### This workflow now has no secrets and a read-only token
name: Dependabot Workflow
on:
  pull_request

jobs:
  do-stuff:
    runs-on: ubuntu-latest
    if: ${{ github.actor == 'dependabot[bot]' }}
    steps:
      - uses: actions/checkout

Either use pull_request_target:

### .github/workflows/dependabot_automerge.yml
### As of 2300 UTC on 11 March, this workflow has secrets and a read-write token
name: Dependabot Workflow
on:
  pull_request_target
  
permissions:
  # down scope as necessary via https://docs.github.com/en/actions/reference/authentication-in-a-workflow#modifying-the-permissions-for-the-github_token

jobs:
  do-stuff:
    runs-on: ubuntu-latest
    if: ${{ github.actor == 'dependabot[bot]' }}
    steps:
      - uses: actions/checkout
        with:
          ref: ${{ github.event.pull_request.head.sha }}
          github-token: ${{ secrets.GITHUB_TOKEN }}

Or make it two workflows:

### .github/workflows/dependabot_pr.yml
### This workflow doesn't have access to secrets and has a read-only token
name: Dependabot PR Check
on:
  pull_request

jobs:
  check-dependabot:
    runs-on: ubuntu-latest
    if: ${{ github.actor == 'dependabot[bot]' }}
    steps:
      - run: echo "PR created by Dependabot"

Which triggers:

### .github/workflows/dependabot_automerge.yml
### This workflow has access to secrets and a read-write token
name: Dependabot Automerge
on:
  workflow_run:
    workflows: ["Dependabot PR Check"]
    types: 
      - completed

permissions:
  # down scope as necessary via https://docs.github.com/en/actions/reference/authentication-in-a-workflow#modifying-the-permissions-for-the-github_token

jobs:
  do-stuff:
    runs-on: ubuntu-latest
    if: ${{ github.event.workflow_run.conclusion == 'success' }}
    steps:
      - uses: actions/checkout
        with:
          ref: ${{ github.event.pull_request.head.sha }}
          github-token: ${{ secrets.GITHUB_TOKEN }}

You can also manually re-run the job.

Isn't this the same level of risk as the original change?

Yes, using pull_request_target and down-scoping the token provides the same functionality as what was available in pull_request, which means it also provides the same level of risk.

If that's the case, why wasn't this just a feature flag?

The Actions team felt like the appropriate fix was to treat Dependabot like a fork rather than special casing it.

If you would like this behavior to be different, see the section below on Actions feature requests to discuss your request with the Actions team.

How do I fix a broken push workflow?

As there is no equivalent to pull_request_target, you will have to use the two workflow method:

### .github/workflows/dependabot_pr.yml
### This workflow doesn't have access to secrets and has a read-only token
name: Dependabot PR Check
on:
  push

jobs:
  check-dependabot:
    runs-on: ubuntu-latest
    if: ${{ github.actor == 'dependabot[bot]' }}
    steps:
      - run: echo "PR created by Dependabot"

Which triggers:

### .github/workflows/dependabot_automerge.yml
### This workflow has access to secrets and a read-write token
name: Dependabot Automerge
on:
  workflow_run:
    workflows: ["Dependabot PR Check"]
    types: 
      - completed

permissions:
  # down scope as necessary via https://docs.github.com/en/actions/reference/authentication-in-a-workflow#modifying-the-permissions-for-the-github_token

jobs:
  do-stuff:
    runs-on: ubuntu-latest
    if: ${{ github.event.workflow_run.conclusion == 'success' }}
    steps:
      - uses: ...

You can also manually re-run the job.

What if I need to block on the result of my push event?

Let's say you relied on the results of the check_run created by merging your Dependabot PRs in for something blocking. Unfortunately, the push event probably doesn't let you get access to your secrets to access whatever you're trying to do, and when you call the workflow_run, it's no longer blocking the merge like the original push was.

Currently this isn't possible, but it's a great feature request for the Actions team.

Why does this work if I manually re-run the job?

Currently only github.actor == "dependabot[bot]" is blocked from accessing secrets/a writable token, as no humans are in the loop. If a human reviews the PR and/or is willing to accept the risk, they can manually re-run the job.

What about $DEPENDABOT_FEATURE_REQUEST?

What if I need a secret to access a private repo/registry?

Can you use Dependabot's private repo or private registry features?

If not, please to file an issue and let us know why.

Otherwise, use the steps outlined in pull_request_target to get access to secrets.

Why does @dependabot merge fail on a push event?

The github.actor == "dependabot[bot]" since you have asked Dependabot to do the merge (vs a human actor).

We don't recommend commenting @dependabot merge to automerge a PR.

What if I want to automerge?

Automerge at your own risk.

See the section on pull_request_target for how to use it and down-scope the permissions for your GITHUB_TOKEN to just those to enable GitHub's automerge or whatever third party action you are using (pull_requests: write).

For example:

name: Dependabot auto-merge
on: pull_request_target
jobs:
  dependabot:
    if: github.actor == 'dependabot[bot]'
    steps:
      - name: Enable auto-merge for Dependabot PRs
        run: gh pr merge --auto --merge "$PR_URL"
        env:
          PR_URL: ${{github.event.pull_request.html_url}}
          GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}

If you want to discuss automerge, #2268 is the place to go.

What about any other Dependabot feature requests?

First, search the issues in this repo to see if someone has already asked the same thing. If so, feel free to add new information to the comment thread, or upvote the original request; if not, please file a new feature request.

What about $ACTIONS_FEATURE_REQUEST?

All of the following are feature requests for the Actions team, outside of how Dependabot functions. Many of these features apply to Actions on forked repos, not just Dependabot.

Can I opt-in to allowing secrets via a flag or checkbox?

Head to "Opt-in to allow secrets on Dependabot workflows" to provide feedback and discuss with the Actions team.

Can I opt-in to up-scoping my GITHUB_TOKEN?

Head to "Opt-in to allow writable tokens on Dependabot workflows" to provide feedback and discuss with the Actions team.

Can we have the ability to use Dependabot secrets instead of Actions secrets?

Head to "Use Dependabot secrets instead of Actions secrets in Dependabot workflows" to provide feedback and discuss with the Actions team.

What about any other Actions feature requests?

Can this be added back for private repos? Enterprise plans? What if I have a really good idea of how to fix this?

Sensing a theme? Head to the GitHub Actions section of github.community and ask away.

What if I want to stop using Dependabot?

We're sorry to see you go. As others in this thread have said, there are third party tools that operate in the original way.

@asciimike
Copy link
Contributor

Above is a FAQ compiled from this thread, and hopefully answers all outstanding questions, or directs folks to the right channels.

I recognize that people are upset about this change, and there are certainly plenty of things that we (GitHub) need to do in the future to both clean this up further as well as prevent similar situations from occurring again.

That said, I believe this issue has outlived its usefulness, and I'm going to close and lock this issue now, as:

  1. the conversation has gotten more negative
  2. the remaining issues are related to either Actions or unsupported features in Dependabot

On 1: While everyone is welcome to question product decisions and engage in a productive conversation on how to resolve issues, when comments become pointlessly negative or turn personal, the community is actively harmed. Several recent comments fall into the latter camp, and (in addition to violating our code of conduct) it just sucks for everyone to have to deal with that level of negativity.

On 2: the majority of the comments are feature requests from the Actions team (e.g. "how can I opt-in to the old behavior") that nobody in this repo can act on. These comments should be directed to the Actions team, who is in the best position to engage with you and get the right product built.

Some chunk of the remaining comments are related to Dependabot features, which are already captured in this repo, or should be captured in separate issues. I am active and will engage appropriately.

Again, I agree that this isn't an ideal situation for anyone, and I want to thank those of you who have rallied together to come up with as elegant a solution as we can at the moment. For those of you interested in continuing to carry that torch, the Actions team is willing to engage on the issues related to them, and I speak for the entire Dependabot team when I say we are also happy to engage on specific issues we have control of.

@dependabot dependabot locked as resolved and limited conversation to collaborators Jun 1, 2021
@asciimike asciimike changed the title Dependabot cant read secrets anymore Dependabot triggered Actions cant access secrets or use a writable token Jun 1, 2021
@asciimike
Copy link
Contributor

There are two changes coming down the pipeline that will affect folks here:

  • The Actions team recently shipped the ability to up-scope the read-only token using permissions (changelog post), which will let you have GITHUB_TOKENs with greater than read-only permissions.
  • The Actions team is also working on enabling Actions to fetch Dependabot secrets during Dependabot workloads, which will allow you to fetch secrets again. I'll link to the changelog post when it's shipped.

With the two of these changes, folks should be able to regain the original functionality.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
T: bug 🐞 Something isn't working
Projects
None yet
Development

No branches or pull requests