Skip to content

GitHub Actions Secrets

GitHub Actions secrets targets allow you to securely store secrets in GitHub for use in CI/CD workflows. Secrets can be stored at repository, environment, or organization levels, providing flexible access control for different deployment scenarios.

Overview

GitHub Actions provides three types of secrets:

  • Repository Secrets - Available to all workflows in a repository
  • Environment Secrets - Scoped to specific deployment environments (production, staging, etc.)
  • Organization Secrets - Shared across multiple repositories in an organization

SecretZero integrates with GitHub's API to automatically create and update these secrets, handling encryption transparently using GitHub's public key infrastructure.

Secret Retrieval Limitation

GitHub's API does not allow retrieving secret values for security reasons. Once a secret is stored, it cannot be read back via the API. This is a GitHub security feature, not a SecretZero limitation.

Use Cases

  • CI/CD Pipelines - Automate deployment credentials for GitHub Actions workflows
  • Multi-Environment Deployments - Manage separate secrets for production, staging, and development
  • Organization-Wide Credentials - Share API keys and tokens across multiple repositories
  • Secret Rotation - Regularly update secrets across all repositories from a single source
  • Infrastructure as Code - Version control secret configurations without exposing values

Prerequisites

Required Dependencies

GitHub support requires the PyGithub library:

# Install with GitHub support
pip install secretzero[github]

# Or install PyGithub separately
pip install PyGithub

GitHub Token Generation

You need a Personal Access Token (PAT) with appropriate permissions:

  1. GitHub.com:
  2. Navigate to: Settings → Developer settings → Personal access tokens → Tokens (classic)
  3. Click "Generate new token (classic)"
  4. Select required scopes (see below)
  5. Generate and save the token securely

  6. GitHub Enterprise:

  7. Navigate to your GitHub Enterprise instance settings
  8. Follow similar steps as GitHub.com
  9. Note your GitHub Enterprise API URL

Token Permissions and Scopes

Required scopes depend on the secret types you'll manage:

Secret Type Required Scope Permission Level
Repository secrets repo Admin access to repository
Environment secrets repo Admin access to repository
Organization secrets admin:org Owner or admin in organization

Recommended token configuration:

repo (Full control of private repositories)
├── repo:status
├── repo_deployment
├── public_repo
└── repo:invite

admin:org (Full control of orgs and teams)
├── write:org
├── read:org
└── manage_runners:org (optional, for self-hosted runners)

Fine-Grained Tokens

GitHub's fine-grained personal access tokens provide more granular control. For repository secrets, grant "Secrets" permission with read/write access.

Target Types

SecretZero provides two target types for GitHub Actions secrets:

GitHubSecretTarget

Stores secrets at repository or environment level.

Provider Configuration:

providers:
  github:
    kind: github
    auth:
      kind: token
      config:
        token: ${GITHUB_TOKEN}
        # Optional: For GitHub Enterprise
        # api_url: https://github.mycompany.com/api/v3

GitHubOrganizationSecretTarget

Stores secrets at organization level, shared across repositories.

Provider Configuration:

providers:
  github:
    kind: github
    auth:
      kind: token
      config:
        token: ${GITHUB_TOKEN}

Configuration Options

Repository Secrets

Store secrets available to all workflows in a repository.

Configuration:

targets:
  - provider: github
    kind: github_secret
    config:
      owner: username-or-org
      repo: repository-name

Options:

Option Type Required Description
owner string Yes Repository owner (username or organization)
repo string Yes Repository name

Environment Secrets

Store secrets scoped to specific deployment environments.

Configuration:

targets:
  - provider: github
    kind: github_secret
    config:
      owner: username-or-org
      repo: repository-name
      environment: production

Options:

Option Type Required Description
owner string Yes Repository owner (username or organization)
repo string Yes Repository name
environment string Yes Environment name (e.g., production, staging, development)

Environment Features: - Environment-specific protection rules - Required reviewers before deployment - Wait timers for staged rollouts - Branch restrictions for environment access

Organization Secrets

Store secrets shared across multiple repositories.

Configuration:

targets:
  - provider: github
    kind: github_organization_secret
    config:
      org: organization-name
      visibility: all

Options:

