anthropic
Токены MCP на Linux хранятся открытым текстом
Promtime
anthropicПроверка Claude Code 2.1.257 на Linux показала, что access-токены подключённых удалённых MCP-серверов хранятся в ~/.claude/.credentials.json обычным JSON, а единственной защитой служат права доступа 0600. Разбор опубликован в блоге Secretspec, при том что документация Claude Code по MCP описывает хранение токенов как безопасное.
Коротко
- Файл содержит объект mcpOAuth верхнего уровня, где для каждого сервера сохранены accessToken, clientId, discoveryState, redirectUri, serverName и serverUrl; в разборе приведена запись cloudflare-observability с затёртыми значениями.
- Поведение совпадает с документацией Anthropic: на macOS используется зашифрованный Keychain с откатом в тот же файл, на Windows защита сводится к правам доступа каталога профиля пользователя.
- У Codex хранилище OAuth-данных для MCP настраивается через параметр mcp_oauth_credentials_store с режимами auto, file и keyring, поэтому плоский файл на Linux там не единственный доступный вариант.
Файл с bearer-токенами к внешним сервисам это привлекательная цель: любой процесс, работающий от имени пользователя, читает его без дополнительных барьеров, а резервные копии и синхронизация домашнего каталога разносят его дальше. Судя по разбору, проблема не в реализации OAuth, а в том, что стандарт вообще не описывает локальное хранилище, и решение остаётся за клиентом. Настраиваемое хранилище в Codex показывает, что выбор технически реализуем уже сейчас.
Внутри .credentials.json нашёлся объект mcpOAuth с токенами каждого сервера
Автор разбора аутентифицировался в нескольких удалённых MCP-серверах через Claude Code 2.1.257 и затем открыл ~/.claude/.credentials.json. Файл имеет режим 0600, как и должно быть, но содержит объект mcpOAuth верхнего уровня, в котором для каждого сервера лежит выданный access-токен. Права доступа остаются единственным барьером.
В опубликованном примере запись cloudflare-observability включает поля accessToken, clientId, discoveryState, redirectUri, serverName и serverUrl; значения учётных данных в тексте затёрты. Такого набора достаточно, чтобы обращаться к удалённому серверу от имени пользователя без повторного входа в браузере, поскольку токен предъявляется как bearer.
Такое поведение описано в документации Anthropic по управлению учётными данными: на macOS Claude Code кладёт токены в зашифрованный Keychain и откатывается к ~/.claude/.credentials.json, когда Keychain недоступен. На Linux используется тот же файл с режимом 0600, а на Windows это каталог .claude внутри %USERPROFILE%, наследующий права доступа профиля пользователя.
OAuth решает выдачу и обновление токена, но не описывает локальное хранилище
Браузерный вход прячет секрет: пользователь выполняет claude mcp login, подтверждает доступ в браузере и возвращается к подключённому MCP-серверу. Токен никто не создавал вручную, не копировал из панели управления и не вставлял в конфигурацию, но Claude Code его получил и обязан сохранить, чтобы соединение пережило перезапуск.
OAuth здесь решает свои задачи: Claude Code находит сервер авторизации, запрашивает конкретные скоупы, выполняет обмен кода на токен, обновляет access-токен и отзывает выданное разрешение. Документация Anthropic по MCP дополнительно позволяет пользователю зафиксировать набор запрашиваемых скоупов. Спецификация OAuth при этом ничего не говорит о защищённом локальном хранилище.
В сравнении, которое приводит Secretspec, OAuth-учётные данные и API-токен с ограниченной областью действия ведут себя одинаково по ключевым пунктам: клиент обязан хранить оба, у обоих бывают ограниченные права и срок жизни, оба воспроизводимы при краже. Независимый отзыв доступен для API-токена и обычно для OAuth.
SecretSpec 0.20 предлагает 33 провайдера в качестве сменного хранилища
Разбор предлагает вынести персистентность в сменный слой: OAuth-клиент Claude Code обращается к интерфейсу хранилища учётных данных, за которым стоят SecretSpec и выбранный пользователем провайдер. В SecretSpec 0.20 таких интеграций 33: локальные кейринги, менеджеры паролей, зашифрованные файлы, облачные секрет-менеджеры и цели развёртывания.
Точкой интеграции назван Node.js/TypeScript SDK SecretSpec, который встраивает резолвер на Rust, поэтому отдельный код под каждый бэкенд на стороне TypeScript не требуется. Claude Code сериализовал бы одну OAuth-запись на сервер и просил бы SecretSpec её загрузить, сохранить или удалить; провайдеры объявляют свои возможности, так что хранилище вправе требовать чтения и записи.
Провайдер по умолчанию задаётся в пользовательской конфигурации, например командой secretspec config global init --provider keyring --profile default. Организация может потребовать OpenBao или облачный секрет-менеджер, а рабочая станция без графической сессии обойтись хранилищем, зашифрованным age; сам OAuth-поток не меняется, меняется только слой хранения.
Что изменится в SecretSpec 0.21 У SecretSpec уже есть хелперы учётных данных для Git и Docker, а для Nix предложен универсальный резолвер секретов с привязкой к операциям. В работе версионированный резолвер и IPC для провайдеров: приложения смогут обращаться к провайдерам по локальному протоколу, без встраивания SDK и кода бэкендов. Дата выпуска версии не называется.
Хранение MCP-токенов в Claude Code сегодня может изменить только Anthropic: публичный репозиторий проекта не включает реализацию основного CLI, а лицензия заявлена как all rights reserved. Авторы SecretSpec отмечают, что в открытых проектах границу обращения с секретами можно проверить и исправить в апстриме.
Комментарии
Пока никто не написал. Будьте первым.
Присоединяйтесь к разговору
Войдите через Google, чтобы оставить комментарий. Имя и аватар подставятся из вашего профиля Google, а комментарий появится после модерации.
Из Google мы используем только имя и аватар. Почту не сохраняем.
