Safeguard
Software Supply Chain•

How do you publish to crates.io without a long-lived token?

Use short-lived OIDC credentials from CI instead of stored crates.io tokens, and scope and expire any token you keep. Here is the model and the checks.

Safeguard Security Team
4 min read

The safest way to publish a Rust crate is to let your CI system prove who it is and receive a short-lived credential, instead of storing a crates.io API token as a secret. Where that is not possible, use a scoped token that expires, keep it out of plain-text files, and rotate it.

Why are stored publish tokens a problem?

A crates.io API token is a bearer secret. Whoever holds it can publish. The Rust RFC that proposes trusted publishing lists the flaws plainly: tokens could have no expiration (as of September 2024 the default became 90 days), and they can be used from any source without restriction, so a token copied from a leaked CI log works from anywhere.

Think of the blast radius. A crate with a few thousand dependents is a path into every one of their builds. A stolen token turns one careless log line into a release.

What is trusted publishing?

The RFC describes it as short-lived access tokens granted through OpenID Connect (OIDC) to authenticate actions against the crates.io APIs, with no manually configured API token. A trusted CI system, GitHub Actions first, asserts its identity, and crates.io hands back a token valid for less than an hour.

The idea follows what other package registries did earlier and aligns with the OpenSSF principles for package repository security. The RFC says GitHub Actions comes first, with other CI systems to follow. The RFC is a design document, so read the current crates.io documentation to confirm what is live for your CI system before you change a pipeline.

What if you still need a token?

Plenty of teams publish from a laptop or a CI system without OIDC support. Then treat the token as a hazard:

  • Create it with the narrowest scope the registry offers, ideally limited to publishing a named crate.
  • Give it an expiry. A forgotten token with no end date is the exact failure the RFC describes.
  • Do not let Cargo keep it in plain text. The Cargo book notes that the cargo:token provider stores credentials unencrypted in the credentials file, and recommends configuring a global credential provider list that uses your operating system's secure store, such as the macOS Keychain or libsecret on Linux.
  • In CI, inject it only into the publish step, not the whole job.

A constructed example

Say a crate called acme-parse publishes from a workflow triggered by any tag push. A contributor opens a pull request that edits the workflow to print the environment. If the token sits in a repository secret available to that run, it is now in a log. If instead the registry only accepts an OIDC identity bound to one repository, one workflow file and one protected environment, the same edit yields nothing reusable, because the credential dies within the hour and is minted only for the approved workflow.

How to check or apply this

  1. List every place a crates.io token lives today: CI secrets, developer machines, password managers, old runner images.
  2. Read the crates.io documentation for the trusted publishing setup that matches your CI provider.
  3. Restrict the publishing workflow to tags on a protected branch and require a reviewed environment for the publish job.
  4. For tokens you keep, set a scope and an expiry, and put a calendar entry on the expiry.
  5. Configure Cargo credential providers so no token sits in plain text on disk.
  6. After each release, confirm the published version matches the tag you built.

Publishing is only half the chain. The other half is what you consume. Safeguard can scan a project's dependency inventory, and the free in-browser scan at gold.safeguard.sh/scan covers up to 100 dependencies.

Quick check

Does trusted publishing remove the need for any secret?

For the publish step, that is the goal: the CI system proves its identity and receives a token that lasts under an hour, so there is no long-lived secret to leak. Other secrets in your pipeline still need care.

Is a default 90 day token expiry good enough?

It is better than none, but a leaked token is still usable from any source for up to 90 days. Short-lived OIDC credentials narrow that window to under an hour.

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.