На Хабре вышла статья о краже цепочек рассуждений у закрытых моделей. Схема атаки: берётся зашифрованный блок сильной модели, подкладывается слабой модели того же провайдера, и та пересказывает содержимое дословно. В результате можно прочитать чужие мысли, включая случайно попавшие туда пароли и ключи. Атака описана в препринте и, судя по всему, работает.
Однако автор материала, разбиравший signature Claude по байтам ещё прошлой зимой, пришёл к выводу, что конверт вокруг рассуждения совсем не opaque. Это обычный protobuf, который читается вообще без ключей. Зашифрован внутри ровно один вложенный кусок — сам текст мысли. Всё остальное лежит открыто.
| Поле | Тип | Длина (байт) | Содержимое |
|---|---|---|---|
| field 1 | varint | 1 | версия схемы (16) |
| field 2 | len-delimited | 312 | вложенное сообщение |
| field 3 | varint | 1 | флаг (1) |
| field 1 (внутри) | len-delimited | 135 | заголовок |
| field 2 (внутри) | len-delimited | 12 | nonce |
| field 3 (внутри) | len-delimited | 12 | nonce / aad |
| field 4 (внутри) | len-delimited | 48 | MAC / подпись |
| field 5 (внутри) | len-delimited | 94 | шифротекст |
Автор перегнал парсер по свежим сессиям и обнаружил, что за полгода протокол подрос на четыре версии схемы. Внутри нашлось кое-что, из-за чего у него есть уточнение к выводам препринта.
Заголовок блока содержит открытым текстом id модели (например, claude-opus-5) и UUID организации из ~/.claude.json.
Разбор одной подписи. Автор открыл свою рабочую сессию Claude Code (~/.claude/projects/…/*.jsonl), попросил модель коротко подумать над пустяковым шагом и выдернул из истории первый попавшийся блок thinking. В JSON он выглядит так: поле thinking пустое, но signature на 428 символов живая. Это означает, что модель думала, но текст мысли не сохраняется в истории.
Сама signature — это base64-строка, которая декодируется в 319 байт бинарных данных. Первые байты (08 02 12 b8 02 …) указывают на protobuf-сообщение. Внешний конверт содержит одно вложенное сообщение на 312 байт в поле 2, плюс два скалярных флажка по краям. Внутри поля 2 — заголовок (135 байт), nonce (12 байт), ещё один nonce или AAD (12 байт), MAC/подпись (48 байт) и шифротекст (94 байта). Три поля посередине имеют константную длину у всех полутора тысяч блоков, что указывает на классический расклад nonce + nonce_or_aad + tag/signature.
Заголовок, который никто не прятал. Разбор 135 байт заголовка тем же protobuf-способом, без единого ключа, даёт: версия схемы (16), тип блока (thinking), auth_blob (64 случайных байта), id модели открытым текстом (claude-opus-5), флаг (1), тип блока строкой (thinking) и UUID длиной 36 символов. Этот UUID — oauthAccount.organizationUuid из ~/.claude.json, то есть идентификатор организации, от имени которой работает аккаунт. В разных сессиях он один и тот же на протяжении месяца и меняется только при смене аккаунта.
Таким образом, каждый зашифрованный блок рассуждений таскает внутри заголовка, открытым текстом, id модели и id вашей организации. Это не абстрактный «технический идентификатор», а реальный ключ, по которому можно связать пользователя с его организацией в Anthropic. Лежит он ровно там, куда никто не смотрел, потому что signature все считали непрозрачной.
Практическое значение. Для обычного пользователя это означает, что приватность thinking-блоков не абсолютна: метаданные (модель, организация, UUID) доступны без расшифровки. Для исследователей безопасности — что атака на кражу цепочек рассуждений может быть дополнена анализом заголовков, которые раскрывают больше, чем предполагалось. Для разработчиков, использующих Claude Code, — что стоит быть осторожными с тем, что попадает в контекст, так как даже «зашифрованные» блоки могут содержать чувствительные метаданные.

