3.8 KiB
Спека: якорь host-терминатора в commit-message lookahead (security-фикс)
Дата: 2026-06-15. Слой: движок (tools/url-whitelist-rules.mjs). Источник: автоматическое security-ревью (MEDIUM, Substring/Unanchored Allowlist Bypass).
Цель
Закрыть обход allowlist в buildCommitMessageUrlPattern: negative-lookahead без host-терминатора пропускает subdomain-спуф (https://liderra.ru.evil.com/exfil не флагуется → канал утечки). Зеркалить уже-корректный buildNavigateWhitelistPatterns. Существующие allow/block-кейсы сохранить.
Дефект
Текущий возврат: new RegExp('\\bhttps?:\\/\\/(?!' + frags.join('|') + ')\\S+', 'i'). Фрагменты (liderra\.ru, github\.com/liderra, …) в lookahead не закрыты терминатором → liderra.ru.evil.com совпадает по префиксу liderra\.ru → lookahead гасится → URL НЕ флагуется (считается своим). Пре-существующий дефект (был в оригинальном SUSPICIOUS_MESSAGE_PATTERNS[0]), перенесён в билдер.
Фикс
Обернуть альтернацию и добавить общий host-терминатор после неё: new RegExp('\\bhttps?:\\/\\/(?!(?:' + frags.join('|') + ')(?:[:/?#]|$))\\S+', 'i'). Терминатор (?:[:/?#]|$) требует, чтобы за разрешённым доменом шёл порт/путь/запрос/фрагмент или конец — . (как в …ru.evil.com) и - (как в …liderra-evil) его не удовлетворяют → спуф флагуется. Зеркало границы buildNavigateWhitelistPatterns.
Инвариант (backward-compat)
Легитимные кейсы не меняются: liderra.ru/x (после домена / ∈ [:/?#] → allow), docs.anthropic.com/x (allow), evil.example.com/p (нет фрагмента → flag/block). Меняется только спуф: liderra.ru.evil.com теперь флагуется (block) — это и есть цель. Существующие тесты commit-message-scanner.test.mjs (anthropic/liderra allow, external block, hex/base64/script) остаются GREEN.
Крайние случаи
Спуф-варианты режутся терминатором: liderra.ru.evil.com (. после ru), liderra-evil.com (нет фрагмента вовсе). Path-домен github.com/liderra + терминатор: github.com/liderra/repo → / ∈ → allow; github.com/liderra-evil → - ∉ → flag. fail-CLOSED не затронут: пустой whitelist → проектных фрагментов нет → liderra.ru любой формы флагуется.
Критерий
Новый тест: buildCommitMessageUrlPattern(['liderra.ru','github.com/liderra']) → .test('see https://liderra.ru.evil.com/x') === true (флагуется). Существующие билдер-тесты (liderra.ru/x false, docs.anthropic.com/x false, evil.example.com/p true, empty→liderra true) — GREEN. Целевой тест-файл url-whitelist-rules.test.mjs GREEN; полный tools/-свод — терминал владельца.
[
{"id":"fx1","kind":"EXTRACTED","ref":"tools/url-whitelist-rules.mjs","anchor":"buildCommitMessageUrlPattern"},
{"id":"fx2","kind":"EXTRACTED","ref":"tools/url-whitelist-rules.mjs","anchor":"buildNavigateWhitelistPatterns"},
{"id":"fx3","kind":"EXTRACTED","ref":"tools/url-whitelist-rules.mjs","anchor":"BASE_COMMIT_MSG_FRAGS"}
]