Option Type Required Default Description
org string Yes - Organization name
visibility string No all Secret visibility: all, private, or selected
selected_repository_ids list No [] List of repository IDs (required if visibility is selected)

Visibility Options: - all - Available to all repositories in the organization - private - Available only to private repositories - selected - Available only to specified repositories (requires selected_repository_ids)

Finding Repository IDs

Use the GitHub API or CLI to find repository IDs:

gh api /repos/owner/repo --jq '.id'

Complete Examples

Basic Repository Secret

Store a simple API key in a repository:

version: '1.0'

providers:
  github:
    kind: github
    auth:
      kind: token
      config:
        token: ${GITHUB_TOKEN}

secrets:
  - name: API_KEY
    kind: random_string
    config:
      length: 32
      charset: alphanumeric
    targets:
      - provider: github
        kind: github_secret
        config:
          owner: myusername
          repo: myapp

Environment-Specific Secrets

Manage separate credentials for production and staging:

version: '1.0'

variables:
  repo_owner: mycompany
  repo_name: webapp

providers:
  github:
    kind: github
    auth:
      kind: token
      config:
        token: ${GITHUB_TOKEN}

secrets:
  # Production database password
  - name: DATABASE_PASSWORD
    kind: random_password
    config:
      length: 32
      special: true
      exclude_characters: '"@/\`'
    targets:
      - provider: github
        kind: github_secret
        config:
          owner: ${repo_owner}
          repo: ${repo_name}
          environment: production

  # Staging database password
  - name: DATABASE_PASSWORD
    kind: random_password
    config:
      length: 32
      special: true
      exclude_characters: '"@/\`'
    targets:
      - provider: github
        kind: github_secret
        config:
          owner: ${repo_owner}
          repo: ${repo_name}
          environment: staging

  # API keys for both environments
  - name: STRIPE_API_KEY
    kind: random_string
    config:
      length: 32
      charset: alphanumeric
    targets:
      - provider: github
        kind: github_secret
        config:
          owner: ${repo_owner}
          repo: ${repo_name}
          environment: production

      - provider: github
        kind: github_secret
        config:
          owner: ${repo_owner}
          repo: ${repo_name}
          environment: staging

  # JWT secret (repository-level, shared across environments)
  - name: JWT_SECRET
    kind: random_string
    config:
      length: 64
      charset: base64
    targets:
      - provider: github
        kind: github_secret
        config:
          owner: ${repo_owner}
          repo: ${repo_name}

Organization-Wide Secrets

Share secrets across multiple repositories:

version: '1.0'

variables:
  organization: mycompany

providers:
  github:
    kind: github
    auth:
      kind: token
      config:
        token: ${GITHUB_TOKEN}

secrets:
  # Shared Docker registry credentials
  - name: DOCKER_USERNAME
    kind: static
    config:
      value: mycompany-ci
    targets:
      - provider: github
        kind: github_organization_secret
        config:
          org: ${organization}
          visibility: all

  - name: DOCKER_PASSWORD
    kind: random_password
    config:
      length: 32
      special: false
    targets:
      - provider: github
        kind: github_organization_secret
        config:
          org: ${organization}
          visibility: all

  # NPM registry token for private packages
  - name: NPM_TOKEN
    kind: random_string
    config:
      length: 36
      charset: alphanumeric
    targets:
      - provider: github
        kind: github_organization_secret
        config:
          org: ${organization}
          visibility: private

  # Cloud provider credentials for deployment
  - name: AWS_ACCESS_KEY_ID
    kind: static
    config:
      value: ${AWS_ACCESS_KEY_ID}
    targets:
      - provider: github
        kind: github_organization_secret
        config:
          org: ${organization}
          visibility: all

  - name: AWS_SECRET_ACCESS_KEY
    kind: static
    config:
      value: ${AWS_SECRET_ACCESS_KEY}
    targets:
      - provider: github
        kind: github_organization_secret
        config:
          org: ${organization}
          visibility: all

Multi-Repository Deployment

Deploy secrets to multiple repositories with different configurations:

version: '1.0'

variables:
  org: mycompany
  repos:
    - frontend
    - backend
    - mobile-app

providers:
  github:
    kind: github
    auth:
      kind: token
      config:
        token: ${GITHUB_TOKEN}

