Skip to content

v-3.1.7 Декомпозиция Bot.ts, аудит безопасности и производительности - #124

Merged
max36895 merged 3 commits into
mainfrom
v-3.1.7
Nov 7, 2026
Merged

max36895 merged 3 commits into
mainfrom
v-3.1.7

Conversation

@max36895

@max36895 max36895 commented Nov 7, 2026

Copy link
Copy Markdown
Owner

Ядро:

  • Декомпозиция Bot.ts на делегаты в src/core/utils/ (WebhookServer, UserQueues, DeliveryDedup, PollingRunner, FormWizard, ShutdownSignals, actions, menu, outbound, http, promise, errors); явные списки экспортов вместо export *; graceful shutdown без принудительного exit; memory-сессии per-platform.
  • ReDoS-валидатор: неоднозначные разбиения строки — пары опциональных атомов ((?:a?b?)+, 868 мс на 41 символе), «сцепленный» одиночный атом ((?:\d\d?)+, числа Фибоначчи, 40 цифр ~20 с), фиксированный {n>=10}; (a?)+, (?:ab?)+, IP-паттерны остаются разрешёнными.
  • Prototype pollution: ключи proto из payload не попадают в данные defineAction, mergeRow FileAdapter и normalizedHeaders webhookEvent.
  • Падение процесса и «зависший» ответ на исключении из responseCb (sync-бросок, async-отклонение, отказ до отправки) — защитная отправка ответа по умолчанию + .catch на промисе обработчика вебхук-сервера.
  • Приоритет реального payload над setContent(); memory-сессия выдаётся поверхностной копией (гонка параллельных запросов одного пользователя). БД:
  • FileAdapter применяет query.rules (обрезка ключа/значения по max) и возвращает пустую выборку без error (контракт _select: error = «данные не загрузились» — раньше валил сохранение userData на обычном промахе); update мержит поля, не затирая отсутствующие (паритет с Mongo).
  • Base.save: upsert-ретрай при отклонённом insert (гонка select→insert больше не теряет правки); Mongo: дедуп конкурентных connect().
  • saveData/saveDataSync не пишут содержимое таблицы в error.log. Адаптеры:
  • Опции alisa_skill_id / smartapp_application_id: отклонение чужого трафика на URL вебхука (HTTP 401; opt-in, без опции поведение прежнее).
  • Пустой userId Алисы → '' (как в Marusia); random_id VK через crypto.randomInt; temp-файл TTS через randomUUID. CLI:
  • mode из flow.json игнорируется — всегда strict_prod (недоверенный вход не понижает безопасность сгенерированного бота).
  • extractHttpSecrets сканирует фрагмент URL (в т.ч. без query); секретные значения с {{var}} предупреждают о литеральной части в генерате.
  • Валидатор: типы response.*/card.images, {{proto}}, итеративный DFS по всем компонентам графа; генерация блокируется ошибкой валидации.
  • Own-check lookup-таблиц (SYSTEM_VARS, TOKEN_ENV_NAMES, PLATFORM_README, PLATFORMS); маскирование токена в ошибках webhook; .env с правами 0600 и проверкой .gitignore; валидация имени env в deploy.js; санитизация doc.name в README. Производительность:
  • ipFilter: предпарсинг CIDR-правил в фабрике (−1,2–2,3 мкс на запрос, было +135% к стоимости запроса); кэш blockNeedsAsync (WeakMap) — генерация flow из тысяч блоков без квадратичных обходов. Документация: CHANGELOG (3.1.7), platform-integration.md (доверие к payload платформ без подписи), configuration.md/dbAdapter.md (FileAdapter и публичные боты; контракт адаптеров), json-format.md (mode), cli/AGENTS.md (закрытые баги генератора), platform-contracts.md (x-marusia-signature — только детект). Тесты: +30 регрессионных (1942 passed, 128 сьютов), защита от дублирующихся реэкспортов и snapshot публичного API в CI.

Ядро:
- Декомпозиция Bot.ts на делегаты в src/core/utils/ (WebhookServer, UserQueues,
  DeliveryDedup, PollingRunner, FormWizard, ShutdownSignals, actions, menu,
  outbound, http, promise, errors); явные списки экспортов вместо `export *`;
  graceful shutdown без принудительного exit; memory-сессии per-platform.
