Files
ipwhitelist-app/research/opus-review-validators.md
T

68 lines
3.6 KiB
Markdown
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.
# Ответ Claude Opus 4 — код-ревью validators.js
> Дата: 2026-05-30
## 🔴 Баг 1 — запрещённые диапазоны обходятся бо́льшей подсетью (критично)
Проверка блокировки использует `isSubnetOf(normalized, blocked)` — то есть «запись внутри запрещённого диапазона». Но не проверяется обратное направление: **запись, которая САМА содержит запрещённый диапазон**.
Поскольку ТЗ разрешает маски вплоть до `/22`, а многие запрещённые блоки — это `/24`, их можно обойти суперсетью:
```
Вход: 192.0.2.0/22
→ нормализуется в 192.0.0.0/22 (диапазон 192.0.0.0 192.0.3.255)
```
Этот `/22` **содержит** TEST-NET-1 (`192.0.2.0/24`) и IANA special (`192.0.0.0/24`), но `isSubnetOf` вернёт `false` (родитель не внутри ребёнка) → запись пройдёт валидацию. То же с `198.18.0.0/15` (Benchmarking) и др.
**Фикс** — использовать пересечение вместо вложенности:
```js
for (const blocked of BLOCKED_RANGES) {
if (overlaps(normalized, blocked)) {
throw new Error(`Диапазон ${normalized} пересекается с запрещённым (${blocked})`);
}
}
```
`overlaps` ловит оба направления (и когда запись внутри блока, и когда блок внутри записи). `isSubnetOf` после этого фикса в блокировке не нужен.
---
## 🟡 Замечание 2 — parseInt глотает мусор в маске
```js
const mask = parseInt(maskStr, 10);
```
`10.0.0.0/24abc``parseInt('24abc')` = `24`, запись принимается как `/24`. Строгая проверка:
```js
if (!/^\d{1,2}$/.test(maskStr)) throw new Error('Некорректная маска');
const mask = parseInt(maskStr, 10);
```
---
## 🟡 Замечание 3 — множественные слэши не отсекаются
`10.0.0.0/24/8`.split('/') → `['10.0.0.0','24','8']`, третий элемент молча игнорируется. Добавить проверку числа частей:
```js
const parts = cidr.split('/');
if (parts.length !== 2) throw new Error('Некорректный формат CIDR');
const [addr, maskStr] = parts;
```
---
## 🟢 Не баги (проверено)
- **`overlaps`** — формула `a.start <= b.end && b.start <= a.start || b.start <= a.end && a.start <= b.start` хоть и обфусцирована, **математически эквивалентна** стандартной `a.start <= b.end && b.start <= a.end`. Работает корректно. Можно упростить для читаемости, но это не дефект.
- **Битовая арифметика** с `<<8` уходит в знаковый 32-бит, но финальный `>>> 0` всё исправляет. Корректно.
- **Маска `/0`**, `1 << (32-mask)` — безопасно, т.к. `mask` ограничен 2232.
---
**Итог:** один настоящий эксплуатируемый баг (#1 — обход TEST-NET/special через `/22`), два мелких по строгости парсинга. Главное — поправить блокировку на `overlaps`.