# Secure Claude API Keys in CI/CD Pipelines with GitHub Actions
## Why Secure API Keys Matter for Claude Integrations
In today's fast-paced DevOps world, CI/CD pipelines power automated deployments, testing, and AI-assisted workflows. When integrating Anthropic's Claude API—whether for code generation with Claude Code CLI, agentic systems, or MCP servers—your API key is the gateway to powerful models like Opus, Sonnet, or Haiku. But exposing it in repo files, logs, or untrusted environments risks account compromise, quota exhaustion, or worse.
GitHub Actions offers robust secrets management, but misconfiguration can still lead to leaks. This guide walks you through secure practices: from GitHub Secrets to OIDC federation alternatives, with Claude-specific examples. By the end, you'll deploy Claude-powered workflows confidently.
**Key Risks to Avoid:**
- Hardcoding keys in YAML or scripts (visible in repo history).
- Echoing secrets to logs during debugging.
- Using long-lived keys in public repos.
- Insufficient RBAC on workflows.
## Prerequisites
Before diving in:
- A GitHub account and repository (public or private).
- An Anthropic account with a Claude API key (generate at [console.anthropic.com](https://console.anthropic.com/settings/keys)).
- Basic YAML knowledge.
- Node.js or Python installed locally for testing (optional).
We'll use a sample repo that calls the Claude API via the official Node.js SDK to summarize code changes—a common CI task for PR reviews.
## Step 1: Store Your Claude API Key as a GitHub Secret
Never commit API keys to your repo. Use GitHub Secrets instead.
1. Go to your repo → **Settings** → **Secrets and variables** → **Actions**.
2. Click **New repository secret**.
3. Name it `CLAUDE_API_KEY` (uppercase for convention).
4. Paste your API key value.
5. Save.
 *(Replace with actual image if publishing)*
**Pro Tip:** For org-level secrets, use **Organization secrets**. Rotate keys quarterly via Anthropic console.
## Step 2: Create a Basic GitHub Actions Workflow
Create `.github/workflows/claude-ci.yml` in your repo:
```yaml
name: Claude API Secure CI
on:
pull_request:
branches: [main]
jobs:
summarize-pr:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: npm ci
- name: Securely call Claude API
env:
CLAUDE_API_KEY: ${{ secrets.CLAUDE_API_KEY }}
run: node summarize-pr.js
```
This workflow triggers on PRs to `main`, checks out code, sets up Node.js, and runs a script using the injected secret.
## Step 3: Inject Secrets Securely in Your Script
Create `summarize-pr.js` for a Claude-powered PR summary:
```javascript
const Anthropic = require('@anthropic-ai/sdk');
const { contextLineNumbers } = require('@actions/github/lib/utils');
const anthropic = new Anthropic({
apiKey: process.env.CLAUDE_API_KEY,
});
async function summarizePR() {
const response = await anthropic.messages.create({
model: 'claude-3-5-sonnet-20240620',
max_tokens: 1000,
messages: [{
role: 'user',
content: 'Summarize these code changes concisely: ' + process.argv[2],
}],
});
console.log('Claude Summary:', response.content[0].text);
}
summarizePR();
```
Install SDK: `npm init -y && npm i @anthropic-ai/sdk @actions/github`.
Run locally: `CLAUDE_API_KEY=yourkey node summarize-pr.js "diff text"`.
In the workflow, `${{ secrets.CLAUDE_API_KEY }}` expands only at runtime—never logged or visible in YAML.
**Security Check:** GitHub masks secrets in logs. Avoid `echo $CLAUDE_API_KEY`—it's redacted but risky.
## Step 4: Enhance with Permissions and Environment Protection
Limit workflow access:
```yaml
permissions:
contents: read # Minimal for checkout
pull-requests: write # For comments
id-token: write # For OIDC (advanced)
```
Protect branches:
```yaml
on:
pull_request:
branches: [main]
# Require approvals for protected branches
```
Repo Settings → **Actions** → **General** → Require approval for first-time contributors.
## Step 5: Advanced - Rotate Secrets and Use OIDC
For production, avoid static secrets. Anthropic supports short-lived tokens, but pair with GitHub OIDC:
1. Enable OIDC in GitHub (default for new repos).
2. While Anthropic doesn't natively federate, use it with a proxy like AWS IAM Roles Anywhere or a custom Vault integration.
**Example: Dynamic Token with AWS Secrets Manager (Claude-Compatible)**
```yaml
- name: Assume AWS Role via OIDC
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123:role/GitHubClaude
aws-region: us-east-1
- name: Fetch Claude Key from Secrets Manager
run: |
CLAUDE_API_KEY=$(aws secretsmanager get-secret-value --secret-id claude-key --query SecretString --output text)
echo "CLAUDE_API_KEY=$CLAUDE_API_KEY" >> $GITHUB_ENV
env:
AWS_REGION: us-east-1
```
Store key in AWS SSM/Secrets Manager, fetch just-in-time.
**Claude Code CLI Integration:**
For Claude Code (Anthropic's AI dev CLI):
```yaml
- name: Install Claude Code
run: |
curl -sSL https://github.com/anthropic/claude-code/releases/latest/download/claude-code_linux_amd64.tar.gz | tar xz
sudo mv claude-code /usr/local/bin/
- name: Run Claude Code with Secure Key
env:
ANTHROPIC_API_KEY: ${{ secrets.CLAUDE_API_KEY }}
run: claude-code generate --prompt "Review this PR"
```
*(Note: Verify latest install method from Anthropic docs.)*
## Best Practices for Claude in CI/CD
- **Least Privilege:** Use project-specific API keys with rate limits.
- **Secret Scanning:** Enable GitHub Advanced Security or Trivy.
- **Audit Logs:** Monitor Anthropic console for anomalous usage.
- **Multi-Factor Rotation:** Automate key rotation with GitHub API + Anthropic SDK.
- **Alternatives:** For agents/MCP, use ephemeral sessions.
- **Testing:** Use Haiku for CI (cheaper, faster).
**Common Pitfalls:**
- Forgetting `permissions: { id-token: write }` for OIDC.
- Self-hosted runners: Secure them separately.
- Forked PRs: Secrets unavailable—use `github.event.pull_request.head.sha` safely.
## Example: Full Workflow for Claude Agent Testing
Deploy a simple Claude agent in CI:
```yaml
name: Test Claude Agent
on: [push]
jobs:
agent-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with: { python-version: '3.12' }
- run: pip install anthropic
- name: Test Agent
env:
ANTHROPIC_API_KEY: ${{ secrets.CLAUDE_API_KEY }}
run: |
python -c "
import anthropic
client = anthropic.Anthropic()
resp = client.messages.create(model='claude-3-haiku-20240307', max_tokens=100, messages=[{'role':'user', 'content':'Hello Claude!'}])
print(resp.content[0].text)
"
```
## Monitoring and Compliance
- Integrate with Slack/Zapier: Notify on failures.
- Use n8n for post-deployment Claude analysis.
- For enterprise: Anthropic's SOC2 compliance + GitHub Enterprise.
## Conclusion
Securing Claude API keys in GitHub Actions unlocks safe, scalable AI automation. Start with Secrets, graduate to OIDC/dynamic fetching. Fork this guide's examples, adapt for your stack—Claude Code, MCP, or custom agents.
**Next Steps:**
- Rotate your keys now.
- Check [Anthropic Docs](https://docs.anthropic.com) for SDK updates.
- Share your workflows in comments!
*Word count: ~1450. Questions? Contact Claude Directory.*