Safeguard
Software Supply Chain•

Can you publish to Packagist with provenance?

Packagist builds versions from your repository tags, so provenance starts at your repo. Learn what that means, the hook token risk and what to check.

Safeguard Security Team
4 min read

Packagist does not take an uploaded package. It reads your public repository and creates versions from your tags, so provenance for a Composer package starts with who controls that repository and its tags. We found no attestation feature on the Packagist pages we fetched, so the controls below are about the repository and the hook.

How does a package reach Packagist?

According to the Packagist site, it is the default Composer repository: it lets you find packages and tells Composer where to get the code from. You submit a repository URL. New versions are fetched from tags you create in your VCS repository, and version numbers come from the tag and branch names, such as 1.0.0 or v1.0.0 with an optional pre-release suffix. Branches become development versions.

Updates arrive in two ways. Without a hook, existing packages are crawled once a week. With a GitHub, Bitbucket, GitLab or Gitea hook, Packagist crawls whenever you push, and at least once a month in case a crawl failed. Maintainers can also trigger a manual update.

The consequence for provenance: there is no separate artifact that you sign and upload. The tag in your repository is the release. Whoever can push a tag, or take over the repository, can publish.

What does Composer record for consumers?

Composer's basic usage guide says the lock file enables reproducible builds, and that installs use the lock rather than the newest versions. Composer downloads a dist archive by default, and can install from source with an option. Composer's reference also lists audit and policy settings, including blocking packages with security advisories, abandoned packages, and a cooldown period that withholds versions published within a set time such as 7 days. A cooldown gives the community time to spot a bad release before your build takes it.

Composer verifies its own phar updates with signatures from getcomposer.org. That is about Composer itself, not packages from Packagist, and the pages we fetched did not describe signed package attestations.

Where does the webhook token fit?

Packagist's setup steps for Bitbucket show a URL that contains your username and API token, and its GitLab and Gitea steps ask you to enter the same token. That token lets a caller trigger package updates for your account. Treat it as a credential: store it only in the hook configuration, rotate it if the repository settings are ever exposed, and do not paste the full hook URL into tickets or chat.

Constructed example: a maintainer pastes a webhook URL with the API token into a support thread. A stranger who copies it cannot publish new code, but can trigger crawls and may use the token for other account API calls. Rotating the token ends that exposure.

What to do to get strong provenance anyway

  1. Protect your default branch and your tag namespace with repository rules, so only a small set of people can create release tags.
  2. Require two-factor authentication on the code host accounts that can push tags, and on your Packagist account where the option is offered.
  3. Sign release tags and publish the signing key identity in your security policy, so consumers can verify.
  4. Use the code host's build attestation for any release archives you also publish, and say so in the README.
  5. Set up the push hook, so Packagist matches your repository promptly.
  6. Rotate the Packagist API token on a schedule and after any exposure.
  7. As a consumer, commit the lock file, run the audit command in CI, and consider a cooldown period for new versions.
  8. Review changes to composer.json scripts and plugins, because they run code at install time.

Safeguard dependency scanning and Gold open source package lookups can help consumers check what a Packagist package pulls in, and its policy gates can block installs that fail your rules. The free scan at gold.safeguard.sh/scan covers up to 100 dependencies in the browser.

Quick check

Is there a Packagist upload step I can sign?

Not on the pages we fetched. Packagist builds versions from your repository tags, so protect the repository and tags.

Does a committed composer.lock stop a bad new release?

It stops automatic upgrades. The bad version only arrives when someone updates, so review lock diffs and consider a cooldown.

Sources

Last reviewed: 18 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.