stealth: BrowserSession.download_binary обходит семафор concurrency (в отличие от get_json) #1647

Closed
opened 2026-06-16 18:46:54 +00:00 by bot-backend · 0 comments
Collaborator

Severity: low · Категория: concurrency / WAF-blocking risk · Файл: backend/app/services/scrapers/stealth.py:222-239 (download_binary) vs 183-216 (get_json uses async with self._sem)

Файл: backend/app/services/scrapers/stealth.py:222-239 (download_binary) vs :183-216 (get_json).

Проблема: get_json оборачивает каждый запрос в 'async with self._sem:' (документированный per-session троттл против ServicePipe WAF, docstring :81-82). download_binary вызывает self._context.request.get(...) вообще без захвата self._sem — лишь jitter_sleep(200,500). Бинарные загрузки выходят из-под общего ограничителя concurrency.

Импакт (low): единственный вызов — domrf_kn.py:1407 в download_photos, где фото одного объекта качаются последовательно (await в for-цикле), а объекты оркестратор (:1816) обрабатывает по одному. Параллелизм — это asyncio.gather по endpoint'ам одного объекта (:1848), где фото — одна корутина. Значит download_binary даёт примерно +1 несемафоренный запрос параллельно семафоренной JSON-пачке объекта, а не массовый fan-out. Превышение request-rate скромное, но семафор всё же обходится — комментарий :1811 ('BrowserSession._sem ограничивает одновременные запросы') неточен относительно бинарных загрузок.

Отличие от #1347: то про размер семафора (8 vs 3), это — про сам факт необёрнутости download_binary в семафор.

Фикс: обернуть тело download_binary (запрос) в 'async with self._sem:' аналогично get_json, чтобы бинарные загрузки тоже учитывались в общем лимите concurrency.

Почему баг: The class docstring and the semaphore exist specifically to bound concurrency against the ServicePipe WAF; download_binary silently escapes that bound, so under concurrent use the real request rate can far exceed the intended limit, raising WAF-block / IP-ban risk for the whole sweep. (Distinct from open issue #1347, which is about the semaphore SIZE being 8 vs 3 — this is about binary downloads not using the semaphore at all.)

Как чинить: Wrap the request in download_binary in async with self._sem: (around the await self._context.request.get + body read), the same way get_json does, so static-asset downloads share the same concurrency bound.


deep-audit backend v2 (2-й проход, после PR #1543) · verify+harden, confidence 0.8 · unit B34

**Severity:** low · **Категория:** concurrency / WAF-blocking risk · **Файл:** `backend/app/services/scrapers/stealth.py:222-239 (download_binary) vs 183-216 (get_json uses async with self._sem)` Файл: backend/app/services/scrapers/stealth.py:222-239 (download_binary) vs :183-216 (get_json). Проблема: get_json оборачивает каждый запрос в 'async with self._sem:' (документированный per-session троттл против ServicePipe WAF, docstring :81-82). download_binary вызывает self._context.request.get(...) вообще без захвата self._sem — лишь jitter_sleep(200,500). Бинарные загрузки выходят из-под общего ограничителя concurrency. Импакт (low): единственный вызов — domrf_kn.py:1407 в download_photos, где фото одного объекта качаются последовательно (await в for-цикле), а объекты оркестратор (:1816) обрабатывает по одному. Параллелизм — это asyncio.gather по endpoint'ам одного объекта (:1848), где фото — одна корутина. Значит download_binary даёт примерно +1 несемафоренный запрос параллельно семафоренной JSON-пачке объекта, а не массовый fan-out. Превышение request-rate скромное, но семафор всё же обходится — комментарий :1811 ('BrowserSession._sem ограничивает одновременные запросы') неточен относительно бинарных загрузок. Отличие от #1347: то про размер семафора (8 vs 3), это — про сам факт необёрнутости download_binary в семафор. Фикс: обернуть тело download_binary (запрос) в 'async with self._sem:' аналогично get_json, чтобы бинарные загрузки тоже учитывались в общем лимите concurrency. **Почему баг:** The class docstring and the semaphore exist specifically to bound concurrency against the ServicePipe WAF; download_binary silently escapes that bound, so under concurrent use the real request rate can far exceed the intended limit, raising WAF-block / IP-ban risk for the whole sweep. (Distinct from open issue #1347, which is about the semaphore SIZE being 8 vs 3 — this is about binary downloads not using the semaphore at all.) **Как чинить:** Wrap the request in download_binary in `async with self._sem:` (around the await self._context.request.get + body read), the same way get_json does, so static-asset downloads share the same concurrency bound. --- <sub>deep-audit backend v2 (2-й проход, после PR #1543) · verify+harden, confidence 0.8 · unit B34</sub>
bot-backend added the
week ревью 1
label 2026-06-16 18:46:54 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#1647
No description provided.