The Impact of the Polyfill Supply Chain Attack
By Kevin Ward
Recently a supply chain attack was discovered for the domain cdn dot polyfill dot io
which was a popular service for the distribution of an open source library polyfill.js
. According to sansec.io, this attack effected over 100,000 sites which involved cdn dot polyfill dot io
injecting malware on mobile devices.
So what happened in the polyfill.io attack?
Polyfill is a service that provides a piece of Javascript code that allows modern functionality on older browsers that do not natively support it. The original authors of the javascript library created the polyfill service to “polyfill makes web development less frustrating by selectively polyfilling just what the browser needs. Use it on your own site, or as a service.”. Reviewing the GitHub repository for the polyfill service, version 0.0.1 was pushed 10 years ago so plenty of time for the service to establish trust with a community of developers.
CAUTION: The GitHub Repository for the polyfill service has been marked as malicious by GitHub and be careful with any links or code hosted within the repository.
In February 2024 a Chinese company, Funnull, bought the domain and GitHub account. The original author made it very clear on X of the change in ownership and stated that the polyfills included in the library are no longer required.
An issue was opened on the GitHub repository discussing the change but it was removed presumably by the new owners in an attempt to maintain trust with its large community. If you are curious, it can still be accessed via the Wayback Machine.
The impact of a Github repo change as part of the attack
The supply chain attack primarily focuses on redirecting users to scam sites and stealing sensitive data. As highlighted by Sansec, it was part of a wider campaign to take control of several domains to spread malware since at least June 2023. The repository and domain takeover occurred months before being detected by security researchers at which point Google, Cloudflare and GitHub began to block or warn users of the malicious content.
Beyond the immediate impact to end users, the attack demonstrates what can happen when a trusted service is taken over by a malicious actor. Domain takeovers are not new. It is relatively simple to acquire a domain that has been left to expire but the interesting idea here is combining this takeover with the GitHub repository. Changes in domain ownership can be found with a WHOIS lookup and can be difficult to track but services exist that monitor changes. GitHub repository owner changes are not as easy to track and are therefore more difficult to detect, especially if the new owner is only using it for legitimacy.
The documentation on GitHub for transferring repositories states:
When you transfer a repository, its issues, pull requests, wiki, stars, and watchers are also transferred. If the transferred repository contains webhooks, services, secrets, or deploy keys, they will remain associated after the transfer is complete. Git information about commits, including contributions, is preserved.
This only applies if the repository is transferred to another user or organisation, not if the account is handed over. If this occurs, unless disclosed, developers and contributors would have no idea of the change in ownership.
The GitHub API can be used to query the repository and attempt to determine who the current owner is but this is dependent on the repository being transferred to another personal account or organisation. The following command can be used to query the repository:
curl -L -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" https://api.github.com/repos/polyfillpolyfill/polyfill-service
{
"id": 21244924,
"node_id": "MDEwOlJlcG9zaXRvcnkyMTI0NDkyNA==",
"name": "polyfill-service",
"full_name": "polyfillpolyfill/polyfill-service",
"private": false,
"owner": {
"login": "polyfillpolyfill",
"id": 160504350,
"node_id": "U_kgDOCZEaHg",
"avatar_url": "https://avatars.githubusercontent.com/u/160504350?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/polyfillpolyfill",
"html_url": "https://github.com/polyfillpolyfill",
"followers_url": "https://api.github.com/users/polyfillpolyfill/followers",
"following_url": "https://api.github.com/users/polyfillpolyfill/following{/other_user}",
"gists_url": "https://api.github.com/users/polyfillpolyfill/gists{/gist_id}",
"starred_url": "https://api.github.com/users/polyfillpolyfill/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/polyfillpolyfill/subscriptions",
"organizations_url": "https://api.github.com/users/polyfillpolyfill/orgs",
"repos_url": "https://api.github.com/users/polyfillpolyfill/repos",
"events_url": "https://api.github.com/users/polyfillpolyfill/events{/privacy}",
"received_events_url": "https://api.github.com/users/polyfillpolyfill/received_events",
"type": "User",
"site_admin": false
},
"html_url": "https://github.com/polyfillpolyfill/polyfill-service",
"description": "Automatic polyfill service.",
...
}
Although this is useful, it will need to be continually monitored to ensure that the ownership has not been transferred. The GitHub API does not automatically provide a notification of changes in ownership and therefore every repository you use needs to be queried as part of your supply chain. This is not a scalable solution for the majority of development teams and there is a limit to the number of requests that can be made to the GitHub API (with and without authentication).
How can you protect your supply chain?
Supply chain security often focuses on what software dependencies are being used and ensuring that they are up to date to prevent vulnerabilities being exploited. Although this is important, it would not have prevented this attack as the polyfill service was intentionally changed to be malicious. The repository could have had security validation checks in place to check for malicious code (e.g. Semgrep, CodeQL) but in the case of polyfill, no malicious code was placed in the repository.
NOTE: the information from security scans is normally not available to consumers of the code and as soon as repository ownership changes, the checks can be removed.
The fundamental issue is trust. The polyfill service was trusted by a large community of developers due to the time it had been in operation, how well the community of developers pushed changes and resolved issues and the fact that it was open source. The owner or owners of a repository must have the freedom to transfer ownership at any time as it is provided in goodwill to the community. In this instance the decision was made to handover the GitHub account instead of transferring it to another personal account or organisation which makes it far more difficult to determine if the repository is still trustworthy.
But what if the repository was transferred as per the GitHub documentation? Consumers still need to monitor the repository for changes and ensure that the new owner is trustworthy. If the consumers were only using the polyfill domain service, the only indication of a change would be WHOIS information. In order to effectively monitor repositories for changes, automated tools must be used and changes be reviewed.
The OpenSSF Scorecard provides a score for the repository settings, a useful indicator if the repo is following best practices but useless for monitoring ownership changes.. The only potential indicator is a change in a signing key used for releases (more on this later).
One tool which does look at the trust of the open source packages is Trusty. According to the website:
Trusty provides a Trusty Score based on statistical analysis of public GitHub package data. This rating system establishes a benchmark for average levels of package activity and is based on individual scores for repo and author activity.
Unfortunately in this case, there are no indicators of malicious activity in the repository, only the promotion of a malicious domain. The Trusty score was originally 7.1 and returned with “Trusty’s security analysis checks did not discover any potential supply chain attacks.”.
Subsequently, I reached out to the Stacklok team and they acknowledged that the Trusty should reflect the recent changes to the polyfill service. Now if you query polyfill service on Trusty it returns a score of 0 and “Trusty’s security analysis has identified potential supply chain attacks. Review is recommended. Please view details for further information”.
Thanks to the Stacklok team for such a fast response to my query and for updating Trusty.
It is clear now that account takeovers of repositories are difficult to detect. One option for detecting an attack is analysing all previous repository activity such as approvals for pull requests or resolution of issues for language used, author cadences and then comparing it with the current activity log. This type of semantic analysis however only provides a statistical likelihood of a change in behaviour and requires a large amount of data to be effective.
What can you do as a Producer?
It is too easy to blame the owners of the polyfill service for the attack and we should remember that open source software is licensed under terms and conditions such as:
Licensor provides the Work (and each Contributor provides its Contributions) on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND.
The original authors disclosed the changing of ownership in the best way they thought possible and from the research conducted it does not violate any of GitHub’s terms of service. An argument could be made that it violates the GitHub Acceptable Use Policy for Impersonation but if the email account is provided alongside the GitHub account, it is technically not impersonation.
A better solution would have been to transfer the repository to another personal account or organisation. This would likely cause a breaking change for developers and also increased the awareness of change in ownership. A change in account ownership would also allow tools like Trusty to reset the trust score and require the new owner to demonstrate that they can be trusted over time. It does not solve the issue of the polyfill dot io
domain change of ownership but referencing a malicious domain in the repository is a violation of GitHub’s terms of service, specifically GitHub Active Malware and Exploits.
I strongly recommend adopting current best practices for open-source software such as signing releases that are normally built off an identity, which indicates that the key used to sign the release is tied to an email address. For the polyfill service, it is unknown whether the email address associated with the account was handed over to the new owners or whether they associated a new email address. I suspect another email address was added to the account which would mean that the signing key would have to be updated (if it was not handed over with the repository). Checking the signature of the release could have indicated a change in ownership but currently it is not a common practice for the majority of producers and consumers of open source software.
The lesson learned from this attack is, that there needs to be a better disclosure process when a service is changing ownership. For a GitHub repository, this can be a notification to consumers during a clone or fork of the repository. But for how long does that notification need to be displayed? And are consumers paying attention to it?
Conclusion
The Polyfill supply chain attack highlights the issues with trust in open source software and what approaches can be taken to mitigate the risk. The attack was not due to a vulnerability in the software but a change in ownership of the repository and domain. At ControlPlane we educate and support our clients in understanding supply chain risks when adopting open source software and advise on various threat actor techniques. At a recent project with Citigroup, ControlPlane delivered a highly scalable and secure-by-default Open Source Ingestion platform that not only secures the software supply chain but also facilitates pre-usage vulnerability assessments. Learn more about how Citigroup continuously secures ingestion for OSS Software Packages.