DarkRiDDeR15 мин

Полевая безопасность веба: авторизованный цикл evidence и ретеста без ложного допуска

БезопасностьПрактика

Проблема полевого security review часто ломается не на знаниях о controls, а на передаче результата. Один участник принёс policy, другой увидел тест, третий услышал «проверено» — и никто не помнит, на какой путь, среду и следующую операцию это разрешение распространялось. Цена высока: hand-off начинает звучать как допуск, а позднее выясняется, что evidence было для другой границы или retest вообще не был определён.

Нужен авторизованный, но узкий цикл: назвать fixed case, показать связанный threat-control-evidence record, ограничить retest scope и вернуть либо stop, либо synthetic-security-review hand-off. В этой статье «авторизованный» означает разрешённый форматом модели, а не право на production action. Единственный положительный output не выпускает изменение, не включает настройку и не подтверждает реальную систему.

Field review хранит границу передачи

Review hand-off полезен только тогда, когда получатель видит его площадь. Для fixed case площадь равна двум observations: named-directives-present и synthetic-negative-script-is-not-authorized. Это не универсальный набор доказательств CSP. Это именованный retest scope в учебном объекте. Получатель может продолжить обсуждение этой пары, но не может честно сделать вывод о логировании, security headers, origin policy или опыте настоящего пользователя.

Именно поэтому case включает comparison boundary: сравниваются только named synthetic literals. Нет browser session, request, response, файлов, времени, метрик, стенда, secret или production service. Такая изоляция кажется слишком строгой, пока не вспомнить обычный дефект передачи: факт из одного окружения переезжает в другую ветку решения без отметки, что контекст исчез. Здесь context не исчезает, потому что он записан в каждом result.

Кольцевой цикл: выбрать named case, подтвердить traceability, ограничить retest двумя observations, записать residual question и передать synthetic hand-off; красные ответвления ведут к отдельным stop.
Узел hand-off не является финальной стрелкой. Он передаёт только область следующего review и никогда не превращается в release decision.
Полевой цикл evidence/retest
ЭтапВходВыходСтоп при дефекте
выбор casenamed fixed idявная область сравненияunknown fixed case
трассировкаthreat + control + evidenceпроверенная связка idsunbound evidence
retest scopeallowed observationsровно два synthetic checkunnamed attack path
residual boundaryremainsOpen + questionследующий вопрос видимunbounded residual risk
передачаbounded resultsynthetic hand-offdisallowed positive result

Retest не должен расширять evidence

Слово retest опасно, когда его используют как синоним «проверить всё снова». В этом overlay retest не открывает приложение и не пытается повторить атаку. Он повторно применяет тот же validator к тому же fixed record и публикует scope двух разрешённых observations. Такой ретест может проверить, что chain не потеряла binding и positive output не стал сильнее. Он не способен узнать, что произошло где-либо вне памяти процесса.

Это различие особенно важно после изменения текста или ownership. В ходе передачи людям легко расширить смысл: «negative case был не авторизован» становится «у нас нет XSS». Модель не даёт такого скачка, потому что retestScope сериализован как список наблюдений, а effect всегда no-system-change. Если кому-то нужен реальный retest, надо создавать другой процесс с другими полномочиями и evidence. Его нельзя спрятать внутри данного public export.

Исполняемый hand-off с ограниченным ретестом

import { createFixedEvidenceRetestCase, reviewFixedEvidenceRetestCase } from './upgrade-2026-04.mjs';

const fixedCase = createFixedEvidenceRetestCase('mapped-injection-path-v1');
const handOff = reviewFixedEvidenceRetestCase(fixedCase);
console.log({ status: handOff.status, scope: handOff.retestScope, effect: handOff.effect });
// { status: 'bounded-security-review-handoff', scope: ['named-directives-present', 'synthetic-negative-script-is-not-authorized'], effect: 'no-system-change' }

Этот вызов использует только exported factory и reviewer. Он не меняет literal, потому что returned object глубоко frozen; он не запрашивает data и не строит сообщение наружу. Положительное значение означает ровно то, что форма synthetic case прошла собственные ограничения. Для неизвестного case или отсутствующей boundary функция вернёт stop, а не будет подбирать похожую запись. Это fail-closed поведение нужно для передачи: неопределённость нельзя конвертировать в удобный зелёный результат.

Как читать stop без попытки обойти его

Stop — это адрес недостающей работы. stop-unknown-fixed-evidence-case просит выбрать named case. stop-unbound-evidence просит связать observation с threat и control. stop-unbounded-residual-risk просит назвать открытый участок и следующий вопрос. Ни один status не просит «попробовать ещё раз» без изменения входа. Такой дизайн защищает review от циклического пересмотра одного и того же неполного пакета под новым названием.

Практическая дисциплина здесь проста: не редактировать result вручную и не заменять status устным объяснением. Если evidence пришло из другого case, оно остаётся чужим до явной привязки. Если residual question требует реального владельца, synthetic record не делает вид, что знает его. Если нужно действие в системе, hand-off не может быть прокси-разрешением. Это меньше похоже на быстрый процесс, но быстрее настоящего разбора, в котором люди спорят о незафиксированных предположениях.

