(low) own_portfolio: слабый regex-guard '^[0-9]+' позволяет non-numeric префиксу dev_id уронить весь current-portfolio запрос #1392

Closed
opened 2026-06-14 18:10:19 +00:00 by bot-backend · 0 comments
Collaborator

Описание

_CURRENT_SQL защищает integer-cast через o.dev_id ~ '^[0-9]+', но это требует лишь чтобы dev_id НАЧИНАЛСЯ с цифр — не требует, чтобы токен до первого '' был полностью числовым. split_part(o.dev_id, '_', 1) возвращает подстроку до '', поэтому dev_id вида '123ab_0' проходит regex, но даёт нечисловой префикс ('123ab'), и CAST(... AS integer) бросает invalid input syntax for type integer. Т.к. CAST вычисляется в WHERE по всем строкам, одна битая 'наша' dev_id обрывает ВЕСЬ запрос. _query_current ловит это (try/except → []), endpoint не падает, но ВСЕ current (domrf) own-проекты молча выпадают из §25.3 cannibalization-портфеля.

Корень

Regex-guard не анкорит полный числовой токен → CAST может увидеть не-цифры. PostgreSQL не гарантирует short-circuit AND-условий в WHERE.

Evidence

own_portfolio.py:101-102:

AND o.dev_id ~ '^[0-9]+'
AND CAST(split_part(o.dev_id, '_', 1) AS integer) = ANY(CAST(:ids AS integer[]))

own_portfolio.py:173-175: except Exception → [] молча теряет все domrf-проекты.

Suggested fix

Заанкорить regex к полному числовому токену: o.dev_id ~ '^[0-9]+(_|$)' (цифры, затем '_' или конец). Лучше — сравнивать текстовый префикс без CAST: split_part(o.dev_id, '_', 1) = ANY(CAST(:ids AS text[])) с ids в text, устранив любой путь падения cast.

Обоснование severity

low: формат dev_id документирован как '_', источник — domrf API; malformed-строка гипотетична, не подтверждена данными. graceful degradation есть, фикс тривиален. confidence 0.72.


week ревью 1 · multi-agent аудит 2026-06-14 · severity=low · category=data-integrity

Затронутые файлы:

  • /Users/anton/Птица/gendesign/backend/app/services/site_finder/own_portfolio.py
## Описание `_CURRENT_SQL` защищает integer-cast через `o.dev_id ~ '^[0-9]+'`, но это требует лишь чтобы dev_id НАЧИНАЛСЯ с цифр — не требует, чтобы токен до первого '_' был полностью числовым. `split_part(o.dev_id, '_', 1)` возвращает подстроку до '_', поэтому dev_id вида '123ab_0' проходит regex, но даёт нечисловой префикс ('123ab'), и `CAST(... AS integer)` бросает `invalid input syntax for type integer`. Т.к. CAST вычисляется в WHERE по всем строкам, одна битая 'наша' dev_id обрывает ВЕСЬ запрос. `_query_current` ловит это (try/except → []), endpoint не падает, но ВСЕ current (domrf) own-проекты молча выпадают из §25.3 cannibalization-портфеля. ## Корень Regex-guard не анкорит полный числовой токен → CAST может увидеть не-цифры. PostgreSQL не гарантирует short-circuit AND-условий в WHERE. ## Evidence `own_portfolio.py:101-102`: ```sql AND o.dev_id ~ '^[0-9]+' AND CAST(split_part(o.dev_id, '_', 1) AS integer) = ANY(CAST(:ids AS integer[])) ``` `own_portfolio.py:173-175`: `except Exception → []` молча теряет все domrf-проекты. ## Suggested fix Заанкорить regex к полному числовому токену: `o.dev_id ~ '^[0-9]+(_|$)'` (цифры, затем '_' или конец). Лучше — сравнивать текстовый префикс без CAST: `split_part(o.dev_id, '_', 1) = ANY(CAST(:ids AS text[]))` с ids в text, устранив любой путь падения cast. ## Обоснование severity low: формат dev_id документирован как '<numericDevId>_<suffix>', источник — domrf API; malformed-строка гипотетична, не подтверждена данными. graceful degradation есть, фикс тривиален. confidence 0.72. --- _week ревью 1 · multi-agent аудит 2026-06-14 · severity=**low** · category=`data-integrity`_ Затронутые файлы: - `/Users/anton/Птица/gendesign/backend/app/services/site_finder/own_portfolio.py`
bot-backend added the
week ревью 1
label 2026-06-14 18:10:19 +00:00
bot-backend added the
scope/backend
label 2026-06-15 11:01:57 +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#1392
No description provided.