Files
playground/security-analysis/findings/pr-5/1787496475-review.json
T
playground-security-bot 67d3eef3c6
security / scan (pull_request) Skipped
security / review (pull_request) Skipped
security / deep-audit (pull_request) Skipped
security: AI review results for PR #5
2026-08-23 14:47:55 +00:00

107 lines
12 KiB
JSON
Raw 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-12",
"source": "ai-review",
"category": "secrets",
"severity": "critical",
"confidence": 1.0,
"file": "orders.py",
"line_start": 12,
"line_end": 12,
"title": "Hardcoded GitHub personal access token",
"description": "В коде захардкожен GitHub token (GITHUB_TOKEN), несмотря на то, что он с замаскированными символами (ghp_xxx...).",
"impact": "Утечка токена позволяет злоумышленнику получить доступ к репозиториям и API GitHub от имени владельца токена, потенциально ведёт к компрометации инфраструктуры, откату или подмене кода, краже данных.",
"exploit_scenario": "Если этот файл попадёт в публичный репозиторий или логи (например, при отправке в Git), злоумышленник может скопировать токен и использовать его для аутентификации в GitHub API (например, через `curl -H 'Authorization: token ghp_...'`), получить доступ к приватным репозиториям, получить secret-базы, выкачать код, выполнить атаки через GitHub Actions.",
"evidence": "GITHUB_TOKEN = \"ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\"",
"recommendation": "Никогда не храните секреты в коде. Используйте переменные окружения (например, `os.getenv('GITHUB_TOKEN')`), secrets-менеджер (HashiCorp Vault, AWS Secrets Manager) или конфигурационные файлы с `.gitignore`. Старый токен немедленно отозвать в настройках GitHub.",
"cwe": "CWE-798",
"status": "OPEN",
"created_at": "2026-08-23T14:47:55Z",
"pr_number": 5,
"commit_sha": "7a4931192d19aa587f994c3220bbf1e5d51ca4dd"
},
{
"id": "ai-review-1-orders.py-84",
"source": "ai-review",
"category": "command-exec",
"severity": "high",
"confidence": 1.0,
"file": "orders.py",
"line_start": 84,
"line_end": 93,
"title": "Command injection via user-controlled host parameter",
"description": "Параметр `host`, передаваемый в эндпоинт /admin/backup, напрямую подставляется в команду rsync через subprocess.run без валидации. Это позволяет выполнить произвольные команды на сервере через инъекцию аргументов.",
"impact": "Полный компрометация сервера: злоумышленник может выполнить произвольные команды с правами сервиса, выкачать данные, установить backdoor, выполнить внутреннюю снэйфинг-атаку.",
"exploit_scenario": "Злоумышленник вызывает POST /admin/backup с хостом вида: `; rm -rf / ; echo 'hacked' ||`. После подстановки в subprocess команда будет выполнена как: `rsync -avz /workspace/orders.py ; rm -rf / ; echo 'hacked' ||:/backup/`. Благодаря || и ; это приведёт к выполнению произвольной команды. Также возможна инъекция через опции rsync (например, `--rsync-path=;malicious`) или через SSH-опции (если SSH-хост — `user@host -oProxyCommand='cmd'`).",
"evidence": "[\"rsync\", \"-avz\", \"/workspace/orders.py\", f\"{host}:/backup/\"] — подстановка user-controlled строки напрямую в аргумент команды без экранирования и валидации.",
"recommendation": "Не использовать user input напрямую в команде. Валидировать host: проверить по белому списку доменов/IP, использовать regex `^[a-zA-Z0-9.-]+$` или IP-адреса, либо использовать `shlex.quote(host)` (но это не защитит от всех случаев, лучше белый список). Рассмотреть альтернативу — вызов через Python-библиотеку (fabric, paramiko), где можно явно передать параметры без shell.",
"cwe": "CWE-77",
"status": "OPEN",
"created_at": "2026-08-23T14:47:55Z",
"pr_number": 5,
"commit_sha": "7a4931192d19aa587f994c3220bbf1e5d51ca4dd"
},
{
"id": "ai-review-2-orders.py-69",
"source": "ai-review",
"category": "idor",
"severity": "medium",
"confidence": 1.0,
"file": "orders.py",
"line_start": 69,
"line_end": 80,
"title": "Missing authorization check for order ownership",
"description": "Все эндпоинты (/orders/{order_id}, /orders, /admin/backup) проверяют наличие токена авторизации, но не проверяют, что пользователь имеет право доступа к конкретному заказу (owner check).",
"impact": "IDOR (Insecure Direct Object Reference) — аутентифицированный пользователь может получить доступ к любым заказам, включая чужие, по известному order_id.",
"exploit_scenario": "Пользователь A создает заказ, получает order_id, и затем посылает GET /orders/{order_id} с любым аутентифицированным заголовком Authorization (в котором достаточно, чтобы токен был non-null), даже если он не владелец заказа (user_id не совпадает). Аналогично — он может изменить сумму чужого заказа через PUT /orders/{order_id}, если знает ID.",
"evidence": "get_order, update_order — проверяют только `if authorization is None`, но не проверяют, что `orders[order_id].user_id == authenticated_user_id`. В POST /orders — user_id передаётся, но не связывается с аутентифицированным пользователем (нет извлечения из токена).",
"recommendation": "Извлекать идентификатор пользователя из токена (например, JWT), валидировать его подпись и claim. Сравнивать `user_id` из запроса с `authenticated_user_id`. Для GET и PUT проверять, что `order.user_id == authenticated_user_id`.",
"cwe": "CWE-639",
"status": "OPEN",
"created_at": "2026-08-23T14:47:55Z",
"pr_number": 5,
"commit_sha": "7a4931192d19aa587f994c3220bbf1e5d51ca4dd"
},
{
"id": "ai-review-3-orders.py-83",
"source": "ai-review",
"category": "authz",
"severity": "medium",
"confidence": 1.0,
"file": "orders.py",
"line_start": 83,
"line_end": 99,
"title": "No role-based access control for /admin/backup endpoint",
"description": "Эндпоинт /admin/backup доступен любому, у кого есть валидный authorization токен — нет роли admin. Это позволяет обычным пользователям вызывать опасную операцию бэкапа, включающую подозрительный вызов rsync с внешним хостом.",
"impact": "Злоумышленник может использовать сервис как прокси для утечки данных или для внутренней репликации вредоносного контента, а также проводить SSRF через rsync (если rsync поддерживает специфичные схемы или настроен на взаимодействие с internal сервисами).",
"exploit_scenario": "Любой аутентифицированный пользователь (даже не admin) вызывает /admin/backup с подконтрольным хостом (например, `evil.com`), и сервер пытается скопировать `orders.py` на этот хост. Если rsync настроен на использование SSH с агентом или ключами, это может привести к утечке кода. Также, если злоумышленник может контролировать content `orders.py`, он может запланировать вредоносные данные.",
"evidence": "В /admin/backup нет проверки ролей или специального заголовка (например, X-Admin: true). Все функции использует только `if authorization is None`.",
"recommendation": "Добавить роль: извлекать claim 'role' или 'scopes' из токена, и явно проверять `if not is_admin(auth_user): raise HTTPException(403)`. Либо использовать специальный service token, передаваемый в другом заголовке.",
"cwe": "CWE-285",
"status": "OPEN",
"created_at": "2026-08-23T14:47:55Z",
"pr_number": 5,
"commit_sha": "7a4931192d19aa587f994c3220bbf1e5d51ca4dd"
},
{
"id": "ai-review-4-orders.py-89",
"source": "ai-review",
"category": "injection",
"severity": "medium",
"confidence": 0.5,
"file": "orders.py",
"line_start": 89,
"line_end": 89,
"title": "Potential SSRF via rsync to user-controlled host",
"description": "Эндпоинт позволяет задавать произвольный хост для rsync, и если rsync сконфигурирован с поддержкой SSH или других протоколов, это может привести к SSRF или утечке данных.",
"impact": "Если rsync использует SSH под капотом, а злоумышленник передаёт хост вроде `localhost`, `127.0.0.1`, `169.254.169.254` (AWS metadata), `internal.local`, это может привести к чтению метаданных инфраструктуры или закрытых сервисов.",
"exploit_scenario": "Вызвать POST /admin/backup с host=169.254.169.254 — если rsync поддерживает URL вида `rsync://...` или ssh-подобные параметры, это может привести к попытке считать metadata-данные. Аналогично, `user@internal-server:...` может привести к внутреннему пробингу, если используется SSH.",
"evidence": "subprocess.run([\"rsync\", \"-avz\", \"/workspace/orders.py\", f\"{host}:/backup/\"]) — host может быть подконтрольным и вредоносным (например, `127.0.0.1#-e/bin/sh -c ...`, если интерпретация команды не экранирована).",
"recommendation": "Блокировать внутренние IP (RFC1918), localhost, AWS metadata-адреса (169.254.169.254/32), домены внутри доверенного списка. Ограничить допустимые хосты (белый список доменов) и проверять host вручную перед вызовом subprocess.",
"cwe": "CWE-918",
"status": "OPEN",
"created_at": "2026-08-23T14:47:55Z",
"pr_number": 5,
"commit_sha": "7a4931192d19aa587f994c3220bbf1e5d51ca4dd"
}
]