[1] major Файл: ai-review.js Строка: 108-143 Тип: security Описание: `downloadFile` загружает произвольный URL (используется для prompt’ов) в память целиком через `Buffer.concat`, без проверки `Content-Length`/типа или лимита на размер. Злоумышленный prompt-шаблон может спокойно отправить файл размером сотни мегабайт и довести рабочий процесс до OOM/DoS, а также в тело попадёт любой контент (в том числе бинарь/вредоносный). Решение: переключить загрузку на поток (`response.pipe(fs.createWriteStream(...))`), отслеживать накопленный размер и прекращать при превышении разумного порога (например, 5–10 МБ), а также валидировать заголовки/расширение перед сохранением. [2] critical Файл: ai-review.js Строка: 334-373 Тип: security Описание: в `getChangedFiles` `targetBranch` подставляется напрямую в шаблонные строки shell-команды `git diff ... origin/${targetBranch}...HEAD` и аналогично с `beforeSha`/`currentSha`. Эти переменные приходят из окружения CI (в том числе из ветки/коммита, которые может выбирать контрибьютор) и не экранируются, поэтому достаточно вставить `; rm -rf /` или кавычки, чтобы исполнить произвольную команду на runner’е. Надо вызывать `git diff` через `spawnSync/execFileSync` с аргументами, а не через `execSync` с оболочкой, и/или валидировать, что branch/sha содержат только допустимые символы. [3] critical Файл: ai-review.js Строка: 1233-1315 Тип: security Описание: функция `saveReportToServer` отправляет `sshpass -p "${CONFIG.sshPassword}"` в командную строку несколько раз, а также запускает `scp`/`ssh` через `execSync`. Пароль появляется в аргументах, а значит виден любому процессу на системе и попадает в логи, что нарушает принципы безопасного хранения учётных данных. Чтобы не раскрывать SSH-пароль, используйте ключевую аутентификацию/агент/`sshpass` с передачей пароля через файл или `SSH_ASKPASS`, либо храните зашифрованный токен и раскодируйте его только при необходимости; по возможности полностью избавьтесь от использования `sshpass`.