# Secrets

> Store tokens and passwords for a repository's workflows on its spindle, and how they reach your workflows.

A repository secret is a named value, such as an API token, that your workflows can read but that never appears in the repository. Secrets are stored on the repository’s spindle.

## Adding a secret

1. Open the repository’s **Settings → Pipelines**. A spindle must be selected.
2. Under **Secrets**, select **Add secret**.
3. Enter a **Name** (for example `CLOUDFLARE_API_TOKEN`) and a **Value**, then select **Add**.

The list shows each secret’s name, when it was added, and by whom. Values are never shown again; to change one, delete it and add it again. In fact, there is no API to read the value of a secret, these are only exposed to each workflow at execution time. Delete removes it from the spindle immediately.

Names can be 1 to 50 characters. Values can be up to 4096 characters. Use names that are valid shell variable names, since that’s how steps read them.

## Using a secret in a step

Every secret is automatically set as an environment variable in every step of every workflow in the repository. So adding a secret with the name `CLOUDFLARE_API_TOKEN` will make that environment variable available to all steps in the workflow:

```yaml
steps:
  - name: Deploy
    command: pnpm exec wrangler deploy # reads $CLOUDFLARE_API_TOKEN
```

Any workflow that runs for the repository gets all of the configured secrets.

## Masking

The spindle replaces secret values with `***` in stored and streamed logs. It also masks the base64 encoding of each value and each line of a multi-line value. Masking is a safety net, not a guarantee and anyone who can run a workflow can read the secrets.

## Visibility of secrets

* **Managing** secrets needs settings access to the repository on the spindle: the repository owner and collaborators.
* **Using** secrets only needs a run. Anyone who can push a branch or tag that matches a workflow can make a step print or send them somewhere. Treat push access as secret access.
* **Untrusted runs get no secrets.** The spindle withholds secrets, caches and OIDC tokens from every run whose code isn’t a branch of this repository: manual runs of a fork, pull requests from forks or patches, and any pull request run a collaborator had to approve, retries included. Approving a run lets it run untrusted, nothing more.
* **The spindle operator** can read secrets. They’re stored in the spindle’s database, or in OpenBao if the operator configured it.

> **Note**
>
> Secrets live on one spindle and are non-transferrable. If you switch from one spindle to another, you will need to add secrets again there.

## Avoiding long-lived secrets

For cloud providers that accept OpenID Connect, set [`audience`](/docs/spindles/workflows/#audience) in the workflow instead of storing a key. The spindle mints a short-lived token per run as `TANGLED_ID_TOKEN`, masked like a secret. This needs the spindle operator to have enabled OIDC.