Skip to content
Latchkey

How to Avoid Caching Secrets on Self-Hosted Runners

Caches and artifacts persist across jobs, so any secret written into them can be restored later by an unrelated job.

Never let credentials land in a cached directory (~/.npmrc, ~/.docker/config.json, .env). Exclude secret paths from caches and clean them up before the cache save step.

Steps

  • Cache only rebuildable stores (package dirs), never credential files.
  • Write auth tokens to a temp path outside the cached directory.
  • Remove any credential file before the cache save step runs.

Keep credentials out of the cache

.github/workflows/ci.yml
steps:
  - uses: actions/cache@v4
    with:
      path: ~/.npm            # package store only
      key: npm-${{ hashFiles('package-lock.json') }}
  - run: |
      echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > "$RUNNER_TEMP/.npmrc"
      npm ci --userconfig "$RUNNER_TEMP/.npmrc"
      rm -f "$RUNNER_TEMP/.npmrc"

Gotchas

  • A .npmrc with an auth token inside a cached folder leaks to every cache hit.
  • Uploaded artifacts are downloadable by anyone with repo read; never put secrets in them.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →