Managing Secrets: Securing Your CI/CD Pipelines
Learn how to use GitHub Secrets to store sensitive tokens and API keys, ensuring your CI/CD pipelines remain secure and free from hardcoded credentials.

Previously in this course, we covered Building Images in CI. Now that your pipeline can build container images, you likely need a way to push those images to a registry or interact with external services. We cannot hardcode passwords or API keys directly into our YAML files, as that would expose them to anyone with repository access. In this lesson, we will solve this by implementing GitHub Secrets.
The Danger of Hardcoded Credentials
When you need to authenticate with a cloud provider or a package registry, the naive approach is to paste your credentials directly into your workflow file. This is a critical security failure. Once a secret is committed to Git, it is part of the repository history forever, even if you delete the line in a later commit.
GitHub Secrets provides an encrypted key-value store tied to your repository. When you add a secret, GitHub encrypts it at rest. When your workflow runs, GitHub decrypts the value and injects it into the runner’s memory, masking the value in the logs so it never accidentally leaks to the console.
Creating a Repository Secret
Before a workflow can use a secret, it must exist in the GitHub UI. Follow these steps:
- Navigate to your repository on GitHub.
- Click the Settings tab.
- In the left sidebar, expand Secrets and variables and click Actions.
- Click New repository secret.
- Give it a name (e.g.,
DOCKERHUB_TOKEN) and paste your actual secret value into the Secret field. - Click Add secret.
Once created, this value is invisible in the UI. You cannot read it back; you can only update or delete it.
Accessing Secrets in Your Workflow
To use the secret, you must map it to an environment variable within your workflow file. You do this using the env context. It is important to remember that GitHub Secrets are not automatically available to your shell; you must explicitly define them.
Here is an example of a workflow step that consumes a secret:
YAMLjobs: build-and-push: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Login to Docker Hub run: echo "$DOCKER_PASSWORD" | docker login -u myuser --password-stdin env: DOCKER_PASSWORD: ${{ secrets.DOCKERHUB_TOKEN }}
In this snippet, we map the GitHub Secret DOCKERHUB_TOKEN to the local environment variable DOCKER_PASSWORD. The run command then uses that variable. Because the value is stored in an environment variable, it remains hidden from the log output.
Hands-on Exercise
- Create a dummy secret: Go to your repository settings and create a secret named
MY_API_KEYwith the valuesuper-secret-123. - Update your workflow: Create a new test step in your existing pipeline that echoes this secret.
- Verify the mask: Run the workflow and inspect the logs for that step. You should see
***instead ofsuper-secret-123. - Failure test: Try to print the secret without mapping it to an environment variable. Observe that the shell cannot find the variable, confirming the secret is not globally available by default.
Common Pitfalls
- Assuming global scope: Secrets are not available as system-wide environment variables. If you don't map them using the
envkeyword in your job or step, they simply won't exist in your shell environment. - Logging the secret: While GitHub automatically masks the secret value, if you accidentally transform it (e.g.,
echo $SECRET | base64), the mask might fail, and the value could appear in your logs. Always avoid manipulating secrets in ways that might bypass masking. - Case sensitivity: Remember that secret names are case-sensitive. If you define
DOCKER_TOKENin settings, callingsecrets.docker_tokenin your YAML will return an empty string.
FAQ
Can I use secrets in other repositories? By default, secrets are scoped to the repository where they are created. To share them across multiple projects, you should look into Organization Secrets or GitHub Environments.
What if I need to use the secret in multiple steps?
You can define the env block at the job level instead of the step level. This makes the environment variable available to every step within that job.
Is it safe to use secrets for non-sensitive data? It is better to use Environment Variables for configuration that isn't secret. Secrets should be reserved for credentials that, if leaked, would compromise your security.
Recap
GitHub Secrets are the primary mechanism for securing your CI/CD pipelines. By creating them in your repository settings and mapping them to env variables, you ensure your credentials remain private while still being accessible to your automated processes.
Up next: Handling Environment Variables — we will learn how to organize your non-sensitive configuration for better maintainability.
Work with me

CI/CD Pipeline & Docker Containerization
Ship with confidence: automated CI/CD pipelines and Docker setups so every push is tested and deployed — no more manual, error-prone releases.

AI Automation & Agentic Workflow Development
Automate the repetitive work eating your time — content pipelines, data workflows, and agentic AI tasks that run themselves.

