Skip to main content

Managing Secrets and Security

1. Storing Secrets in Contexts

Property Description Usage
context.name Name of the context Used to reference the context in configuration
context.secrets Map of secret names to values Accessed via CIRCLECI_CONTEXT_SECRET

Example: Defining a Context with Secrets

version: 2.1
contexts:
  my-context:
    secrets:
      api_key:
        description: "API key for external service"
      database_url:
        description: "Database connection string"

Example: Using Context Secrets in a Job

version: 2.1
jobs:
  build:
    docker:
      - image: circleci/node:16
    environment:
      DB_URL: <value from context>
    steps:
      - run:
          name: Use Secret
          command: |
            echo "Using API key: $API_KEY"
Note: Contexts are scoped to the project and can be shared across multiple workflows and jobs.
Warning: Never hardcode secrets in configuration files or commit them to version control.

2. Using Project Environment Variables

Variable Type Description Usage
CIRCLECI boolean Indicates if the build is running on CircleCI if [[ "$CIRCLECI" == "true" ]]; then echo "Running on CircleCI"; fi
CIRCLE_PROJECT_REPONAME string Name of the repository echo "Repository: $CIRCLE_PROJECT_REPONAME"
CIRCLE_BUILD_NUM number Build number echo "Build Number: $CIRCLE_BUILD_NUM"
CIRCLE_SHA1 string Git commit SHA echo "Commit: $CIRCLE_SHA1"
CIRCLE_BRANCH string Branch name echo "Branch: $CIRCLE_BRANCH"
CIRCLE_TAG string Tag name if build is from a tag echo "Tag: $CIRCLE_TAG"

Example: Using Environment Variables in a Script

#!/bin/bash
echo "Build Number: $CIRCLE_BUILD_NUM"
echo "Repository: $CIRCLE_PROJECT_REPONAME"
echo "Branch: $CIRCLE_BRANCH"
Note: Environment variables set in the CircleCI project settings are automatically available to all jobs in that project.

3. Masking Secrets in Logs

CircleCI automatically masks secrets in build logs to prevent sensitive information from being exposed. This masking is applied to environment variables and other configuration values that match specific patterns.

Secret Pattern Masking Behavior Notes
CIRCLE_TOKEN ******** API token used for CircleCI API access
AWS_ACCESS_KEY_ID ******** Amazon Web Services access key ID
AWS_SECRET_ACCESS_KEY ******** Amazon Web Services secret access key
GCP_SERVICE_ACCOUNT_KEY ******** Google Cloud Platform service account key
SLACK_WEBHOOK_URL ******** Slack incoming webhook URL

Example: Environment Variable Usage

export AWS_SECRET_ACCESS_KEY="secret-key-value"
echo "Using AWS secret: $AWS_SECRET_ACCESS_KEY"

In the build log, the value will be masked as:

Using AWS secret: ********
Note: The masking is applied only to environment variables and configuration values that match predefined patterns. Custom secrets must be handled carefully to avoid exposure in logs.

4. Avoiding Hardcoded Secrets

Approach Description Best Practice
Environment Variables Store secrets as environment variables in CircleCI project settings. Use env in config to access them.
CircleCI Contexts Group related environment variables into contexts for reuse across jobs. Securely manage shared secrets with context in config.
Encrypted Files Store sensitive files (e.g., SSH keys) as encrypted artifacts. Use circleci encrypt to encrypt and store securely.

Example: Using Environment Variables

version: 2.1
jobs:
  build:
    steps:
      - run:
          command: |
            echo "API Key is: $API_KEY"
Note: Never commit secrets to version control or expose them in logs.
Warning: Hardcoded secrets in config files will be visible to anyone with access to the repository.

Key Takeaways

  • Never hardcode secrets in config.yml.
  • Use CircleCI's project settings to store secrets.
  • Utilize contexts for managing shared secrets across jobs.

5. Rotating Credentials Regularly

Credential Type Rotation Method Notes
API Tokens Generate new token via CircleCI UI or CLI Old tokens remain valid until explicitly revoked
SSH Keys Regenerate key pair and update CircleCI project settings Update deployment configurations to use new private key
Environment Variables Update via CircleCI dashboard or API Ensure all jobs referencing the variable are updated