- ReDoS-валидатор: неоднозначные разбиения строки — пары опциональных атомов
  ((?:a?b?)+, 868 мс на 41 символе), «сцепленный» одиночный атом
  ((?:\d\d?)+, числа Фибоначчи, 40 цифр ~20 с), фиксированный {n>=10};
  (a?)+, (?:ab?)+, IP-паттерны остаются разрешёнными.
- Prototype pollution: ключи __proto__ из payload не попадают в данные
  defineAction, mergeRow FileAdapter и normalizedHeaders webhookEvent.
- Падение процесса и «зависший» ответ на исключении из responseCb
  (sync-бросок, async-отклонение, отказ до отправки) — защитная отправка
  ответа по умолчанию + .catch на промисе обработчика вебхук-сервера.
- Приоритет реального payload над setContent(); memory-сессия выдаётся
  поверхностной копией (гонка параллельных запросов одного пользователя).
БД:
- FileAdapter применяет query.rules (обрезка ключа/значения по max) и
  возвращает пустую выборку без error (контракт _select: error = «данные
  не загрузились» — раньше валил сохранение userData на обычном промахе);
  update мержит поля, не затирая отсутствующие (паритет с Mongo).
- Base.save: upsert-ретрай при отклонённом insert (гонка select→insert
  больше не теряет правки); Mongo: дедуп конкурентных connect().
- saveData/saveDataSync не пишут содержимое таблицы в error.log.
Адаптеры:
- Опции alisa_skill_id / smartapp_application_id: отклонение чужого
  трафика на URL вебхука (HTTP 401; opt-in, без опции поведение прежнее).
- Пустой userId Алисы → '' (как в Marusia); random_id VK через
  crypto.randomInt; temp-файл TTS через randomUUID.
CLI:
- mode из flow.json игнорируется — всегда strict_prod (недоверенный вход
  не понижает безопасность сгенерированного бота).
- extractHttpSecrets сканирует фрагмент URL (в т.ч. без query); секретные
  значения с {{var}} предупреждают о литеральной части в генерате.
- Валидатор: типы response.*/card.images, {{__proto__}}, итеративный DFS
  по всем компонентам графа; генерация блокируется ошибкой валидации.
- Own-check lookup-таблиц (SYSTEM_VARS, TOKEN_ENV_NAMES, PLATFORM_README,
  PLATFORMS); маскирование токена в ошибках webhook; .env с правами 0600
  и проверкой .gitignore; валидация имени env в deploy.js; санитизация
  doc.name в README.
Производительность:
- ipFilter: предпарсинг CIDR-правил в фабрике (−1,2–2,3 мкс на запрос,
  было +135% к стоимости запроса); кэш blockNeedsAsync (WeakMap) —
  генерация flow из тысяч блоков без квадратичных обходов.
Документация: CHANGELOG (3.1.7), platform-integration.md (доверие к payload
платформ без подписи), configuration.md/dbAdapter.md (FileAdapter и публичные
боты; контракт адаптеров), json-format.md (mode), cli/AGENTS.md (закрытые
баги генератора), platform-contracts.md (x-marusia-signature — только детект).
Тесты: +30 регрессионных (1942 passed, 128 сьютов), защита от дублирующихся
реэкспортов и snapshot публичного API в CI.
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 7, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-07T14:03:13.254396Z 258964e New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ce4fe15353

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/middleware/ipFilter.ts Outdated
// Если задан whitelist — должен быть match
if (whitelist && whitelist.length) {
const matched = whitelist.some((cidr) => ipInCidr(ip, cidr));
if (whitelistRules && whitelistRules.length) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep invalid whitelists fail-closed

When a nonempty whitelist contains only invalid entries, such as ['192.0.2.0/33'], toRules() drops every entry and this condition skips whitelist enforcement entirely. Requests from every IP then reach next(), whereas the previous implementation rejected them because none matched. Preserve the distinction between an absent/empty whitelist and a configured whitelist with no valid rules, or reject invalid configuration at middleware creation.

Useful? React with 👍 / 👎.

Comment thread cli/flowGenerator.js Outdated
})
.join('&');
action.url = action.url.slice(0, queryStart + 1) + query + action.url.slice(end);
let newUrl = action.url.slice(0, queryStart + 1);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve the URL prefix when only a fragment is present

