Skip to content

Security: intertwine/sops-encrypted-envs-mac

Security

docs/security.md

Security

This repo helps with local secret hygiene. It is not a complete secret-management system.

Threat model: what this repo helps with

The SOPS + age + Keychain pattern reduces risk from:

  • plaintext .env files sitting in local repos for months
  • accidental commits of plaintext secrets
  • broad local search, indexing, or agent inspection over repo contents
  • backups and sync tools sweeping up long-lived plaintext dotenv files
  • clone workflows where developers need the repo but should not receive a copied private identity file

What it does not solve

This repo does not fully protect you from:

  • malware or an attacker already running as your macOS user
  • secrets leaking into logs, shell history, crash reports, or test output
  • plaintext .env files that already exist in git history
  • team-wide sharing, revocation, RBAC, or audit requirements
  • production or CI secret delivery on its own

Once a command is running under sops exec-env or the wrapper, the secrets are in process environment space. That is better than a long-lived plaintext file on disk, but it is not the same thing as a hardware-backed or centrally governed secret-management system.

Recommended baseline safeguards

If you adopt this repo publicly, pair it with:

  • one recipient per person or per device where possible
  • secret rotation after migration, especially if plaintext may have leaked before
  • GitHub push protection or equivalent host-side secret scanning
  • repo-by-repo validation instead of blind bulk rewrites
  • explicit smoke commands in migration instructions

The built-in validate-repo secret scan is a high-signal spot check for common prefixes. It is useful, but it is not comprehensive enough to replace host-side secret scanning or a dedicated scanner.

Hardening options outside this repo

This repo intentionally stops before central secret management. When you need more than local workflow hardening, add one of these layers:

Human secret stores

  • 1Password for friendlier human-facing secret storage and sharing
  • macOS Keychain if you only need local single-user storage on one machine

Team or production secret managers

  • HashiCorp Vault for dynamic secrets, leases, and deeper policy control
  • Infisical for a friendlier open-source team secret workflow
  • Doppler for centralized developer and environment secret management
  • AWS Secrets Manager, GCP Secret Manager, or Azure Key Vault for cloud-native delivery

Git-host hardening

  • GitHub secret scanning
  • GitHub push protection
  • organization rules or CI checks that reject committed plaintext dotenv files

CI note

This repo is primarily a local macOS workflow. CI is secondary and should not reuse the macOS Keychain helper.

If CI must decrypt SOPS files:

  • use a dedicated CI recipient or cloud KMS, not a developer's personal Keychain identity
  • store that identity in the CI secret manager
  • inject it through SOPS_AGE_KEY or a file-backed equivalent

Minimal GitHub Actions example:

jobs:
  test:
    runs-on: ubuntu-latest
    env:
      SOPS_AGE_KEY: ${{ secrets.SOPS_AGE_KEY }}
    steps:
      - uses: actions/checkout@v4
      - run: sops exec-env .env -- uv run pytest

For .env.sops, use the repo's wrapper boundary instead of the macOS Keychain helper:

- run: scripts/sops-env .env.sops -- npm run test:raw

If you do not need encrypted dotenvs in CI, keep CI out of scope and document the local-only boundary clearly.

Recipient rotation

Rotate recipients when a device is retired, a private identity may have leaked, or you are moving from a single-user bootstrap to per-person recipients.

Typical flow:

  1. create the new age identity
  2. update .sops.yaml with the new recipient list
  3. run sops updatekeys -y ENV_FILE
  4. validate with scripts/validate-repo ... -- smoke command
  5. rotate the underlying application secrets too if the old recipient may have exposed them

Scope boundary

Use this repo when you want:

  • a macOS-friendly local workflow
  • better defaults for repos that currently rely on plaintext dotenv files
  • agent-assisted migration help
  • a publishable, explainable pattern for one repo at a time

Use a central secret manager when you want:

  • shared production access
  • audited team onboarding and offboarding
  • dynamic credentials
  • environment-level rotation and policy
  • service-to-service secret delivery

There aren’t any published security advisories