> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pipefort.com/llms.txt
> Use this file to discover all available pages before exploring further.

# CICD-SEC-2 — Package published with a long-lived token instead of OIDC

> Publishing with a standing registry token where OIDC trusted publishing is available.

| Field      | Value                                                                                                                                                                    |
| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Category   | `CICD-SEC-2`                                                                                                                                                             |
| Severity   | **MEDIUM**                                                                                                                                                               |
| Confidence | HIGH                                                                                                                                                                     |
| OWASP      | [CICD-SEC-2: Inadequate Identity and Access Management](https://owasp.org/www-project-top-10-ci-cd-security-risks/CICD-SEC-02-Inadequate-Identity-And-Access-Management) |
| Auto-fix   | ✗                                                                                                                                                                        |

## What the check does

Flags a publishing step that authenticates to a package registry with a
long-lived token where the registry supports **OIDC trusted publishing**:

* PyPI via `pypa/gh-action-pypi-publish` with a `password:` input
* `npm publish` with `NODE_AUTH_TOKEN`
* `cargo publish` with `CARGO_REGISTRY_TOKEN`
* `gem push` with `GEM_HOST_API_KEY`

## Why it matters

A long-lived registry token is a standing secret: if it leaks (a poisoned
dependency, a log spill, a compromised runner) an attacker can publish malicious
package versions until someone notices and rotates it. OIDC trusted publishing
replaces the standing token with a short-lived credential minted per run and
scoped to the specific workflow, so there is no durable secret to steal.

```yaml theme={null}
- uses: pypa/gh-action-pypi-publish@<sha>
  with:
    password: ${{ secrets.PYPI_TOKEN }}   # ← standing secret
```

## Safe alternative

Configure trusted publishing on the registry and drop the token. For PyPI:

```yaml theme={null}
permissions:
  id-token: write            # ← OIDC token for this run
steps:
  - uses: pypa/gh-action-pypi-publish@<sha>   # no password: needed
```

See [PyPI trusted publishers](https://docs.pypi.org/trusted-publishers/) and
the equivalent OIDC flows for npm, crates.io, and RubyGems.
