How to Share Secrets in GitHub Actions Without HashiCorp Vault

By

CI pipelines need temporary credentials all the time. A deploy key that should only live for one run. A token passed between two repos during a migration. A credential rotated in one workflow and consumed in another.

The standard advice is "use a secrets manager." But spinning up HashiCorp Vault or configuring AWS Secrets Manager just to hand off a single credential between workflows is like renting a warehouse to mail a letter.

GitHub repo secrets handle the static case well — long-lived API keys, deploy tokens, service account credentials. But they fall short for anything temporary or dynamic.

The gap: temporary secret sharing in CI/CD

Repo secrets are designed for values that change infrequently and are consumed by a single repository. They don't cover:

  • One-time handoffs during key rotation — You rotate a credential in one workflow and need another workflow (or team) to pick up the new value exactly once.
  • Cross-repo credential sharing — Two repos need to exchange a short-lived token, but neither should store it permanently.
  • Time-limited contractor access — A CI token that should expire after a contractor's deploy window closes.
  • Knowing when a secret was consumed — Repo secrets provide no visibility into whether or when a value was read.

These are temporary problems that need a temporary solution.

A lighter approach: encrypted self-destructing links

The Vaulted GitHub Action lets you create and retrieve encrypted, self-destructing secrets directly from your workflows — no infrastructure to manage.

Creating a secret:

- name: Share rotated credential
  id: share
  uses: vaulted-fyi/share-secret@v1
  with:
    secret: ${{ steps.rotate.outputs.new_token }}
    views: 1
    expires: 1h

The step outputs a URL containing the encrypted secret. The encryption key lives in the URL fragment, so it never touches Vaulted's servers.

Retrieving a secret:

- name: Get shared credential
  id: get
  uses: vaulted-fyi/share-secret/get@v1
  with:
    url: ${{ needs.rotate.outputs.secret_url }}

- name: Deploy with rotated credential
  run: ./deploy.sh
  env:
    API_TOKEN: ${{ steps.get.outputs.secret }}

After retrieval, the link is consumed and the server-side ciphertext is deleted. The secret exists only in the runner's memory for the duration of that job.

Security model

Three properties make this safe for CI/CD use:

  1. Zero-knowledge encryption. The secret is encrypted with AES-256-GCM inside the GitHub runner before it leaves the process. The encryption key is embedded in the URL fragment, which is never sent to the server. Vaulted only stores ciphertext it cannot decrypt.

  2. Automatic log masking. The action calls core.setSecret before core.setOutput, registering every line of the secret value with GitHub's log masker. Multi-line secrets are masked per-line, so even partial matches are redacted from workflow logs.

  3. Self-destructing links. View limits and time-based expiry are enforced server-side. A secret created with views: 1 and expires: 1h is permanently deleted after the first retrieval or after one hour — whichever comes first.

When to use this vs. a secrets manager

| Scenario | Secrets manager | Vaulted Action | |---|---|---| | Long-lived production credentials | Yes | No | | App runtime config (DB URLs, API keys) | Yes | No | | One-time credential handoff between workflows | Overkill | Yes | | Temporary cross-repo token sharing | Overkill | Yes | | Time-limited contractor CI access | Overkill | Yes | | Post-rotation credential distribution | Overkill | Yes |

Secrets managers are the right tool for secrets that applications consume at runtime. Vaulted is for the handoff — the moment a credential moves from one place to another and should not persist.

Getting started

Add the action to any workflow:

- uses: vaulted-fyi/share-secret@v1
  with:
    secret: ${{ secrets.TEMP_CREDENTIAL }}
    views: 1
    expires: 1h

Find it on the GitHub Marketplace. Secrets created by the action are compatible with the web app and the CLI — anything created in one can be retrieved from another.


No Vault server. No IAM policies. No infrastructure. Just encrypted links that self-destruct.