I am working towards a course project to alleviate "trusting trust" attacks in the Github CI/CD ecosystem. The idea is that Github actions have a lot of pull in supply chains, and the publication method allows malicious developers to upload compromised actions artifacts.
For example, Github prefers that all Javascript actions are minified and compressed to the smallest size possible, recommending rollup.js to compile all dependencies into one large .js file. This file format is small and portable, but not so fun for auditors. Github's trust model assumes the build artifacts developers upload match the source, but there's nothing stopping someone from injecting obfuscated JavaScript into the release!
The usual solution for linking build artifacts to release artifacts are reproducible builds. To be done effectively, that requires the project maintainers to be extremely explicit in what environment and dependencies were used to compile their artifacts (named 'provenance attestations'). Under those circumstances, anyone can have some degree of certainty an artifact is legitimate by building it themselves under the same conditions and getting an output which is identical down to each individual bit.
Note this only provides partial protection from actions artifacts. It provides an indication if the developer compromised their build artifacts directly, but does says nothing on whether the original source code is legitimate. It also can't attest to whether all of the independent builders used a compromised toolchain. For the latter, you would need to bootstrap the full environment by compiling absolutely everything from the legitimate source, including the compiler. Such is what we try to avoid by auditing the artifacts authored by actions publishers.
Problem number two: if a Github actions maintainer truly wanted to compromise dependent projects by injecting malware into their bundled actions, they certainly would not release information on how they built their project. If the maintainer doesn't want to cooperate, it's difficult to discern if something is intentionally not reproducible.
What is there to do?
Diffoscope is the standard tool for determining what differs between two sets of build artifacts. In the JavaScript example, it uses js-beautify to de-obfuscate bundled code and diff them in a readable way. In cases of unreproduciblity, it may be possible to feed this prettified output into further static analysis tools to access whether or not a payload has been introduced.
There are legitimate (albeit uninformed) reasons why a piece of software isn't reproducible. I've recently come across this in packaging software for GNU Guix (which aims to defeat trusting trust), in which diffoscope also saved the day, and may write a follow up post. As for actions, the question I ask myself now is whether or not some heuristic could be automated and scaled up to cover a larger portion of the Github actions marketplace. For example, could we create a Github app to scan new commits from tracked repositories and upload potentially evil code snippets directly on the commit that adds them?