For an HTTP action URL containing # but no ?, queryStart is -1, so this initializes newUrl with slice(0, 0) and discards the entire scheme, host, and path. For example, https://api.example.com/hooks#section becomes #section; the generated Node.js fetchWithTimeout() call consequently receives a relative URL and fails instead of executing the action. Initialize the prefix through hashIndex when there is no query string, and assert the complete generated URL in the fragment-only regression test.

AGENTS.md reference: cli/AGENTS.md:L125-L126

Useful? React with 👍 / 👎.

Ядро:
- Декомпозиция Bot.ts на делегаты в src/core/utils/ (WebhookServer, UserQueues,
  DeliveryDedup, PollingRunner, FormWizard, ShutdownSignals, actions, menu,
  outbound, http, promise, errors); явные списки экспортов вместо `export *`;
  graceful shutdown без принудительного exit; memory-сессии per-platform.
- ReDoS-валидатор: неоднозначные разбиения строки — пары опциональных атомов
  ((?:a?b?)+, 868 мс на 41 символе), «сцепленный» одиночный атом
  ((?:\d\d?)+, числа Фибоначчи, 40 цифр ~20 с), фиксированный {n>=10};
  (a?)+, (?:ab?)+, IP-паттерны остаются разрешёнными.
- Prototype pollution: ключи __proto__ из payload не попадают в данные
  defineAction, mergeRow FileAdapter и normalizedHeaders webhookEvent.
- Падение процесса и «зависший» ответ на исключении из responseCb
  (sync-бросок, async-отклонение, отказ до отправки) — защитная отправка
  ответа по умолчанию + .catch на промисе обработчика вебхук-сервера.
- Приоритет реального payload над setContent(); memory-сессия выдаётся
  поверхностной копией (гонка параллельных запросов одного пользователя).
БД:
- FileAdapter применяет query.rules (обрезка ключа/значения по max) и
  возвращает пустую выборку без error (контракт _select: error = «данные
  не загрузились» — раньше валил сохранение userData на обычном промахе);
  update мержит поля, не затирая отсутствующие (паритет с Mongo).
- Base.save: upsert-ретрай при отклонённом insert (гонка select→insert
  больше не теряет правки); Mongo: дедуп конкурентных connect().
- saveData/saveDataSync не пишут содержимое таблицы в error.log.
Адаптеры:
- Опции alisa_skill_id / smartapp_application_id: отклонение чужого
  трафика на URL вебхука (HTTP 401; opt-in, без опции поведение прежнее).
- Пустой userId Алисы → '' (как в Marusia); random_id VK через
  crypto.randomInt; temp-файл TTS через randomUUID.
CLI:
- mode из flow.json игнорируется — всегда strict_prod (недоверенный вход
  не понижает безопасность сгенерированного бота).
- extractHttpSecrets сканирует фрагмент URL (в т.ч. без query); секретные
  значения с {{var}} предупреждают о литеральной части в генерате.
- Валидатор: типы response.*/card.images, {{__proto__}}, итеративный DFS
  по всем компонентам графа; генерация блокируется ошибкой валидации.
- Own-check lookup-таблиц (SYSTEM_VARS, TOKEN_ENV_NAMES, PLATFORM_README,
  PLATFORMS); маскирование токена в ошибках webhook; .env с правами 0600
  и проверкой .gitignore; валидация имени env в deploy.js; санитизация
  doc.name в README.
Производительность:
- ipFilter: предпарсинг CIDR-правил в фабрике (−1,2–2,3 мкс на запрос,
  было +135% к стоимости запроса); кэш blockNeedsAsync (WeakMap) —
  генерация flow из тысяч блоков без квадратичных обходов.
Документация: CHANGELOG (3.1.7), platform-integration.md (доверие к payload
платформ без подписи), configuration.md/dbAdapter.md (FileAdapter и публичные
боты; контракт адаптеров), json-format.md (mode), cli/AGENTS.md (закрытые
баги генератора), platform-contracts.md (x-marusia-signature — только детект).
Тесты: +30 регрессионных (1942 passed, 128 сьютов), защита от дублирующихся
реэкспортов и snapshot публичного API в CI.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 80764a526d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

