Use when publishing Rust crates to crates.io or managing crate repositories. Provides supply chain attack countermeasures including crates.io token management, CI/CD publishing pipelines, and pre-publish security checklists. Adapted from Shai-Hulud npm attack lessons.
This skill provides guidelines for securely publishing and maintaining Rust crates on crates.io, adapted from the Shai-Hulud supply chain attacks. While crates.io has different mechanics than npm, the same principles of token management, CI/CD security, and access control apply.
Apply these guidelines when:
| Aspect | npm | crates.io |
|---|---|---|
| Publish | npm publish | cargo publish |
| Auth | npm token | crates.io API token |
| 2FA |
| Supported |
| NOT yet supported (as of 2025) |
| Unpublish | Within 72 hours | Yank only (code remains available) |
| Provenance | npm provenance (OIDC) | Not yet available |
| Build scripts | preinstall/postinstall | build.rs included in package |
| Immutability | Mutable (can unpublish + republish) | Immutable (yank does not delete) |
crates.io does NOT support 2FA for publishing. This makes token security even more critical than npm.
# Create a scoped token (RECOMMENDED)
cargo login -- --token-type scoped --scope publish:<crate-name>
# Or via crates.io web UI:
# Account Settings -> API Tokens -> New Token
# Set scope to specific crates only
| Rule | Implementation |
|---|---|
| Scope to specific crates | Never use tokens with access to all crates |
| Set expiration | 90 days maximum |
| Use CI-specific tokens | Separate tokens for CI and local development |
| Store in secrets manager | Never in files, env vars in CI only |
| Rotate regularly | At least every 90 days |
| Location | Safe? | Notes |
|---|---|---|
~/.cargo/credentials.toml | RISKY | Shai-Hulud-style malware targets credential files |
| CI/CD secrets | YES | Encrypted, scoped, auditable |
| Environment variable in CI | YES | Ephemeral, per-job |
# Ensure credentials.toml has restricted permissions
chmod 600 ~/.cargo/credentials.toml
# Verify no credentials in project directory
test -f .cargo/credentials.toml && echo "WARNING: credentials in project directory!"
# Preview what files will be published
cargo package --list
# Check package size
cargo package --no-verify
ls -la target/package/*.crate
Verify:
.env files includedbuild.rs does not contain suspicious codeUse include (allowlist) rather than exclude (denylist):
[package]
# GOOD: allowlist approach (more secure)
include = [
"src/**/*",
"Cargo.toml",
"LICENSE",
"README.md",
]
# AVOID: denylist approach (easy to miss files)
# exclude = [".env", "secrets/"]
# If your crate has build.rs, verify it before publishing:
# - No network access
# - No credential reading
# - No unnecessary file system access
# - No Command::new with user-controlled input
# Check for vulnerabilities
cargo audit
# Run cargo-deny policy check
cargo deny check
# Verify lockfile
cargo build --locked