Laravel Badge

Guide

Securing Your Packagist Account as a Package Developer

By Peter Fox

The Laravel-Lang supply chain attack in May 2026 didn't start with a clever exploit or a zero-day vulnerability. It started with a leaked GitHub Personal Access Token.

If you maintain a package on Packagist, your account credentials are all that stands between an attacker and every application that installs your code. This guide covers what that means in practice and the specific steps you should take today.

For context on the broader supply chain picture and how to audit your GitHub organisation's security posture, see Securing Your Laravel Packages with Laravel Moat.


How account compromise leads to supply chain attacks

Packagist doesn't host your code directly. It reads metadata from GitHub (or Bitbucket, GitLab, etc.) and tells Composer where to fetch each version. When Composer installs a package, it follows that pointer.

The attack surface is split across two accounts:

  • Your Packagist account controls which repositories are registered, who co-maintains them, and webhook configuration.
  • Your GitHub account controls the actual code and tags that Packagist points at.

In the Laravel-Lang attack, the entry point was a GitHub PAT with write access to the organisation. The attacker rewrote git tags across four packages to point at malicious forks. Packagist saw no change in repository URL or version number. It trusted the tags completely.

This is why Packagist is rolling out significant supply chain security updates, including stable version immutability, a public transparency log, and eventually mandatory MFA ecosystem-wide. Platform-level protections only go so far, though. What happens to your account is still your responsibility.


Enable MFA on your Packagist account

This is the most important thing you can do, and Packagist is about to make it visible.

MFA on Packagist isn't currently mandatory, but that's changing. The platform will soon surface MFA status on maintainer profiles and in its transparency logs, making it publicly visible which maintainers are protected and which aren't. Mandatory MFA ecosystem-wide is on the roadmap.

Enable it now: open the dropdown under your username and go to Two-Factor Authentication, then follow the setup flow to register an authenticator app (TOTP).

If your Packagist account is breached without MFA, an attacker can remove co-maintainers, add their own account, modify webhook URLs, or transfer package ownership. None of those actions require GitHub access.


Know your two API tokens

Packagist gives you two API tokens, both accessible from your profile dropdown, and the distinction matters.

The main API token has full access: package creation, editing, and updates. Treat it like a password. It should never appear in a GitHub repository, a webhook URL, or anywhere it could be exposed.

The safe API token is limited to package update triggers, telling Packagist to re-crawl a repository. This is the token to use for GitHub webhooks. Packagist's own documentation describes it as "not very sensitive if leaked" because even if someone obtains it, they can only trigger a metadata refresh and nothing more destructive.

If you currently have your main API token in a GitHub webhook, swap it for the safe token.

Packagist provides a Rotate API Tokens button that regenerates both tokens in one click. It's worth doing this periodically as routine hygiene. If you ever suspect your main token has been compromised, rotating it immediately expires the stolen one and cuts off the attacker.


MFA beyond Packagist

Your Packagist account doesn't operate in a vacuum. Your GitHub account controls the code and tags Packagist points at, and both accounts rely on email for password resets. If either of those is compromised, Packagist MFA won't help.

Make sure MFA is also enabled on your GitHub account, and enforced at the organisation level if you maintain packages under a GitHub org. Do the same for the email accounts linked to both services. Covering all three removes the most obvious routes in for an attacker who can't get through Packagist directly.


What Packagist is doing for you

The Packagist supply chain security update introduces several platform-level protections in direct response to recent attacks:

Stable version immutability: Released stable versions can no longer be silently rewritten. If a tag pointing to a given version changes, Packagist will flag it. This directly closes the attack vector used in the Laravel-Lang incident.

Transparency log: Security-relevant events (ownership changes, version modifications, MFA status changes) are now recorded in a public log. This is what allowed the Laravel-Lang investigation to reconstruct the attack timeline quickly.

Aikido malware detection: Package metadata flowing through Packagist is scanned for indicators of malicious code. Suspicious versions are flagged automatically before they reach Composer users.

Composer 2.10 unified dependency policy: A unified framework for dependency security constraints is now available as part of the Composer 2.10 release.

Coming soon: Minimum release age/cooldown policies, mandatory MFA, FIDO2-backed staged release workflows, and direct hosting of immutable build artifacts with SLSA provenance.

These protections are being built around you, but they don't replace account security. Immutability doesn't help if an attacker adds themselves as a co-maintainer through your compromised Packagist account. Transparency logs detect attacks after they happen.


The reality of being a target

Packagist packages are valuable targets because of the trust Composer places in your composer.json. When your package is installed, it runs code on the machines of everyone who depends on it, potentially hundreds or thousands of applications.

The Laravel-Lang packages were not obscure. They were well-maintained, widely trusted, and had been around for years. None of that stopped the attack. What stopped further spread was Packagist's ability to delist the packages within hours of notification.

The platform is getting better. But a compromised account can cause damage in minutes that takes days to recover from.