Authorized означает разрешено схемой, не организацией

Термин authorised здесь намеренно ограничен. Schema authorizes только один переход: complete fixed traceability превращается в bounded hand-off. Она не authorizes publication, release, deployment, настройки заголовков, изменения кода, отправку уведомлений, работу с секретами или запросы к API. Это важная языковая дисциплина для зрелого автора: не называть механизмом доступа то, что всего лишь проверяет структуру аргумента.

NISTIR 8397 говорит о developer verification techniques, включая threat modeling, automated testing, code review и scanners. Из этого следует полезная организационная мысль, но не полномочие: разные техники производят разные evidence. Полевой loop не склеивает их в один виртуальный сертификат. Он оставляет место следующему reviewer, который применит подходящий метод с реальным scope, если такой метод и право действительно существуют.

Последовательность передачи

  1. Выбрать case по id. Не строить новую запись из пересказа и не угадывать аналог.
  2. Зафиксировать boundary. Сразу перечислить, чего review не читает, не запускает и не утверждает.
  3. Прогнать traceability. Проверить path, interruption, двойной binding evidence и residual question.
  4. Ограничить retest. Передать только named observations, не расширяя их в общий security statement.
  5. Сохранить stop. Отдельно записать причину и exact next action, если цепь неполна.
  6. Передать hand-off. Положительный результат остаётся synthetic и не имеет production effect.

Где заканчивается browser-policy review

CSP3 описывает Content-Security-Policy response header как предпочитаемый механизм доставки policy и подчёркивает его роль defence-in-depth. Это объясняет, почему в модели control расположен у execution boundary. Но document не говорит, что только CSP покрывает каждый вид injection или что Report-Only observation равен enforcement. Поэтому в field loop нет вывода «policy присутствует — review завершён». Есть только ограниченное наблюдение и residual вопрос о том, что происходит до этой границы.

ASVS 5.0.0 также просит document expected browser security features и поведение при их отсутствии. Для hand-off это напоминание о форме: результат должен явно показывать feature, evidence и limit, а не быть словом «проверено». Однако ASVS не присваивает ownership и не разрешает выбрать риски вместо команды. В synthetic package owner question остаётся вопросом; без него зелёная ветка закрыта. Это честнее, чем заполнить ячейку именем, которого data model не подтверждает.

Передача между ролями без растворения контекста

У reviewer, разработчика и владельца следующего исследования разные задачи, но hand-off не обязан моделировать их как людей. Достаточно передать предмет: case id, два evidence observations, residual list и exact next action. Получатель может проверить эти поля, не угадывая, что предыдущий участник имел в виду под «готово». Если нужно добавить мнение или риск-приоритет, это новый объект поверх данной записи, а не замена её status свободным текстом.

Такой формат особенно полезен при асинхронной работе. Через неделю вспомнить название control легко, а его исходную boundary — нет. Named fixed case сохраняет минимальную семантику без притворства, что он сохраняет всю историю решений. Поэтому loop не требует журналов, метрик или timestamp: отсутствие этих данных не является дефектом в учебном контуре; дефектом была бы попытка выдать их неявно за evidence.

Ограничения и следующий шаг

Полевой цикл не является эксплуатационным playbook, тестовым стендом или политикой исключений. Он не осуществляет authorised access к чему-либо и не делает claims о security posture. SVG, таблица и code показывают только fixed synthetic data. Даже успешно исполненный fixture говорит о согласованности validator, а не о том, что какой-то browser, endpoint или команда действует так же.

Следующий шаг — взять один реальный процесс передачи и сначала не автоматизировать его. Выписать на бумаге: какой attack path, какой control interruption, какое evidence разрешено передавать и какой residual question остаётся. Если формулировка просит release вместо hand-off, разделите процесс. Если case не имеет named boundary, верните stop. Когда структура выдержит этот ручной тест, можно обсуждать отдельное, уполномоченное исследование вне данного пакета.

Проверяемые источники

  • W3C Content Security Policy Level 3 — версия: W3C Working Draft, 21 April 2026, dated immutable snapshot. CSP3 от 21.04.2026 описывает header delivery policy и ограниченную роль CSP как defense-in-depth. Граница: Snapshot не подтверждает header, enforcement или retest какого-либо приложения.
  • OWASP Application Security Verification Standard 5.0.0 — версия: release tag v5.0.0_release, commit 5cf9b032440be53ce345ab3c130fda46ba1ce7a2, 30 May 2025, immutable commit pin. Pinned ASVS 5.0.0 требует документировать ожидаемые browser security features и поведение при их отсутствии. Граница: Стандарт не авторизует hand-off, release или действия в системе и не создаёт ownership residual risk.
  • NISTIR 8397: Guidelines on Minimum Standards for Developer Verification of Software — версия: NIST IR 8397, 6 October 2021, immutable DOI publication. NISTIR 8397 различает наборы developer verification techniques, а не заменяет их единым result. Граница: Документ не делает fixed synthetic fixture доказательством реального retest или security assessment.