{"id":34743217,"url":"https://github.com/dotsecenv/dotsecenv","last_synced_at":"2026-04-02T17:15:32.768Z","repository":{"id":329820812,"uuid":"1116454799","full_name":"dotsecenv/dotsecenv","owner":"dotsecenv","description":"safe environment secrets","archived":false,"fork":false,"pushed_at":"2026-03-28T14:52:33.000Z","size":2806,"stargazers_count":3,"open_issues_count":3,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-28T15:25:07.295Z","etag":null,"topics":["bash","environment-variables","fish","secure-coding","zsh"],"latest_commit_sha":null,"homepage":"https://dotsecenv.com","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dotsecenv.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-14T22:11:06.000Z","updated_at":"2026-03-28T11:57:54.000Z","dependencies_parsed_at":"2026-01-30T03:00:30.007Z","dependency_job_id":null,"html_url":"https://github.com/dotsecenv/dotsecenv","commit_stats":null,"previous_names":["dotsecenv/dotsecenv"],"tags_count":29,"template":false,"template_full_name":null,"purl":"pkg:github/dotsecenv/dotsecenv","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dotsecenv%2Fdotsecenv","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dotsecenv%2Fdotsecenv/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dotsecenv%2Fdotsecenv/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dotsecenv%2Fdotsecenv/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dotsecenv","download_url":"https://codeload.github.com/dotsecenv/dotsecenv/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dotsecenv%2Fdotsecenv/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31232811,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-31T09:14:28.471Z","status":"ssl_error","status_checked_at":"2026-03-31T09:14:19.506Z","response_time":111,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bash","environment-variables","fish","secure-coding","zsh"],"created_at":"2025-12-25T04:27:14.021Z","updated_at":"2026-04-02T17:15:32.761Z","avatar_url":"https://github.com/dotsecenv.png","language":"Go","readme":"# dotsecenv: safe environment secrets\n\n[![CI](https://github.com/dotsecenv/dotsecenv/actions/workflows/ci.yml/badge.svg)](https://github.com/dotsecenv/dotsecenv/actions/workflows/ci.yml)\n[![Release](https://github.com/dotsecenv/dotsecenv/actions/workflows/release.yml/badge.svg)](https://github.com/dotsecenv/dotsecenv/actions/workflows/release.yml)\n[![GitHub Action E2E](https://github.com/dotsecenv/dotsecenv/actions/workflows/action-e2e.yml/badge.svg)](https://github.com/dotsecenv/dotsecenv/actions/workflows/action-e2e.yml)\n[![Contrib E2E](https://github.com/dotsecenv/dotsecenv/actions/workflows/contrib-e2e.yml/badge.svg)](https://github.com/dotsecenv/dotsecenv/actions/workflows/contrib-e2e.yml)\n[![Hermetic E2E](https://github.com/dotsecenv/dotsecenv/actions/workflows/hermetic-e2e.yml/badge.svg)](https://github.com/dotsecenv/dotsecenv/actions/workflows/hermetic-e2e.yml)\n[![Publish Packages](https://github.com/dotsecenv/packages/actions/workflows/publish.yml/badge.svg)](https://github.com/dotsecenv/packages/actions/workflows/publish.yml)\n[![Homebrew install](https://github.com/dotsecenv/homebrew-tap/actions/workflows/post-release.yml/badge.svg)](https://github.com/dotsecenv/homebrew-tap/actions/workflows/post-release.yml)\n[![Shell plugins CI](https://github.com/dotsecenv/plugin/actions/workflows/ci.yml/badge.svg)](https://github.com/dotsecenv/plugin/actions/workflows/ci.yml)\n[![Publish Website](https://github.com/dotsecenv/website/actions/workflows/deploy-website.yml/badge.svg)](https://github.com/dotsecenv/website/actions/workflows/deploy-website.yml)\n\nA complete Go CLI application for securely managing environment secrets with GPG-based encryption, multi-user support, and FIPS 186-5 compliant algorithm defaults.\n\n## Quick Start\n\n### Store your first secret\n\n```bash\n# After installation (see below)\ndotsecenv init config\ndotsecenv init vault -v ~/.local/share/dotsecenv/vault\ndotsecenv login \u003cYOUR GPG FINGERPRINT\u003e # gpg --list-public-keys\necho \"xyz\" | dotsecenv secret store TEST_SECRET\n# Subsequently, you can decrypt secrets\n# as long as you hold the corresponding secret key in GPG agent\ndotsecenv secret get TEST_SECRET # should output \"xyz\"\n```\n\n### Installation\n\n#### Install Script (recommended)\n\nThe universal install script (`install.sh`) is the fastest way to install dotsecenv on macOS and Linux. It auto-detects your platform, downloads the correct binary, verifies checksums and GPG signatures, and installs shell completions, man pages, the shell plugin, and the Terraform credentials helper automatically.\n\n##### Usage\n\n```bash\n# Piped (simplest)\ncurl -fsSL https://get.dotsecenv.com/install.sh | bash\n\n# Piped with CLI flags\ncurl -fsSL https://get.dotsecenv.com/install.sh | bash -s -- [OPTIONS]\n\n# Piped with environment variables\nVERSION=v1.2.3 curl -fsSL https://get.dotsecenv.com/install.sh | bash\n\n# Downloaded and run locally\ncurl -fsSL https://get.dotsecenv.com/install.sh -o install.sh\nchmod +x install.sh\n./install.sh --version v1.2.3\n```\n\nThe script works with either `curl` or `wget`.\n\n##### Options\n\nEvery setting can be configured via a CLI flag or an environment variable. **Precedence order:** CLI flags \u003e environment variables \u003e defaults.\n\n| Setting | CLI Flag | Env Var | Default | Description |\n|---------|----------|---------|---------|-------------|\n| Version | `--version VERSION` | `VERSION` | `latest` | Version to install (e.g., `v1.2.3`) |\n| Install directory | `--install-dir DIR` | `INSTALL_DIR` | `~/.local/bin` | Binary install path |\n| System-wide install | `--system` | `SYSTEM_INSTALL` | `0` (no) | Install to system paths (`/usr/local/bin` on macOS, `/usr/local/bin` on Linux) instead of user-level paths |\n| Shell plugin | `--[no-]install-shell-plugin` | `INSTALL_SHELL_PLUGIN` | `1` (yes) | Install the shell plugin for zsh/bash/fish |\n| Completions | `--[no-]install-completions` | `INSTALL_COMPLETIONS` | `1` (yes) | Install shell completions for bash, zsh, and fish |\n| Man pages | `--[no-]install-man-pages` | `INSTALL_MAN_PAGES` | `1` (yes) | Install man pages |\n| TF credentials helper | `--[no-]install-tf-credentials-helper` | `INSTALL_TF_CREDENTIALS_HELPER` | `1` (yes) | Install the Terraform credentials helper |\n| Verification | `--[no-]verify` | `VERIFY` | `1` (yes) | Verify SHA-256 checksums and GPG signatures |\n| Help | `-h`, `--help` | — | — | Show help and exit |\n\n##### What the Installer Does\n\n1. **Detects your platform** — OS (Linux or macOS) and architecture (x86_64 or arm64)\n2. **Resolves the version** — Queries the GitHub API for the latest release, or uses the version you specified\n3. **Downloads the release archive** — From GitHub Releases\n4. **Verifies integrity** — SHA-256 checksum verification and GPG signature verification (when `gpg` is available)\n5. **Installs the binary** — To `~/.local/bin` by default; pass `--system` to install to `/usr/local/bin` instead (uses `sudo` when needed)\n6. **Installs shell completions** — For bash, zsh, and fish, placed under `~/.local/share/` by default (or system directories with `--system`)\n7. **Installs man pages** — To `~/.local/share/man/man1/` by default (or `/usr/local/share/man/man1/` / `/usr/share/man/man1/` with `--system`)\n8. **Installs the shell plugin** — Auto-detects your plugin manager (Oh My Zsh, Zinit, Antidote, Oh My Bash, Fisher, Oh My Fish) and installs accordingly. Falls back to cloning to `~/.local/share/dotsecenv/plugin` with manual sourcing instructions.\n9. **Installs the Terraform credentials helper** — To `~/.terraform.d/plugins/` (skip with `--no-install-tf-credentials-helper`)\n\n##### Examples\n\n**CI/CD: Install specific version, skip interactive components:**\n\n```bash\nVERSION=v1.2.3 INSTALL_SHELL_PLUGIN=0 INSTALL_MAN_PAGES=0 \\\n  curl -fsSL https://get.dotsecenv.com/install.sh | bash\n```\n\n**Custom install directory:**\n\n```bash\ncurl -fsSL https://get.dotsecenv.com/install.sh | bash -s -- \\\n  --install-dir /opt/dotsecenv/bin\n```\n\n**System-wide install:**\n\n```bash\ncurl -fsSL https://get.dotsecenv.com/install.sh | bash -s -- --system\n```\n\n**Minimal install (binary only):**\n\n```bash\ncurl -fsSL https://get.dotsecenv.com/install.sh | bash -s -- \\\n  --no-install-shell-plugin \\\n  --no-install-completions \\\n  --no-install-man-pages \\\n  --no-install-tf-credentials-helper\n```\n\n**Download and inspect before running:**\n\n```bash\ncurl -fsSL https://get.dotsecenv.com/install.sh -o install.sh\nless install.sh  # review the script\nbash install.sh --version v1.2.3\n```\n\n#### Mise\n\n```bash\nmise use github:dotsecenv/dotsecenv\n```\n\n#### macOS (Homebrew)\n\n```bash\nbrew tap dotsecenv/tap\nbrew install dotsecenv\n```\n\n#### Linux Package Managers\n\nPackage repositories for Debian/Ubuntu, RHEL/CentOS/Fedora, and Arch Linux are available at [get.dotsecenv.com](https://get.dotsecenv.com).\n\n#### Binary Download\n\nDownload the latest release for your platform from the [Releases page](https://github.com/dotsecenv/dotsecenv/releases).\n\n#### Linux Packages (.deb / .rpm / .archlinux)\n\nDownload the appropriate package from the [Releases page](https://github.com/dotsecenv/dotsecenv/releases) and install it:\n\n**Debian/Ubuntu:**\n\n```bash\nsudo dpkg -i dotsecenv_amd64.deb\n```\n\n**RHEL/CentOS/Fedora:**\n\n```bash\nsudo rpm -i dotsecenv_amd64.rpm\n```\n\n**Arch Linux:**\n\n```bash\nsudo pacman -U dotsecenv_amd64.pkg.tar.zst\n```\n\n#### Windows\n\n\u003e **NOTICE:** dotsecenv on Windows is currently WIP. You can follow [this issue](https://github.com/dotsecenv/dotsecenv/issues/8) for updates.\n\nDownload the `.zip` file for your architecture from the [Releases page](https://github.com/dotsecenv/dotsecenv/releases):\n\n- `dotsecenv_vX.X.X_Windows_x86_64.zip` for 64-bit Intel/AMD\n- `dotsecenv_vX.X.X_Windows_arm64.zip` for ARM64\n\nExtract and add the binary location to your PATH.\n\n**GPG Requirement**: Install [Gpg4win](https://www.gpg4win.org/) for GPG support. If GPG is not in your PATH, `dotsecenv init config` will attempt to detect it automatically, or you can set `gpg_program` in your config file.\n\n#### Build from Source\n\n```bash\n# Clone the repository\ngit clone https://github.com/dotsecenv/dotsecenv.git\ncd dotsecenv\n\n# Build using make\nmake build\n\n# Binary will be at bin/dotsecenv\n```\n\n### GitHub Action\n\nUse the official GitHub Action to install `dotsecenv` in your CI/CD workflows:\n\n```yaml\n- uses: dotsecenv/dotsecenv@v0\n```\n\nThe action downloads the appropriate binary for your runner's architecture and verifies its integrity.\n\n#### Inputs\n\nRelease binaries achieve [SLSA Build Level 3](#security-features) compliance with verified provenance attestations. Using `build-from-source: true` or `verify-provenance: false` bypasses these security guarantees and is generally NOT recommended.\n\n| Input               | Default  | Description                                        |\n| ------------------- | -------- | -------------------------------------------------- |\n| `version`           | `latest` | Version to install (e.g., `v1.2.3` or `latest`)    |\n| `build-from-source` | `false`  | Build from source instead of downloading a release |\n| `verify-provenance` | `true`   | Verify GPG signatures, checksums, and attestations |\n\n#### Outputs\n\n| Output        | Description                                 |\n| ------------- | ------------------------------------------- |\n| `version`     | The version of dotsecenv that was installed |\n| `binary-path` | Full path to the installed binary           |\n\n#### Examples\n\n**Basic usage (latest release):**\n\n```yaml\njobs:\n  deploy:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: dotsecenv/dotsecenv@v0\n      - run: dotsecenv secret get DATABASE_URL\n```\n\n**Pin to a specific version:**\n\n```yaml\n- uses: dotsecenv/dotsecenv@v0\n  with:\n    version: v0.0.1\n```\n\n**Build from source:**\n\n```yaml\n- uses: dotsecenv/dotsecenv@v0\n  with:\n    build-from-source: true\n```\n\n### Shell Completions\n\ndotsecenv supports shell completions for Bash, Zsh, Fish, and PowerShell.\n\n#### Bash\n\nRequires the `bash-completion` package:\n\n```bash\n# macOS\nbrew install bash-completion@2\n\n# Debian/Ubuntu\nsudo apt install bash-completion\n\n# RHEL/CentOS/Fedora\nsudo dnf install bash-completion\n\n# Arch\nsudo pacman -S bash-completion\n```\n\nAdd to `~/.bashrc` or `~/.bash_profile`:\n\n```bash\n# Load bash-completion (macOS with Homebrew)\n[[ -r \"$(brew --prefix)/etc/profile.d/bash_completion.sh\" ]] \u0026\u0026 . \"$(brew --prefix)/etc/profile.d/bash_completion.sh\"\n\n# dotsecenv completions\nif command -v dotsecenv \u0026\u003e /dev/null; then\n  eval \"$(dotsecenv completion bash)\"\nfi\n```\n\n#### Zsh\n\nAdd to `~/.zshrc`:\n\n```zsh\n# dotsecenv completions\nif command -v dotsecenv \u0026\u003e /dev/null; then\n  eval \"$(dotsecenv completion zsh)\"\nfi\n```\n\n#### Fish\n\nAdd to `~/.config/fish/config.fish`:\n\n```fish\n# dotsecenv completions\nif command -v dotsecenv \u0026\u003e /dev/null\n  dotsecenv completion fish | source\nend\n```\n\n#### PowerShell\n\nAdd to your PowerShell profile (`$PROFILE`):\n\n```powershell\n# dotsecenv completions\nif (Get-Command dotsecenv -ErrorAction SilentlyContinue) {\n  dotsecenv completion powershell | Out-String | Invoke-Expression\n}\n```\n\n#### Pre-installed Paths\n\nIf you installed via a package manager (Homebrew, deb, rpm, Arch), completions are pre-installed at these paths:\n\n| Shell | Homebrew (macOS/Linux)                                            | Linux Packages (deb/rpm/Arch)                         |\n| ----- | ----------------------------------------------------------------- | ----------------------------------------------------- |\n| Bash  | `$(brew --prefix)/etc/bash_completion.d/dotsecenv`                | `/usr/share/bash-completion/completions/dotsecenv`    |\n| Zsh   | `$(brew --prefix)/share/zsh/site-functions/_dotsecenv`            | `/usr/share/zsh/site-functions/_dotsecenv`            |\n| Fish  | `$(brew --prefix)/share/fish/vendor_completions.d/dotsecenv.fish` | `/usr/share/fish/vendor_completions.d/dotsecenv.fish` |\n\n### Shell Plugins\n\nShell plugins that automatically load `.env` and `.secenv` files when entering directories\nare available for `zsh`, `bash`, and `fish`.\n\nFor example, given a `/path/to/project/.secenv` file, e.g.:\n\n```env\nA_SECRET={dotsecenv}\nANOTHER_SECRET={dotsecenv/SOME_OTHER_KEY}\nMY_NAMESPACED_SECRET={dotsecenv/my::SECRET}\n```\n\nThe three keys will be available as environment variables, when cd-ing into `/path/to/project/`.\n\n#### Install shell plugins\n\nYou can install zsh/bash/fish plugins with:\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/dotsecenv/plugin/main/install.sh | bash\n```\n\nFor plugin manager installation and additional details, see [github.com/dotsecenv/plugin#installation](https://github.com/dotsecenv/plugin#installation).\n\n### Basic Usage\n\n```bash\n# Initialize configuration\n## Create default config\ndotsecenv init config\n## Specify where to store the config\ndotsecenv init config -c /path/to/config\n## Initialize the config with a single vault\ndotsecenv init config -v /path/to/vault\n## Customize both the config and the vault location\ndotsecenv init config -c ... -v ...\n## Skip GPG detection (for systems without GPG installed)\ndotsecenv init config --no-gpg-program\n## Set GPG program path explicitly (without validation)\ndotsecenv init config --gpg-program /usr/local/bin/gpg\n\n# Initialize a vault\n## Interactive prompt, asking which vault to initialize\ndotsecenv init vault\n## Specify which vault to initialize\ndotsecenv init vault -v /path/to/vault\n\n# Login with your GPG fingerprint\ndotsecenv login \u003cFINGERPRINT\u003e\n\n# Store a secret (reads value from stdin)\necho \"secret-value\" | dotsecenv secret store MY_SECRET\n\n# Retrieve a secret\ndotsecenv secret get MY_SECRET\ndotsecenv secret get MY_SECRET --all   # All values across all vaults\ndotsecenv secret get MY_SECRET --last  # Most recent value across all vaults\ndotsecenv secret get MY_SECRET --json  # Output as JSON\n\n# Share a secret with another identity (auto-adds identity if needed)\ndotsecenv secret share MY_SECRET \u003cTARGET_FINGERPRINT\u003e\n\n# Revoke access to a secret\ndotsecenv secret revoke MY_SECRET \u003cTARGET_FINGERPRINT\u003e\n\n# Describe vaults with identities and secrets\ndotsecenv vault describe\ndotsecenv vault describe --json\n\n# Run health checks on vaults and environment\ndotsecenv vault doctor\ndotsecenv vault doctor --json\n\n# Validate vault and config\ndotsecenv validate\ndotsecenv validate --fix  # Attempt to fix issues\n```\n\n## Command Reference\n\n### Global Flags\n\n| Flag       | Short | Description                                 |\n| ---------- | ----- | ------------------------------------------- |\n| `--config` | `-c`  | Path to config file                         |\n| `--vault`  | `-v`  | Path to vault file or vault index (1-based) |\n| `--silent` | `-s`  | Silent mode (suppress warnings)             |\n\n### Commands\n\n| Command                                         | Description                                  |\n| ----------------------------------------------- | -------------------------------------------- |\n| `init config [--gpg-program\\|--no-gpg-program]` | Initialize configuration file                |\n| `init vault`                                    | Initialize vault file(s)                     |\n| `login FINGERPRINT`                             | Initialize user identity                     |\n| `secret store SECRET`                           | Store an encrypted secret (reads from stdin) |\n| `secret get SECRET [--all\\|--last\\|--json]`     | Retrieve a secret value                      |\n| `secret share SECRET FINGERPRINT [--all]`       | Share a secret with another identity         |\n| `secret revoke SECRET FINGERPRINT [--all]`      | Revoke access to a secret                    |\n| `vault describe [--json]`                       | Describe vaults with identities and secrets  |\n| `vault doctor [--json]`                         | Run health checks and fix issues             |\n| `validate [--fix]`                              | Validate vault and config integrity          |\n| `version`                                       | Show version information                     |\n| `completion`                                    | Generate shell completion scripts            |\n\n## Features\n\n- **Explicit Initialization**: Safe bootstrapping of configuration and vaults\n- **Encrypted at Rest**: All secrets are encrypted using AES-256-GCM (RFC 9580)\n- **Multi-User Support**: Secrets can be encrypted for multiple identities using GPG multi-recipient encryption\n- **Portable Vault**: The vault file can be safely committed to git and shared between machines\n- **Secret Sharing**: Share and revoke access to secrets with other team members\n- **Append-Only Design**: Cryptographic history is preserved for audit trails\n- **GPG Agent Integration**: Leverages gpg-agent for secure key management\n- **XDG Compliance**: Respects XDG Base Directory Specification for configuration files\n- **SUID Mode Support**: Restricted operations when running with elevated privileges\n- **JSON Output**: Machine-readable output format for scripting\n\n## Claude Code\n\nInstall the dotsecenv plugin for [Claude Code](https://claude.ai/claude-code):\n\n```\n/plugin marketplace add dotsecenv/dotsecenv\n/plugin install dotsecenv@dotsecenv\n```\n\nSee the [Claude Code guide](https://dotsecenv.com/guides/claude-code/) for details.\n\n## Configuration\n\n### Config File Resolution\n\nThe configuration file location is determined in the following order of precedence:\n\n1. **`-c` flag** (highest priority): Explicitly specify a config file path\n2. **`DOTSECENV_CONFIG` environment variable**: Override the default location\n3. **XDG default**: `$XDG_CONFIG_HOME/dotsecenv/config` (typically `~/.config/dotsecenv/config`)\n4. **SUID mode**: `/etc/dotsecenv/config` (when running with elevated privileges)\n\nWhen both `-c` and `DOTSECENV_CONFIG` are specified, the `-c` flag takes precedence and a warning is printed to stderr (unless `-s` silent mode is enabled):\n\n```\nwarning: DOTSECENV_CONFIG environment variable ignored because -c flag was specified\n```\n\nIn SUID mode, the `DOTSECENV_CONFIG` environment variable is ignored for security reasons.\n\n### Config File Format\n\nExample config:\n\n```yaml\n# Default configuration uses FIPS 186-5 compliant algorithm minimums\napproved_algorithms:\n  - algo: ECC\n    curves:\n      - P-384\n      - P-521\n    min_bits: 384\n  - algo: EdDSA\n    curves:\n      - Ed25519\n      - Ed448\n    min_bits: 255\n  - algo: RSA\n    min_bits: 2048\nvault:\n  - /path/to/vault1\ngpg:\n  program: gpg # Path to GPG executable\n```\n\n### GPG Configuration\n\nThe `gpg.program` option specifies the path to the GPG executable.\n\n**Resolution order:**\n\n1. **Explicit configuration**: If `gpg.program` is set, it must be an absolute path to an existing, executable program\n2. **PATH inference**: If `gpg.program` is not set (or empty), dotsecenv will look up `gpg` from your system PATH and print a warning to stderr\n\n**Examples:**\n\n```yaml\n# Explicit path (recommended for production)\ngpg:\n  program: /usr/bin/gpg\n\n# Not specified - will infer from PATH with a warning\ngpg:\n  program: \"\"\n\n# Windows with Gpg4win\ngpg:\n  program: \"C:\\\\Program Files (x86)\\\\GnuPG\\\\bin\\\\gpg.exe\"\n```\n\n**Automatic detection**: When running `dotsecenv init config`, dotsecenv will detect available GPG installations and set `gpg.program` to the detected absolute path. If multiple GPG installations are found, you'll be prompted to choose one.\n\n**When to use explicit paths:**\n\n- When you have multiple GPG versions installed\n- When GPG is installed in a non-standard location\n- In CI/CD environments where PATH may vary\n\n## Vault File Format\n\nDefault vault location: `$XDG_DATA_HOME/dotsecenv/vault`\n\nThe vault uses a JSONL (JSON Lines) format for efficient append operations and indexed lookups.\nEach entry includes a hash and cryptographic signature to prevent against tampering.\n\n**Header (Line 1):**\n\n```json\n{\n  \"version\": 1,\n  \"identities\": [\n    [\"FINGERPRINT1\", 2],\n    [\"FINGERPRINT2\", 3]\n  ],\n  \"secrets\": { \"SECRET_KEY\": { \"secret\": 4, \"values\": [5, 6] } }\n}\n```\n\n**Identity Entry:**\n\n```json\n{\n  \"type\": \"identity\",\n  \"data\": {\n    \"added_at\": \"2024-11-09T12:00:00Z\",\n    \"algorithm\": \"ECC\",\n    \"algorithm_bits\": 521,\n    \"curve\": \"P-521\",\n    \"created_at\": \"2024-10-01T10:00:00Z\",\n    \"fingerprint\": \"1E378219F90018AB2102B2131C238966B12A6F21\",\n    \"hash\": \"sha256:...\",\n    \"public_key\": \"base64...\",\n    \"signed_by\": \"1E378219F90018AB2102B2131C238966B12A6F21\",\n    \"signature\": \"base64...\",\n    \"uid\": \"user@example.com\"\n  }\n}\n```\n\n**Secret Definition Entry:**\n\n```json\n{\n  \"type\": \"secret\",\n  \"data\": {\n    \"added_at\": \"2024-11-09T12:05:00Z\",\n    \"hash\": \"sha256:...\",\n    \"key\": \"DATABASE_URL\",\n    \"signature\": \"base64...\",\n    \"signed_by\": \"1E378219F90018AB2102B2131C238966B12A6F21\"\n  }\n}\n```\n\n**Secret Value Entry:**\n\n```json\n{\n  \"type\": \"value\",\n  \"secret\": \"DATABASE_URL\",\n  \"data\": {\n    \"added_at\": \"2024-11-09T12:05:00Z\",\n    \"available_to\": [\"1E378219F90018AB2102B2131C238966B12A6F21\"],\n    \"hash\": \"sha256:...\",\n    \"signature\": \"base64...\",\n    \"signed_by\": \"1E378219F90018AB2102B2131C238966B12A6F21\",\n    \"value\": \"base64-encrypted-value\"\n  }\n}\n```\n\n## Security Features\n\n- **[RFC 9580](https://www.rfc-editor.org/rfc/rfc9580.html) OpenPGP compliance**: Modern OpenPGP standard with mandatory AEAD encryption\n- **AES-256-GCM symmetric encryption**: NIST-approved authenticated encryption ([SP 800-38D](https://csrc.nist.gov/pubs/sp/800/38/d/final))\n- **[FIPS 186-5](https://csrc.nist.gov/pubs/fips/186-5/final) digital signatures**: RSA, ECDSA, and EdDSA signature schemes for vault entry authenticity and non-repudiation\n- **FIPS 186-5 compliant defaults**: Algorithm minimums meet the Digital Signature Standard requirements\n- **FIPS 140-3 Crypto**: Release binaries are built with Go's native FIPS 140-3 cryptographic module (`GOFIPS140=v1.0.0`) for NIST-validated cryptographic primitives on all platforms\n- Multi-recipient PGP encryption with hybrid cryptography\n- Hash-based integrity checking (SHA-256/SHA-512)\n- GPG agent integration for secure key management\n- Full secret encryption/decryption lifecycle\n- Validation logic with optional auto-fix\n- SUID mode restrictions for elevated privilege protection\n- [SLSA Build Level 3](https://slsa.dev/spec/v1.2/build-requirements): Release binaries include verifiable provenance attestations generated via GitHub's [attest-build-provenance](https://github.com/actions/attest-build-provenance) action on hardened GitHub-hosted runners\n- **Hermetic E2E Testing**: Every pull request runs e2e tests in a network-isolated Linux namespace with eBPF verification via [harden-runner](https://github.com/step-security/harden-runner), proving zero external network connections. See [Security Model](https://dotsecenv.com/concepts/security-model/#hermetic-testing).\n\n### SUID Mode Restrictions\n\nWhen running with SUID privileges, the following restrictions apply:\n\n- `-c` and `-v` flags are blocked\n- `DOTSECENV_CONFIG` and `DOTSECENV_FINGERPRINT` environment variables are ignored\n- Config defaults to `/etc/dotsecenv/config`\n- Write operations are blocked: `login`, `init config`, `init vault`, `secret store`, `secret share`, `secret revoke`\n\nThis prevents privilege escalation attacks when the binary is installed with elevated permissions.\n\n## Exit Codes\n\n| Code | Name                  | Description                      |\n| ---- | --------------------- | -------------------------------- |\n| `0`  | Success               | Operation completed successfully |\n| `1`  | General Error         | Unspecified error                |\n| `2`  | Config Error          | Configuration file issue         |\n| `3`  | Vault Error           | Vault file issue                 |\n| `4`  | GPG Error             | GPG operation failed             |\n| `5`  | Auth Error            | Authentication failed            |\n| `6`  | Validation Error      | Validation failed                |\n| `7`  | Fingerprint Required  | No fingerprint configured        |\n| `8`  | Access Denied         | Permission denied                |\n| `9`  | Algorithm Not Allowed | Algorithm not in allow-list      |\n\n## Environment Variables\n\n| Variable                | Description                                             |\n| ----------------------- | ------------------------------------------------------- |\n| `DOTSECENV_CONFIG`      | Override config file path (ignored in SUID mode)        |\n| `DOTSECENV_FINGERPRINT` | Override fingerprint from config (ignored in SUID mode) |\n| `XDG_CONFIG_HOME`       | Override config directory (defaults to: `~/.config`)    |\n| `XDG_DATA_HOME`         | Override data directory (defaults to: `~/.local/share`) |\n\n## Known Limitations\n\n### Ed448 Keys (GnuPG v5 Format)\n\nEd448 keys generated by GnuPG 2.4+ use the OpenPGP v5 key format, which is not yet fully supported by the underlying cryptographic library (gopenpgp/go-crypto). This results in a parsing error when trying to add Ed448 identities:\n\n```shell\nfailed to get public key: failed to parse public key: gopenpgp: error in reading key ring: openpgp: invalid data: first packet was not a public/private key\n```\n\n**Workaround**: Use Ed25519 keys instead, which are fully supported and provide equivalent security for most use cases. Ed25519 keys use the OpenPGP v4 format which has full library support.\n\n**Status**: This limitation will be resolved when:\n\n- GnuPG adopts RFC 9580 v6 format for Ed448 keys, OR\n- go-crypto adds compatibility for GnuPG's v5 Ed448 format\n\nEd448 is included in the approved algorithms configuration to ensure readiness when support becomes available.\n\n## FAQ\n\n### How do I generate a GPG key?\n\n```bash\n# Generate a new GPG key and choose sensible defaults, i.e.:\n# - (9) ECC (sign and encrypt)\n# - (1) Curve 25519\n# - Key expiration: 1y\ngpg --full-generate-key\n```\n\n### agent_genkey failed: No pinentry\n\nIf you are unable to generate a key due to this error, install `pinentry`:\n\n```bash\n# macOS\nbrew install pinentry-mac\n\n# Linux\nsudo apt-get install pinentry\nsudo dnf install pinentry-tty\nsudo yum install pinentry-tty\nsudo pacman -S pinentry-tty\n# etc.\n```\n\nIn rare cases you may need to add a `pinentry-program` line to your `~/.gnupg/gpg-agent.conf` and restart the gpg-agent (`killall gpg-agent`).\n\n### gpg: signing failed: Inappropriate ioctl for device\n\nThis error occurs when GPG cannot find the terminal for pinentry input. Add the following to your shell profile (`~/.bashrc`, `~/.zshrc`):\n\n```bash\nexport GPG_TTY=$(tty)\n```\n\nOr for fish shell, add the following to `~/.config/fish/config.fish`:\n\n```fish\nset -gx GPG_TTY (tty)\n```\n\nThen restart your shell or run the command directly.\n\n### gpg: decryption failed\n\nIf you encounter this error, first try to define GPG_TTY (see above) before searching\nfor other possible solutions.\n\n```shell\n$ dotsecenv secret get bla\nfailed to decrypt secret: failed to decrypt with gpg-agent: exit status 2\nGPG error: gpg: decryption failed: No secret key\n```\n\n## Development\n\n### Setup\n\n```bash\n# Install all development tools (lefthook, golangci-lint, syft, goreleaser)\nmake install-tools\n```\n\n### Building\n\n```bash\n# Build with FIPS 140-3 crypto (no CGO required)\nmake build\n```\n\nThe default `make build` uses Go's native FIPS 140-3 cryptographic module (`GOFIPS140=v1.0.0`), which provides NIST-validated cryptographic primitives on all platforms without requiring CGO. See [go.dev/blog/fips140](https://go.dev/blog/fips140) for details.\n\n### Testing\n\n```bash\n# Run all tests\nmake test\n\n# Run tests with race condition detection\nmake test-race\n\n# Run end-to-end tests\nmake build e2e\n```\n\n### Linting\n\n```bash\n# Run linting (installs golangci-lint if needed)\nmake lint\n```\n\n### Releasing\n\nReleases are triggered by pushing a signed semver tag. Following GitHub Actions conventions, a major version tag (e.g., `v0`) should also be maintained to allow users to pin to a major version.\n\nThe [releasetools-cli](https://github.com/releasetools/cli) simplifies this process:\n\n```bash\nrt git::release --major --sign --force --push v0.1.2\n```\n\nThis creates both `v0.1.2` and `v0` tags pointing to the same commit, signs them, and pushes to the remote.\n\n## Security Considerations\n\n### What dotsecenv Protects Against\n\n- Accidental exposure of unencrypted secrets in version control\n- Secrets stored in plaintext on disk\n- Access to secrets by unauthorized users without GPG keys\n- Tampering with vault entries (signature verification)\n- Privilege escalation via SUID binaries\n- Stealth network exfiltration of secrets during CI/CD (hermetic testing)\n\n### What dotsecenv DOES NOT Protect Against\n\n- Operating system-level access (root/admin can always read memory)\n- Compromised GPG private keys\n- Quantum computing attacks (future consideration)\n- Side-channel attacks\n- Physical memory dumps\n- Environment snooping\n\n### Recommendations\n\n1. **Private Keys**: Never commit GPG private keys to repositories\n2. **Key Management**: Use gpg-agent with passphrase protection\n3. **Vault Files**: Can be committed to git, technically safe in public repositories, but not recommended\n4. **Multi-User Systems**: Use strong user isolation and file permissions\n5. **Monitoring**: Audit all secret access in production environments\n6. **Rotation**: Periodically rotate encryption keys by updating and then re-encrypting secrets\n\n## License\n\nApache 2.0 License. See LICENSE file for details.\n\n## Acknowledgments\n\n- [SOPS](https://github.com/getsops/sops) for the idea of storing encrypted secrets alongside source code\n- [ProtonMail gopenpgp](https://github.com/protonmail/gopenpgp) for PGP cryptography\n- [Cobra](https://github.com/spf13/cobra) for CLI framework\n- [Go standard library](https://golang.org/) for easy multi-platform functionality\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdotsecenv%2Fdotsecenv","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdotsecenv%2Fdotsecenv","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdotsecenv%2Fdotsecenv/lists"}