Bypassing GitHub Actions policies in the dumbest way possible

(blog.yossarian.net)

Comments

kj4ips 11 June 2025
This is a prime example of "If you make an unusable secure system, the users will turn it into an insecure usable one."

If someone is actively subverting a control like this, it probably means that the control has morphed from a guardrail into a log across the tracks.

Somewhat in the same vein as AppLocker &co. Almost everyone says you should be using it, but almost no-one does, because it takes a massive amount of effort just to understand what "acceptable software" is across your entire org.

monster_truck 11 June 2025
Had these exact same thoughts while I was configuring a series of workflows and scripts to get around the multiple unjustified and longstanding restrictions on what things are allowed to happen when.

That sinking feeling when you search for how to do something and all of the top results are issues that were opened over a decade ago...

It is especially painful trying to use github to do anything useful at all after being spoiled by working exclusively from a locally hosted gitlab instance. I gave up on trying to get things to cache correctly after a few attempts of following their documentation, it's not like I'm paying for it.

Was also very surprised to see that the recommended/suggested default configuration that runs CodeQL had burned over 2600 minutes of actions in just a day of light use, nearly doubling the total I had from weeks of sustained heavy utilization. Who's paying for that??

TheTaytay 11 June 2025
I don’t understand the risk honestly.

Anyone who can write code to the repo can already do anything in GitHub actions. This security measure was never designed to mitigate against a developer doing something malicious. Whether they clone another action into the repo or write custom scripts themselves, I don’t see how GitHub’s measures could protect against that.

hk1337 11 June 2025
This is why I avoid using non-official actions where possible and always set a version for the action.

We had a contractor that used some random action to ssh files to the server and referenced master as the version to boot. First, ssh isn't that difficult to upload files and run commands but the action owner could easily add code to save private keys and information to another server.

I am a bit confused on the "bypass" though. Wouldn't the adversary need push access to the repository to edit the workflow file? So, the portion that needs hardening is ensuring the wrong people do not have access to push files to the repository?

On public repositories I could see this being an issue if they do it in a section of the workflow that is run when a PR is created. Private repositories, you should take care with who you give access.

XCabbage 12 June 2025
I don't see the vulnerability. In fact, I think considering this a problem at all is ridiculous.

Obviously it's impossible to block all ways of "bypassing" the policy. If you are a developer who has already been entrusted with the ability to make your GitHub Actions workflows run arbitrary code, then OF COURSE you can make it run the code of some published action, even if it's just by manual copy and paste. This fact doesn't need documenting because it's trivially obvious that it could not possibly be any other way.

Nor does it follow from this that the existence of the policy and the limited automatic enforcement mechanism is pointless and harmful. Instead of thinking of the enforcement mechanism as a security control designed to outright prevent a malicious dev from including code from a malicious action, instead think of it more like a linting rule: its purpose is to help the developer by bringing the organisation's policy on third party actions to the dev's attention and pointing out that what they are trying to do breaks it.