secrets:
  # Shared API endpoint
  - name: API_ENDPOINT
    kind: static
    config:
      value: https://api.mycompany.com
    targets:
      - provider: github
        kind: github_secret
        config:
          owner: ${org}
          repo: frontend

      - provider: github
        kind: github_secret
        config:
          owner: ${org}
          repo: backend

      - provider: github
        kind: github_secret
        config:
          owner: ${org}
          repo: mobile-app

  # Frontend-specific secrets
  - name: SENTRY_DSN_FRONTEND
    kind: random_string
    config:
      length: 32
      charset: alphanumeric
    targets:
      - provider: github
        kind: github_secret
        config:
          owner: ${org}
          repo: frontend

  # Backend-specific secrets
  - name: DATABASE_URL
    kind: static
    config:
      value: ${DATABASE_URL}
    targets:
      - provider: github
        kind: github_secret
        config:
          owner: ${org}
          repo: backend
          environment: production

  # Mobile-specific secrets
  - name: FIREBASE_CONFIG
    kind: static
    config:
      value: ${FIREBASE_CONFIG}
    targets:
      - provider: github
        kind: github_secret
        config:
          owner: ${org}
          repo: mobile-app

Selected Repository Access

Grant organization secrets to specific repositories only:

version: '1.0'

variables:
  organization: mycompany
  # Repository IDs can be found using: gh api /repos/owner/repo --jq '.id'
  production_repos:
    - 123456789  # mycompany/api-production
    - 234567890  # mycompany/web-production
    - 345678901  # mycompany/worker-production

providers:
  github:
    kind: github
    auth:
      kind: token
      config:
        token: ${GITHUB_TOKEN}

secrets:
  # Production-only database credentials
  - name: PROD_DB_PASSWORD
    kind: random_password
    config:
      length: 32
      special: true
    targets:
      - provider: github
        kind: github_organization_secret
        config:
          org: ${organization}
          visibility: selected
          selected_repository_ids: ${production_repos}

  # Production API keys
  - name: PROD_API_KEY
    kind: random_string
    config:
      length: 64
      charset: base64
    targets:
      - provider: github
        kind: github_organization_secret
        config:
          org: ${organization}
          visibility: selected
          selected_repository_ids: ${production_repos}

Using Secrets in GitHub Actions Workflows

Once secrets are stored in GitHub, they can be accessed in workflow files.

Repository Secrets

name: Deploy Application

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Configure environment
        run: |
          echo "API_KEY=${{ secrets.API_KEY }}" >> .env
          echo "JWT_SECRET=${{ secrets.JWT_SECRET }}" >> .env

      - name: Deploy
        run: ./deploy.sh

Environment Secrets

name: Deploy to Production

on:
  push:
    branches: [main]

jobs:
  deploy-staging:
    runs-on: ubuntu-latest
    environment: staging

    steps:
      - uses: actions/checkout@v4

      - name: Deploy to staging
        env:
          DATABASE_PASSWORD: ${{ secrets.DATABASE_PASSWORD }}
          STRIPE_API_KEY: ${{ secrets.STRIPE_API_KEY }}
        run: ./deploy.sh staging

  deploy-production:
    runs-on: ubuntu-latest
    environment: production
    needs: deploy-staging

    steps:
      - uses: actions/checkout@v4

      - name: Deploy to production
        env:
          DATABASE_PASSWORD: ${{ secrets.DATABASE_PASSWORD }}
          STRIPE_API_KEY: ${{ secrets.STRIPE_API_KEY }}
        run: ./deploy.sh production

Organization Secrets

name: Build and Push Docker Image

on:
  push:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Log in to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}

      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          push: true
          tags: mycompany/myapp:latest

Multiple Environments with Matrix

name: Deploy to Multiple Environments

on:
  workflow_dispatch:
    inputs:
      environment:
        description: 'Environment to deploy'
        required: true
        type: choice
        options:
          - development
          - staging
          - production

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: ${{ github.event.inputs.environment }}

    steps:
      - uses: actions/checkout@v4

      - name: Deploy to ${{ github.event.inputs.environment }}
        env:
          DATABASE_PASSWORD: ${{ secrets.DATABASE_PASSWORD }}
          API_KEY: ${{ secrets.API_KEY }}
        run: |
          echo "Deploying to ${{ github.event.inputs.environment }}"
          ./deploy.sh ${{ github.event.inputs.environment }}

