GitHub Secrets provide a secure way to store sensitive values that are needed by GitHub Actions workflows. Examples include API keys, passwords, access tokens, and deployment credentials.
GitHub Secrets are encrypted values that can be used by GitHub Actions workflows without placing the sensitive value directly in the workflow file.
Secret
↓
GitHub
↓
Workflow
↓
Application / Command
Secrets help keep sensitive credentials separate from normal project source code.
API_KEY
DATABASE_PASSWORD
DEPLOY_TOKEN
ACCESS_TOKEN
SECRET_KEY
These types of values should normally be handled carefully and should not be committed as plain text into a repository.
| Secret | Normal Variable |
|---|---|
| Used for sensitive values | Used for normal configuration |
| Should be protected | Can often be visible in workflow configuration |
| Example: API token | Example: application name |
Repository administrators can add secrets through the repository's GitHub settings.
Repository
↓
Settings
↓
Secrets and variables
↓
Actions
↓
New repository secret
The exact interface can change, but the purpose is to store a sensitive value securely for workflows.
A secret has a name that is used to reference it from a workflow.
API_KEY
Use clear and meaningful names for secrets so that workflow configuration remains understandable.
The secret value is the sensitive information associated with the secret name.
Name:
API_KEY
Value:
your-sensitive-api-key
The actual sensitive value should not be placed directly in the workflow source code.
A GitHub Actions workflow can reference a secret using the
secrets context.
${{ secrets.API_KEY }}
Here, API_KEY is the name of the stored secret.
A secret can be provided to a workflow step through an environment variable.
steps:
- name: Run Application
run: npm start
env:
API_KEY: ${{ secrets.API_KEY }}
The application can then read the environment variable according to its programming language.
steps:
- name: Run Migration
run: php migrate.php
env:
DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
The workflow can provide the password to the command without writing the password directly into the workflow file.
Repository secrets are associated with a particular repository and can be used by workflows in that repository when permitted.
Repository
↓
Repository Secret
↓
Workflow
↓
Job / Step
Organizations can manage secrets that can be made available to selected repositories according to the organization's configuration.
Organization
↓
Organization Secret
↓
Selected Repositories
↓
Workflows
This can be useful when multiple repositories need access to the same type of sensitive configuration.
GitHub environments can also have secrets associated with them. This can help separate values used for different environments.
Development
↓
Development Secret
Production
↓
Production Secret
This is useful when deployment environments require different credentials.
Development
DB_PASSWORD = Development Value
Production
DB_PASSWORD = Production Value
Using separate environment-specific values helps prevent accidentally using the wrong credentials in a deployment environment.
Workflows triggered by pull requests can have restrictions around access to secrets, especially when code comes from outside the repository.
Pull Request
↓
Workflow
↓
Security Rules
↓
Secret Access
This is important because untrusted code should not automatically receive access to sensitive credentials.
When workflows are triggered from forked repositories, secret access is restricted to help protect the secrets of the original repository.
Original Repository
↓
Secret
↓
Forked Code
↓
Restricted Secret Access
Always consider the security implications of running untrusted code in workflows.
GitHub attempts to prevent recognized secret values from being displayed directly in workflow logs.
Secret:
my-secret-value
Log:
***
However, masking should not be treated as permission to intentionally print secrets in logs.
A workflow should not intentionally print sensitive values.
# Avoid
- run: echo "${{ secrets.API_KEY }}"
Even when GitHub provides masking, exposing secrets unnecessarily is a poor security practice.
Never place real passwords or API keys directly in source code.
// Bad practice
const API_KEY = "real-secret-key";
Instead, use environment variables or a suitable secret-management solution.
Do not write real credentials directly into workflow YAML files.
# Bad
env:
API_KEY: "real-secret-value"
Use the GitHub Secrets context instead:
env:
API_KEY: ${{ secrets.API_KEY }}
steps:
- name: Deploy
run: ./deploy.sh
env:
DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
The deployment script can read the environment variable without the token being written directly into the workflow configuration.
name: API Test
on:
workflow_dispatch:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run API Test
run: python test_api.py
env:
API_KEY: ${{ secrets.API_KEY }}
The API key is supplied to the step through an environment variable.
Credentials should be replaced or rotated according to the security requirements of the service using them.
Old Secret
↓
Replace / Rotate
↓
New Secret
↓
Update GitHub Secret
↓
Workflow Uses New Value
If a sensitive credential is accidentally exposed, do not simply remove it from the visible file and assume the problem is solved.
name: Deploy
on:
workflow_dispatch:
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deploy Application
run: ./deploy.sh
env:
DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
The deployment token is supplied to the deployment step through the secret context.
Create Secret
↓
Store in GitHub
↓
Workflow Starts
↓
Secret Referenced
↓
Environment Variable
↓
Command / Action
↓
Application Uses Credential
↓
Secret Not Stored in Source Code
secrets context.
GitHub Secrets provide a secure mechanism for storing sensitive
values used by GitHub Actions workflows. They can be referenced
through the secrets context and passed to workflow steps
when required.
Secret
↓
GitHub
↓
Workflow
↓
Environment Variable
↓
Application / Deployment
↓
Secure Automation
Using secrets correctly helps prevent passwords, API keys, tokens, and other sensitive credentials from being stored directly in workflow files or application source code.
${{ secrets.NAME }}.Question: What is the main purpose of GitHub Secrets?