INN-regex затирает легитимные слитные 10/12-значные числа (крупные суммы в рублях) в text/строковых fields перед отправкой в LLM #1640

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

Severity: low · Категория: correctness/data-corruption · Файл: backend/app/services/llm/redaction.py:82-83, 103-112, 115-129

redaction.py:83 — _INN_RE = (?<!\d)(?:\d{12}|\d{10})(?!\d) матчит ЛЮБОЕ обособленное слитное 10- или 12-значное число и заменяет на [REDACTED:inn] (scrub_text, redaction.py:124-125; применяется к text и к строковым значениям fields через _scrub_value, redaction.py:132-141, 168-172). Проверено标准 standalone-тестом: 'Стоимость проекта: 1200000000 руб' → 'Стоимость проекта: [REDACTED:inn] руб'; 'Бюджет 123456789012 рублей' → '...[REDACTED:inn]...'. В домене (девелопмент РФ) суммы 1 млрд+ руб — 10 слитных цифр, бюджеты ~трлн — 12. Вектор в чате: text = вопрос пользователя (safe_payload.py:77), куда юзер может вписать слитную сумму ('выгоден ли проект при бюджете 1200000000?'); и строковые значения секций отчёта. Импакт: при правиле 3 chat-промпта (числа только вербатим) число молча превращается в '[REDACTED:inn]' до модели → ответ некорректен для дорогих проектов. Смягчающие факторы: (1) числовые int/float-значения fields НЕ затрагиваются (_scrub_value скрабит только str) — основной носитель агрегатов отчёта безопасен; (2) суммы с разделителями тысяч ('1 200 000 000', '1.200.000.000') НЕ матчатся, т.к. _INN_RE требует слитные цифры; (3) это деградация качества ответа, НЕ утечка данных. Фикс: сузить _INN_RE контекстными якорями (ИНН/налогоплательщик рядом) или валидировать контрольную сумму ИНН, либо исключить редактирование чисто-числового free-text при отсутствии PII-контекста.

Почему баг: Число в свободном тексте/строковом поле молча подменяется маркером ДО отправки модели. С учётом правила 3 чата (числа только вербатим, ничего не выдумывать, при отсутствии данных — честно сказать 'данных нет'), модель либо отрапортует, что суммы в отчёте нет, либо повторит '[REDACTED:inn]' — неверный результат основной фичи чата для дорогих (млрд+) проектов. Числовые fields-значения типа int НЕ затрагиваются (scrub только для str), поэтому скоуп — free text и строковые поля, но именно туда docstring велит класть агрегаты/цитаты из отчёта.

Как чинить: Сузить ИНН-эвристику: либо требовать контекст-якорь ('ИНН' рядом), либо валидировать контрольную цифру ИНН (алгоритм Росреестра/ФНС) перед заменой, либо не скрабить числа в text, полагаясь на то, что суммы — публичные агрегаты. Минимум — задокументировать, что числа ≥10 цифр в text будут затёрты, чтобы консьюмер клал их в числовые fields, а не в текст.


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

**Severity:** low · **Категория:** correctness/data-corruption · **Файл:** `backend/app/services/llm/redaction.py:82-83, 103-112, 115-129` redaction.py:83 — _INN_RE = (?<!\d)(?:\d{12}|\d{10})(?!\d) матчит ЛЮБОЕ обособленное слитное 10- или 12-значное число и заменяет на [REDACTED:inn] (scrub_text, redaction.py:124-125; применяется к text и к строковым значениям fields через _scrub_value, redaction.py:132-141, 168-172). Проверено标准 standalone-тестом: 'Стоимость проекта: 1200000000 руб' → 'Стоимость проекта: [REDACTED:inn] руб'; 'Бюджет 123456789012 рублей' → '...[REDACTED:inn]...'. В домене (девелопмент РФ) суммы 1 млрд+ руб — 10 слитных цифр, бюджеты ~трлн — 12. Вектор в чате: text = вопрос пользователя (safe_payload.py:77), куда юзер может вписать слитную сумму ('выгоден ли проект при бюджете 1200000000?'); и строковые значения секций отчёта. Импакт: при правиле 3 chat-промпта (числа только вербатим) число молча превращается в '[REDACTED:inn]' до модели → ответ некорректен для дорогих проектов. Смягчающие факторы: (1) числовые int/float-значения fields НЕ затрагиваются (_scrub_value скрабит только str) — основной носитель агрегатов отчёта безопасен; (2) суммы с разделителями тысяч ('1 200 000 000', '1.200.000.000') НЕ матчатся, т.к. _INN_RE требует слитные цифры; (3) это деградация качества ответа, НЕ утечка данных. Фикс: сузить _INN_RE контекстными якорями (ИНН/налогоплательщик рядом) или валидировать контрольную сумму ИНН, либо исключить редактирование чисто-числового free-text при отсутствии PII-контекста. **Почему баг:** Число в свободном тексте/строковом поле молча подменяется маркером ДО отправки модели. С учётом правила 3 чата (числа только вербатим, ничего не выдумывать, при отсутствии данных — честно сказать 'данных нет'), модель либо отрапортует, что суммы в отчёте нет, либо повторит '[REDACTED:inn]' — неверный результат основной фичи чата для дорогих (млрд+) проектов. Числовые fields-значения типа int НЕ затрагиваются (scrub только для str), поэтому скоуп — free text и строковые поля, но именно туда docstring велит класть агрегаты/цитаты из отчёта. **Как чинить:** Сузить ИНН-эвристику: либо требовать контекст-якорь ('ИНН' рядом), либо валидировать контрольную цифру ИНН (алгоритм Росреестра/ФНС) перед заменой, либо не скрабить числа в text, полагаясь на то, что суммы — публичные агрегаты. Минимум — задокументировать, что числа ≥10 цифр в text будут затёрты, чтобы консьюмер клал их в числовые fields, а не в текст. --- <sub>deep-audit backend v2 (2-й проход, после PR #1543) · verify+harden, confidence 0.82 · unit B29</sub>
bot-backend added the
week ревью 1
label 2026-06-16 18:46:27 +00:00
bot-backend added the
needs-human
label 2026-06-17 06:26:28 +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#1640
No description provided.