Example: Rotating an API Token

circleci api-token rotate --token-id <old-token-id>
Note: Rotate credentials at least every 90 days or when a security incident occurs.
Warning: Never hardcode credentials in your configuration files or job scripts.

6. Implementing Least Privilege

Example: Setting up a job with minimal permissions

version: 2.1
jobs:
  build:
    docker:
      - image: circleci/node:16
    steps:
      - checkout
      - run:
          name: Run tests
          command: npm test
      - run:
          name: Deploy to staging
          command: npm run deploy-staging
Permission Level Description Use Case
Read-Only Allows reading configuration and job details Monitoring or CI status checks
Read-Write Allows reading and modifying jobs, workflows CI/CD pipeline configuration changes
Admin Full access to all project resources and settings Project owner or administrator tasks

Best Practices for Least Privilege

  • Assign the minimum level of access required for each role or user
  • Use environment variables for sensitive data instead of hardcoding secrets
  • Regularly review and audit permissions to ensure they are still necessary
  • Implement role-based access control (RBAC) for better management of permissions

7. Using OIDC Tokens

Property Description Value
oidc.token Token used for authentication with external services string
oidc.issuer URL of the OpenID Connect provider https://circleci.com/oidc
oidc.audience Intended recipient of the token circleci

Example: Using OIDC Token in a Job

jobs:
  deploy:
    docker:
      - image: circleci/python:3.9
    steps:
      - run:
          name: Deploy with OIDC Token
          command: |
            curl -H "Authorization: Bearer $OIDC_TOKEN" \
                 https://api.circleci.com/deploy
Note: OIDC tokens are valid for 1 hour and must be refreshed before expiration.
Warning: Never expose OIDC tokens in logs or public repositories.

8. Restricting Context Access

Option Values Notes
context.name my-context Name of the context to be created or modified
context.description Production environment variables Description for the context (optional)
context.variables { "API_KEY": "secret-key" } Key-value pairs of environment variables
context.projects [ "org/project1", "org/project2" ] List of projects that can access this context

Example: Creating a Context with Restricted Access

version: 2.1
contexts:
  production-context:
    description: "Context for production secrets"
    variables:
      API_KEY: "secret-key"
      DATABASE_URL: "postgres://user:pass@host/db"
    projects:
      - "my-org/my-app"
      - "my-org/another-app"
Note: Contexts are scoped to the organization and can be shared across projects. Ensure that only necessary projects have access.
Warning: Never store sensitive data in plain text within configuration files. Use CircleCI's encrypted context variables or environment variables.

9. Managing SSH Keys Securely

Property Description Usage
circleci ssh key add Adds an SSH key to your CircleCI project circleci ssh key add <project-slug> <key-path>
circleci ssh key list Lists all SSH keys configured for a project circleci ssh key list <project-slug>
circleci ssh key remove Removes an SSH key from a project circleci ssh key remove <project-slug> <key-id>
Note: SSH keys must be added to the project's settings in CircleCI to allow secure access to external systems during builds.
Warning: Never store SSH keys in plain text within your configuration files or environment variables. Always use CircleCI's encrypted environment variables or project settings.

10. Auditing Secret Usage

Field Description Example
secret.name Name of the secret as configured in CircleCI API_KEY
secret.value Value of the secret (masked in logs) **********
project.name Name of the project using the secret myapp/prod
build.number Build number where secret was used 1234
job.name Name of the job using the secret deploy-to-prod
timestamp Time when secret was accessed 2026-01-15T10:30:00Z

Example: Secret Usage Audit Log

{
  "secret.name": "API_KEY",
  "project.name": "myapp/prod",
  "build.number": 1234,
  "job.name": "deploy-to-prod",
  "timestamp": "2026-01-15T10:30:00Z"
}
Note: CircleCI logs all secret usage in the build output, but values are masked. You can audit these logs to track which secrets were accessed and by which jobs.
Warning: Ensure that secrets are not logged or printed in build steps, even if masked. Use circleci env to inspect environment variables safely.

Was this article helpful?