Developers still hard-code API tokens, passwords, and other credentials into source code or .env files and push them to Git. That happens in side projects and in production systems.

The pattern is familiar: if there is no straightforward way to supply secrets to automation and deployment pipelines, Git starts to look like the only durable place to keep them. Teams tell themselves they will clean it up later. In practice, once a secret is committed, it is almost impossible to remove it from history completely.

Why Git Is Dangerous for Secrets

Git keeps every revision. You can delete a token from the tip of a branch, but older commits still contain it. Clones, forks, mirrors, CI checkouts, and backup copies all spread that history. The moment a secret lands in a commit, you should assume it has left your direct control.

Who can read the repository also tends to be wider than people expect — contractors, short-term contributors, internal forks — any of whom may see credentials they were never meant to hold.

GitHub and GitLab run secret scanning. If a provider flags a token, treat it as leaked: revoke it and rotate anything that depended on it.

Where Secrets Belong Instead of Git

A secret is not just another file in the tree. It is a credential that should live outside the repository, be readable only by the right principals, support rotation, and differ per environment (dev, staging, production).

Self-hosting Vault or OpenBao is a valid approach, but it adds infrastructure to run, patch, and monitor.

Semaphore includes a Key Store that ties directly into automation. You can keep secrets in either:

  • Semaphore’s encrypted store (default)
  • An external backend such as:
    • HashiCorp Vault — store credentials in your own Vault deployment instead of Semaphore’s database; values are read when a job needs them (Pro).
    • OpenBao — the community-maintained, Vault-compatible fork; connects through the same integration path as Vault (Pro).
    • Devolutions Server — use Devolutions as the secrets backend for Enterprise installs, in the same spirit as Vault (Enterprise).

Use the built-in store for a fast path, or connect your existing enterprise secrets system. Both integrate with workflows without custom glue code.

What You Can Store in Key Store

  • API tokens
  • SSH keys
  • Passwords
  • Environment variables
  • JSON and other configuration payloads

Values never live in the repo; they are supplied to jobs at runtime. You can use different entries per environment and restrict who or which workflows may use each secret.

How It Works in Practice

You create a Key Store entry, attach secrets to it, and reference that entry from your task configuration. Semaphore resolves and injects the values when the job runs.

For example, during an AWS deploy, access keys exist only for the lifetime of that job, on the agent that executes it. Developers do not need a copy in their checkout, and nothing sensitive needs to be committed to Git.

Example

In the UI, open Secrets → New Secret and define variables such as:

  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY

Reference the secret by name in your workflow. Semaphore exposes the values as environment variables for that job:

blocks:
  - name: Deploy
    task:
      secrets:
        - name: aws-credentials
      jobs:
        - name: deploy
          commands:
            - aws s3 sync ./dist s3://my-bucket

For SSH, store the private key in a secret; Semaphore can place it under ~/.ssh/ for the job:

blocks:
  - name: Deploy via SSH
    task:
      secrets:
        - name: production-ssh-key
      jobs:
        - name: deploy
          commands:
            - ssh deploy@production-server "cd /app && git pull"

Key Store vs. Other Approaches

Method Secure Visibility Revocable
.env in Git Whole team No
GitHub Actions Secrets ⚠️ Depends Yes
Semaphore Key Store Scoped Yes

You also get rotation without editing application code, access boundaries by role or team, and clean separation between environments.

The Bottom Line

Treat any token that has been committed to Git as compromised. History fans out across machines and organizations; every extra copy is another place an attacker can look.

Key Store keeps material out of repositories, delivers it only at execution time, and gives you levers for rotation and access control. For Ansible, Terraform, OpenTofu, or PowerShell-based automation, that is not optional polish — it is the minimum bar for operating safely.

You might also like