← Blog

API Key Management on GitHub: Do It Right

2026-09-17 · 5 min read · SubToAPI Team

API Key Management on GitHub: Do It Right

If you're searching for "api key management github," you're probably trying to solve one of two problems: how to store API keys safely so they don't end up in a public repo, or how to pass them securely into GitHub Actions workflows without hardcoding them. Both problems have the same root cause — API keys are just strings, and strings get copy-pasted into places they shouldn't be.

This article covers the practical mechanics: where keys should live, how GitHub's built-in tools help, what to do when a key leaks anyway, and how to structure key management so it scales past a single repo.

Where API Keys Should Never Live

Before talking about the right way, it's worth being explicit about the wrong way, because it's the most common mistake:

Private repos are not a safe place for secrets. Access control changes, forks happen, collaborators come and go, and git history keeps everything forever unless you rewrite it. Treat every repo — public or private — as if its full history could eventually be read by someone who shouldn't have your keys.

Local Development: .gitignore and .env

The baseline setup for any project:

# .gitignore
.env
.env.local
*.key
# .env (never committed)
ANTHROPIC_API_KEY=sk-ant-...
SUBTOAPI_KEY=sub_live_...

Load it with whatever your stack supports (dotenv in Node, python-dotenv in Python, etc.). Commit a .env.example with placeholder values so teammates know what variables are needed:

# .env.example
ANTHROPIC_API_KEY=
SUBTOAPI_KEY=

This is the minimum bar. It doesn't protect against someone accidentally running git add -A and force-adding a gitignored file, so it's not sufficient on its own for teams — but it's necessary everywhere.

GitHub Actions Secrets

For CI/CD, keys need to be available to workflows without appearing in workflow files or logs. GitHub Actions has built-in encrypted secrets for exactly this:

  1. Go to your repo → Settings → Secrets and variables → Actions
  2. Add a repository secret, e.g. SUBTOAPI_KEY
  3. Reference it in your workflow via ${{ secrets.SUBTOAPI_KEY }}
name: run-tests
on: [push]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Run integration tests
        env:
          SUBTOAPI_KEY: ${{ secrets.SUBTOAPI_KEY }}
        run: npm test

A few details that matter:

GitHub Secret Scanning

GitHub scans public repos (and private repos on paid plans with the feature enabled) for known secret patterns — AWS keys, Stripe keys, common API key formats — and alerts you or the provider automatically. For private repos, enable it under Settings → Code security and analysis → Secret scanning. It won't catch every custom key format, but it's a free safety net worth turning on everywhere.

Push protection goes a step further and blocks the push itself if a recognized secret pattern is detected, before it ever reaches the remote history. This is the single highest-leverage setting most repos are missing.

What to Do When a Key Leaks

It will happen eventually. When it does:

  1. Revoke the key immediately at the provider, not just in the codebase. Removing it from a file doesn't invalidate it — the string is still valid until the issuer revokes it.
  2. Rotate to a new key and update it everywhere it's used (local .env, CI secrets, deployed environments).
  3. Don't rely on git filter-branch or force-pushing history rewrite as your fix — treat the key as compromised regardless of what you do to history, since it may have already been cloned, cached, or scraped.
  4. Check usage logs for the leaked key if the provider exposes them, to see if it was actually used before revocation.

This is exactly why keys should be trivial to rotate. If rotating a key means editing code and redeploying, you'll be slow to react to a leak. If it means updating one dashboard entry, you'll do it in minutes.

Separate Concerns: Provider Keys vs. Application Keys

A pattern that scales better than sharing one raw provider key across every repo and environment: keep your underlying provider credential (Anthropic key, cloud key, whatever) in one place, and issue separate scoped application keys for each service, environment, or team that needs access.

This is where a layer like SubToAPI fits for teams using Claude across multiple projects. Instead of distributing your Anthropic account credentials into every repo's CI secrets, you generate sub_live_... keys per application from the SubToAPI dashboard, each independently revocable, with its own usage metadata. If one repo's key leaks, you revoke that key alone — nothing else is affected, and your underlying Claude access never touched that repo's secrets in the first place. See /docs/quickstart for setup and /pricing for plan details.

curl https://api.subtoapi.app/v1/messages \
  -H "Authorization: Bearer $SUBTOAPI_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-3-5-sonnet-20241022",
    "max_tokens": 512,
    "messages": [{"role": "user", "content": "Summarize this PR diff."}]
  }'

A Practical Checklist

Questions

Does deleting a file with an API key from git history make it safe? No. Even after rewriting history with tools like git filter-repo, assume the key was already exposed to anyone who cloned, forked, or cached the repo. Revoke and rotate the key — history rewriting is cleanup, not remediation.

Are GitHub Actions secrets visible in logs? GitHub automatically masks secret values that appear verbatim in logs, but transformed, encoded, or partially printed versions can slip through. Avoid printing secrets in any form, even for debugging.

Should private repos handle API keys differently than public ones? Not fundamentally — use the same gitignore, secrets, and scanning practices. Private repos reduce exposure but don't eliminate risk from collaborator turnover, forks, or misconfigured visibility settings.

Turn your Claude access into an HTTPS API

SubToAPI gives you application API keys, streaming, tool use and usage insights on top of your existing Claude access — set up in minutes.

Start free  Read the quickstart →