{
	"id": "05b60e20-c355-40aa-be91-8329e7067606",
	"created_at": "2026-04-06T00:08:23.787945Z",
	"updated_at": "2026-04-10T03:24:39.819447Z",
	"deleted_at": null,
	"sha1_hash": "4e8ff35b2d966ab4971a7465783735f4e8afe462",
	"title": "GitHub Actions Supply Chain Attack: A Targeted Attack on Coinbase Expanded to the Widespread tj-actions/changed-files Incident: Threat Assessment (Updated 4/2)",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 2024598,
	"plain_text": "GitHub Actions Supply Chain Attack: A Targeted Attack on\r\nCoinbase Expanded to the Widespread tj-actions/changed-files\r\nIncident: Threat Assessment (Updated 4/2)\r\nBy Omer Gil, Aviad Hahami, Asi Greenholts, Yaron Avital\r\nPublished: 2025-03-21 · Archived: 2026-04-05 18:19:44 UTC\r\nExecutive Summary\r\nUpdate April 2: Recent investigations have revealed preliminary steps in the tj-actions and reviewdog\r\ncompromise that were not known until now. We have pieced together the stages that led to the original\r\ncompromise, providing insights into other impacted GitHub organizations and users.\r\nWe discovered the first steps that appear to have been taken in this multi-layered attack flow. The attackers\r\nobtained initial access by taking advantage of the GitHub Actions workflow of SpotBugs, a popular open-source\r\ntool for static analysis of bugs in code. This enabled the attackers to move laterally between SpotBugs\r\nrepositories, until obtaining access to reviewdog.\r\nAccording to our research, the attack started in November 2024, but only came to light months later. Our ongoing\r\nresearch sheds light on this attack as a whole, revealing a larger scope of impact and longer attack period than\r\nwere previously reported. Jump to our Update section to read the full details.\r\nUpdate March 20: The recent compromise of the GitHub action tj-actions/changed-files and additional actions\r\nwithin the reviewdog organization has captured the attention of the GitHub community, marking another major\r\nsoftware supply chain attack. Our team conducted an in-depth investigation into this incident and uncovered many\r\nmore details about how the attack occurred and its timeline. These attackers compromised continuous\r\nintegration/continuous delivery (CI/CD) pipelines of thousands of repositories, putting them at risk.\r\nOur team also discovered that the initial attack targeted Coinbase. The payload was focused on exploiting the\r\npublic CI/CD flow of one of their open source projects (agentkit) probably with the purpose of leveraging it for\r\nfurther compromises. However, the attacker was not able to use Coinbase secrets or publish packages.\r\nAfter this initial attack, we believe the same actor moved on to the larger attack that has since gained widespread\r\nattention globally. Our investigations also reveal that the attacker began preparing several days before reports\r\nsurfaced, eventually affecting specific versions of tj-actions/changed-files and putting a significant number of\r\nrepositories at risk.\r\nThis incident underscores how attackers can abuse third-party actions or dependencies to compromise software\r\nsupply chains, potentially resulting in unauthorized access, data breaches and code tampering.\r\nOverview of the Attack\r\nhttps://unit42.paloaltonetworks.com/github-actions-supply-chain-attack\r\nPage 1 of 28\n\nGitHub Actions is a CI/CD platform that helps users automate their development pipeline. Individual GitHub\r\nactions can become reusable workflow components that other pipelines can utilize. The tj-actions/changed-files\r\nGitHub action was recently compromised, allowing attackers to access sensitive workflow secrets that relied on\r\nthis action. This GitHub action was used by over 23,000 GitHub repositories.\r\nThe compromise was first identified on March 14, 2025, when security researchers detected suspicious activity\r\nmade by the action. The attackers injected a payload that dumped the CI/CD runner’s memory, exposing sensitive\r\nenvironment variables and secrets directly to the workflow logs.\r\nA lead provided by Adnan Khan suggested that the compromise of the tj-actions/changed-files action originated in\r\nthe compromise of a repository belonging to another GitHub organization: reviewdog/action-setup. We can now\r\nconfirm that tj-actions/changed-files was compromised because it used the tj-actions/eslint-changed-files action,\r\nwhich relied on reviewdog/action-setup as a dependency. Further investigation revealed that additional actions\r\nbelonging to the reviewdog organization were hijacked as well. By March 20, the maintainers of both tj-actions\r\nand reviewdog had applied the necessary security measures, and mitigated the threat.\r\nRecommended Mitigations\r\nOur recommendations focus on detection and prevention steps from the perspective of the consumers of the\r\ncompromised tj-actions/changed-files action, and actions belonging to the reviewdog organization. The\r\ncommunity should learn from the compromise of these actions and their hosting repositories.\r\nThe detailed mitigations and recommended actions below include immediate steps for affected users, such as:\r\nIdentifying usage\r\nReviewing workflow logs to identify leaked tokens and secrets\r\nRotating secrets\r\nInvestigating malicious activity\r\nWe also share ways to make long-term security improvements related to this issue, as well as information on how\r\nPalo Alto Networks cloud security products can assist with protecting against this and similar security risks.\r\nIf you think you might have been compromised or have an urgent matter, contact the Unit 42 Incident Response\r\nteam.\r\nOverview of the Attack Flow\r\nFirst Things First: Let’s Talk About tj-actions and reviewdog\r\nSomewhere between March 10 and March 14, 2025, an attacker successfully pushed a malicious commit to the tj-actions/changed-files GitHub repository. This commit contained a Base64-encoded payload shown in Figure 1,\r\nwhich prints all of the credentials that were present in the CI runner’s memory to the workflow’s log.\r\nhttps://unit42.paloaltonetworks.com/github-actions-supply-chain-attack\r\nPage 2 of 28\n\nFigure 1. The malicious snippet that was introduced to tj-actions/changed-files.\r\nThe attacker was able to add the malicious commit (0e58ed8) to the repository by using a GitHub token with write\r\npermissions that they obtained previously. The attacker disguised the commit to look as if it was created by\r\nrenovate[bot] — a legitimate user.\r\nThe commit was then added to a legitimate pull request that was opened by the real renovate[bot] and\r\nautomatically merged, as configured for this workflow. These steps enabled the attacker to infect the repository,\r\nwithout the activity being detected. Once the commit was merged, the attacker pushed new git tags to the\r\nrepository to override its existing tags, making them all point to the malicious commit in the repository.\r\nFrom that point of compromise, the attacker impacted every GitHub workflow run that depended on the tj-actions/changed-files action.\r\nOn March 14, 2025, the attack on tj-actions/changed-files was detected by StepSecurity’s researchers, who\r\nreported the incident to the maintainers of the tj-actions organization. As soon as details of the incident were\r\npublished, the GitHub community started patching workflows and repositories to mitigate the attack.\r\nOn March 16, Adnan Khan shared his research, pointing to the compromise of another GitHub organization —\r\nreviewdog. Adnan hypothesized that in the original compromise, the attacker leveraged a workflow configured in\r\nthe tj-actions/changed-files repository that was using another action belonging to the same organization: tj-actions/eslint-changed-files.\r\nIn turn, the tj-actions/eslint-changed-files action directly depended on the reviewdog/action-setup action, and used\r\nit in its runtime as a composite action. This implied that consumers of the tj-actions/eslint-changed-files action\r\nwere compromised once it ran, as this action automatically executed the malicious code residing in the\r\ncompromised reviewdog/action-setup action.\r\nWhen the tj-actions/eslint-changed-files action was executed, the tj-actions/changed-files CI runner’s secrets were\r\nleaked, allowing the attackers to steal the credentials used in the runner, including a Personal Access Token (PAT)\r\nbelonging to the tj-bot-actions GitHub user account.\r\nAdnan followed up his statement by sharing details of a suspicious commit that he identified in reviewdog/action-setup: f0d342.\r\nhttps://unit42.paloaltonetworks.com/github-actions-supply-chain-attack\r\nPage 3 of 28\n\nAdnan also pointed out that reviewdog uses an auto-invite mechanism. This mechanism automatically invites\r\nGitHub users who contributed to the reviewdog organization to be a part of it, granting them write permission to\r\nits repositories. The maintainer of reviewdog later agreed that this mechanism may indeed have been the entry\r\npoint of the attacker to the reviewdog organization.\r\nFrom our inspection of reviewdog/action-setup, it appeared to us that the f0d342 commit was introduced to the\r\nrepository by an attacker — probably the same actor who attacked tj-actions. However, with more information and\r\nhelp from the maintainer of reviewdog, haya14busa, we are able to identify that what was actually pushed are git\r\ntags — not commits.\r\nSummarizing what we’ve gathered by now, we can state the following:\r\nA token with write access to the reviewdog organization was leaked (or maybe a contributor went rogue)\r\nand this token was used to compromise both of the tj-actions repositories mentioned above.\r\nAs tj-actions/changed-files depend on reviewdog/action-setup, we can assume that reviewdog was\r\ncompromised prior to tj-actions.\r\nIn the next section, we shed light on the techniques that were used by the attacker to introduce stealthy commits to\r\nthese repositories and provide detail about the impacts that followed.\r\nDeep Analysis\r\nWhile both the initial and subsequent compromises appear to be similar at first glance, they have some\r\ndifferences.\r\nIn the tj-actions/changed-files infection, we saw that the attacker infected the index.js file via a “legitimate” pull\r\nrequest. In order to infect this file, the attacker must have had a token with write permission to the repository.\r\nWithout this, they wouldn’t have been able to push the impersonated commit (0e58ed8).\r\nWe now know that they obtained this capability using the PAT that they previously acquired by infecting\r\nreviewdog/action-setup, which in turn poisoned tj-actions/changed-files’s workflow. In addition to the pull request\r\ninfiltration, the attacker used the token to update the existing git tags of the tj-actions/changed-files repository,\r\nmaking all tags point to the malicious 0e58ed8 commit.\r\nThis eventually led to code execution in the CI runners of any GitHub action or workflow using this action, and\r\nreferencing it by one of these tags.\r\nWe assume that although the attacker had a GitHub token with write permission to the repository, they preferred to\r\ndisguise their malicious commit by impersonating a valid user in a valid pull request — a technique called\r\n“commit impersonation.”\r\nThis impersonation technique was published more than a decade ago. You can find more information about it in\r\nthis repository.\r\nIn the initial infection, on reviewdog/action-setup, we observed that although there was no pull request infiltration\r\nor visibly malicious commit, an update was made that caused the git tags to point to a malicious commit (thank\r\nhttps://unit42.paloaltonetworks.com/github-actions-supply-chain-attack\r\nPage 4 of 28\n\nyou again, haya14busa!). This implied, again, that the attacker had obtained a GitHub token with write permission\r\nto this repository as well.\r\nThis educated assumption still leaves us with some important questions:\r\nHow were the malicious commits introduced to the reviewdog/action-setup repository?\r\nAnd if we can’t find any traces of branches or pull requests, where did they come from?\r\nGitHub Forks\r\nGitHub forks are a common version control system (VCS) feature that are used extensively worldwide for\r\nlegitimate purposes, but they can also be used in a darker fashion.\r\nAfter a user forks a repository in GitHub, they can add their commits to the fork. These commits are added to the\r\n“fork network” and can be referenced from the original repository.\r\nWhen browsing to these commits, they appear within the original repository, but show a dangling commit warning\r\n(Figure 2).\r\nFigure 2. Dangling commit in the reviewdog/action-setup repository.\r\nThis means that a malicious actor could abuse the forking functionality to introduce arbitrary commits to a\r\nforkable GitHub repository, even if the attacker doesn’t have write permission. And to spice things up, if such\r\nforks are deleted and the exact commit SHA values from the fork are not known, these commits will be\r\nuntraceable and impossible to identify.\r\nWith these facts in mind, we started to suspect that forks had been involved in this attack. Deeper investigation\r\nrevealed that our suspicion was correct.\r\nInfecting reviewdog\r\nWhen we looked for forks of either of the compromised repositories, we weren’t able to detect any suspicious\r\ninstances. This indicated that either GitHub deleted the instances because they were involved in malicious activity,\r\nhttps://unit42.paloaltonetworks.com/github-actions-supply-chain-attack\r\nPage 5 of 28\n\nor that something else took place.\r\nTo unravel this conundrum, we utilized our custom tools and capabilities, and discovered the following:\r\nOn 2025-03-11, 17:06:12 (UTC) a user named iLrmKCu86tjwp8 forked the reviewdog/action-setup\r\nrepository. When we looked for the user, we found that it had vanished and no longer existed in GitHub.\r\nThis immediately raised our suspicions.\r\nWithin their fork, we saw that this user had pushed 13 commits containing various payloads. Some were\r\nidentical to the malicious payload found in commit 0e58ed8 at reviewdog/action-setup and some were\r\n“cleanup” commits, like 8d73381.\r\nWe also saw that this user forked the reviewdog/action-typos repository on 2025-03-11, 17:21:52 (UTC), and\r\npushed another 15 commits containing various payloads. However, since this user was deleted, we were unable to\r\ndirectly access the fork and its commits.\r\nThis is where we were able to use the fork network functionality in our favor. Working under the assumption that\r\nthe attacker created a fork, we understood that their commits should be available under reviewdog‘s repository —\r\nand indeed they were.\r\nThe Indicators of Compromise section towards the end of this article provides the list of all the commits the user\r\ncreated in their fork in order to later infect the original repository.\r\nWhen inspecting the commits, we observed that the attacker prepared the infection of reviewdog/action-setup, and\r\nalso prepared reviewdog/action-typos to point to the malicious commits.\r\nThe infection itself contained variations of the snippet shown below in Figure 3 to collect victim credentials when\r\nthe runner script was executed.\r\nFigure 3. The malicious code snippet in the reviewdog/action-setup repository.\r\nIn addition to this finding, from the logs of reviewdog we learned that the attacker pushed new tags to point to the\r\nmalicious commits. This made us wonder why the attacker used this approach specifically, and it didn’t take us\r\nlong to realize the following. Git tag changes that are pushed to GitHub are not recorded in the GitHub audit\r\nlog for organizations and repositories using GitHub’s free tier.\r\nhttps://unit42.paloaltonetworks.com/github-actions-supply-chain-attack\r\nPage 6 of 28\n\nThis means that by using a shadow commit from a deleted fork and pushing a git tag that is not saved in the audit\r\nlog, an attacker can almost completely evade detection.\r\nThe following points summarize our analysis of the reviewdog infection:\r\nThe attacker’s preparations commenced on March 11, 2025, at 17:06:12 (UTC), and the attack was\r\ndetected three days later\r\nThe attacker is well aware of the forking features and knows that they can use commits coming from a fork\r\nwithin the repository’s legitimate codebase\r\nThe attacker used a token with write permission to push git tags to the repository and stay undetected by\r\nintroducing the commits via the fork method\r\nAs we now understood that the malicious commits were introduced to the reviewdog repositories via forks, we\r\nwere faced with another question: Why couldn’t we see their traces?\r\nHiding GitHub Users\r\nAlthough we are fairly confident about our above conclusions, this section will remain a hypothesis that GitHub\r\ncan either confirm or refute.\r\nWe believe that when the iLrmKCu86tjwp8 user was registered, it used a legitimate email, as standard GitHub\r\nusers do. Later, after introducing the shadow commits, the user changed this email to a disposable/anonymous\r\nemail that is disallowed by GitHub’s policy.\r\nIn such cases, GitHub will flag the account and hide it from the public. This includes hiding every interaction and\r\naction that the user performed on the GitHub platform.\r\nWe hypothesize that the user performed this email change in order to cause GitHub to clean their traces and\r\naccount, making it much more difficult to trace their actions and identity.\r\nMore Forks and More Dummy Users\r\nWhen we looked for the forks of tj-actions/changed-files, we found two other suspicious users:\r\n2ft2dKo28UazTZ\r\nmmvojwip\r\nBoth of these accounts were also deleted from GitHub.\r\nWhen we inspected the behavior of the 2ft2dKo28UazTZ user, we saw that although it forked the tj-actions/changed-files, it was used differently. Unlike the iLrmKCu86tjwp8 user, 2ft2dKo28UazTZ was used to\r\ntest the creation and deletion of git tags. Namely v39 and v47, as shown in Figure 4.\r\nhttps://unit42.paloaltonetworks.com/github-actions-supply-chain-attack\r\nPage 7 of 28\n\nFigure 4. The 2ft2dKo28UazTZ user experimenting with git tag creations.\r\nWhile we know that eventually the actor overrode all of the git tags of tj-actions/changed-files, we noticed that\r\nhere, the actor targeted two specific git tags:\r\nv39\r\nv47\r\nThe third user that was identified, mmvojwip, forked tj-actions/changed-files as well, but did not interact in any\r\nway with its fork.\r\nTo clear things up before we move on, let’s summarize the last two sections:\r\n1. The attacker used three dummy accounts to perform the preparations and testing: iLrmKCu86tjwp8,\r\n2ft2dKo28UazTZ and mmvojwip\r\n2. After using the accounts, we hypothesize that the attacker made GitHub flag their accounts and clean up\r\ntheir traces\r\nRevealing the Connection to Coinbase\r\nWhen we searched for what activities the 2ft2dKo28UazTZ and mmvojwip users performed, we noted that they\r\nhad created the following forks:\r\n2025-03-12 15:28:44 → 2ft2dKo28UazTZ forks coinbase/onchainkit\r\n2025-03-12 15:29:04 → 2ft2dKo28UazTZ forks coinbase/agentkit\r\n2025-03-12 15:32:02 → 2ft2dKo28UazTZ forks coinbase/x402\r\n2025-03-13 20:36:02 → mmvojwip forks coinbase/agentkit\r\n2025-03-13 21:04:58 → mmvojwip forks coinbase/agentkit again\r\nWe kept looking and saw that both of these users made changes to their forks of coinbase/agentkit, but not to the\r\nother two repositories, so we focused on coinbase/agentkit. Having discovered that the actor forked these\r\nrepositories before the large attack on tj-actions/changed-files took place, we suspected that Coinbase might have\r\nbeen the actual target (or one target) of the campaign.\r\nWhen we browsed to the coinbase/agentkit repository, we saw that it is labeled as a “framework for easily\r\nenabling AI agents to take actions onchain.”\r\nWhen we further inspected the activity of 2ft2dKo28UazTZ within its fork of coinbase/agentkit, we saw that it\r\nwas mainly creating pull requests from its own branches to itself. It was updating the\r\nhttps://unit42.paloaltonetworks.com/github-actions-supply-chain-attack\r\nPage 8 of 28\n\n.github/workflows/changelog.yml file or experimenting with releasing the nightly-20250311 tag.\r\nWhen we looked in coinbase/agentkit we didn’t find any indications of a compromise in the nightly-20250311 tag,\r\nbut oddly, we found that the changelog.yml file was actually deleted by the maintainer on March 14. Although it\r\nwas deleted, we could see that the workflow referenced v39 of tj-actions/changed-files, which is the exact same\r\ntag the actor was fiddling with in their own fork. This also strengthened our suspicion that the attacker had\r\ntargeted Coinbase.\r\nAs observed in the initial attack, the commits were introduced to the repository via a fork, meaning that we could\r\nsee them inside the coinbase/agentkit repository. After identifying these commits, we saw that throughout the\r\nchanges in 2ft2dKo28UazTZ’s coinbase/agentkit fork, they updated and alternated the references of tj-actions/changed-files to one of the following SHA values:\r\nfbc2c5ebe64389f297a7808025379f77133f1292\r\ne1e36574b3af1ddaab74f5e69505d8836bf12f52\r\nce4a123414f9fffa959d1f329c4749da83c4bf10\r\nc17ac4b5c1cb901a7ccddf00ac9722b8e2725345\r\nWhen we attempted to access these SHAs in tj-actions/changed-files we reached a dead end. They had all been\r\ndeleted.\r\nThe full commits list of the 2ft2dKo28UazTZ user can be found below in the Indicators of Compromise section.\r\nAt this point, we know that:\r\n2ft2dKo28UazTZ experimented with the modification of the changelog.yml file in coinbase/agentkit that\r\nwas using v39 of tj-actions/changed-files, and tested the creation of the nightly-20250311 tag\r\nEither the legitimate maintainer or an actor with a leaked token deleted the changelog.yml file from the\r\ncoinbase/agentkit repository\r\nGiven that we didn’t find any other open ends for the 2ft2dKo28UazTZ user, we moved on to the third user that\r\nwe found.\r\nA Smoking Gun\r\nAt this point in our investigations, we started looking into the actions of the mmvojwip user, while also fetching\r\nthe deleted workflow logs of the changelog.yml workflow in coinbase/agentkit via the GitHub API.\r\nIn the same way as described in the initial compromise, the user created a fork with their changes.\r\nThe full list of commits is provided in the Indicators of Compromise section, but three commits in particular stood\r\nout:\r\ncoinbase / agentkit - Commit 8edc60f\r\ncoinbase / agentkit - Commit b3a1c72\r\ncoinbase / agentkit - Commit b39e2d4\r\nhttps://unit42.paloaltonetworks.com/github-actions-supply-chain-attack\r\nPage 9 of 28\n\nAll of these commits changed the reference of tj-actions/changed-files to or from SHA\r\n6e6023c01918b353229af0881232f601a4cc8365. When we accessed that commit, we saw that it was another\r\ndangling commit as shown in Figure 5. This time, it was impersonating (or abusing) the github-actions[bot].\r\nFigure 5. tj-actions/changed-files with newly-discovered impersonated malicious commit.\r\nIt is important to note that at this point, the actor had write permissions to the tj-actions/changed-files repository\r\nand could push arbitrary commits or branches, impersonating any user and staying under the radar.\r\nWhen we looked into the payload of this commit, we found a payload that was yet to be revealed. This payload\r\ndemonstrates the connection between the actor, tj-actions/changed-files and coinbase/agentkit as shown in\r\nFigure 6.\r\nFigure 6. A malicious commit spear-targeting coinbase/agentkit inside the tj-actions/changed-files\r\nrepository.\r\nThe details in this commit prove that the attacker was looking specifically for the Coinbase repository.\r\nhttps://unit42.paloaltonetworks.com/github-actions-supply-chain-attack\r\nPage 10 of 28\n\nAt this point, we approached Coinbase and also started searching for the commit inside the workflow logs of\r\ncoinbase/agentkit, to see whether their workflow had pulled the malicious SHA. It wasn’t long before we found\r\nour answer as shown in Figure 7.\r\nFigure 7. coinbase/agentkit pulling and executing the malicious SHA targeted at Coinbase.\r\nWe also identified that this workflow was executed with write-all permissions in the repository, allowing sensitive\r\nactions to be performed, possibly allowing the introduction of malicious code into the coinbase/agentkit\r\nrepository’s codebase.\r\nAt this point, we can state the following:\r\nThe attacker created a campaign targeted at Coinbase\r\nThe attacker obtained a GitHub token with write permissions to the coinbase/agentkit repository on March\r\n14, 2025, 15:10 UTC, less than two hours before the larger attack was initiated against tj-actions/changed-files\r\nWe don’t know whether other organizations were spear-targeted in the same fashion\r\nWe are yet to tell whether the deletion of the changelog.yml file inside coinbase/agentkit is the result of a\r\ncompromised token, or whether the maintainer deleted this workflow due to a security report\r\nAlthough the payloads collected sensitive information, but as far as we know, they did not contain more\r\nsevere operations such as remote code execution or reverse shell actions typically associated with\r\nmalicious actors\r\nContacting Coinbase\r\nOn March 19 at 18:28, we emailed the Coinbase maintainer who deleted the changelog.yml workflow to ascertain\r\nwhether the maintainer removed the workflow on their own initiative, and if they were aware of the leak.\r\nBy 19:15 the maintainer replied that indeed they had removed the workflow following a security report and had\r\nremediated the attack.\r\nWe followed up by sharing more details of our findings with Coinbase, which stated that the attack was\r\nunsuccessful at causing any damage to the agentkit project, or any other Coinbase asset.\r\nhttps://unit42.paloaltonetworks.com/github-actions-supply-chain-attack\r\nPage 11 of 28\n\nAffected Repositories\r\nTo provide a visual representation of the potential impact of this attack, we constructed an actions dependency tree\r\nfor reviewdog/action-setup, which was the nucleus of this event. To create the tree shown in Figure 8, we searched\r\nfor all the actions dependent on reviewdog/action-setup, and those that depend on the dependent actions\r\nrecursively up to three levels.\r\nEach node represents an action. The actions in the innermost circle all depend on reviewdog/action-setup directly\r\nas a composite action, or indirectly by using it in their workflows.\r\nInside each node are a number of repositories (actions and workflows) that directly depend on the action. Figure 8\r\nalso includes the sum of dependent repositories in each level.\r\nThese are the potentially affected repositories and projects of the entire campaign. Each level expands\r\nsignificantly as more repositories are affected.\r\nThe actual dependent numbers are much higher, because:\r\nThe figure only contains public repositories\r\nIt has partial results due to search limitations\r\nIt does not include actions that have no public dependents\r\nThe figure was created a few days after the attack, and as such it does not contain the projects that have removed\r\nthe vulnerable actions. This demonstrates that the impact at the time of the attack was even larger.\r\nhttps://unit42.paloaltonetworks.com/github-actions-supply-chain-attack\r\nPage 12 of 28\n\nFigure 8. Actions dependency tree showing where Coinbase depends on tj-actions/changed-files that\r\nappears on the second level.\r\nThe concept of exploiting the GitHub Actions dependency chain was demonstrated in previous research by our\r\nteam.\r\nConclusions and Summary as of March 20, 2025\r\nWhile Coinbase’s response effectively remediated the attack on their own organization, the community has yet to\r\ndetermine whether other organizations were subject to targeted attacks or whether there are additional aspects to\r\nthe full picture of the campaign.\r\nThere remain several open questions, such as:\r\nThe motivations of the attacker who triggered the widespread impact on tj-actions\r\nHow the token for reviewdog/action-setup was leaked\r\nThe reason an initially targeted attack turned into a large-scale and less stealthy campaign\r\nThe reason the attacker printed to logs rather than undertaking more damaging actions\r\nhttps://unit42.paloaltonetworks.com/github-actions-supply-chain-attack\r\nPage 13 of 28\n\nBelow, we provide the full timeline according to our investigations, and the full list of commits that were made by\r\nthe three users that we identified during the research.\r\nWe would like to commend Coinbase on their security practices, and their cooperation regarding our inquiries\r\nduring the course of our research. Coinbase also demonstrated a swift response to the event and implemented\r\nmitigations within a short timeframe.\r\nWe would also like to thank the maintainers of tj-actions and reviewdog for their help in our investigation.\r\nUpdate: April 2, 2025\r\nOn March 18, the maintainer of reviewdog published a security advisory, followed by two clarifications regarding\r\nthe various known parts of the attack thus far. In this update, we share the updated attack path, newly-found IoCs,\r\nand additional names of impacted GitHub organizations and repositories that led to the eventual compromise of tj-actions.\r\nChronologically, this update relates to the prequel to the attack on tj-actions and covers the events that took place\r\nprior to what we have described so far. For ease of reading, please note that the following details represent a\r\ntracing-back process that will eventually help us to explain the complete timeline of this compromise.\r\nReviewdog’s Compromise\r\nWe now know that reviewdog was compromised due to a reviewdog maintainer’s leaked PAT.\r\nFor reference purposes, and in order to keep the maintainer’s identity private, we will refer to the maintainer as\r\nRD_MNTNR (short for reviewdog maintainer) from now on.\r\nAt the time of the attack, RD_MNTNR's PAT had sufficient permissions to push tags to the reviewdog/action-setup repository. This allowed the attacker to override the v1 tag in the repository and point it to the malicious\r\ncommit (b833eecd) that originated in a fork. By doing this, the attacker impacted any consumers of the v1 tag of\r\nthe reviewdog/action-setup repository and everything else revealed in our article up to this point. Having\r\ndiscovered this, we can now ask the following question:\r\nHow did the attackers get RD_MNTNR's PAT?\r\nSpotBugs\r\nWhile RD_MNTNR was an active maintainer in reviewdog, this maintainer was also taking an active part in other\r\nopen-source projects, one of which was spotbugs. According to its description: “SpotBugs is FindBugs' successor.\r\nA tool for static analysis to look for bugs in Java code.” As a Java ecosystem tool, the spotbugs organization\r\nmaintains repositories for maven plugins, sonar and more.\r\nWe now know that RD_MNTNR's PAT was leaked by the attacker from the spotbugs/spotbugs repository. The\r\nattacker pushed a malicious GitHub Actions workflow file to the spotbugs/spotbugs repository, creating a\r\nmalicious workflow run in the context of the repository. The attacker used this malicious workflow to leak all\r\nspotbugs/spotbugs secrets, which included RD_MNTNR's PAT. By reviewing the IoCs and speaking to the\r\nhttps://unit42.paloaltonetworks.com/github-actions-supply-chain-attack\r\nPage 14 of 28\n\nmaintainers of the involved repositories, we estimate that this PAT had access to both spotbugs/spotbugs and\r\nto reviewdog/action-setup.\r\nThe malicious commit and the workflow itself is shown below in Figure 9.\r\nhttps://unit42.paloaltonetworks.com/github-actions-supply-chain-attack\r\nPage 15 of 28\n\nFigure 9. Malicious workflow in spotbugs/spotbugs.\r\nhttps://unit42.paloaltonetworks.com/github-actions-supply-chain-attack\r\nPage 16 of 28\n\nBy examining the workflow, we saw that it reacted to any push to the branch hewrkbwkyk. Once running, the\r\nworkflow stringified all the available secrets, encrypted them with AES (symmetric encryption) and encrypted the\r\nsymmetric key using a hard-coded RSA public key (asymmetric encryption). This ensured that the encrypted\r\nleaked secrets and their encryption key could only be decrypted and read by the attacker. The workflow then\r\ncontinued to upload this data as a workflow artifact, which the attacker could later download.\r\nReturning to the attack flow, as stated above, the attacker was able to push this workflow to the spotbugs/spotbugs\r\nrepository. When browsing to the spotbugs/spotbugs activity log, we saw the IoC shown in Figure 10 below.\r\nFigure 10. spotbugs/spotbugs activity log.\r\nThe branch was created and deleted within one second (2025-03-11T10:52:22 UTC to 2025-03-11T10:52:23\r\nUTC). This triggered a GitHub Actions run for the pushed changes, specifically for the malicious workflow,\r\nleaving barely any traces.\r\nSummarizing this part, we now know that:\r\nRD_MNTNR’s PAT was stored as a secret in spotbugs/spotbugs and it had access to both\r\nspotbugs/spotbugs and reviewdog/action-setup\r\nThe attacker leaked RD_MNTNR’s PAT using a malicious workflow pushed to spotbugs/spotbugs and later\r\nabused it for the reviewdog attack\r\nThe attacker somehow had an account with write permission in spotbugs/spotbugs, which they were able to\r\nuse to push a branch to the repository and access the CI secrets.\r\nThis, then, leads to another question:\r\nhttps://unit42.paloaltonetworks.com/github-actions-supply-chain-attack\r\nPage 17 of 28\n\nHow did the attacker obtain write permission to spotbugs?\r\nJurkaOfAvak\r\nWhen browsing to the commit that the attacker used in order to introduce the malicious workflow to\r\nspotbugs/spotbugs, we discovered that it was created by the user jurkaofavak, which was subsequently deleted.\r\nThis commit is shown in Figure 11.\r\nFigure 11. Commit f5434e in spotbugs/spotbugs.\r\nWhen we looked for other activities performed by this user, we found none. This suggests that jurkaofavak was\r\nanother malicious user that the attacker created in order to perform a specific action. But with that said, we still\r\nhad to understand how jurkaofavak obtained write access to spotbugs/spotbugs.\r\nFurther investigation led us to the following:\r\nThe user jurkaofavak was invited to the spotbugs/spotobugs repository as a member by one of the\r\nspotbugs/spotbugs maintainers\r\nSpecifically, jurkaofavak was added as a member to the spotbugs/spotbugs repository on 2025-03-11T10:50:16\r\nUTC, just two minutes prior to pushing the malicious branch and workflow. We obtained evidence of this\r\ninvitation using internal tools and this was later verified by the spotbugs/spotbugs maintainer.\r\nTo keep this compromised maintainer’s identity private, we refer to them as SPTBGS_MNTNR (short for\r\nspotbugs maintainer) from now on.\r\nAs the details unfold, let’s review our findings:\r\nhttps://unit42.paloaltonetworks.com/github-actions-supply-chain-attack\r\nPage 18 of 28\n\nThe attacker pushed a branch with a malicious workflow into spotbugs/spotbugs by creating a disposable\r\nuser called jurkaofavak\r\njurkaofavak had write permission in spotbugs/spotbugs, as they were a member in that repository\r\nThe attacker somehow obtained the PAT of SPTBGS_MNTNR, which allowed the attacker to invite\r\njurkaofavak to be a member of spotbugs/spotbugs\r\nNow we have yet another question: How did the attacker obtain the PAT of SPTBGS_MNTNR?\r\nThe Initial Leak\r\nOur tracing-back process was now bringing us closer to the initial leak that enabled this entire attack chain.\r\nFollowing our new discoveries, we reached out to SPTBGS_MNTNR. We would like to thank SPTBGS_MNTNR\r\nfor their cooperation and conscientious response to this incident.\r\nIn our communication with SPTBGS_MNTNR, the maintainer filled us in on some additional details:\r\nOn Friday March 21, GitHub Support contacted SPTBGS_MNTNR regarding malicious activity conducted\r\non SPTBGS_MNTNR's behalf\r\nA few hours later, haya14busa (owner of reviewdog) also contacted SPTBGS_MNTNR with a report of\r\nsuspicious activity\r\nGitHub supplied SPTBGS_MNTNR with their audit log from March 11, for further inspection\r\nSPTBGS_MNTNR then immediately rotated all of their tokens and PATs, to revoke and prevent further\r\naccess by the attackers\r\nWhen we looked for suspicious activity associated with the spotbugs organization, we noted that a fork followed\r\nby a pull request, was made to the spotbugs/sonar-findbugs repository by another deleted user: randolzfow. Our\r\ncommunication with SPTBGS_MNTNR confirmed that this indeed was the pull request that was used to leak their\r\nPAT.\r\nSurprise! Pull_request_target\r\nOn 2024-11-28T09:45:13 UTC SPTBGS_MNTNR modified one of the spotbugs/sonar-findbugs workflows to use\r\ntheir own PAT, as they were having technical difficulties in a part of their CI/CD process. This change is shown in\r\nFigure 12.\r\nFigure 12. Modification of a spotbugs/sonar-findbugs workflow to use a PAT.\r\nOn 2024-12-06 02:39:00 UTC, the attacker submitted a malicious pull request to spotbugs/sonar-findbugs, which\r\nexploited a GitHub Actions workflow that used the pull_request_target trigger.\r\nhttps://unit42.paloaltonetworks.com/github-actions-supply-chain-attack\r\nPage 19 of 28\n\nFor those unfamiliar with the risks involved in using the pull_request_target trigger in GitHub Actions, this is a\r\nGitHub Actions workflow trigger that allows workflows running from forks to access secrets, which may lead to a\r\npoisoned pipeline execution attack (PPE).\r\nThe pull request payload modified the repository's mvnw file, which was later used during the CI’s invocation.\r\nWe have confirmed with SPTBGS_MNTNR that the PAT that was used as a secret in this workflow was the same\r\nPAT that later invited jurkaofavak to the spotbugs/spotbugs repository.\r\nThese realizations finally seemed to answer all of the questions that had been cropping up throughout the course\r\nof this chain of events and our investigation. Figure 13 shows the malicious pull request.\r\nFigure 13. Malicious pull request in spotbugs/sonar-findbugs targeting the mvnw file.\r\nAttack Flow Summary\r\nNow that the above was laid out, we could map the full attack from its inception. This is demonstrated visually in\r\nFigure 14.\r\nThe attackers abused a workflow in the spotbugs/sonar-findbugs repository\r\nThis workflow used the pull_request_target trigger to leak the PAT of a spotbugs maintainer\r\nThis PAT also had access to spotbugs/spotbugs\r\nAfter obtaining the spotbugs maintainer’s PAT, the attackers created and invited a disposable, malicious\r\nuser (jurkaofavak) to be a member in the spotbugs/spotbugs repository\r\njurkaofavak pushed a branch with a malicious workflow that triggered a GitHub Actions run and\r\nimmediately deleted the branch\r\nThe malicious workflow invocation in spotbugs/spotbugs leaked the PAT of a reviewdog\r\nmaintainer; in this case, a maintainer of both spotbugs/spotbugs and reviewdog/action-setup\r\nThe leaked PAT had permissions to both of these repositories\r\nThe attacker used the reviewdog maintainer’s stolen PAT to override reviewdog/action-setup’s v1 tag,\r\ncausing it to point to a malicious commit that was done in a fork by the malicious user iLrmKCu86tjwp8\r\nhttps://unit42.paloaltonetworks.com/github-actions-supply-chain-attack\r\nPage 20 of 28\n\nAfter this, tj-actions/changed-files’s CI workflow was invoked\r\nThis workflow uses the tj-actions/eslint-changed-files GitHub action as a pipeline dependency,\r\nwhich in turn depends on and runs the malicious code at reviewdog/action-setup\r\nThe malicious code stole a GitHub token that had write permission to tj-actions/changed-files\r\nUsing this token, the attacker overrode a tag in tj-actions/changed-files, making it point to a malicious\r\ncommit done in a fork by the malicious user mmvojwip, specifically targeting the coinbase/agentkit\r\nrepository\r\nNext, coinbase/agentkit’s CI workflow executed, consuming the malicious tag from tj-actions/changed-files and leaking the credentials to the attacker\r\nCoinbase was alerted by a third-party researcher that its CI was consuming malicious code, and it removed\r\nthe vulnerable workflow\r\nThe attacker overrode all tags in tj-actions/changed-files, making them point to a malicious commit,\r\nresulting in all workflow secrets being printed to the log by consumers of tj-actions/changed-files\r\nFigure 14. Attack flow from start to finish. Icon source: Andrean Prabowo on Flaticon.\r\nFollowups and Open Questions\r\nAs a responsible maintainer of other projects in the open-source community, SPTBGS_MNTNR raised their\r\nconcerns with us regarding the potential for further impact on other projects that they maintain. Although\r\nSPTBGS_MNTNR was not able to detect any further impact caused by their leaked PAT, we continue to\r\ninvestigate SPTBGS_MNTNR’s audit logs. We’re also auditing organizations and repositories that\r\nSPTBGS_MNTNR contributes to, to make sure that the attackers did not achieve further lateral movement\r\ncapabilities.\r\nIn general, the whole attack flow as it unfolds leaves us with some unknowns. For instance, there is a three-month\r\ngap between when the attackers leaked SPTBGS_MNTNR’s PAT and when they abused it.\r\nhttps://unit42.paloaltonetworks.com/github-actions-supply-chain-attack\r\nPage 21 of 28\n\nWe know the attacker specifically targeted Coinbase, and coinbase/agentkit's workflow started using tj-actions/changed-files only on March 7. As such, one possible hypothesis is that the attackers monitored the\r\nprojects dependent on the tj-actions/changed-files and waited for an opportunity to compromise a high-value\r\ntarget.\r\nGiven the attacker's modus operandi of multiple attack stages, stealthy operations and attempts to erase all traces\r\nof malicious activity, we still have a mystery to solve. Having invested months of effort and after achieving so\r\nmuch, why did the attackers print the secrets to logs, and in doing so, also reveal their attack?\r\nWe continue to investigate, and will provide further updates as they become available.\r\nEvents Timeline\r\nThis timeline is based on available information. All times are UTC+0.\r\nDate: November 28, 2024\r\nTime Action\r\n09:45:13 SPTBGS_MNTNR added their own PAT to spotbugs/sonar-findbugs\r\nDate: December 6, 2024\r\nTime Action\r\n02:39:00 The attacker leaks SPTBGS_MNTNR's PAT from spotbugs/sonar-findbugs\r\nDate: March 7, 2025\r\nTime Action\r\n20:04:00\r\nCoinbase maintainer creates a workflow in the coinbase/agentkit repository, which depends on\r\nv39 of tj-actions/changed-files\r\nDate: March 11, 2025\r\nTime Action\r\n17:06:12 Fork of reviewdog/actions-setup by iLrmKCu86tjwp8, setup and preparations\r\n17:21:52 Fork of reviewdog/actions-typos by iLrmKCu86tjwp8, setup and preparations\r\n18:17:20 Last recorded interaction of the user iLrmKCu86tjwp8 with the reviewdog/actions-setup fork\r\n18:17:53  Last recorded interaction of the user iLrmKCu86tjwp8 with the reviewdog/actions-typos fork\r\n18:42:09\r\nPush in reviewdog/actions-setup of the “v1” tag to\r\nb833eecdf13c615cd60d5dede6f6593a4b3b4376 (malicious)\r\nhttps://unit42.paloaltonetworks.com/github-actions-supply-chain-attack\r\nPage 22 of 28\n\n20:31:49\r\nForce push in reviewdog/actions-setup of the “v1” tag to\r\n3f401fe1d58fe77e10d665ab713057375e39b887 (clean)\r\nDate: March 12, 2025\r\nTime Action\r\n15:28:44 Fork of coinbase/onchainkit by 2ft2dKo28UazTZ without any further actions\r\n15:29:04 Fork of coinbase/agentkit by 2ft2dKo28UazTZ, followed by setup and preparations\r\n15:32:02 Fork of coinbase/x402 by 2ft2dKo28UazTZ without any further actions\r\n16:54:44 Fork of tj-actions/changed-files by 2ft2dKo28UazTZ, followed by setup and preparations\r\nDate: March 13, 2025\r\nTime Action\r\n02:08:59 Last recorded interaction with the fork of tj-actions/changed-files by 2ft2dKo28UazTZ\r\n17:55:11 Last interaction with the fork of coinbase/agentkit by 2ft2dKo28UazTZ\r\n20:36:02 Fork of coinbase/agentkit by mmvojwip, followed by setup and preparations\r\nDate: March 14, 2025\r\nTime Action\r\n13:49:00 Last recorded interaction with the fork of coinbase/agentkit by mmvojwip\r\n15:10:00\r\nCoinbase executes a malicious version of tj-actions/changed-files and leaks a token with write\r\npermissions\r\n16:37:00 Coinbase maintainer removes the vulnerable workflow of coinbase/agentkit from the repository\r\n16:57:00 Push event in tj-actions/changed-files, replacing all the tags with malicious commits\r\nIndicators of Compromise\r\nCommits Made by User iLrmKCu86tjwp8:\r\nreviewdog/action-setup\r\n1. https://github.com/reviewdog/action-setup/commit/0f176b316e1d41a945e574fc2ba76b0dc752d585\r\n2. https://github.com/reviewdog/action-setup/commit/96be5a72d8adac89200e08658f69273912fe4783\r\n3. https://github.com/reviewdog/action-setup/commit/61902a2b3c982d3551ad219bb0ff22f3663e44de\r\n4. https://github.com/reviewdog/action-setup/commit/f966d8d897bc8033657b8e77da56a988029ce8c7\r\n5. https://github.com/reviewdog/action-setup/commit/909ace6b17fc4045030e55f5ac27ca99f276ae80\r\nhttps://unit42.paloaltonetworks.com/github-actions-supply-chain-attack\r\nPage 23 of 28\n\n6. https://github.com/reviewdog/action-setup/commit/454c8a19a12cde77505464d7e4549500c8ac68d0\r\n7. https://github.com/reviewdog/action-setup/commit/04d5b6d4c18c06d7df6edabf914d0ded986c3a87\r\n8. https://github.com/reviewdog/action-setup/commit/81796e43b6348d628e3e739a910d50704a5292c1\r\n9. https://github.com/reviewdog/action-setup/commit/8d73381aa1c2ccd12c8ddcfefa47aeb1443e67e3\r\n10. https://github.com/reviewdog/action-setup/commit/c27af8180030e1f3d0434473731f030dc1849edf\r\n11. https://github.com/reviewdog/action-setup/commit/efa6ce46bcaa8751ad223e44be7977798c909304\r\n12. https://github.com/reviewdog/action-setup/commit/143a52c0d919c1a69bdeafeab564650f6939a2b3\r\n13. https://github.com/reviewdog/action-setup/commit/31b1df0e735ad8511fd7df3be8cf9351d8cb4de7\r\nreviewdog/action-typos\r\n1. https://github.com/reviewdog/action-typos/commit/26f36301be817815fbcb896d2c85e89f04b17df4\r\n2. https://github.com/reviewdog/action-typos/commit/9bb460e92befdbb6506d2e643ae06c8b50205f97\r\n3. https://github.com/reviewdog/action-typos/commit/75b5741c6bd9de9815741a40a41844598d409e7b\r\n4. https://github.com/reviewdog/action-typos/commit/f33bbbbf1282af26b285a9a131e0bd43ca355e79\r\n5. https://github.com/reviewdog/action-typos/commit/3a06be07e9c02ee1c5fede46928b6031d8d2383c\r\n6. https://github.com/reviewdog/action-typos/commit/6db74f2d6b0600b8e38cf24b18fda283217e5ffb\r\n7. https://github.com/reviewdog/action-typos/commit/1d10399139bd16e69ed2b7dbfda38735ea1cf324\r\n8. https://github.com/reviewdog/action-typos/commit/3b9482055ba84ea8761eed6b3b9ecf9e79692a55\r\n9. https://github.com/reviewdog/action-typos/commit/6c7b129ed2bbb59ed684c3847a587f4f4e94eaf8\r\n10. https://github.com/reviewdog/action-typos/commit/cb6e155e9dec580de71f0fe89f832d2d9932997b\r\n11. https://github.com/reviewdog/action-typos/commit/eb183376a83bdc6ecfc8168b22ffa6e2b1a9cb6e\r\n12. https://github.com/reviewdog/action-typos/commit/5db6a72f3984e847a2a7d2a25169ca5e849798da\r\n13. https://github.com/reviewdog/action-typos/commit/16c5092f4eb672004001d9bcdc0cf693fb76c1b4\r\n14. https://github.com/reviewdog/action-typos/commit/1368857b9c9a47ba08727409ae9fbdeeba8a590a\r\n15. https://github.com/reviewdog/action-typos/commit/48fbacf68b808429af544d0d7ebd90a5b4cec642\r\nCommits Made by User 2ft2dKo28UazTZ\r\n1. https://github.com/coinbase/agentkit/commit/0723a75a67a1de4b1b1c6cd66a8cab551023fc30\r\n2. https://github.com/coinbase/agentkit/commit/868213ddd4dad8b24a3cb716a6ccc9f89e10d087\r\n3. https://github.com/coinbase/agentkit/commit/8a269616e225e93b8f74d0eb4a86be041a493a76\r\n4. https://github.com/coinbase/agentkit/commit/0723a75a67a1de4b1b1c6cd66a8cab551023fc30\r\n5. https://github.com/coinbase/agentkit/commit/71f4822157821d0998d4a0f8e9e849cdcce9bdd2\r\n6. https://github.com/coinbase/agentkit/commit/18b3e737f9449d94d73fad0bca718ba677676ac7\r\n7. https://github.com/coinbase/agentkit/commit/7a7432e65a8666e4b04695f7c1ef03dfca75ad0b\r\n8. https://github.com/coinbase/agentkit/commit/1ca37970d73ee40c173725de97fc8696aac93aa1\r\n9. https://github.com/coinbase/agentkit/commit/bbbb1c63ceae1e7fb40054bb763f407dc200b37d\r\n10. https://github.com/coinbase/agentkit/commit/2161165ec14fcb9d985970c353e17e84794fd694\r\n11. https://github.com/coinbase/agentkit/commit/823bd75199f474ea7abdbe3a5debf9825c490156\r\n12. https://github.com/coinbase/agentkit/commit/9cefe659a770b8d32ffe5f08f44de6456d9592af\r\n13. https://github.com/coinbase/agentkit/commit/c00af6911bf03512d130462b6b7fe6a286f7ec98\r\nhttps://unit42.paloaltonetworks.com/github-actions-supply-chain-attack\r\nPage 24 of 28\n\nCommits Made by User mmvojwip\r\n1. https://github.com/coinbase/agentkit/commit/8edc60f030035f377780f421431a7ac66828253d\r\n2. https://github.com/coinbase/agentkit/commit/b3a1c722b2aed7fa3e373fb04861826a7a00d0aa\r\n3. https://github.com/coinbase/agentkit/commit/db25249e859d0259011a2f820ec75b5d1047c99b\r\n4. https://github.com/coinbase/agentkit/commit/b39e2d4c31bc786b3a93ea832da887debfee1fc1\r\n5. https://github.com/coinbase/agentkit/commit/a3bbd802082446e36b8976de78a7727e71638e36\r\n6. https://github.com/coinbase/agentkit/commit/faf8d9d8b35369541d38f8d087d71e92cbeadd6b\r\nCommits Made by User jurkaofavak\r\n1. https://github.com/spotbugs/spotbugs/commit/f5434e31b6259b4e08684618a305bae127b6d784\r\nMalicious Pull Request\r\n1. https://github.com/spotbugs/sonar-findbugs/pull/1116\r\nMitigations and Recommended Actions\r\nImmediate Steps for Affected Users\r\nIdentify usage: Search for the tj-actions/changed-files action and other actions mentioned above in your\r\nrepositories to determine whether and where it has been used.\r\nReview workflow logs: Examine past workflow runs for evidence of secret exposure double-encoded in\r\nBase64 text, especially if the logs are public.\r\nRotate secrets: Revoke and regenerate any credentials that may have been exposed. Ensure that all API\r\nkeys, access tokens and deployment credentials are refreshed.\r\nInvestigate malicious activity: If you encounter any signs that the compromised action has been executed,\r\ninvestigate further for any signs of malicious activity.\r\nLong-Term Security Improvements\r\nGovern third-party services in use: Implement vetting procedures to ensure external actions receive\r\napproval before being integrated into workflows.\r\nImplement strict Pipeline-Based Access Controls (PBAC): Reduce the permissions granted to GitHub\r\nActions workflows to the minimum necessary. Use fine-grained and short-lived tokens instead of long-term\r\nand broadly scoped secrets.\r\nPin GitHub actions: Instead of referencing GitHub actions by tag or branch (e.g., @v3 or @main), pin\r\nactions to a full-length commit SHA-1 hash to ensure that the code cannot be changed by a malicious actor.\r\nTo learn more about protecting your Version Control Systems (VCS) and CI/CD systems, we recommend reaching\r\nout to the OWASP Top 10 CI/CD Security Risks project.\r\nThe tj-actions/changed-files compromise underscores the risks inherent in CI/CD pipelines, and those posed by\r\nthird-party dependencies. As adversaries increasingly target these environments to gain quick access to production\r\nhttps://unit42.paloaltonetworks.com/github-actions-supply-chain-attack\r\nPage 25 of 28\n\nassets, organizations must adopt a security-first approach when incorporating external tools into their workflows.\r\nThe likelihood of supply chain attacks can be significantly reduced by implementing strict security measures, such\r\nas:\r\nPinning dependencies\r\nUsing verified actions\r\nAdopting PBAC\r\nTeams must prioritize security and take proactive steps to safeguard their automation pipelines against potential\r\nthreats.\r\nPalo Alto Networks Protections and Mitigations\r\nFor existing customers, Prisma Cloud identifies executables and GitHub actions that are executed in their\r\npipelines. The product identifies tools used by the organization, allowing customers to readily find whether the\r\nvulnerable action is in use, and in which pipelines. Customers can also implement out-of-the-box policies to\r\nprotect against associated risks, as detailed below.\r\nAs customers are upgraded from Prisma Cloud to Cortex Cloud, they can benefit from all existing protections,\r\nenhanced with the ability for users to allow or restrict the usage of tools running in their pipelines, and to track\r\ndeployment of forbidden tools – as shown below in Figure 9.\r\nFigure 9. Identifying all uses of a malicious Github Action in Cortex Cloud.\r\nThrough various out-of-the-box policies designed to identify vulnerable areas within CI/CD environments,\r\ncustomers can help prevent similar future attacks, and reduce the impact of a potential breach.\r\nRelevant Out-of-the-Box CI/CD Policies for Palo Alto Networks Customers\r\nPalo Alto Networks customers should refer to the following policies in their environments, and mitigate the issues\r\nin accordance with the recommendations provided in each policy.\r\nUnpinned GitHub actions: Unpinned GitHub actions are mutable. This allowed the attackers to push a\r\nmalicious version of the tj-actions/changed-files action as an existing tag, thereby introducing poisoned\r\nhttps://unit42.paloaltonetworks.com/github-actions-supply-chain-attack\r\nPage 26 of 28\n\ncode that could be executed in consumers’ pipelines – even if the attacker did not change the tag’s version.\r\nAny consumer using an unpinned version of this action could be vulnerable to this malicious code\r\nexecution, if the compromised version is executed.\r\nUnrestricted usage of GitHub actions allowed in the repository/across the organization: Allowing all\r\nGitHub actions to be used in the repository regardless of their author exposes the organization to the risk of\r\na malicious actor taking control over an action’s repository, as happened in the recent breach. GitHub\r\nallows restricting allowed actions solely to Enterprise actions, preventing the execution of external actions.\r\nExcessive GitHub actions pipeline permissions on the repository: When a pipeline is executed, GitHub\r\ncreates a short-lived GITHUB_TOKEN for interacting with the repository. If permissions granted to the\r\nGITHUB_TOKEN are not defined in the pipeline’s YAML file, the pipeline’s default permissions are set to\r\neither read and write (default setting in older repositories) or read repository contents for all scopes,\r\nwithout considering the specific requirements of the workflow.\r\nAnother security concern is when either read-all or write-all permissions are defined in a pipeline, as this grants\r\nthe GITHUB_TOKEN permissions across all scopes. As the GITHUB_TOKEN was leaked from memory in the\r\nattack, attackers who gained access to a GitHub Actions pipeline with excessive permissions could take full\r\nadvantage and exploit the permissive GITHUB_TOKEN.\r\nGitHub actions access cloud providers using insecure long-term credentials: Long-term credentials\r\nthat are intended for use by GitHub Actions workflows to authenticate to a cloud provider account are\r\nstored on GitHub as a secret. This increases the impact of credential theft, as stolen credentials can be used\r\nlong after a workflow run is complete.\r\nGitHub supports the OpenID Connect (OIDC) authentication protocol to replace long-term credentials with short-lived access tokens. Using OIDC, the GitHub Actions workflow can request a short-lived token directly from the\r\ncloud provider; this token expires automatically when the workflow run ends.\r\nIn addition, OIDC allows more granular control over how secrets can be used. For example, it is possible to filter\r\naccess to tokens when the request originates in specific protected branches or environments.\r\nPalo Alto Networks Offers Comprehensive Protections Against Future Vulnerabilities in Code\r\nCortex Cloud Application Security helps customers build secure apps and stop threats before they emerge. By\r\nunifying code, pipeline, runtime, application context and third-party findings within a single risk, policy and\r\nautomation engine, teams get the visibility and control that they need to prevent issues at the source. Cortex Cloud\r\nApplication Security combines context-aware, AI-based prioritization with a prevention-first approach to\r\nempower teams to accelerate secure deployments. This helps organizations to identify the security gaps in their\r\nenvironments, and to mitigate and reduce the impact of the most significant threats.\r\nIf you think you may have been compromised or have an urgent matter, get in touch with the Unit 42 Incident\r\nResponse team or call:\r\nNorth America: Toll Free: +1 (866) 486-4842 (866.4.UNIT42)\r\nUK: +44.20.3743.3660\r\nEurope and Middle East: +31.20.299.3130\r\nhttps://unit42.paloaltonetworks.com/github-actions-supply-chain-attack\r\nPage 27 of 28\n\nAsia: +65.6983.8730\r\nJapan: +81.50.1790.0200\r\nAustralia: +61.2.4062.7950\r\nIndia: 00080005045107\r\nUpdated March 21, 2025, at 7:25 a.m. PT to clarify language around forking and pull requests. \r\nUpdated March 21, 2025, at 3:05 p.m. PT to add row to timeline table under March 14. \r\nUpdated April 2, 2025, at 12:13 p.m. PT to add substantial update section of new findings and add to the timeline\r\ntable as well as IoCs. \r\nSource: https://unit42.paloaltonetworks.com/github-actions-supply-chain-attack\r\nhttps://unit42.paloaltonetworks.com/github-actions-supply-chain-attack\r\nPage 28 of 28\n\nWhen we inspected actions/changed-files, the behavior it was of the used differently. 2ft2dKo28UazTZ Unlike the user, we saw iLrmKCu86tjwp8 that although it user, 2ft2dKo28UazTZ forked the tj\u0002 was used to\ntest the creation and deletion of git tags. Namely v39 and v47, as shown in Figure 4.\n   Page 7 of 28",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"MITRE"
	],
	"references": [
		"https://unit42.paloaltonetworks.com/github-actions-supply-chain-attack"
	],
	"report_names": [
		"github-actions-supply-chain-attack"
	],
	"threat_actors": [
		{
			"id": "d90307b6-14a9-4d0b-9156-89e453d6eb13",
			"created_at": "2022-10-25T16:07:23.773944Z",
			"updated_at": "2026-04-10T02:00:04.746188Z",
			"deleted_at": null,
			"main_name": "Lead",
			"aliases": [
				"Casper",
				"TG-3279"
			],
			"source_name": "ETDA:Lead",
			"tools": [
				"Agentemis",
				"BleDoor",
				"Cobalt Strike",
				"CobaltStrike",
				"RbDoor",
				"RibDoor",
				"Winnti",
				"cobeacon"
			],
			"source_id": "ETDA",
			"reports": null
		},
		{
			"id": "77b28afd-8187-4917-a453-1d5a279cb5e4",
			"created_at": "2022-10-25T15:50:23.768278Z",
			"updated_at": "2026-04-10T02:00:05.266635Z",
			"deleted_at": null,
			"main_name": "Inception",
			"aliases": [
				"Inception Framework",
				"Cloud Atlas"
			],
			"source_name": "MITRE:Inception",
			"tools": [
				"PowerShower",
				"VBShower",
				"LaZagne"
			],
			"source_id": "MITRE",
			"reports": null
		}
	],
	"ts_created_at": 1775434103,
	"ts_updated_at": 1775791479,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/4e8ff35b2d966ab4971a7465783735f4e8afe462.pdf",
		"text": "https://archive.orkl.eu/4e8ff35b2d966ab4971a7465783735f4e8afe462.txt",
		"img": "https://archive.orkl.eu/4e8ff35b2d966ab4971a7465783735f4e8afe462.jpg"
	}
}