Best Practices

1. Use Environment Protection

Configure environment protection rules for production secrets:

# Repository Settings → Environments → production

# Protection rules:
- Required reviewers: 2
- Wait timer: 5 minutes
- Allowed branches: main, release/*
- Environment secrets: DATABASE_PASSWORD, API_KEY

This ensures: - Manual approval before production deployments - Time for rollback if issues detected - Restricted branch access to production

2. Prefer OIDC Over Static Credentials

For cloud providers, use OpenID Connect instead of static credentials:

# Don't store cloud credentials as secrets
# Instead, configure OIDC trust relationships

name: Deploy to AWS

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read

    steps:
      - uses: actions/checkout@v4

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789012:role/GitHubActions
          aws-region: us-east-1

      - name: Deploy
        run: ./deploy.sh

Benefits: - No long-lived credentials - Automatic token rotation - Audit trail via cloud provider logs - Reduced secret sprawl

3. Rotate Secrets Regularly

Automate secret rotation with SecretZero:

# Rotate secrets monthly via cron job
0 0 1 * * cd /opt/secretzero && secretzero sync -f Secretfile.yml

# Or use GitHub Actions workflow
name: Rotate Secrets
on:
  schedule:
    - cron: '0 0 1 * *'  # Monthly
  workflow_dispatch:

jobs:
  rotate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup SecretZero
        run: pip install secretzero[github]

      - name: Rotate secrets
        env:
          GITHUB_TOKEN: ${{ secrets.ADMIN_GITHUB_TOKEN }}
        run: secretzero sync -f Secretfile.yml

4. Use Descriptive Secret Names

Follow naming conventions:

# Good: Clear purpose and scope
DATABASE_PASSWORD
AWS_ACCESS_KEY_ID
STRIPE_API_KEY_PRODUCTION
SENTRY_DSN_FRONTEND

# Bad: Ambiguous or unclear
PASSWORD
KEY
SECRET
TOKEN

5. Separate Secrets by Environment

Don't share secrets across environments:

# Good: Environment-specific
secrets:
  - name: DATABASE_PASSWORD
    targets:
      - config:
          environment: production

  - name: DATABASE_PASSWORD
    targets:
      - config:
          environment: staging

# Bad: Shared across environments
secrets:
  - name: DATABASE_PASSWORD
    targets:
      - config:
          owner: mycompany
          repo: myapp

6. Document Secret Requirements

Maintain documentation of required secrets:

# secrets.md
# Required Secrets

## Repository Secrets
- `API_KEY` - Third-party API authentication
- `JWT_SECRET` - JWT token signing key

## Environment Secrets (production)
- `DATABASE_PASSWORD` - Production database password
- `STRIPE_API_KEY` - Production Stripe API key

## Organization Secrets
- `DOCKER_USERNAME` - Docker Hub username
- `DOCKER_PASSWORD` - Docker Hub password

7. Use the Lockfile

Track secret changes with SecretZero's lockfile:

# Commit .secretzero.lock to track secret metadata
git add .secretzero.lock
git commit -m "Update secret configurations"

Benefits: - Audit trail of secret changes - Prevent accidental updates - Coordinate updates across team

8. Implement Least Privilege

Grant minimal permissions:

# Organization secrets: Use 'selected' visibility
visibility: selected
selected_repository_ids: [123456]  # Only repositories that need it

# Repository secrets: Use environment secrets when possible
environment: production  # Restricted to production deployments

# Token permissions: Grant minimum scopes
# Don't grant admin:org if only repo access needed

Security Considerations

Secret Scanning

GitHub automatically scans for accidentally committed secrets:

# .github/secret_scanning.yml
# Additional patterns to detect

patterns:
  - name: Custom API Key
    pattern: 'mycompany_key_[a-zA-Z0-9]{32}'
    description: MyCompany API keys

Best practices: - Review secret scanning alerts immediately - Rotate compromised secrets within 1 hour - Update SecretZero configurations if secrets leaked - Investigate how secret was exposed

Audit Logs

Monitor secret access in GitHub audit logs:

  1. Organization Audit Log:
  2. Settings → Organization → Audit log
  3. Filter by action:org.create_actions_secret
  4. Review who accessed secrets

  5. Automated Monitoring:

    # Export audit logs for analysis
    gh api /orgs/mycompany/audit-log \
      --jq '.[] | select(.action | contains("secret"))' \
      > secret_audit.json
    

  6. Alert on Suspicious Activity:

  7. New secrets created outside SecretZero
  8. Secrets accessed from unusual IP addresses
  9. Excessive secret modifications

Secret Encryption

GitHub handles secret encryption automatically:

  • Secrets encrypted at rest using AES-256-GCM
  • Encryption keys rotated regularly by GitHub
  • Secrets decrypted only during workflow execution
  • No plaintext storage in GitHub's systems

SecretZero's role: 1. Generates secret values 2. Fetches repository public key via API 3. Encrypts secret using libsodium (sealed box) 4. Sends encrypted value to GitHub 5. GitHub stores encrypted secret

Environment Protection

Configure environment protection for sensitive deployments:

# Repository Settings → Environments → production

# Required reviewers
required_reviewers:
  - security-team
  - ops-team

# Wait timer
wait_timer: 300  # 5 minutes

# Deployment branches
deployment_branches:
  custom_branches:
    - main
    - release/*

# Secrets
secrets:
  - DATABASE_PASSWORD
  - API_KEY

Network Restrictions

Limit workflow execution:

# Only allow workflows from specific IPs
# (GitHub Enterprise only)

name: Secure Deploy
on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: self-hosted  # Use self-hosted runner in VPN

    steps:
      - name: Deploy
        run: ./deploy.sh

Webhook Security

Secure webhooks that might trigger workflows:

name: Webhook Triggered Deploy

on:
  repository_dispatch:
    types: [deploy]

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Verify webhook signature
        env:
          WEBHOOK_SECRET: ${{ secrets.WEBHOOK_SECRET }}
        run: |
          # Verify HMAC signature
          ./verify_signature.sh

      - name: Deploy if verified
        run: ./deploy.sh

Troubleshooting

Authentication Failed

Symptom: Error: "Bad credentials" or "401 Unauthorized"

Solutions:

  1. Verify token is valid:

    # Test authentication
    curl -H "Authorization: token ${GITHUB_TOKEN}" \
      https://api.github.com/user
    

  2. Check token hasn't expired:

  3. Personal access tokens can expire
  4. Regenerate if expired

  5. Verify token has correct scopes:

    # Check token scopes
    curl -I -H "Authorization: token ${GITHUB_TOKEN}" \
      https://api.github.com/user | grep x-oauth-scopes
    

  6. For GitHub Enterprise, verify API URL:

    providers:
      github:
        auth:
          config:
            token: ${GITHUB_TOKEN}
            api_url: https://github.company.com/api/v3  # Correct URL
    

Permission Denied

Symptom: Error: "Resource not accessible by integration" or "403 Forbidden"

Solutions:

  1. Repository secrets - verify repo access:
  2. Token owner must have admin access to repository
  3. Required scope: repo

  4. Organization secrets - verify org permissions:

  5. Token owner must be organization owner or have admin rights
  6. Required scope: admin:org

  7. Environment secrets - verify environment access:

  8. Repository admins can manage environment secrets
  9. Environments must exist before adding secrets

  10. Check organization SSO:

    # If using SSO, authorize token
    # GitHub → Settings → Applications → Authorized OAuth Apps
    # Click "Authorize" next to your organization
    

Secret Not Appearing in Workflows

Symptom: Secret is created but ${{ secrets.SECRET_NAME }} is empty

Solutions:

  1. Verify secret name matches exactly:

    # Secret names are case-sensitive
    secrets:
      - name: API_KEY  # Must use API_KEY, not api_key
    
    # In workflow:
    ${{ secrets.API_KEY }}  # Must match exactly
    

  2. For environment secrets, specify environment:

    jobs:
      deploy:
        environment: production  # Required for environment secrets
        steps:
          - name: Use secret
            env:
              PASSWORD: ${{ secrets.DATABASE_PASSWORD }}
    

  3. Check organization secret visibility:

    # If visibility: selected, repository must be in selected_repository_ids
    config:
      visibility: selected
      selected_repository_ids:
        - 123456  # Must include current repository ID
    

  4. Verify secret was created successfully:

    # Check repository secrets
    gh secret list --repo owner/repo
    
    # Check organization secrets
    gh secret list --org organization
    

Token Scope Issues

Symptom: Some operations work, others fail with permission errors

Solutions:

  1. Audit current scopes:

    curl -I -H "Authorization: token ${GITHUB_TOKEN}" \
      https://api.github.com/user \
      | grep x-oauth-scopes
    

  2. Required scopes by operation:

    Repository secrets:    repo
    Environment secrets:   repo
    Organization secrets:  admin:org
    Read repositories:     repo (or public_repo for public only)
    

  3. Regenerate token with correct scopes:

  4. GitHub → Settings → Developer settings → Personal access tokens
  5. Delete old token
  6. Create new token with all required scopes

Repository Not Found

Symptom: Error: "Not Found" or "404" for repository operations

Solutions:

  1. Verify repository path:

    config:
      owner: mycompany  # Organization or username
      repo: myrepo      # Repository name (not URL)
    

  2. Check repository visibility:

  3. Private repositories require repo scope
  4. Public repositories require public_repo scope minimum

  5. Verify organization membership:

    # Check if user is org member
    gh api /orgs/mycompany/members/myusername
    

Environment Not Found

Symptom: Error: "Environment not found" when creating environment secrets

Solutions:

  1. Create environment first:
  2. Go to repository Settings → Environments
  3. Click "New environment"
  4. Name must match exactly (case-sensitive)

  5. Or create via API:

    gh api -X PUT /repos/owner/repo/environments/production \
      -f wait_timer=0 \
      -f prevent_self_review=false
    

  6. Then sync secrets:

    secretzero sync -f Secretfile.yml
    

Rate Limiting

Symptom: Error: "API rate limit exceeded"

Solutions:

  1. Check rate limit status:

    curl -H "Authorization: token ${GITHUB_TOKEN}" \
      https://api.github.com/rate_limit
    

  2. Authenticated requests have higher limits:

  3. Unauthenticated: 60 requests/hour
  4. Authenticated: 5,000 requests/hour
  5. GitHub Enterprise: Often higher limits

  6. Implement exponential backoff:

  7. SecretZero handles this automatically
  8. Wait for rate limit reset if needed

  9. Batch operations when possible:

    # Sync all secrets at once instead of individually
    secretzero sync -f Secretfile.yml
    

GitHub Enterprise Connectivity

Symptom: Connection errors with GitHub Enterprise

Solutions:

  1. Verify API URL format:

    providers:
      github:
        auth:
          config:
            api_url: https://github.company.com/api/v3
            # Note: Includes /api/v3 suffix
    

  2. Check SSL certificate:

    # Test connectivity
    curl -v https://github.company.com/api/v3
    
    # If self-signed cert, may need to configure trust
    

  3. Verify firewall rules:

  4. Ensure outbound HTTPS (443) access
  5. Check corporate proxy settings

  6. Test with curl first:

    curl -H "Authorization: token ${GITHUB_TOKEN}" \
      https://github.company.com/api/v3/user
    

Secret Value Truncated

Symptom: Secret appears truncated or corrupted in workflows

Solutions:

  1. Check for special characters:

    # Exclude problematic characters
    secrets:
      - name: PASSWORD
        kind: random_password
        config:
          exclude_characters: '"@/\`$'  # Exclude shell special chars
    

  2. Verify encoding:

  3. GitHub secrets support UTF-8
  4. Binary data must be base64 encoded

  5. Check secret length limits:

  6. Maximum secret size: 64 KB
  7. Large secrets should be stored elsewhere (e.g., AWS Secrets Manager)

Debugging Tips

  1. Enable debug logging:

    secretzero sync -f Secretfile.yml --log-level debug
    

  2. Test with dry-run:

    secretzero sync -f Secretfile.yml --dry-run
    

  3. Verify provider connectivity:

    secretzero test -f Secretfile.yml
    

  4. Check secret metadata (not values):

    # List repository secrets
    gh secret list --repo owner/repo
    
    # View secret details (not value)
    gh api /repos/owner/repo/actions/secrets/SECRET_NAME
    

  5. Review GitHub Actions workflow logs:

  6. Secrets are redacted in logs
  7. Look for error messages about missing secrets
  8. Check workflow permissions

Next Steps