Can workflow changes be used with pull_request_target?

I have Dependabot configured in my repository. As mentioned in numerous threads already, Dependabot recently rolled out a feature where GitHub secrets will not be available to Dependabot PRs. The documented solution for this is to change the trigger on a PR gate workflow from using pull_request to pull_request_target. Since the Dependabot PRs are essentially fork PRs, this will result in the workflows being run in the context of the base of the PR.

The problems I’m seeing with using pull_request_target as the trigger is that it seems to prevent you from making changes to a GitHub Actions workflow because it uses what’s in the base branch not what’s in the PR. I think this is the same reason why people are also having issues with workflows with pull_request_target getting picked up (I assume this is when they are submitting a PR that is creating the PR workflow).

Having pull_request and pull_request_target set as triggers will run the workflows twice so that’s not a solution.

How can this be addressed?

Tell checkout (or git or whatever you’re using) to checkout the branch you actually want:

uses: actions/checkout@v2
        ref: ${{github.event.pull_request.head.ref}}
        repository: ${{github.event.pull_request.head.repo.full_name}}

That checkout will work in the sense of using the PR code, but to quote the GitHub blog post that went along with that change:

TL;DR : Combining pull_request_target workflow trigger with an explicit checkout of an untrusted PR is a dangerous practice that may lead to repository compromise.

Some things can be done safely, but that requires a close look at your workflow and code. The blog post that quote is from has a lot of detail:

1 Like

@kingthorin @airtower-luna Extextremely helpful information. Thank you!

Since the repos I work with are all private repos, PRs will only be created by devs in my organization and dependabot. Given this, I think @kingthorin’s solution is acceptable.

Just to confirm, using an example, if repo2 forks the main branch in repo1 then makes a PR:

  • if a workflow uses pull_request, it will checkout the PR’d branch from repo2 by default.
  • if a workflow uses pull_request_target, it will checkout the main branch from repo1 by default.

This is what I’m concluding based off @kingthorin’s solution which seems like it would effectively allow you to use the pull_request_target trigger to pick up fork PRs but use the code in the PR for the workflow.

Pretty close. If you check the event descriptions for pull_request and pull_request_target (or any other event) you can see what GITHUB_REF is for each event. That’s what actions/checkout checks out if you don’t specify anything else in parameters. :slightly_smiling_face:

1 Like

@airtower-luna @kingthorin Circling back to the original question, how are changes to the workflows themselves supposed to be picked up when using pull_request_target? Or is it even possible? Because setting ref and repository will obviously only change what is used during the workflow, not how the workflow itself is defined. pull_request will run workflows that are part of the PR code whereas pull_request_target will run workflows in the target repo/branch.

I’m wondering if I need to use both triggers, each with an additional qualification (pull_request where the repo is the same as the target and pull_request_target when the repo is different from the target) so it will only run once. I’m not sure if that’s possible and it doesn’t seem like it is looking at the GA documentation. Seems like the only additional qualification is types.

Actually, would enabling “Run workflows from fork pull requests” (disabled by default) and switching my trigger back to pull_request get me where I want to be?

Not with pull_request_target, no. I’m sure you can imagine how an untrusted PR being able to change the workflow and access secrets could go wrong. :sweat_smile:

Not as such, because those workflows still wouldn’t get the secrets. AFAIK there’s a separate option to allow that for organizations, maybe that’d work for you?

1 Like

Yep, those form-related Settings > Actions configurations is what I was referring to. I’ll give that a shot!

Imagine your CI runs code.
Imagine @dependabot is responding to a supply-chain attack by offering a supply-chain infected update.

If your code uses pull_request_target with a merge and then runs testing, the supply chain infected code now has access to a write token to your repository.

This is generally deemed game over

Obviously, it’s worse if you automatically merge a compromise of your supply chain.