Files
portal/docs/security/2026-06-17-open-items.md
T
Дмитрий ebd94f3fc5
Accessibility (Pa11y live) / a11y (push) Has been cancelled
SAST — Semgrep / Semgrep SAST scan (push) Has been cancelled
docs(security): go-live трекер — все блокеры B1-B6 сняты (GO), B2 anon на проде; gitignore lychee/walk артефактов
2026-06-18 06:13:56 +03:00

95 lines
8.5 KiB
Markdown

# Открытые вопросы — снимок 17.06.2026
Сводный трекер по итогам сессии (go-live security gate + кросс-сессионная сверка).
Зона = где правится; «коллизия с фронт-сессией» = пересекается ли с параллельной
сессией, которая ведёт находки осмотра во фронтенде `app/resources/js`.
---
## 🔴 Блокеры безопасности (мешают выходу в интернет)
> **Живых блокеров нет — все сняты.** B1 (`d1976c9c`); B2 anon-маски применены на прод (`8bb72b34`); B3/B6 прод-`.env` (`APP_DEBUG=false`, `APP_ENV=production`, `SAAS_ADMIN_TEST_BYPASS=false` + `config:cache`); B4/B5 — код. **Security go-live: GO** (CSP пока Report-Only; 152-ФЗ — ручное).
| # | Пункт | Суть | Зона | Коллизия |
|---|---|---|---|---|
| B1 | **F-P1 / 152-ФЗ retention** | ✅ ЗАКРЫТО (`d1976c9c`) — Телефоны удалённых лидов не вычищаются (нет анонимизации/hard-delete после soft-delete). Подтверждён фактом по `Deal`-модели + схеме. | `app/Console/Commands` + миграция (бэкенд/БД) | низкая (бэкенд) |
| B2 | **pg_anonymizer** | ✅ ЗАКРЫТО (17.06, прод) — anon стоял, но было 0 правил маскирования; применены SECURITY LABEL на ПДн-колонки (`db/anon_masking_labels.sql`, `8bb72b34`) → `pg_dump` под masked-ролью маскирует. | БД/инфра + `docs/security` | нет |
| B3 | **SAAS_ADMIN_TEST_BYPASS** | ✅ ЗАКРЫТО (17.06, прод) — в боевом `.env` выставлено `SAAS_ADMIN_TEST_BYPASS=false` + `php artisan config:cache`; `/api/admin/**` снова только за middleware `saas-admin`. Бэкап `.env.bak-2026-06-17-b3`. | `.env.production` / config | нет |
| B4 | **SSRF через `/api/webhooks/test`** | ✅ ЗАКРЫТО (код: `WebhookUrlGuard`) — Нет фильтрации URL → запрос на metadata YC `169.254.169.254` → IAM-токен. | бэкенд (контроллер/сервис) | низкая |
| B5 | **Открытые без auth ручки** | ✅ ЗАКРЫТО (код: `web.php` auth:sanctum) — `/api/dashboard/summary` (E18), `/api/managers` + `/api/lead-statuses` (E9). | `routes/api.php` + middleware (бэкенд) | низкая |
| B6 | **Ward [High] APP_DEBUG** | ✅ ЗАКРЫТО (17.06, прод) — проверено фактом: в боевом `.env` `APP_DEBUG=false`, `APP_ENV=production`. | `.env.production` | нет |
## 🟠 P1 (важно, не критично к go-live)
| # | Пункт | Зона |
|---|---|---|
| P1 | Нет rate-limit на `login`/`forgot`/`2fa/verify` (Laravel Throttle) | `routes/api.php` (бэкенд) |
| P2 | URL-secret поставщика виден в access-логах (E4) → перейти на HMAC, ротация | бэкенд/инфра |
## 🟢 Инструменты аудита — статус
| Инструмент | Статус 17.06 | Действие |
|---|---|---|
| gitleaks #8 | ✅ OK (2462 коммита, 0 утечек) | — |
| Ward #70 | ✅ OK (2 dev-находки: APP_DEBUG/APP_ENV) | проверить на боевом `.env` |
| Nuclei #69 | ✅ OK (1 info `php`, 0 medium+) | — |
| Semgrep #25 | ✅ OK (semgrep-1.166.0, `npm run sast` exit 0 → 0 находок) | — |
| ZAP #68 | ✅ OK (spider+passive, 0 high; active scan не гнали — гард IS8) | active scan перед публичным деплоем |
## 🟡 Находки осмотра портала (ведёт параллельная фронт-сессия)
| Находка | Статус | Зона | Коллизия |
|---|---|---|---|
| F1 (Город в карточке) | ✅ закоммичено | фронт | — её зона |
| F2 (стоимость лида) | ✅ закоммичено | фронт | — её зона |
| F4 (пустой столбец «Операция») | 🔧 в работе у неё (`TransactionsTable.spec.ts`) | фронт | **её зона — не трогать** |
| F3 (прогноз «хватит на дни» дашборд↔биллинг) | ❓ проверить, закрыта ли | фронт | её зона |
| F5 (мок «средняя 2248 ₽») | ❓ проверить (есть `format-rub-demo-spec`) | фронт | её зона |
## 🧱 Баги машинерии стены (для claude-brain)
| # | Пункт | Файл |
|---|---|---|
| W1 | Чтение под планом блокируется (impl-режим ДР-1) | `docs/superpowers/2026-06-17-wall-read-block-bug.md` |
| W2 | Десинк указателя F-J (счётчик двигается на упавшем шаге) | там же + GUIDE |
| W3 | Недетерминизм судьи на байт-идентичном тексте | GUIDE «Уроки живого прогона» |
| W4 | Наставник: пустой `recommendation``no_mentor_go` | `docs/superpowers/2026-06-16-mentor-empty-recommendation-bug.md` |
## 🧹 Хозяйственное
| # | Пункт |
|---|---|
| H1 | Незакоммичено: спека/план/файл-баг чтения, спека/план/отчёт/трекер аудита, обновление отчёта |
| H2 | Не запушено: docs-коммит `e693cfc6` (локально) |
| H3 | Нормативный хвост (проверить): синхронизация квинтета CLAUDE.md 2.46→2.47 + долг lychee по относительным ссылкам |
| H4 | Ward оставил артефакты `ward-report.{json,sarif,html,md}` в корне — решить, в .gitignore или удалить |
---
**Рекомендация по очерёдности (с учётом недельного лимита):** реальные блокеры
B1–B6 — бэкенд/БД/config, **не пересекаются** с фронт-сессией. Самый дешёвый и
отдельный — **B5** (закрыть открытые ручки) + **B3/B6** (проверка боевого `.env`).
Semgrep/ZAP — поставить инструменты (одна команда + Java), затем добить статику/DAST.
## ПОПРАВКА — верификация по коду (17.06.2026)
Три пункта, ранее помеченные как P0 «из модели угроз», проверены по реальному коду и оказались закрытыми:
- E9 (`/api/managers`, `/api/lead-statuses`) + E18 (`/api/dashboard/summary`) — под `auth:sanctum`(+`tenant`), `app/routes/web.php`.
- E20 (`/api/admin/*`) — за middleware `saas-admin` (prod fail-closed 503).
- SSRF (`/api/webhooks/test`) — `WebhookUrlGuard` блокирует cloud-metadata/RFC1918/loopback (на сохранении и тесте), URL только `https://`.
**Вердикт ОСТАЁТСЯ NO-GO.** Реальные блокеры НЕ сняты: F-P1 (ретеншен телефонов лидов), pg_anonymizer (не установлен), прод-`.env` (APP_DEBUG/APP_ENV). Остаточные не-блокеры: bypass-флаг + SSO админки (config / Б-1), DNS-rebind на будущей доставке webhook (edge), rate-limit на login (P1 — проверить throttle).
---
## ДОБИВАНИЕ АУДИТА (17.06.2026) — pg_anonymizer + ZAP
**pg_anonymizer:** проверено фактом (`pg_extension WHERE extname='anon'` → пусто) — **НЕ установлен** (phase-3, OPEN-И-24). pg_dump отдаёт ПДн открыто → блокер B2 в силе.
**ZAP #68** (spider + passive, цель 127.0.0.1:8000, демон 2.17.0; active scan не гнали — гард IS8): spider завершён (status 100). Сводка alerts — **High 0**, Medium 4, Low 28, Informational 4. **0 high/critical → блокеров от ZAP нет.** 4 Medium = предупреждения (вероятно security-заголовки), разобрать.
**Аудит инструментами ЗАКРЫТ:** gitleaks 0 · Semgrep 0 · Ward 2(dev) · Nuclei 0(medium+) · ZAP 0(high).
**Вердикт остаётся NO-GO** — держат не сканеры, а: F-P1 (ретеншен телефонов), pg_anonymizer (не установлен), прод-`.env` (APP_DEBUG/APP_ENV).