Skip to main content
Glama
DINAKAR-S

keywarden

by DINAKAR-S

keywarden

Ваш ИИ-агент может использовать ваши API-ключи. Но никогда не сможет их прочитать.

keywarden — это локальное зашифрованное хранилище учётных данных, которое говорит на MCP. Claude Code, Claude Desktop, Cursor или любой MCP-клиент подключается к нему и получает две возможности: совершать аутентифицированный API-вызов и запускать команду с учётными данными в своём окружении. Ни одна из них никогда не помещает сами учётные данные в контекст модели.

Инструмента get_secret не существует. Это отсутствие и есть весь продукт.

   agent                keywarden                    upstream
     |                     |                          |
     |  "POST /v1/chat     |                          |
     |   using openai/prod"|                          |
     |-------------------->|                          |
     |                     | check policy             |
     |                     | decrypt key              |
     |                     | attach Authorization     |
     |                     |------------------------->|
     |                     |<-------------------------|
     |  response only      | scrub any key from body  |
     |<--------------------| append to audit log      |

Зачем

Сейчас обычный способ дать агенту использовать ваш OpenAI-ключ — положить ключ в файл .env и позволить агенту прочитать его. Как только он это делает, ключ оказывается в контекстном окне модели. Оттуда он попадает в логи провайдера, возможно, в обучающий набор, возможно, в отчёт о сбое, и уж точно — в вашу собственную историю транскриптов, которую вы вставите в отчёт об ошибке через полгода.

Ротация ключа — это неприятно. Не знать, утёк ли он, — ещё хуже.

keywarden убирает тот шаг, на котором модель вообще видит ключ.

Related MCP server: AgentPay MCP Server

Установка

npm install -g keywarden

Node 20.10 или новее. Две зависимости времени выполнения: MCP SDK и zod. Никаких нативных модулей, компилятора и демона.

Быстрый старт

keywarden init --passphrase
keywarden add openai/prod --provider openai
keywarden mcp-config

init создаёт ~/.keywarden/ с зашифрованным хранилищем и политикой «запрещено по умолчанию». add запрашивает каждое поле, поэтому ничего не попадает в историю вашей оболочки. mcp-config выводит блок для вставки в ваш MCP-клиент.

Затем в Claude Code:

Вызови endpoint моделей OpenAI с моим прод-ключом и скажи, к каким из них у меня есть доступ.

Модель вызывает http_request с ref: "openai/prod". keywarden подставляет ключ, совершает вызов и возвращает ответ. Попросите её напечатать ключ — она ответит, что не может.

Инструменты, которые получает агент

Инструмент

Что делает

list_secrets

Только метаданные: refs, провайдеры, имена полей, последнее использование. Никогда значения.

describe_secret

Одно учётное данное плюс как его можно использовать, какие хосты, какие переменные окружения.

list_providers

Встроенные пресеты и что ожидает каждый из них.

http_request

Аутентифицированный HTTPS-вызов. keywarden подставляет учётные данные.

run

Запускает локальный процесс с учётными данными, внедрёнными как переменные окружения.

audit_tail

Последние записи из журнала, защищённого от подделки.

Установите KEYWARDEN_DISABLE_EXEC=1, чтобы полностью убрать run и оставить только HTTP-прокси.

Три поверхности, одна модель авторизации

Одно и то же хранилище, механизм политик, гранты и журнал аудита доступны тремя способами. То, какой из них вы используете, ничего не меняет в том, что разрешено.

поверхность

для

как идентифицируется вызывающий

MCP (stdio)

Claude Code, Claude Desktop, Cursor

клиент, который запустил сервер

CLI

вы, в терминале

доступ к файловой системе хранилища

HTTP (loopback)

любой язык, CI, скрипт, веб-интерфейс

ограниченный API-ключ keywarden

HTTP-поверхность — это то, что делает keywarden пригодным для кода, который не говорит на MCP, и это первое место, где keywarden может отличить одного вызывающего от другого:

