What’s the recommended way to store secrets in GitHub Actions? #187776
Replies: 7 comments
-
|
The recommended and safest way to store sensitive information in GitHub Actions is by using GitHub Secrets. You should never store API keys, passwords, or tokens directly in your repository (even in private repos), since they can be exposed through commits, forks, logs, or pull requests. Instead, use one of the following:
Best practices:
Using GitHub’s built-in encrypted secrets system is the standard and recommended approach for handling sensitive data in GitHub Actions. |
Beta Was this translation helpful? Give feedback.
-
|
The recommended way to store secrets in GitHub Actions is to use GitHub Secrets — never hard-code credentials in your repo. Best Practice: Use GitHub Secrets Types of secrets Path : Environment secrets Organization secrets How to add a secret Go to Settings → Secrets and variables → Actions |
Beta Was this translation helpful? Give feedback.
-
|
Yeah, as the others mentioned, anything related to private and confidential variables that are only used in GitHub Actions needs to be stored in GitHub Actions secrets and variables.
|
Beta Was this translation helpful? Give feedback.
-
|
The recommended and safest way to store sensitive information in GitHub workflows is by using GitHub Actions Secrets. Sensitive data such as API keys, passwords, and access tokens should never be stored directly in a repository, even if the repository is private. This information can be exposed through commit history, forks, logs, or pull requests, which may lead to security risks. Instead, GitHub provides secure and encrypted mechanisms for storing confidential data: 1. Repository Secrets: 2. Organization Secrets: 3. Environment Secrets: Best Practices:
In conclusion, GitHub’s built-in encrypted secrets system provides a secure and standardized approach for managing sensitive information in GitHub Actions workflows and helps prevent unauthorized access or data exposure. |
Beta Was this translation helpful? Give feedback.
-
|
Store secrets in GitHub repository or organization settings under Secrets. In workflows, reference them using |
Beta Was this translation helpful? Give feedback.
-
|
The industry standard and GitHub-recommended approach is to use Encrypted Secrets. You should never hardcode sensitive data like API keys or passwords in your workflow files or repository. Storage Levels: |
Beta Was this translation helpful? Give feedback.
-
|
The replies above cover GitHub Secrets basics well. Here are the advanced patterns that matter for production workflows. 1. Use Environments for deployment secretsDon't put production secrets at the repository level. Use GitHub Environments — they add approval gates and scope secrets to specific workflows: jobs:
deploy-prod:
environment: production # requires approval + uses production-only secrets
runs-on: ubuntu-latest
steps:
- name: Deploy
run: ./deploy.sh
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }} # only exists in "production" environmentSet up at: Settings → Environments → New environment → Add required reviewers This means a PR workflow can't accidentally access production database credentials — only the deploy job that targets the 2. Use OIDC instead of static secrets for cloud providersThis is the biggest improvement most teams miss. Instead of storing AWS/GCP/Azure access keys as secrets, use OpenID Connect (OIDC) federation — GitHub Actions gets temporary credentials directly from your cloud provider with zero stored secrets: jobs:
deploy:
permissions:
id-token: write # required for OIDC
contents: read
runs-on: ubuntu-latest
steps:
- uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/github-actions-deploy
aws-region: us-east-1
# No access keys needed — OIDC handles itOn the AWS side, create an IAM role that trusts GitHub's OIDC provider: {
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
},
"StringLike": {
"token.actions.githubusercontent.com:sub": "repo:your-org/your-repo:ref:refs/heads/main"
}
}
}]
}Benefits:
Works with AWS, GCP, Azure, and HashiCorp Vault. 3. Prevent secret leaks in workflow logsGitHub automatically masks secrets in logs, but it only masks the exact value. If your workflow transforms the secret (base64 encodes it, URL-encodes it, etc.), the masked version is exposed: # DANGEROUS — transformed secret is not masked
- run: echo "${{ secrets.API_KEY }}" | base64
# SAFE — register the transformed value as a mask
- run: |
ENCODED=$(echo "${{ secrets.API_KEY }}" | base64)
echo "::add-mask::$ENCODED"
echo "ENCODED_KEY=$ENCODED" >> $GITHUB_ENVAlso, never dump environment variables: # NEVER do this — exposes all secrets
- run: env
- run: printenv4. Pull secrets from external vaults at runtimeFor teams with many secrets or strict compliance requirements, pull from an external secrets manager directly in your workflow: # Using HashiCorp Vault
- name: Import secrets from Vault
uses: hashicorp/vault-action@v3
with:
url: https://vault.yourcompany.com
method: jwt
role: github-actions
secrets: |
secret/data/production/db DATABASE_URL ;
secret/data/production/api STRIPE_KEY ;
# Using AWS Secrets Manager
- name: Get secrets from AWS
uses: aws-actions/aws-secretsmanager-get-secrets@v2
with:
secret-ids: |
prod/database
prod/api-keys
parse-json-secrets: true5. Audit who accesses secretsGitHub provides an audit log for secret access in organization settings. You can also add a workflow step that logs (without revealing) which secrets are being used: - name: Verify required secrets are available
run: |
if [ -z "${{ secrets.DATABASE_URL }}" ]; then
echo "::error::DATABASE_URL secret is not configured"
exit 1
fi
echo "All required secrets are available"Quick reference
|
Beta Was this translation helpful? Give feedback.


Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Where should I safely store sensitive information (like API keys, passwords, tokens) so they are not exposed in my code when using GitHub Actions?
Beta Was this translation helpful? Give feedback.
All reactions