If they decide to find a workaround at that point (which of course they CAN do, because there's no feasible way to constrain them from doing so), that's an insubordination issue, just like breaking any other policy. Unless his employer has planted a chip in his brain, an employee can also "bypass" the sexual harassment policy "in the dumbest way possible" - just walk up to Wendy from HR and squeeze her tits! There is literally no technical measure in place to make it physically impossible for him do so. Is the sexual harassment policy therefore also worse than nothing, and is it a problem that the lack of employee brain chips isn't documented?

OptionOfT 11 June 2025
We forked the actions as a submodule, and then pointed the uses to that directory.

That way we were still tracking the individual commits which we approved as a team.

Now there is interesting dichotomy. On one hand PMs want us to leverage GitHub Actions to build out stuff more quickly using pre-built blocks, but on the other hand security has no capacity or interest to whitelist actions (not to mention that the whitelist list is limited to 100 actions as per the article).

That said, even tagging GitHub actions with a sha256 isn't perfect for container actions as they can refer to a tag, and the contents of that tag can be changed: https://docs.github.com/en/actions/sharing-automations/creat...

E.g. I publish an action with code like

   runs:
     using: 'docker'
     image: 'docker://optionoft/actions-tool:v3.0.0'
You use the action, and pin it to the SHA of this commit.

I get hacked, and a hacker publishes a new version of optionoft/actions-tool:v3.0.0

You wouldn't even get a Dependabot update PR.

fkyoureadthedoc 11 June 2025
This doesn't seem like a big deal to be honest.

My main problem with the policy and how it's implemented at my job is that the ones setting the policies aren't the ones impacted by them, and never consult people who are. Our security team tells our GitHub admin team that we can't use 3rd party actions.

Our GitHub admin team says sure, sounds good. They don't care, because they don't use actions, and they in fact don't delivery anything at all. Security team also delivers nothing, so they don't care. Combined, these teams crowning achievement is buying GitHub Enterprise and moving it back and forth between cloud and on prem 3 times in the last 7 years.

As a developer, I'll read the action I want to use, and if it looks good I just clone the code and upload it into our own org/repo. I'm already executing a million npm modules in the same context that do god knows what. If anyone complains, it's getting hit by the same static/dynamic analysis tools as the rest of the code and dependencies.

clysm 11 June 2025
I’m not seeing the security issue here. Arbitrary code execution leads to arbitrary code execution?

Seems like policies are impossible to enforce in general on what can be executed, so the only recourse is to limit secret access.

Is there a demonstration of this being able to access/steal secrets of some sort?

bob1029 11 June 2025
I feel like GitHub's CI/CD offering is too "all-in" now. Once we are at a point where the SCM tool is a superset of AWS circa 2010, we probably need to step back and consider alternatives.

A more ideal approach could be to expose a simple rest API or webhook that allows for the repo owner to integrate external tooling that is better suited for the purpose of enforcing status checks.

I would much rather write CI/CD tooling in something like python or C# than screw around with yaml files and weird shared libraries of actions. You can achieve something approximating this right now, but you would have to do it by way of GH Actions to some extent.

PRs are hardly latency sensitive, so polling a REST API once every 60 seconds seems acceptable to me. This is essentially what we used to do with Jenkins, except we'd just poll the repo head instead of some weird API.

hiatus 11 June 2025
That the policy can be "bypassed" by a code change doesn't seem so severe. If you are not reviewing changes to your CI/CD workflows all hope is lost. Your code could be exfiltrated, secrets stolen, and more.
throwaway889900 11 June 2025
Not only can you yourself manually check out a specific repo, but if you have submodules and do a recursive checkout, it's also possible to pull in other security nightmares from places you never expected now. That would be one complicated attack to pull off though, chain of compromised workflows haha
ghusto 11 June 2025
> world’s dumbest policy bypass: instead of doing uses: actions/checkout@v4, the user can git clone (or otherwise fetch) the actions/checkout repository into the runner’s filesystem, and then use uses: ./path/to/checkout to run the very same action

Good lord.

This is akin to saying "Instead of doing `apt-get install <PACKAGE>`, one can bypass the apt policies by downloading the package and running `dpkg -i <PACKAGE>`.

b0a04gl 6 hours ago
its blind to the actual execution path. anyone with push access can run whatever they want anyway. and the fact that it only scans static uses: entries just means teams will start pulling stuff in manually. all of this should’ve been obvious from the beginning
john-h-k 11 June 2025
There is no meaningful way to get around this. Ban them in `uses:` keys? Fine, they just put it in a bash script and run that. Etc etc. If it allows running arbitrary code, this will always exist
0xbadcafebee 11 June 2025
You call it a security issue. I call it my only recourse when the god damn tyrannical GitHub Org admins lock it down so hard I can't do my job.

(yes it is a security issue (as it defeats a security policy) but I hope it remains unfixed because it's a stupid policy)

chelmzy 11 June 2025
Does anyone know how to query what actions have been imported from the Actions Marketplace (or anywhere) in Github enterprise? I've been lazily looking into this for a bit and can't find a straight answer.
jamesblonde 11 June 2025
Run data integration pipelines with Github actions -

https://dlthub.com/docs/walkthroughs/deploy-a-pipeline/deplo...

It's the easiest way for many startups to get people to try out your software for free.

solatic 11 June 2025
If your Security folk are trying to draw up a wall around the enterprise (prevent using stuff not intentionally mirrored in) but there are no network controls - no IP address based firewalls, no DNS firewalls, no Layer 7 firewalls (like AWS VPC Endpoint Policy or GCP VPC Service Controls) governing access to object storage and the like.... Quite frankly, the implementation is either immature or incompetent.

If you work for an org with restrictive policy but not restrictive network controls, anyone at work could stand up a $5 VPS and break the network control. Or a Raspberry Pi at home and DynDNS. Or a million others.

Don't be stupid and think that a single security control means you don't need to do defense in depth.

bluelightning2k 11 June 2025
I don't think this is a security flaw.

That's like saying it's a security flaw in the Chrome store that you could enable dev mode, copy the malware and run it that way.

zingababba 11 June 2025
Copilot repository exclusions is another funny control from GitHub. It gets the local repo context from the .git/config remote origin URL. Just comment that out and you can use copilot on an 'excluded' repo. Remove the comment to push your changes. Very much a paper control.
lmm 11 June 2025
Meh. Arbitrary code execution allows you to execute arbitrary code. If you curl | sh something in your github action script then that will "bypass the policy" too.
gchamonlive 11 June 2025
I'm inclined to add https://github.com/marketplace/actions/sync-to-gitlab to all my repos in github, so that I can tap into the social value of GitHub's community and the technical value of GitLab's everything else.