fix(payments): reject HTML-special chars in product titles (VK payment guard) #279

Merged
developer merged 1 commits from feature/vk-title-guard into development 2026-07-16 19:17:45 +00:00
Owner

Что и зачем

Продукт с HTML-спецсимволом в названии (& < > " ') молча ломает оплату через VK. VK HTML-экранирует символ в эхе item_title во втором платёжном callback (order_status_change), напр. "&quot;, но подпись sig считает над другой формой → подпись, которую шлюз проверяет по пришедшему телу, не сходится → vk callback: bad signature (403) → VK не получает подтверждение. Первый callback (get_item) цел — в его запросе названия нет.

Подтверждено на проде на проводе: наш ответ get_item отдаёт "title":"… \"…\" …" (настоящие кавычки, JSON-эскейп), а VK-эхо приходит item_title=…%26quot%3B… (&quot;) — т.е. экранирует именно VK. Корень — сторона VK; у нас — guard от повторения.

Правка

validateProduct (единственный валидатор, на пути CreateProduct/UpdateProduct/SetProductActive из admin-консоли) теперь отклоняет названия с & < > " '. Reject, не transform: оператор перепечатывает чистое название (ёлочки «»), поэтому сохранённое значение одинаково везде — витрина, кошелёк, платёжное окно VK. Ни второй callback, ни шлюз не трогаем; знать точный набор экранируемых VK символов не требуется — запрещаем весь HTML-спецнабор.

Тесты / доки

  • catalog_admin_test.go — кейсы на " & < > ' (ошибка) + ёлочки (ок) + черновик.
  • Локально зелено: payments unit + vet + gofmt + build + integration (catalog_editor_test).
  • Доки: docs/PAYMENTS.md §7, agent field notes, Go Doc на validateProduct.
  • Без wire/schema.
## Что и зачем Продукт с HTML-спецсимволом в названии (`& < > " '`) **молча ломает оплату через VK**. VK HTML-экранирует символ в эхе `item_title` во втором платёжном callback (`order_status_change`), напр. `"` → `&quot;`, но подпись `sig` считает над другой формой → подпись, которую шлюз проверяет по пришедшему телу, не сходится → `vk callback: bad signature` (403) → VK не получает подтверждение. Первый callback (`get_item`) цел — в его запросе названия нет. Подтверждено на проде **на проводе**: наш ответ get_item отдаёт `"title":"… \"…\" …"` (настоящие кавычки, JSON-эскейп), а VK-эхо приходит `item_title=…%26quot%3B…` (`&quot;`) — т.е. экранирует именно VK. Корень — сторона VK; у нас — guard от повторения. ## Правка `validateProduct` (единственный валидатор, на пути `CreateProduct`/`UpdateProduct`/`SetProductActive` из admin-консоли) теперь **отклоняет** названия с `& < > " '`. Reject, не transform: оператор перепечатывает чистое название (ёлочки `«»`), поэтому сохранённое значение одинаково везде — витрина, кошелёк, платёжное окно VK. Ни второй callback, ни шлюз не трогаем; знать точный набор экранируемых VK символов не требуется — запрещаем весь HTML-спецнабор. ## Тесты / доки - `catalog_admin_test.go` — кейсы на `" & < > '` (ошибка) + ёлочки (ок) + черновик. - Локально зелено: payments unit + vet + gofmt + build + integration (`catalog_editor_test`). - Доки: `docs/PAYMENTS.md` §7, agent field notes, Go Doc на `validateProduct`. - Без wire/schema.
developer added 1 commit 2026-07-16 18:57:23 +00:00
fix(payments): reject HTML-special chars in product titles (VK payment guard)
CI / changes (pull_request) Successful in 3s
CI / unit (pull_request) Successful in 12s
CI / integration (pull_request) Successful in 20s
CI / ui (pull_request) Has been skipped
CI / conformance (pull_request) Successful in 11s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m52s
f60327c1ce
A product title containing & < > " ' silently breaks VK purchases: VK
HTML-escapes the character in its order_status_change payment-callback echo
(e.g. " -> &quot;) but signs the notification over a different form, so the
gateway's signature check no longer matches ("vk callback: bad signature")
and the purchase never confirms — while get_item (whose request carries no
title) still passes.

validateProduct now rejects those characters at the admin catalog editor —
the single write path for CreateProduct/UpdateProduct/SetProductActive — so a
title can't reintroduce the break. Reject, not transform: the operator retypes
a clean title (« » guillemets, not straight quotes), so the stored value stays
identical everywhere (storefront, wallet, VK box).

Docs: docs/PAYMENTS.md §7 + agent field notes; Go Doc on validateProduct.
Test: validateProduct HTML-special-char cases. No wire/schema change.
owner approved these changes 2026-07-16 19:15:42 +00:00
developer merged commit 0ba8fb6514 into development 2026-07-16 19:17:45 +00:00
developer deleted branch feature/vk-title-guard 2026-07-16 19:17:46 +00:00
Sign in to join this conversation.
No Reviewers
No Label
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: developer/scrabble-game#279