keywarden apikey create ci-runner --ref 'openai/**' --http --audit --ttl 30d
keywarden serve --port 8787
curl -s http://127.0.0.1:8787/v1/proxy/openai%2Fprod \
  -H "Authorization: Bearer kw_live_..." \
  -H "content-type: application/json" \
  -d '{"method":"POST","url":"/v1/chat/completions","body":{"model":"gpt-4o","messages":[]}}'

Вызывающий держит ключ keywarden с областью действия openai/**, несущий только те возможности, которые были предоставлены, истекающий через 30 дней, отзываемый одной командой. Он никогда не содержит OpenAI-ключ. Маршруты: /v1/secrets, /v1/secrets/:ref, /v1/proxy/:ref, /v1/run, /v1/audit, /v1/usage, /v1/whoami, /healthz.

Сервер привязывается к 127.0.0.1 и отказывается работать на маршрутизируемом интерфейсе без --allow-remote, потому что любой, кто может дотянуться до этого порта, получает оракул авторизации для каждого учётного данного, которое покрывает ключ.

Кто что использовал и сколько это стоило

Каждая запись в журнале аудита называет субъекта, и субъект находится внутри хэша, поэтому атрибуцию нельзя переписать, не разорвав цепочку. Каждый проксированный ответ разбирается для извлечения количества токенов, сообщённого провайдером.

keywarden usage --since 7d
CREDENTIAL        CALLS          IN         OUT       TOTAL
openai/prod         142     418,220      96,410     514,630
anthropic/prod       38      92,004      31,887     123,891

ACTOR             CALLS          IN         OUT       TOTAL
http:ci-runner      118     356,900      74,220     431,120
mcp:mcp-client       62     153,324      54,077     207,401

keywarden записывает токены, а не деньги. Цены меняются, различаются по контрактам, и устаревшая захардкоженная ставка даёт уверенно неверное число в финансовом отчёте. Обратите внимание, что run нельзя тарифицировать: как только учётные данные оказываются внутри дочернего процесса, keywarden видит код возврата, а не количество токенов.

Два способа использовать учётные данные

Прокси — для HTTP API. Агент описывает запрос, keywarden подставляет учётные данные и совершает вызов. Работает для OpenAI, Anthropic, Stripe, GitHub, Slack, Cloudflare, Vercel, Supabase и любого API, которое аутентифицируется через заголовок или query-параметр.

// what the agent sends
{ "ref": "openai/prod", "method": "POST", "url": "/v1/chat/completions", "body": { "model": "gpt-4o", "messages": [] } }

Инъекция — для всего остального. AWS требует подписи запросов SigV4, Postgres URL — это вообще не HTTP, а terraform apply хочет настоящие переменные окружения. keywarden сам запускает процесс:

{ "command": "aws", "args": ["s3", "ls"], "inject": ["aws/prod"] }

Дочерний процесс получает AWS_ACCESS_KEY_ID и остальных. Модель получает stdout, причём любые учётные данные, появляющиеся в нём, маскируются на выходе.

Политика

~/.keywarden/policy.json определяет, какое учётное данное может быть использовано, какой возможностью и против чего. Правила оцениваются сверху вниз, побеждает первое совпадение, а по умолчанию — запрет.

{
  "version": 1,
  "default": "deny",
  "redactResponses": true,
  "rules": [
    {
      "ref": "openai/**",
      "http": { "allow": true, "methods": ["POST"], "paths": ["/v1/**"] },
      "exec": { "allow": false, "commands": [] },
      "rateLimitPerMinute": 30
    },
    {
      "ref": "aws/prod",
      "http": { "allow": false },
      "exec": { "allow": true, "commands": ["aws", "terraform"] },
      "rateLimitPerMinute": 10,
      "expiresAt": "2026-12-31T00:00:00.000Z"
    }
  ]
}

Или из CLI:

keywarden policy allow "openai/**" --http --path "/v1/**" --method POST
keywarden policy allow aws/prod --exec aws --exec terraform --arg-deny "s3://*"
keywarden policy test aws/prod exec terraform

* совпадает внутри одного сегмента пути, ** охватывает несколько сегментов. expiresAt делает правило временным.

Просто назвать команду недостаточно. Разрешите aws для aws s3 ls — и тот же бинарник сделает aws s3 cp в чужой бакет. Это разрыв на уровне последовательности, на который постоянно указывает литература по угрозам MCP: каждый отдельный вызов авторизован, а их комбинация — это эксфильтрация. Поэтому правила ограничивают и аргументы:

"exec": {
  "allow": true,
  "commands": ["aws"],
  "argsDeny": ["s3://*", "--endpoint-url"],   // any match refuses the call
  "argsAllow": ["s3", "ls", "--region", "*"]  // if set, every argument must match
}

Гранты: временный, истекающий, ограниченный по использованию доступ

Политика — это постоянная конфигурация. Она не подходит для сценария «позволь агенту сделать вот это, сейчас, на пятнадцать минут», который сегодня означает расширение правила и забывание снова его сузить.

Грант — это возможность, которая несёт собственные ограничения, заимствованная из традиции macaroon и biscuit, и выдаётся вами в терминале:

keywarden grant aws/prod --exec aws --ttl 15m --uses 5 --arg-deny "s3://*"
keywarden grant openai/prod --http --path "/v1/chat/**" --method POST --ttl 1h --uses 20
keywarden grant list
keywarden grant revoke <id>

Гранты истекают сами, умирают, когда заканчивается их бюджет использования, и подписываются HMAC-ключом, производным от вашего хранилища, поэтому отредактированный вручную grants.json отклоняется, а не принимается. Отклонённая попытка не сжигает использование.

Установите "requireGrant": true в правиле политики — и постоянная конфигурация становится необходимой, но не достаточной: ничего не происходит, пока вы не выдадите грант. Это шаг одобрения с участием человека, без необходимости интерактивного запроса внутри stdio-сервера.

политика

грант

результат

разрешает, без requireGrant

разрешить

разрешает, с requireGrant

действующее совпадение

разрешить

разрешает, с requireGrant

нет

запретить

запрещает

действующее совпадение

разрешить

запрещает

нет

запретить

Целостность конфигурации

Шифрование секретов — это половина дела. policy.json решает, можно ли использовать учётное данное, а providers.json решает, куда оно отправляется. Оба — обычные файлы. Тот, кто не может расшифровать ни одного байта, всё равно может добавить провайдера, чьи хосты принадлежат ему, и перенаправить ваше учётное данное на него.

Поэтому хранилище фиксирует хэш обоих файлов и отказывается работать с любым из них, пока вы не посмотрите на изменение:

keywarden trust show    # what drifted
keywarden trust         # review, then pin the current contents

Сам файл хранилища снабжается MAC-кодом целиком, а не только по полям, потому что замена provider: "openai" на что-то другое никогда не затрагивает шифротекст и в противном случае прошла бы проверку чисто.

Что keywarden действительно обеспечивает

  • Нет инструмента, возвращающего открытый текст. В MCP-поверхности нет пути кода, который возвращает значение учётного данного.

  • Разрешающий список исходящих. Учётное данное может быть отправлено только на хосты, объявленные его провайдером, плюс те, что вы добавили в политику. Инъекция в промпт, говорящая агенту отправить ваш ключ на attacker.example, проваливается на проверке хоста, ещё до обращения к сети.

  • Только HTTPS, без перехода по редиректам. 302 на другой origin не повторит ваш заголовок Authorization вне хоста.

  • Защита от SSRF. Loopback, частные диапазоны, CGNAT и link-local (что покрывает endpoint метаданных облака 169.254.169.254) блокируются, а адрес проверяется в том DNS-запросе, который реально использует сокет, поэтому DNS-ребinding не открывает окно.

  • Никакого шелла. run передаёт массив argv в spawn с shell: false. Нет разбора метасимволов, в который можно внедриться.

  • Сконструированное окружение дочернего процесса. Дочерний процесс получает разрешающий список унаследованных переменных плюс внедрённые. Ваши остальные секреты и собственная парольная фраза keywarden не наследуются.

  • Редактирование вывода. Каждый результат инструмента сканируется на известные значения учётных данных, их base64 и URL-encoded формы и около дюжины известных форм ключей. Это эшелонированная защита, а не основной контроль.

  • Аудит, защищённый от подделки. Каждое решение — разрешение или запрет — добавляется в журнал с хэш-цепочкой. keywarden audit verify пересчитывает цепочку и сообщает о первой изменённой или удалённой записи.

  • Целостность всего файла. Хранилище снабжается MAC-кодом, включая метаданные, поэтому учётное данное нельзя перенаправить другому провайдеру без обнаружения. policy.json и providers.json привязаны по хэшу к хранилищу и отклоняются при изменении вне полосы.

  • Усиление окружения. Сервер отказывается запускаться, когда установлены NODE_TLS_REJECT_UNAUTHORIZED=0, NODE_OPTIONS или SSLKEYLOGFILE, и предупреждает о NODE_EXTRA_CA_CERTS и HTTPS_PROXY. CVE-2026-21852 против Claude Code был одним переопределением окружения, которое перенаправляло исходящий трафик с прикреплённым заголовком Authorization; процесс, чья работа — прикреплять учётные данные, не должен запускаться, когда путь запроса находится под чужим контролем.

  • Ограничения аргументов. argsAllow / argsDeny сужают какие именно вызовы разрешённой команды допустимы, а не только какой бинарник.

  • Ослабленные гранты. Истекающие, ограниченные по использованию, выдаваемые оператором возможности, устойчивые к подделке благодаря MAC, производному от хранилища.

  • Обрамление недоверенных данных. Тела проксированных ответов помечаются как недоверенное содержимое от указанного хоста, поэтому внедрённая инструкция в API-ответе подаётся модели как данные.

Криптография

Конвертное шифрование, всё из node:crypto, никаких сторонних криптобиблиотек.

  • Случайный 256-битный ключ данных шифрует каждое поле с помощью AES-256-GCM, используя ref и имя поля учётного данного как дополнительные аутентифицированные данные, поэтому шифротекст нельзя переместить между записями хранилища.

  • Ключ данных оборачивается ключом, производным от вашей парольной фразы, с помощью scrypt при N=2^17, r=8, около 128 MiB и примерно секунда на попытку. Это сделано намеренно: файл хранилища — это то, с чем уходит атакующий, поэтому офлайн-подбор должен быть дорогим.

  • Ротация парольной фразы переоборачивает 32 байта. Она не перешифровывает каждый секрет.

Режимы хранилища

--passphrase — это надёжный режим. MCP-серверу нужен KEYWARDEN_PASSPHRASE в его окружении, чтобы разблокироваться без запроса.

--keyfile записывает случайный ключ в ~/.keywarden/masterkey, чтобы ничто не требовало запроса. Это удобно, но означает, что любой, кто может читать ваш домашний каталог, сможет открыть хранилище. Это всё равно гораздо лучше, чем разбросанные по проектам файлы .env в открытом виде, потому что ключ находится в одном месте, его использование ограничено политикой, и каждое использование логируется. Знайте, на какой компромисс вы пошли. keywarden doctor вам напомнит.

В Windows режимы файлов устанавливаются, но не соблюдаются так, как POSIX соблюдает 0600. См. THREAT_MODEL.md.

CLI

keywarden init --passphrase|--keyfile   create the vault
keywarden doctor                        check the install, flag weak settings
keywarden trust [show]                  re-pin policy.json + providers.json after reviewing a change
keywarden grant <ref> ...               issue a temporary, use-capped capability
keywarden grant list | revoke <id>
keywarden add <ref> --provider <id>     store a credential (prompts for each field)
keywarden list                          metadata only
keywarden describe <ref>                metadata plus how it can be used
keywarden reveal <ref>                  print plaintext, asks first, always audited
keywarden rm <ref> [--field f]          delete
keywarden exec <ref[,ref]> -- <cmd>     run a command with credentials injected
keywarden policy show|init|allow|deny|test
keywarden audit [tail|verify]
keywarden passphrase                    rotate
keywarden providers                     built-in presets
keywarden mcp-config                    print the MCP client config
keywarden doctor                        check the install, flag weak settings

Пользовательские провайдеры

Всё, что не встроено, помещается в ~/.keywarden/providers.json. См. docs/PROVIDERS.md.

{
  "acme": {
    "label": "Acme Internal API",
    "hosts": ["api.acme.internal", "*.acme.io"],
    "baseUrl": "https://api.acme.io",
    "fields": ["token", "tenant"],
    "required": ["token"],
    "auth": { "type": "header", "name": "X-Acme-Key", "template": "{{token}}" },
    "env": { "ACME_TOKEN": "{{token}}", "ACME_TENANT": "{{tenant}}" }
  }
}

От чего keywarden вас не защищает

Прочтите THREAT_MODEL.md, прежде чем доверить ему что-либо дорогое. Краткая версия:

  • Если агент может выполнять произвольные локальные команды через какой-либо другой инструмент, он сможет прочитать ваш файл хранилища и, в режиме ключевого файла, ваш мастер-ключ. keywarden защищает контекст модели, а не ваш диск.

  • run передаёт учётные данные реальному процессу. Если вы внесёте в список разрешённых команду, которую можно направить на извлечение собственного окружения, учётные данные уйдут. Вносите в список разрешённых узко.

  • Редактирование — это страховочная сетка с дырами. Учётные данные, которые API возвращает в перекодированном виде, который мы не распознаём, не будут обнаружены.

  • keywarden не мешает агенту сделать что-то дорогостоящее или разрушительное с учётными данными, которые ему разрешено использовать. Для этого существуют политики ограничения и лимиты скорости.

Разработка

npm install
npm run build
npm test          # 89 unit tests + 46 end-to-end checks against the real CLI, MCP and HTTP servers

Набор e2e-тестов управляет реальными бинарными файлами во временной KEYWARDEN_HOME и проверяет, в частности, что ни один ответ инструмента не содержит учётные данные.

Чтение

  • THREAT_MODEL.md — что входит в область применения, а что честно нет

  • docs/RESEARCH.md — литература 2026 года, на которой основан этот дизайн, что было принято, а что рассмотрено и отклонено

  • docs/COMPETITORS.md — ландшафт, и в чём keywarden действительно отличается, а не просто по-другому маркетируется

  • docs/TEAM.md — многопользовательская архитектура: идентичность, обмен ключами без читаемого сервера, процесс утверждения, учёт затрат и порядок сборки

  • docs/PROVIDERS.md — написание собственного провайдера

Хостинговая версия

Планируется хостинговая версия для тех, кто хочет командное хранилище, управление через браузер и синхронизацию между машинами, с той же гарантией нулевой экспозиции. Всё в этом репозитории остаётся под лицензией MIT и полностью пригодным для автономного использования. См. docs/HOSTED.md.

Лицензия

MIT

Install Server
A
license - permissive license
A
quality
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    A
    quality
    A
    maintenance
    Credential isolation proxy for AI agents. Injects API keys at the network boundary so your agent never sees the raw credential. Supports domain allowlists, agent auth, policy enforcement, and audit logging.
    3
    89
    13
    Apache 2.0
  • F
    license
    Not graded
    quality
    A
    maintenance
    Provides a trust and governance layer for AI agents, enabling secure API access, credential vaulting, paid execution with human approval, and automatic call resume.
    8
    2
  • A
    license
    A
    quality
    A
    maintenance
    Identity and credential governance for AI agents. Every agent gets its own cryptographic identity, scoped short-lived credentials per platform, human approval on sensitive actions, and an immutable audit log.
    7
    1
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables AI agents to securely perform privileged actions like creating GitHub issues by minting short-lived, single-purpose tokens on demand, with policy enforcement and audit logging.
    MIT

View all related MCP servers

Related MCP Connectors

  • Issue, rotate and revoke scoped API-key passes for 25+ providers — the agent never sees a real key

  • Encrypted secret store and rotation for autonomous agent credentials

  • Operate Linux, macOS and Windows from your LLM. Every action runs through an auditable allowlist.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/DINAKAR-S/keywarden'

If you have feedback or need assistance with the MCP directory API, please join our Discord server