Use Dependabot secrets instead of Actions secrets in Dependabot workflows

Currently, Actions that run off Dependabot PRs don’t have access to secrets, as they are treated like PRs from forks (c.f.: GitHub Actions: Workflows triggered by Dependabot PRs will run with read-only permissions | GitHub Changelog).

Dependabot users in Dependabot cant read secrets anymore · Issue #3253 · dependabot/dependabot-core · GitHub have a desire to allow Dependabot triggered workflows access to secrets, potentially swapping the Actions secrets for Dependabot secrets.

This has the same attack vector as the original issue, but the scope is Dependabot’s secrets (which are presumably not your AWS deploy keys) rather than Action’s secrets (which may well be).

12 Likes

Secrets used to be available in workflow runs triggered by Dependabot and stopped working, thereby breaking many workflows where secrets are necessary.

They are certainly an attack vector but they are equally a necessary feature to have, as workflows using them will most likely not work if the secrets are not there.

I wonder how other CI systems like Travis and CircleCI have (always) handled this. I assume they expose the same attack vectors as GitHub Actions, maybe they have simply not been widely exploited yet?

I would generally consider Dependabot a trusted user because as a repository owner I must have explicitly enabled it, hence I am expecting it to create PRs and to be able to execute workflows. Clearly, somebody publishing a malicious dependency version could trigger the creation of a Dependabot PR which updates that dependency and that dependency, if executed during the workflow run, could steal the secrets. Yet, I’m not sure if the solution lies in making secrets inaccessible to such workflows, as the vulnerability lies in the malicious dependency version which could probably exploit in many other ways other than during a workflow run.

1 Like

Please consider implementing this soon. The current behaviour led to broken updates being merged to master in my company.

More concretely, I implemented a workflow based on pull_request_target and checking out the PR head, which was one of the suggestions of the GitHub issue where this was discussed. However, someone else in my company tried to apply the same flow to another repository. Unfortunately, they forgot to change the branch to be checked out. This is IMHO not my coworker’s fault: This is really a very easy mistake to make as this workaround is very hard to understand.

What this means is that we got a dependency update with a broken update, but the PR passed because the tests were being run on the main branch. Therefore, it was merged to main. Thankfully, we still run tests on main before deploying, so it didn’t go into production, but this still seems dangerous.

I understand that the changes to PRs from outside sources were made with the best of intentions. There clearly is a security risk involved in allowing arbitrary PRs to run code and read secrets. However, there is a very concrete need for this kind of behaviour, the risks can be mitigated through other means (e.g. disabling forks), and the workarounds that have to be implemented have significant downsides.

I agree that the original GitHub issue had become very unproductive at some point, but it still showed that a lot of people (including paying customers) were very unhappy with the changes and therefore I think that this feature should be prioritised.

The argument raised by GitHub’s security team (which btw is 100% correct) is that PR builds running with secrets available are a risk in general whenever those PRs come from outside your repo which could be malicious and run arbitrary code. So, while this change seems to impact Dependabot exclusively, it actually also applies to any external PRs. Of course, this particular threat could be mitigated by a) disabling forks or b) explicitly having to whitelist particular forks before they can access secrets. If dependabot could be similarly whitelisted, it would probably solve the issue.

1 Like

Disclaimer - I have read through all posts and linked issue FAQ and new docs to the best of my abilities

Our team is also currently in the process of investigation of optimal workflows for dependabot to access secrets, and honestly so far neither solutions seem to be appealing either from security perspective (because they restore attack vector which github tried to protect against) or from perspective of having worse DX.

The conclusion that I have come up with, is that there’s a problem with isolation when it comes to secrets and the way of what dependabot (or any other untrusted but automated actor) can access.

All the solutions proposed are either:

  • removing access to secrets completely - good default
  • assume the eventual presence of a trusted party and then give away access to entire secrets object - does not seem to be safe in light of our new knowledge

While I think that dependabot should not by default read repository secrets, I still need to store them in the repo for workflows other than dependabot. Hence things like pull_request_target or workflow_run while providing a “fix”, still leave attacker with a possibility to capture secrets, although not automated. The main reason for this - is that even if we introduce human interaction in between the process, it’s unlikely that humans are capable (or willing) of going through dependency chain and verifying that patches are actually legit. To build automations for humans we need secrets…

Github Actions have actually a good (but incomplete) candidate to manage this problem - environments.
https://docs.github.com/en/actions/reference/environments

We could create a special “Dependabot” environment where we add a set of secrets, which are accessible to dependabot. While setting up humans can make sure that those tokens are as minimal and downscoped as possible, thus even if because of human error somebody does toJson(secrets), damage will be at least manageable and contained. In combination with some automated monitoring on Github’s side, it would be possible to “invalidate” entire environment in case of a known widespread breach.

The problem with current implementation of environments, that environment secrets are superset of global secrets, thus some extra configuration checkbox is needed to be able to isolate environment from everywhere else. Or Github could create a standard dependabot environment which is later user-configurable and make it a default during an initial provisioning of dependabot.yml, which is also completely isolated from repo secrets (and potentially could allow selective cherry picking “safe” secrets from global pool).

I am aware of “Dependabot Secrets” on org level, but in my opinion it’s an ortogonal solution to repo-level secrets in actions, and it should not be recycled for repo-level access


In our fairly simple case we would like to perform yarn install on repository with a Github PAT to access private package registry. No other secrets are required (but many more are actually in the repo). Having isolated environment would allow us to somewhat safely use triggers like pull_request_target, have a required approval to secrets (built-in feature into environments) and even potential enable again access to secrets from pull_request and other downscoped triggers.


Not sure if you considered this @asciimike, but would be interesting to hear your thoughts.

2 Likes

I think that offering a “Dependabot” environment is a nice middle ground here, though you really should be working to convince @chrispat rather than me :wink:

In our fairly simple case we would like to perform yarn install on repository with a Github PAT to access private package registry.

Is there a reason you can’t use Dependabot’s private registry support (which uses Dependabot Secrets)?

Thanks for replying so fast!

though you really should be working to convince @chrispat rather than me :wink:

Gladly, just let me know how :slight_smile:

I think having a full-blown dependabot environment supported by Github would be ideal, but it’s a bit of a stretch goal. Short term having a possibility to toggle global secret extension (aka isolate) environment would seem to be enough.

We would still need to create a separate workflow exclusive for dependabot to reference that environment, but I think it’s more or less ok. We could avoid even this tho, if there would be conditional way to switch environment based on actor.

A bit offtop, but it’s hard to figure out what is a “proper” communication channel for feature requests as such, since things are a bit all over the place. Current discussion on issue is locked (understandably), feedback submission form is a black box (since nobody ever reaches back) and actions part of community could get more feedback from Github staff. I wish there would be a single place to write (and read) community ADRs for actions in a structured way.

Is there a reason you can’t use Dependabot’s private registry support (which uses Dependabot Secrets)?

We use it, but if I understood correctly these secrets are used by dependabot “Github App” itself to be able to access registries and repos to create PRs and they are not really propagated in any way to actions, where yarn install happens. If I didn’t understand it correctly, please let me know :slight_smile:

A reasonable request. Unfortunately I think it’s a bit fragmented by nature (e.g. I spend most of my time in dependabot-core, other teams have their own equivalents). The Actions team told me that they spend time here, which is why I posted them here.

My understanding is that teams are transitioning to Discussions · github/feedback · GitHub in an attempt to centralize, though there isn’t an Actions category there yet (nor a Dependabot one).

We use it, but if I understood correctly these secrets are used by dependabot “Github App” itself to be able to access registries and repos to create PRs and they are not really propagated in any way to actions, where yarn install happens.

Got it, so it’s more than just accessing the private registry.

2 Likes

Hello. Similar to @dentuzhik we need to access private registry inside jobs triggered by dependabot pr. “Dependabot” env with own secrets sounds like a good solution to me.

1 Like

Hi

+1 to @dentuzhik proposal.

Just wanted to add, that recently I discovered an option to approve workflow runs for PR coming from public forks (Approving workflow runs from public forks - GitHub Docs).

I think it would be cool to have a native feature similar to it to approve Dependabot PRs. Especially in the lights of having an api to automate it https://docs.github.com/en/rest/reference/actions#approve-a-workflow-run-for-a-fork-pull-request :new_moon_with_face: