
Безопасный CLI-инструмент для управления секретами окружения с использованием встроенных хранилищ учетных данных ОС (связка ключей macOS, Linux Secret Service, диспетчер учетных данных Windows)
Безопасное управление секретами окружения с использованием встроенных хранилищ учётных данных ОС.

myapp.dev, stripe-api.prod, work.staging)cmd (поиск, список, запуск, удаление).env (с отслеживанием генерации через audit)eval $(envsec env)).env (с обнаружением конфликтов)envsec tui) для управления секретами без запоминания командЭто монорепозиторий, содержащий следующие пакеты:
Для программного доступа к секретам из Node.js или Bun используйте @envsec/sdk:```bash
npm install @envsec/sdk
- name: Загрузить отчёты о покрытии в Codecov
uses: codecov/codecov-action@v5
with:
files: build/reports/jacoco/test/jacocoTestReport.xml
flags: integration
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}```typescript
import { loadSecrets } from "@envsec/sdk";
// Load and inject into process.env
await loadSecrets({ context: "myapp.dev", inject: true });
// Or use the client for full control
import { EnvsecClient } from "@envsec/sdk";
const client = await EnvsecClient.create({ context: "myapp.dev" });
const apiKey = await client.get("api.key");
await client.close();
См. полную документацию SDK по всем API, поддержке нескольких контекстов и опциям.
Никаких дополнительных зависимостей. Используется встроенная связка ключей (Keychain) через CLI-инструмент security.
Требуется libsecret-tools (предоставляет команду secret-tool), которая взаимодействует с GNOME Keyring, KDE Wallet или любым провайдером Secret Service API через D-Bus.```bash
sudo apt install libsecret-tools
sudo dnf install libsecret
sudo pacman -S libsecret
A running D-Bus session and a keyring daemon (e.g. `gnome-keyring-daemon`) must be active. Most desktop environments handle this automatically.
### Windows
No extra dependencies. Uses the built-in Windows Credential Manager via `cmdkey` and PowerShell.
## Установка
### Homebrew (macOS / Linux)```bash
brew tap davidnussio/homebrew-tap
brew install envsec
npm install -g envsec
### npx (без установки)```bash
npx envsec
mise use -g npm:envsec
## Использование
Большинство команд требуют указания контекста с помощью `--context` (или `-c`).
Контекст — это свободная метка для группировки секретов, например `myapp.dev`, `stripe-api.prod`, `work.staging`.
### Глобальные опции
Эти опции доступны для всех команд:
- `--context`, `-c` — Имя контекста (например, `myapp.dev`, `stripe-api.prod`). Также читает переменную окружения `ENVSEC_CONTEXT`
- `--debug`, `-d` — Включить отладочное логирование
- `--json` — Вывод в формате JSON для скриптов
- `--db` — Путь к файлу базы данных SQLite (по умолчанию: `~/.envsec/store.sqlite`). Также читает переменную окружения `ENVSEC_DB`
### Пользовательский путь к базе данных
По умолчанию метаданные хранятся в `~/.envsec/store.sqlite`. Вы можете переопределить это с помощью `--db` или переменной окружения `ENVSEC_DB`:```bash
# Use a project-local database
envsec --db ./local-store.sqlite -c myapp.dev list
# Or via environment variable
export ENVSEC_DB=/shared/team/envsec.sqlite
envsec -c myapp.dev list
Флаг --db имеет приоритет над ENVSEC_DB. Варианты использования включают базы данных для отдельных проектов, общие базы данных на сетевых дисках и CI/CD с временным хранилищем.
Хранит секрет в хранилище учётных данных ОС.
<key> — Имя ключа секрета (например, api.key, db.password)--value, -v — Сохраняемое значение (опустите для интерактивного маскированного ввода)--expires, -e — Срок действия (например, 30m, 2h, 7d, 4w, 3mo, 1y)```bashenvsec -c myapp.dev add api.key --value "sk-abc123"
envsec -c myapp.dev add api.key -v "sk-abc123"
envsec -c myapp.dev add api.key
envsec -c myapp.dev add api.key -v "sk-abc123" --expires 30d
envsec -c myapp.dev add api.key -v "sk-abc123" -e 6mo
### Получить секрет
Извлечь значение секрета из хранилища учетных данных ОС.
- `<key>` — Имя ключа секрета для извлечения
- `--quiet`, `-q` — Выводить только сырое значение (без предупреждений или дополнительного вывода)
- `--json` — Вывод в формате JSON (включает контекст, ключ, значение, expires_at)```bash
envsec -c myapp.dev get api.key
# Print only the raw value (no warnings or extra output)
envsec -c myapp.dev get api.key --quiet
envsec -c myapp.dev get api.key -q
Удалить секрет из хранилища учетных данных ОС.
<key> — Имя ключа секрета для удаления (необязательно, если используется --all)--yes, -y — Пропустить запрос подтверждения--all — Удалить все секреты в контексте```bash
envsec -c myapp.dev delete api.keyenvsec -c myapp.dev del api.key
### Переименование секрета
Переименуйте ключ секрета в том же контексте. Значение и метаданные срока действия сохраняются.
- `<old-key>` — Текущее имя ключа секрета
- `<new-key>` — Новое имя ключа секрета
- `--force`, `-f` — Перезаписать цель, если она уже существует```bash
# Rename a key
envsec -c myapp.dev rename old.key new.key
# Overwrite target if it already exists
envsec -c myapp.dev rename old.key existing.key --force
Вывести все ключи секретов и метаданные в контексте.
--json — Вывод в формате JSON```bash
envsec -c myapp.dev list### Список всех контекстов
Список всех доступных контекстов с количеством секретов.
- `--json` — Вывод в формате JSON```bash
# Without --context, lists all available contexts with secret counts
envsec list
Поиск секретов или контекстов с использованием glob-шаблонов.
<pattern> — Glob-шаблон для поиска (например, api.*, myapp.*)--json — Вывод в формате JSON```bashenvsec -c myapp.dev search "api.*"
envsec search "myapp.*"
### Перемещение секретов между контекстами
Перемещение секретов из одного контекста в другой. Исходные секреты удаляются после перемещения.
- `<pattern>` — Шаблон glob или точный ключ для перемещения (необязательно, если используется `--all`)
- `--to`, `-t` — Целевой контекст для перемещения секретов
- `--all` — Переместить все секреты из исходного контекста
- `--force`, `-f` — Перезаписать существующие секреты в целевом контексте
- `--yes`, `-y` — Пропустить запрос подтверждения```bash
# Move a single secret
envsec -c myapp.dev move api.token --to myapp.prod
# Move secrets matching a glob pattern
envsec -c myapp.dev move "redis.*" --to myapp.prod -y
# Move all secrets from one context to another
envsec -c myapp.dev move --all --to myapp.prod -y
# Overwrite existing secrets in the target context
envsec -c myapp.dev move "redis.*" --to myapp.prod --force -y
Копирование секретов из одного контекста в другой. Исходные секреты остаются нетронутыми.
<pattern> — Glob-шаблон или точный ключ для копирования (необязательно, если используется --all)--to, -t — Целевой контекст, в который копировать секреты--all — Копировать все секреты из исходного контекста--force, -f — Перезаписывать существующие секреты в целевом контексте--yes, -y — Пропустить запрос подтверждения```bashenvsec -c myapp.dev copy api.token --to myapp.staging
envsec -c myapp.dev copy "redis.*" --to myapp.staging -y
envsec -c myapp.dev copy --all --to myapp.staging -y
envsec -c myapp.dev copy "redis.*" --to myapp.staging --force -y
### Выполнить команду с секретами
Выполнить команду, подставляя секретные значения через плейсхолдеры или внедряя их как переменные окружения.
- `<command>` — Команда для выполнения. Используйте плейсхолдеры `{key}` для подстановки секретов
- `--inject`, `-i` — Внедрить все секреты контекста как переменные окружения (`KEY.NAME` → `KEY_NAME`)
- `--save`, `-s` — Сохранить эту команду для последующего использования
- `--name`, `-n` — Имя для сохранённой команды (запрашивается интерактивно, если опущено с `--save`)```bash
# Placeholders {key} are resolved with secret values before execution
envsec -c myapp.dev run 'curl {api.url} -H "Authorization: Bearer {api.token}"'
# Any {dotted.key} in the command string is replaced with its value
envsec -c myapp.prod run 'psql {db.connection_string}'
# Inject ALL context secrets as environment variables (KEY.NAME → KEY_NAME)
envsec -c myapp.dev run --inject 'node server.js'
envsec -c myapp.dev run -i 'docker compose up'
# Combine --inject with placeholders
envsec -c myapp.dev run --inject 'curl {api.url} -H "Authorization: Bearer $API_TOKEN"'
# Save the command for later use with --save (-s) and --name (-n)
envsec -c myapp.dev run --save --name deploy 'kubectl apply -f - <<< {k8s.manifest}'
# If you use --save without --name, you'll be prompted interactively
envsec -c myapp.dev run --save 'psql {db.connection_string}'
Если какой-либо плейсхолдер ссылается на несуществующий секрет, команда не выполнится, и вы увидите четкую ошибку:``` ❌ Missing secrets in context "myapp.dev":
Add them with: envsec -c myapp.dev add
### Сохраненные команды
Сохраненные команды находятся в подкоманде `cmd`, держа их отдельно от секретных операций.
#### cmd list
Список всех сохраненных команд.```bash
envsec cmd list
Запустить сохранённую команду (использует контекст, с которым она была сохранена).
<name> — Имя сохранённой команды для выполнения--override-context, -o — Переопределить сохранённый контекст во время выполнения--quiet, -q — Подавить информационный вывод (выводить только результат команды)--inject, -i — Внедрить все секреты контекста как переменные окружения```bash
envsec cmd run deployenvsec cmd run deploy --quiet envsec cmd run deploy -q
envsec cmd run deploy --override-context myapp.prod envsec cmd run deploy -o myapp.prod
envsec cmd run deploy --inject envsec cmd run deploy -i
#### cmd search
Поиск сохраненных команд по имени или строке команды.
- `<pattern>` — Шаблон поиска
- `--name`, `-n` — Поиск только по именам команд
- `--command`, `-m` — Поиск только по строкам команд```bash
envsec cmd search psql
# Search only by name
envsec cmd search deploy -n
# Search only by command string
envsec cmd search kubectl -m
Удалить сохранённую команду.
<name> — Имя команды для удаления```bash
envsec cmd delete deploy### Создать файл .env
Экспортировать все секреты из контекста в файл `.env`.
- `--output`, `-o` — Путь к выходному файлу (по умолчанию: `.env`)```bash
# Creates .env with all secrets from the context
envsec -c myapp.dev env-file
# Specify a custom output path
envsec -c myapp.dev env-file --output .env.local
Вывод операторов экспорта для использования с eval или источником оболочки.
--shell, -s — Целевой синтаксис оболочки: bash (по умолчанию), zsh, fish, powershell--unset, -u — Вывод команд снятия/удаления вместо экспорта```basheval $(envsec -c myapp.dev env)
envsec -c myapp.dev env --shell fish envsec -c myapp.dev env --shell powershell
eval $(envsec -c myapp.dev env --unset)
envsec -c myapp.dev env --unset --shell fish
Поддерживаемые оболочки: `bash` (по умолчанию), `zsh`, `fish`, `powershell`. Ключи преобразуются в `UPPER_SNAKE_CASE` (например, `api.token` → `API_TOKEN`). Вывод идёт в stdout, поэтому его можно передать в `eval` или выполнить напрямую — файл на диск не записывается.
### Запуск сессии оболочки с ограниченными секретами
Запускает интерактивную подоболочку со всеми секретами из контекста, переданными в качестве переменных окружения. Когда вы выходите (`exit`), секреты исчезают — очистка не требуется.
- `--shell`, `-s` — Оболочка для запуска (`bash`, `zsh`, `fish`, `powershell`). По умолчанию: автоопределение
- `--no-inherit` — Не наследовать переменные окружения родительского процесса
- `--quiet`, `-q` — Подавить приветственное сообщение и сообщение о выходе```bash
envsec -c myapp.dev shell
[No input content provided to translate.]``` ▶ envsec shell — context: myapp.dev (8 secrets loaded) Type 'exit' or press Ctrl+D to leave the session.
(envsec:myapp.dev) ~ $ echo $DATABASE_URL postgres://user:pass@localhost/mydb
(envsec:myapp.dev) ~ $ exit → Exiting envsec shell — secrets cleared.
[](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-34362)
[](https://www.mandiant.com/resources/blog/fortinet-multi-platform-vulnerability)
[](https://github.com/fortinet/fortinet-vulnerability)
[](https://fortiguard.com/psirt/FG-IR-23-200)```bash
# Force a specific shell
envsec -c myapp.dev shell --shell zsh
# Only envsec secrets in env (no parent variables, except PATH)
envsec -c myapp.dev shell --no-inherit
# Suppress the startup/exit banner
envsec -c myapp.dev shell --quiet
Переменная ENVSEC_CONTEXT всегда задана внутри сессии, поэтому вы можете
ссылаться на неё в скриптах или настройках приглашения.
Импорт секретов из файла .env в контекст.
--input, -i — Путь к входному .env-файлу (по умолчанию: .env)--force, -f — Перезаписывать существующие секреты без запроса--batch, -b — Пакетный режим: отложить сохранение в базу данных до завершения импорта всех секретов```bashenvsec -c myapp.dev load
envsec -c myapp.dev load --input .env.local
envsec -c myapp.dev load --force
Ключи преобразуются из `UPPER_SNAKE_CASE` в `dotted.lowercase` (например, `API_TOKEN` → `api.token`). Если ключ уже существует, он пропускается с предупреждением, если не указан `--force` (`-f`).
### Обмен секретами (зашифрованными GPG)
Зашифровать все секреты из контекста для члена команды с помощью GPG.
- `--encrypt-to` — ключ получателя GPG (email, ID ключа или отпечаток) для шифрования
- `--output`, `-o` — Путь к выходному файлу (по умолчанию: stdout). Используйте `-` для явного указания stdout
- `--json` — Использовать JSON формат внутри зашифрованной полезной нагрузки (по умолчанию: формат `.env`)```bash
# Encrypt all secrets from a context for a team member
envsec -c myapp.dev share --encrypt-to [email protected]
# Save encrypted output to a file
envsec -c myapp.dev share --encrypt-to [email protected] -o secrets.enc
# Use JSON format inside the encrypted payload
envsec -c myapp.dev --json share --encrypt-to [email protected] -o secrets.enc
Получатель может расшифровать с помощью gpg --decrypt secrets.enc и передать результат в envsec load. По умолчанию зашифрованная нагрузка использует формат .env (KEY="value"); с флагом --json используется структурированный JSON-объект. Требуется установленный GPG и наличие открытого ключа получателя в вашей связке ключей.
Проверка на истекшие или истекающие секреты и отслеживаемые экспорты файлов .env.
--within, -w — Показать секреты, истекающие в течение этого срока (по умолчанию: 30d). Используйте 0d, чтобы показать только уже истекшие--json — Вывод в формате JSON```bashenvsec -c myapp.dev audit
envsec -c myapp.dev audit --within 7d
envsec -c myapp.dev audit --within 0d
envsec audit
envsec -c myapp.dev audit --json
Secrets with an `--expires` duration set via `envsec add` are tracked in metadata. The `audit` command scans for secrets that are already expired or will expire within the specified window. The `get` and `list` commands also display expiry warnings inline.
The `audit` command also tracks generated `.env` files. Every time `env-file` is used, the output path, context, and timestamp are recorded. The audit output includes a second section listing these files. If a tracked `.env` file no longer exists on disk, audit automatically removes it from the metadata and reports the cleanup.
### Generate a random secret
Generate a cryptographically secure random secret, optionally storing it.
- `<key>` — Secret key name (optional; omit for standalone password generation)
- `--length`, `-l` — Length of the generated secret (default: `32`)
- `--prefix`, `-p` — Prefix to prepend to the generated secret (e.g. `sk_`)
- `--expires`, `-e` — Expiry duration (e.g. `30m`, `2h`, `7d`, `4w`, `3mo`, `1y`)
- `--alphanumeric`, `-a` — Use only alphanumeric characters `[a-zA-Z0-9]` (default)
- `--special`, `-s` — Include common special characters `[a-zA-Z0-9!@#$%^&*]`
- `--all-chars`, `-A` — Use all printable ASCII characters for maximum entropy```bash
# Generate and store a 32-char alphanumeric secret
envsec -c myapp.dev secret api.key
# Custom length and prefix
envsec -c myapp.dev secret api.key --prefix "sk_" --length 48
# Character sets:
# --alphanumeric (-a) [a-zA-Z0-9] (default)
# --special (-s) [a-zA-Z0-9] + !@#$%^&*
# --all-chars (-A) all printable ASCII
envsec -c myapp.dev secret db.password --special --length 64
# With expiry
envsec -c myapp.dev secret api.key --prefix "sk_" -l 48 --expires 90d
# Standalone password generator (no store, just print)
envsec secret --length 32
envsec secret --special --length 64 --prefix "pk_"
Когда указаны и контекст, и ключ, сгенерированное значение сохраняется и выводится. Если ни то, ни другое не указано, исходное значение выводится в stdout — полезно для передачи в pbcopy, xclip или другие инструменты.
envsec включает полноэкранный терминальный интерфейс для интерактивного управления секретами — нет необходимости запоминать команды.```bash
envsec tui
envsec -c myapp.dev tui
The TUI предоставляет восемь экранов, доступных из главного меню:
- **Contexts** — просмотр всех контекстов, установка активного контекста с помощью `s`, очистка контекста с помощью `x`, просмотр количества секретов, удаление целых контекстов
- **Secrets** — список секретов в таблице, раскрытие значений, добавление или удаление секретов
- **Add Secret** — интерактивная форма с маскированным вводом и необязательной продолжительностью действия
- **Search** — поиск по шаблону glob среди секретов или контекстов
- **Saved Commands** — список, просмотр и удаление сохранённых шаблонов команд
- **Audit** — проверка на истекшие/истекающие секреты, просмотр отслеживаемых экспортов файлов `.env`
- **Import .env** — загрузка секретов из файла `.env` в текущий контекст
- **Export .env** — экспорт секретов в файл `.env` (отслеживается для аудита)
Сочетания клавиш:
| Клавиша | Действие |
|---------|----------|
| `↑` / `↓` | Навигация по пунктам меню и строкам таблицы |
| `Enter` | Выбрать / подтвердить |
| `c` | Открыть просмотр контекстов (главное меню) |
| `s` | Установить выбранное как активный контекст (просмотр контекстов) |
| `x` | Очистить активный контекст (просмотр контекстов) |
| `a` | Добавить новый секрет (просмотр секретов) |
| `d` | Удалить выбранный элемент |
| `r` | Показать значение секрета (детальный просмотр) |
| `Esc` | Назад / отмена |
| `q` | Выйти из TUI |
### Диагностика вашей установки
Запустите проверки работоспособности, чтобы убедиться в корректности вашей установки envsec.
- `--json` — Вывод в формате JSON для использования в скриптах```bash
# Run all health checks
envsec doctor
# JSON output for scripting
envsec --json doctor
Команда doctor проверяет, что ваша установка envsec работает корректно. Она проверяет:
ENVSEC_DB, ENVSEC_CONTEXT)envsec поддерживает динамическое автодополнение по табуляции для bash, zsh и fish. Дополнения учитывают контекст: они предлагают ваши актуальные имена контекстов, ключи секретов и сохранённые имена команд в реальном времени, запрашивая базу данных метаданных.```bash
eval "$(envsec --completions bash)"
eval "$(envsec --completions zsh)"
envsec --completions fish | source
Что динамически завершается:
- `--context` / `-c` — выводит список всех ваших контекстов
- Аргументы секретного ключа (`get`, `add`, `delete`) — выводит ключи для текущего контекста
- `cmd run` / `cmd delete` — выводит имена сохраненных команд
- `--override-context` / `-o` — выводит контексты для `cmd run`
- Подкоманды, флаги и статические варианты (оболочки и т.д.) также завершаются
## Сравнение
Как envsec соотносится с другими инструментами управления секретами окружения?
| Возможность | envsec | dotenv / dotenvx | 1Password CLI (`op`) |
|---|---|---|---|
| Хранилище секретов | Системное хранилище учётных данных ОС (Keychain, Secret Service, Credential Manager) | Файлы `.env` на диске (dotenvx добавляет шифрование) | Облачное хранилище 1Password |
| Шифрование в покое | Делегировано ОС (Keychain, GNOME Keyring, DPAPI) | Нет (dotenv) / ECIES на файл (dotenvx) | AES-256 в облаке 1Password |
| Секреты на диске | Никогда — значения сразу попадают в системное хранилище | Всегда — файлы `.env` по умолчанию в открытом виде | Никогда локально (извлекаются во время выполнения из облака) |
| Офлайн-доступ | Полный — секреты локальны в системном хранилище | Полный — файлы локальны | Требуется сеть (кэшированные элементы доступны офлайн в приложении) |
| Учётная запись / подписка | Нет — бесплатно, с открытым исходным кодом, без регистрации | Бесплатно (dotenv) / бесплатно с открытым исходным кодом (dotenvx) | Платная подписка (от ~$3/мес для частных лиц, ~$8/мес на пользователя для бизнеса) |
| Кроссплатформенность | macOS, Linux, Windows | Любая платформа с Node.js / любая среда выполнения (dotenvx) | macOS, Linux, Windows |
| Организация контекстов/окружений | Контексты (например, `myapp.dev`, `stripe.prod`) | Отдельные файлы `.env` для каждого окружения | Хранилища и элементы |
| Запуск команд с секретами | `envsec run` — интерполяция заполнителей + `--inject` переменные окружения | `dotenvx run -- cmd` — внедрение из зашифрованного `.env` | `op run -- cmd` — внедрение через ссылки на секреты |
| Экспорт в файл `.env` | `envsec env-file` (отслеживается для аудита) | Родной формат — файлы `.env` являются источником истины | `op inject --out-file` |
| Импорт из файла `.env` | `envsec load` (с обнаружением конфликтов) | Н/П — `.env` является основным хранилищем | Ручное создание элементов |
| Экспорт переменных окружения в оболочку | `eval $(envsec env)` — bash, zsh, fish, powershell | `dotenvx run` или `node -r dotenv/config` | `op run --env-file` |
| Интерактивный сеанс оболочки | `envsec shell` — изолированная подоболочка с автоматической очисткой | Не встроено | Не встроено |
| Поиск секретов | Глобальные шаблоны по ключам и контекстам | Не встроено | Фильтрация `op item list --tags/--category` |
| Аудит срока действия/ротации | `envsec audit` — просроченные, истекающие, отслеживаемые файлы `.env` | Не встроено | Watchtower (в приложении, не в CLI) |
| Сохранённые команды | `envsec cmd` — сохранить, вывести список, найти, выполнить, удалить | Не встроено | Не встроено |
| Перемещение/копирование секретов | `envsec move` и `envsec copy` между контекстами | Ручное копирование файлов | `op item move` между хранилищами |
| Переименование секретов | `envsec rename` (сохраняет значение и метаданные) | Ручное редактирование файла `.env` | `op item edit` |
| Обмен с GPG-шифрованием | `envsec share --encrypt-to` | Зашифрованные файлы `.env`, сохранённые в git (dotenvx) | Встроенный обмен хранилищами, подготовка команды |
| Интерактивный TUI | `envsec tui` — полноэкранный терминальный интерфейс | Не встроено | Не встроено |
| Диагностика здоровья | `envsec doctor` — проверяет платформу, связку ключей, целостность БД | Не встроено | Не встроено |
| Автодополнение в оболочке | Динамическое (контексты, ключи, команды) для bash, zsh, fish | Не встроено | Статическое дополнение для bash, zsh, fish, powershell |
| SDK / программный доступ | `@envsec/sdk` для Node.js / Bun | `require('dotenv').config()` — основной сценарий использования | SDK 1Password (Node.js, Python, Go и др.) |
| Работа в команде / многопользовательский режим | GPG-обмен (вручную) | Обмен на основе git с зашифрованными `.env` (dotenvx) | Встроенное управление командой, RBAC, журналы аудита |
<!-- | CI/CD интеграция | Стандартный CLI — работает везде, где выполняется Node.js | `dotenvx run` в любом CI-пайплайне | Сервисные учётные записи, нативные интеграции CI/CD | -->
| Биометрическая аутентификация | Наследует биометрию ОС (например, разблокировка Keychain на macOS) | Нет | Отпечаток пальца / Touch ID через интеграцию с приложением |
| Отслеживание метаданных | SQLite (имена ключей, метки времени — никогда значения) | Нет | История элементов и журналы аудита в облаке |
Коротко: dotenv — самый простой подход (файлы на диске), 1Password CLI — самый функциональный для команд с облачной синхронизацией и RBAC, а envsec находится посередине — предлагает шифрование на уровне ОС без учётных записей, без облачных зависимостей и ориентированный на разработчика рабочий процесс, выходящий за рамки возможностей файлов `.env`.
## Как это работает
Секреты хранятся в собственном хранилище учётных данных ОС. Бэкенд выбирается автоматически в зависимости от платформы:
| ОС | Бэкенд | Инструмент / API |
|---------|-------------------------------|-----------------------------------|
| macOS | Keychain | `security` CLI |
| Linux | Secret Service API (D-Bus) | `secret-tool` (libsecret) |
| Windows | Credential Manager | `cmdkey` + PowerShell (advapi32) |
Метаданные (имена ключей, метки времени) хранятся в базе данных SQLite по пути `~/.envsec/store.sqlite` (настраивается через `--db` или `ENVSEC_DB`). Ключи должны содержать хотя бы один разделитель-точку (например, `service.account`), что соответствует структуре сервис/учётная запись в хранилище учётных данных.
## Безопасность
envsec построен на простом принципе: ваши секреты должны храниться в ОС, а не в dot-файлах. Каждое проектное решение исходит из этого принципа.
### Как envsec защищает ваши секреты
**Шифрование на уровне ОС, никакой собственной криптографии.** Значения секретов хранятся напрямую в macOS Keychain, GNOME Keyring / KDE Wallet или Windows Credential Manager. envsec никогда не изобретает собственное шифрование — оно делегирует эту задачу проверенным хранилищам учётных данных, которые уже предоставляет ваша операционная система, защищённым вашим пользовательским сеансом и (на macOS) связкой ключей входа.
**Полная поддержка Unicode.** Значения секретов могут содержать любые символы Unicode, включая эмодзи и буквы с диакритическими знаками. Значения кодируются в Base64 перед сохранением в системное хранилище, что позволяет избежать особенностей кодирования, специфичных для платформы (например, шестнадцатеричное кодирование не-ASCII вывода в macOS `security` CLI). Секреты в устаревшем открытом тексте читаются прозрачно для обратной совместимости.
**Секреты никогда не записываются на диск в открытом виде.** Значения попадают прямо из вашего терминала в системное хранилище учётных данных. Они никогда не записываются в конфигурационные файлы, журналы или промежуточное хранилище.
**Нет секретов в выводе терминала.** Команды `list` и `search` отображают только имена ключей — значения никогда не выводятся. Это предотвращает попадание секретов в буфер прокрутки, записи экрана и от просмотра через плечо.
**Безопасное выполнение команд.** Команда `run` внедряет секреты как переменные окружения дочернего процесса, а не интерполирует их в строку команды. Это означает, что значения секретов не отображаются в выводе `ps` или истории оболочки. Если какой-либо указанный секрет отсутствует, команда полностью блокируется — никакого частичного выполнения с неполными учётными данными.
**Проверка ввода и предотвращение внедрения.** Имена контекстов проверяются по строгому разрешённому списку (буквенно-цифровые символы, точки, дефисы, подчёркивания) с проверками на обход пути и загрязнение прототипа. Все SQLite-запросы используют подготовленные операторы с параметрами привязки, что предотвращает SQL-инъекции. Аргументы PowerShell в Windows экранируются для защиты от внедрения команд.
**Ограничительные права доступа к файлам.** Каталог метаданных (`~/.envsec/`) создаётся с правами `0700`, а база данных SQLite — с `0600`, что ограничивает доступ только владельцем.
### Известные ограничения и области для улучшения
Мы верим в честность перед пользователями относительно того, что envsec пока не охватывает. Это реальные компромиссы, а не ошибки — и их понимание помогает вам принимать обоснованные решения.
**Метаданные видны.** База данных SQLite в `~/.envsec/store.sqlite` хранит имена ключей, имена контекстов и метки времени — никогда значения секретов, но достаточно, чтобы показать, *какие* секреты существуют. Там же хранятся шаблоны сохранённых команд (с заполнителями `{key}`). Если конфиденциальность метаданных для вас важна, убедитесь, что ваш домашний каталог находится на зашифрованном томе.
**Экспорт `env-file` — в открытом виде.** Команда `env-file` записывает значения секретов в файл `.env` на диск. Это, по сути, чувствительные данные — обращайтесь с выходным файлом соответствующим образом и никогда не сохраняйте его в системе контроля версий. Считайте это удобным мостом, а не механизмом хранения.
**Выполнение в оболочке сопряжено с неотъемлемым риском.** Команда `run` передаёт ваш шаблон команды через `/bin/sh` (или `cmd.exe` в Windows). Если сам шаблон получен из ненадёжного источника, возможна инъекция в оболочку. Запускайте только те шаблоны команд, которые вы написали или которым доверяете.
**Нет контроля доступа между контекстами.** Любой процесс, запущенный от имени вашего пользователя ОС, может прочитать все секреты всех контекстов. envsec полагается на изоляцию пользователей на уровне ОС — он не добавляет собственный уровень авторизации между контекстами.
**Серверные среды Linux.** В Linux envsec зависит от активного сеанса D-Bus и демона связки ключей (например, `gnome-keyring-daemon`). В контейнерах или на серверах без графического сеанса связка ключей может быть недоступна или может хранить секреты с более слабой защитой.
**Шифрование зависит от вашей ОС.** envsec не добавляет дополнительного шифрования в состоянии покоя сверх того, что предоставляет собственное хранилище учётных данных. В системах без полнодискового шифрования злоумышленник с физическим доступом потенциально может извлечь секреты из связки ключей. Мы рекомендуем включить полнодисковое шифрование (FileVault, LUKS, BitLocker) для максимальной защиты.
## Разработка
### Предварительные требования
- Node.js >= 22
- pnpm
### Настройка```bash
git clone https://github.com/davidnussio/envsec.git
cd envsec
pnpm install
pnpm run build
packages/
cli/ → envsec CLI (published as envsec)
sdk/ → Node.js/Bun SDK (published as @envsec/sdk)
core/ → Core engine, shared by CLI and SDK (published as @envsec/core)
tui/ → Interactive terminal UI (published as @envsec/tui)
apps/
website/ → Documentation website
### Общие команды```bash
# Build all packages
pnpm run build
# Lint and format check (all packages)
pnpm run check
# Auto-fix lint and formatting
pnpm run fix
# Release (build + changeset publish)
pnpm run release
Создайте временный псевдоним, чтобы использовать локальную сборку так, как если бы она была установлена глобально:```bash
alias envsec="node $(pwd)/packages/cli/dist/main.js"
alias envsec "node (pwd)/packages/cli/dist/main.js"
### Тестирование автодополнения оболочки локально
После сборки и настройки псевдонима загрузите автодополнения в текущем сеансе:```bash
# Bash
alias envsec="node $(pwd)/packages/cli/dist/main.js"
eval "$(envsec --completions bash)"
# Zsh
alias envsec="node $(pwd)/packages/cli/dist/main.js"
eval "$(envsec --completions zsh)"
# Fish
alias envsec "node (pwd)/packages/cli/dist/main.js"
envsec --completions fish | source
Затем нажмите TAB после envsec -c , чтобы увидеть ваши контексты, или после envsec -c myapp.dev get , чтобы увидеть ключи секретов.
Сквозные интеграционные тесты покрывают полный жизненный цикл CLI (add, get, list, search, env-file, load, delete, run, cmd, audit, share, completions).```bash
pnpm run build
bash packages/cli/test/e2e-test.sh
pwsh packages/cli/test/e2e-test.ps1
CI запускается автоматически при push/PR в ветку `main` через GitHub Actions, выполняя `e2e-test.sh` на macOS и Ubuntu, и `e2e-test.ps1` на Windows.
## Лицензия
MIT
| Пакет | Описание | npm |
|---|
envsec | CLI-инструмент для управления секретами | |
@envsec/sdk | Node.js / Bun SDK для программной загрузки секретов | |
@envsec/core | Основной движок — адаптеры хранилищ учётных данных ОС + база метаданных | |
@envsec/tui | Интерактивный терминальный интерфейс для управления секретами |