if (typeof value === 'string') {
// Без эллипсиса: хранимое значение — чистый префикс, «…»
// испортил бы ключ строки и JSON в поле data.
element[field] = Text.resize(value, rule.max, false);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep primary-key normalization consistent across reads and writes

When a string primary key exceeds its model rule's max, the new write path truncates it, but _select() and _remove() still use the original, untruncated key. For example, inserting a UsersData row with a 251-character user ID succeeds, yet selecting it with that same ID returns { status: false } because the stored ID has been shortened to 250 characters. Subsequent requests therefore cannot reload their saved state, and deletion by the original ID cannot remove it. Apply a consistent key policy across all operations, or reject oversized keys rather than silently changing their identity.

Useful? React with 👍 / 👎.

Ядро:
- Декомпозиция Bot.ts на делегаты в src/core/utils/ (WebhookServer, UserQueues,
  DeliveryDedup, PollingRunner, FormWizard, ShutdownSignals, actions, menu,
  outbound, http, promise, errors); явные списки экспортов вместо `export *`;
  graceful shutdown без принудительного exit; memory-сессии per-platform.
- ReDoS-валидатор: неоднозначные разбиения строки — пары опциональных атомов
  ((?:a?b?)+, 868 мс на 41 символе), «сцепленный» одиночный атом
  ((?:\d\d?)+, числа Фибоначчи, 40 цифр ~20 с), фиксированный {n>=10};
  (a?)+, (?:ab?)+, IP-паттерны остаются разрешёнными.
- Prototype pollution: ключи __proto__ из payload не попадают в данные
  defineAction, mergeRow FileAdapter и normalizedHeaders webhookEvent.
- Падение процесса и «зависший» ответ на исключении из responseCb
  (sync-бросок, async-отклонение, отказ до отправки) — защитная отправка
  ответа по умолчанию + .catch на промисе обработчика вебхук-сервера.
- Приоритет реального payload над setContent(); memory-сессия выдаётся
  поверхностной копией (гонка параллельных запросов одного пользователя).
БД:
- FileAdapter применяет query.rules (обрезка ключа/значения по max) и
  возвращает пустую выборку без error (контракт _select: error = «данные
  не загрузились» — раньше валил сохранение userData на обычном промахе);
  update мержит поля, не затирая отсутствующие (паритет с Mongo).
- Base.save: upsert-ретрай при отклонённом insert (гонка select→insert
  больше не теряет правки); Mongo: дедуп конкурентных connect().
- saveData/saveDataSync не пишут содержимое таблицы в error.log.
Адаптеры:
- Опции alisa_skill_id / smartapp_application_id: отклонение чужого
  трафика на URL вебхука (HTTP 401; opt-in, без опции поведение прежнее).
- Пустой userId Алисы → '' (как в Marusia); random_id VK через
  crypto.randomInt; temp-файл TTS через randomUUID.
CLI:
- mode из flow.json игнорируется — всегда strict_prod (недоверенный вход
  не понижает безопасность сгенерированного бота).
- extractHttpSecrets сканирует фрагмент URL (в т.ч. без query); секретные
  значения с {{var}} предупреждают о литеральной части в генерате.
- Валидатор: типы response.*/card.images, {{__proto__}}, итеративный DFS
  по всем компонентам графа; генерация блокируется ошибкой валидации.
- Own-check lookup-таблиц (SYSTEM_VARS, TOKEN_ENV_NAMES, PLATFORM_README,
  PLATFORMS); маскирование токена в ошибках webhook; .env с правами 0600
  и проверкой .gitignore; валидация имени env в deploy.js; санитизация
  doc.name в README.
Производительность:
- ipFilter: предпарсинг CIDR-правил в фабрике (−1,2–2,3 мкс на запрос,
  было +135% к стоимости запроса); кэш blockNeedsAsync (WeakMap) —
  генерация flow из тысяч блоков без квадратичных обходов.
Документация: CHANGELOG (3.1.7), platform-integration.md (доверие к payload
платформ без подписи), configuration.md/dbAdapter.md (FileAdapter и публичные
боты; контракт адаптеров), json-format.md (mode), cli/AGENTS.md (закрытые
баги генератора), platform-contracts.md (x-marusia-signature — только детект).
Тесты: +30 регрессионных (1942 passed, 128 сьютов), защита от дублирующихся
реэкспортов и snapshot публичного API в CI.
@max36895
max36895 merged commit 8aca4bb into main Nov 7, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant