-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Add runner-level config to enforce PR security #783
base: main
Are you sure you want to change the base?
Conversation
@chrispat Tagging you since you commented on #494. I agree that solving this at the GitHub level would be a better solution, but on apache/airflow we are struggling without being able to use self-hosted runners (we share an actions queue with every other Apache Software Foundation project using Github, so leads to rather unpredictable and uncontrollable queue lengths.) So here is a "maybe good enough approach" -- happy to redesign things/rework as needed, but I think this is a good stop-gap measure. Thoughts? |
(Oh and of course this will need tests adding.) |
Question: should these security settings also apply to branch builds? |
9242ee1
to
cdc0d4f
Compare
This is similar to what we're doing to use self-hosted runners in the Rust project. Our current solution of using a fork with a patch similar to this is far from ideal, as we need to be quick to rebase our changes on top of the latest releases before the runner stops working due to the auto-update being prevented. Not having to rebase the fork every week or two by having a patch land in the runner would be awesome. |
@pietroalbini Would love to collaborate on this. Does this PR do everything you need for Rust? |
cdc0d4f
to
51ebb8d
Compare
We don't plan to execute any pull request build on self-hosted runners, so a toggle to just reject all PRs (even if those are sent by owners) would be best for Rust. For reference this is the patch on our fork we're currently running in prod. |
Gotcha, yes that makes sense. I'll roll that in to my PR. |
This has been open a while as a draft (and original issue) so I thought I would add some commentary here so you know that we are talking/thinking about this. A couple of thoughts:
So TLDR for now is I don't think we would merge this, but this is a great concept that we will talk about internally and see how we can tackle a better experience. I also want to mention we really appreciate your contribution and willingness to dig into the code so please don't take us not merging the PR as a reason to not continue to push on interesting ideas like this. |
Thanks for looking into this @hross!
I'm not sure that's actually a threat this PR is meant to solve. My understanding is, this PR would successfully prevent people without write access to the repository from ever submitting a build to the runner, so the only way the configuration change could happen is if the malicious entity already has write access to the repo (which allows them to just push a branch instead of opening PRs). Also, if the runner is executed on a persistent VM then a malicious entity with the ability to change the configuration could also reconfigure the runner to point to a different repository without the server side limitation. If the runner is executed on an ephemeral VM instead, the configuration change wouldn't matter as the change wouldn't persist across executions. |
You are totally right about this, of course (and all of your other comments):
It's more about what does an inexperienced user think about a "security setting" and do they understand the implications of what you're explaining? Do we design for that (ideally yes). In any case it's something we have to think about before we'd release a setting like this as "official". |
I see your point! A possible solution would be to call this a "filter" instead of a security feature, so that people who stumble into it without any extra context won't be misled by its name. Then, when the feature is documented on docs.github.com some extra context can be added there to explain what this feature does and doesn't protects against. I thought about possible designs for the configuration with the new "filter" naming:
I'm also really happy to collaborate with y'all to brainstorm possible documentation |
51ebb8d
to
d7c3495
Compare
Having now started using this "in anger" the current config scheme I have in this PR is clearly not right. |
30ad312
to
f326681
Compare
I've just run in to a less-than ideal behaviour (which is likely only a problem for the This means that for us, it would allow every apache author to be able to run on our self-hosted runners, which isn't what we want -- just anyone able to commit to the repo is what we are aiming for. |
d395557
to
bed3b45
Compare
07c0b78
to
bdd9830
Compare
@ashb I have followed this PR here and find your enhancement to the actions/runner very useful. It is really a pity that GitHub seems to ignore it so far because I think it would be great if they could add some more security for using self-hosted runners also for public repos. And your PR seem to provide some quite straight forward way of securing the use of self-hosted runners in public repos and I still hope GitHub will once pickup your idea and implement it because we really need some additional level of security here for using self-hosted runners also in public repos! Nevertheless, do you have any resource where you publish own/separate builds of actions/runner with your PR modification? This would allow to use these instead of the GitHub version of actions/runner which is know to be prone to the pull-request security issue we all know. |
My fork is set up with automation (GitHub actions of course) to automatically build a release with my changes incorporated when ever a release is published in the upstream repo https://github.com/ashb/runner/releases |
That's great! And if using your runner instead of the standard github one it will also automatically update itself then from your fork and not switch back to the official one? |
No, not yet sadly. I haven't worked out the message/mechanism that GitHub use to out that message (or the contents of that message) so I cant "redirect" the update. |
That's indeed sad. I also couldn't quickly grep for the update url or similar in the runner source code. Too bad that GitHub isn't providing more documentation on the actual runner implementation. Do you know at least of a way to disable the automatic update? Because otherwise changes are high that if I run your PR secured runner variant it will be automatically updated to the official runner once github released a new one. And this would remove the additional PR security of your work... |
ebac631
to
42aaf7b
Compare
5495e71
to
634127d
Compare
f9ebe67
to
0ffde16
Compare
ee7a966
to
b89c5fa
Compare
ccd14e2
to
678f186
Compare
b270539
to
ef89e5a
Compare
e4f33ba
to
6057f98
Compare
53963f9
to
e292d48
Compare
e292d48
to
1448196
Compare
This allows self-hosted runners to limit who can run jobs to give "just enough protection" to allow using self-hosted runners with public repos. By default, the current behaviour is unchanged -- all jobs passed to the runner are executed. If the `.runner` config file has this block added to it: ``` "pullRequestSecurity": {} ``` Then by only PRs from "CONTRIBUTORS" and "OWNERS" can run (as defined by the field in https://docs.github.com/en/free-pro-team@latest/graphql/reference/objects#pullrequest -- nothing for us to have to work out ourselves.) It is also possible to explicitly list users that are allowed to run jobs on this worker: ``` "pullRequestSecurity": { "allowedAuthors": ["ashb"] } ``` Or to _only_ allow the given users, but not all contributors: ``` "pullRequestSecurity": { "allowContributors": false, "allowedAuthors": ["ashb"] } ``` Owners of the repo are always allowed to run jobs. If an allowed user pushes a commit to a PR from a non-allowed user, than _that_ build will be allowed to run on the self-hosted runner.
1448196
to
eaa6f8f
Compare
This closes #494 at the runner level to give "just enough protection"
to allow using self-hosted runners with public repos.
This PR could do with a bit of a tidy up (some strings should likely become constants/enums, and a few things should possibly be added as methods on the GitHubContext class) but I wanted to get a 👍 from the approach first.
(Also C# is not my "native" language so there may be some oddities in here)
By default, the current behaviour is unchanged -- all jobs passed to the runner are executed.
If the
.runner
config file has this block added to it:"pullRequestSecurity": {}
Then by only PRs from "CONTRIBUTORS" (as defined by the field in https://docs.github.com/en/free-pro-team@latest/graphql/reference/objects#pullrequest -- nothing for us to have to work out ourselves.)
It is also possible to explicitly list users that are allowed to run jobs on this worker:
Or to only allow the given users, but not all contributors:
Owners of the repo are always allowed to run jobs.