stages: [verify] verify:no_secrets: stage: verify image: alpine:latest script: - apk add --no-cache git grep # Global secret scan (cheap but effective) - | set +e secret_re='(BEGIN (RSA|OPENSSH|EC) PRIVATE KEY|-----BEGIN PGP PRIVATE KEY BLOCK-----|aws_secret_access_key|AKIA[0-9A-Z]{16}|xox[baprs]-[0-9A-Za-z-]{10,}|ghp_[A-Za-z0-9]{36}|glpat-[A-Za-z0-9_-]{20,})' git grep -nE "$secret_re" -- . status=$? set -e if [ "$status" -eq 0 ]; then echo "❌ Potential secret detected. Remove it or encrypt it into vault/." exit 1 elif [ "$status" -ne 1 ]; then echo "❌ Secret scan failed (git grep exit $status)." exit "$status" fi # Vault plaintext guard (tracked files only) - | set -eu allowed_vault_re='(^vault/README\.md$|^vault/\.gitkeep$|^vault/tmp/\.gitignore$|\.age$|\.sops\.)' bad_vault_files="$(git ls-files vault | grep -vE "$allowed_vault_re" || true)" if [ -n "$bad_vault_files" ]; then echo "❌ Plaintext file detected in vault/. Encrypt before commit:" echo "$bad_vault_files" exit 1 fi