Маскирование и потоковая защита

Обнаруженные чувствительные участки должны редактироваться на месте, в потоке байт в реальном времени, без буферизации всего вывода команды и без нарушения структуры окружающих данных (кадры JSON-RPC, терминальные управляющие последовательности, частичные строки). В этой главе описывается механика этого процесса.

Проблема потоковой обработки

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

%%{init: {"theme": "base", "themeVariables": {"fontFamily": "-apple-system, Segoe UI, Helvetica, Arial, sans-serif", "primaryColor": "#eef2f7", "primaryTextColor": "#0b0b0b", "primaryBorderColor": "#5b6b7c", "lineColor": "#5b6b7c", "secondaryColor": "#eef4ff", "tertiaryColor": "#f4f3f0", "clusterBkg": "#f9f9f7", "clusterBorder": "#c3c2b7", "edgeLabelBackground": "#fcfcfb", "actorBkg": "#eef2f7", "actorBorder": "#5b6b7c", "actorTextColor": "#0b0b0b", "actorLineColor": "#5b6b7c", "signalColor": "#52514e", "signalTextColor": "#0b0b0b", "labelBoxBkgColor": "#eef4ff", "labelBoxBorderColor": "#5b6b7c", "labelTextColor": "#0b0b0b", "loopTextColor": "#0b0b0b", "noteBkgColor": "#fdf3d9", "noteBorderColor": "#c98500", "noteTextColor": "#3d2f00", "activationBorderColor": "#5b6b7c", "activationBkgColor": "#eef4ff", "sequenceNumberColor": "#ffffff"}}}%% flowchart LR In["Входящие байты\n(вывод команды / JSON-RPC)"] --> Pending["Буфер ожидания\n(макс. 64 КБ)"] Pending --> Scan["Поиск совпадений,\nотсортированных по смещению"] Scan --> Straddle{"Совпадение пересекает\nграницу записи?"} Straddle -- да --> Retain["Удержать хвост\n(≥ длины самого длинного\nвозможного совпадения,\nпо умолчанию 16 КБ)"] Straddle -- нет --> Emit["Безопасно вывести\nдо безопасной границы"] Retain --> Idle{"Простой 20 мс\nбез новых данных?"} Idle -- да --> ForceEmit["Принудительный сброс\n(не удерживать короткие значения,\nтакие как интерактивные приглашения)"] Idle -- нет --> Pending

Механика и константы

  • Замена на основе смещений, один проход, совпадения отсортированы по позиции; если совпадения перекрываются, побеждает более длинное совпадение. Пустой пустая замещающая строка оставляет соответствующую область без изменений.
  • Удерживаемый хвост: байты, удерживаемые на границе безопасного вывода, размером не менее длины самого длинного возможного совпадения, которое может дать активный набор механизмов обнаружения (по умолчанию 16 КБ) — именно это предотвращает проскальзывание наполовину замаскированного секрета, разделённого между двумя записями.
  • Максимальный буфер ожидания: 64 КБ. При нехватке памяти буфер обрезается по концу пересекающего границу совпадения — никогда не посередине значения — поэтому ограничение потребления памяти никогда не приводит к утечке данных; в худшем случае оно приводит лишь к более раннему принудительному сбросу.
  • Сброс по простою: 20 мс. Без этого короткое значение (интерактивное приглашение, эхо оболочки), которое самостоятельно никогда не достигает порога размера хвоста, удерживалось бы бесконечно. Это осознанный компромисс в пользу отзывчивости терминала.
  • Сброс полностью опустошает буфер — после финального/явного сброса удерживаемого хвоста не остаётся.
  • Замещающие строки подставляются на месте — замаскированный блок PEM отображается как -----[MASKED:PRIVATE_KEY]-----, сохраняя окружающую структуру.

Производительность

  • Тест производительности с синтетическим механизмом обнаружения (BenchmarkStreamingWriter100MB, воспроизводимый тест Go) фиксирует пропускную способность около 1,5 ГБ/с для самого механизма маскирования на том оборудовании, на котором он выполнялся.

Далее: Механизм применения политик и цепочка доверия.

results matching ""

    No results matching ""