There's basically no reason for GitHub workflows to ever have any credentials by default; credentials should always be explicitly provisioned, and limited only to events that can be provenanced back to privileged actors (read: maintainers and similar). But GitHub Actions instead has this weird concept of "default-branch originated" events (like pull_request_target and issue_comment) that are significantly more privileged than they should be.
The LLM is a cute way to carry out this vulnerability, but in fact it's very easy to get code execution and poison a cache without LLMs, for example when executing code in the context of a unit test.
It is genuinely a wonder that we haven't seen massive supply-chain compromises yet. Imagine what kind of horror you could do by compromising "actions/cache" and using CD credentials to pivot to everyone's AWS / GCP / Azure environments!
> But GitHub Actions instead has this weird concept of "default-branch originated" events (like pull_request_target and issue_comment) that are significantly more privileged than they should be.
That is just very convenient when setting up the workflow
They just didn't gave a shred of thought about how something open to public should look
Well, it is pretty weird if you end up using it on a cloud based open platform where anyone can do anything. The history is not an argument for it not being weird, it is an argument against the judgement of whomever at Microsoft thought it'd be a good idea. I'm sure that person is now long gone in early retirement. It'd been great if developers weren't so hypnotized by the early brand of GitHub to see GitHub Actions for what it is, or namely, what it isn't.
So you end up with GHA's over-privileged credentials handing off to npm's over-privileged install hooks.
I've started running --ignore-scripts by default and only whitelisting packages that genuinely need postinstall. It's a bit annoying, but the alternative is trusting
every transitive dependency not to do something during install.You can also do a lot more with GHA compared to waiting for Zapier to support your scenario. Plus most people I knew who used Zapier connected it to some Lambda or another webhook where they got the data from there and ran arbitrary code anyway.
Until we do so, every single form of input should be considered hostile. We've already seen LLMs run base64-encoded instructions[0], so even something as trivial as passing a list of commit shorthashes could be dangerous: someone could've encoded instructions in that, after all.
And all of that is before considering the possibility of a LLM going "rogue" and hallucinating needing to take actions it wasn't explicitly instructed to. I genuinely can't understand how people even for a second think it is a good idea to give a LLM access to production systems...
I don’t think it can be.¹
¹ https://matthodges.com/posts/2025-08-26-music-to-break-model...
Work is still being done on how to bulletproof input “sanitization”. Research like [1] is what I love to discover, because it’s genuinely promising. If you can formally separate out the “decider” from the “parser” unit (in this case, by running two models), together with a small allowlisted set of tool calls, it might just be possible to get around the injection risks.
[1] Google DeepMind: Defeating Prompt Injections by Design. https://arxiv.org/abs/2503.18813
At a fundamental level, having two contexts as suggested by some of the research in this area isn’t enough; errors or bad LLM judgement can still leak things back and forth between them. We need something like an SQL driver’s injection prevention: when you use it correctly, code/data confusion cannot occur since the two types of information are processed separately at the protocol level.
Simon Willison has a good explainer on CaMeL: https://simonwillison.net/2025/Apr/11/camel/
I have significant doubt that a P-LLM (as in the camel paper) operating a programming-language-like instruction set with “really good checks” is sufficient to avoid this issue. If it were, the P-LLM could be replaced with a deterministic tool call.
EDIT: And if you think "well, how else could it work": I think GitHub Actions simply do too much. Before GHA, you would use e.g. Travis for CI, and Zapier for issue automation. Zapier doesn't need to run arbitrary binaries for every single action, so compromising a workflow there is much harder. And even if you somehow do, it may turn out it was only authorized to manage issues, and not (checks notes) write to build cache.