Safeguard
Supply Chain•

crates.io trusted publishing: publish by hand once, then use OIDC

How crates.io trusted publishing replaces a stored API token with a short-lived one from GitHub Actions, and the first-release step people miss.

Safeguard Security Team
3 min read

crates.io trusted publishing lets a GitHub repository you name request a short-lived API token through OpenID Connect, so CI no longer holds a long-lived token. You publish the first release manually, then configure the trusted repository for later releases. It works with GitHub Actions only for now.

What changes compared with a token

The classic route is to create a token at crates.io/settings/tokens, run cargo login, and store the same token as a CI secret. Cargo's docs call that token a secret and say to revoke it at once if it leaks. It is shown only once, and it stays valid until you revoke it.

With trusted publishing, no secret is stored. The workflow asks GitHub for an identity token, exchanges it on crates.io for a short-lived API token, and uses that for cargo publish. The Rust project describes the design in RFC 3691 and announced the feature in its July 2025 crates.io development update.

The first release is manual

The announcement is explicit: publish your first release manually, then set up trusted publishing for later ones. That means a new crate still needs one token based publish. Plan for it: create a token with the narrowest scope that works, publish, then revoke it.

A minimal workflow shape

The announcement's sample runs on version tags, grants id-token: write, uses the rust-lang/crates-io-auth-action step to get a token, then passes that token to cargo publish. Check the current crates.io trusted publishing docs for exact inputs and versions before copying.

Habits that carry over from other registries:

  • grant id-token: write to the publish job only,
  • use a GitHub environment with required reviewers for the publish job,
  • run cargo publish --dry-run earlier in the pipeline, which packages and compiles from the extracted .crate file without uploading.

Remember that publishing is permanent

Cargo's reference states that a version can never be overwritten or deleted. Yanking stops new dependencies from resolving to a version but deletes no code, and it does not remove secrets that were uploaded by accident. So the review step before the tag matters more than any cleanup afterwards. See cargo yank does not remove bad crates.

Quick check

Can I use trusted publishing for a brand new crate?

Not for the very first release. The Rust announcement says to publish the first release manually, then set up trusted publishing.

Does it work with GitLab CI today?

The announcement says it currently works only with GitHub Actions, with room for other providers later.

Sources

Last reviewed: 19 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.