Технології
Дублікати ключів у JSON в NestJS: чому це небезпечно, що пропускають інші, і як @pas7/nestjs-strict-json це закриває
Більшість Node/Nest стеків мовчки приймають дублікати ключів у JSON (last-one-wins). Це реальна пастка для безпеки й коректності. Тут — модель загроз, конкуренти і чому PAS7 Studio зробили @pas7/nestjs-strict-json.

Що ви отримаєте з цього матеріалу
Це практичний розбір для backend-інженерів: модель загроз, як дублікати ключів поводяться «в дикій природі», що роблять (і не роблять) популярні інструменти, та який підхід ми заклали в @pas7/nestjs-strict-json.
• Чому дублікати ключів взагалі існують, і чому стандарти попереджають про них. [1]
• Чому парсинг “last-one-wins” — це ризик для коректності й безпеки. [2][3]
• Огляд конкурентів: що закривають бібліотеки на кшталт secure-json-parse (і що не закривають). [4]
• Як @pas7/nestjs-strict-json вбудовується в NestJS без перетворення API на науковий проєкт.
• Рекомендована стратегія впровадження: строгий режим без миттєвого ламання продакшн-клієнтів.
Чому дублікати ключів — реальна проблема (а не педантизм)
Імена полів у JSON-об’єкті *мають* бути унікальними, щоб поведінка була передбачуваною. JSON-стандарт прямо попереджає: якщо імена неунікальні, реалізації можуть поводитись непередбачувано, а деякі збережуть останнє значення. Це не теорія — так працюють реальні парсери й реальні API. [1]
Пастка проста: різні шари можуть по-різному інтерпретувати один і той самий payload. Ваш gateway може побачити перше значення, застосунок — останнє, логування — ще інше, а підпис/верифікацію можна обійти, якщо на різних етапах йде різна нормалізація. Цей клас проблем добре описаний у дослідженнях про JSON-інтероперабельність. [3]
Threat model: де дублікати ключів б'ють по вам
Дублікати ключів — класичний трюк «виглядає невинно». Ось типові фейли, які ми бачили у командах:
• Плутанина в авторизації: проксі або middleware перевіряє одне значення, а застосунок використовує інше (role / scope / isAdmin).
• Обхід валідації: схема перевіряє одну репрезентацію, business logic читає іншу.
• Невідповідність аудиту/логів: розбір інциденту ускладнюється, коли логи не збігаються з ефективним payload.
• Різний парсинг WAF / кешу / підпису: інструменти безпеки нормалізують інакше, ніж runtime-парсери (інтероперабельні баги). [3]
Конкуренти і чому вони не закривають це повністю
Є сильні бібліотеки для hardening JSON-парсингу, але багато з них фокусуються на іншій поверхні атаки, ніж дублікати ключів.
secure-json-parse (екосистема Fastify)
Це популярний drop-in парсер, орієнтований на ризики прототипного отруєння (__proto__ та constructor.prototype). Для цієї категорії він дуже корисний, але це не “strict duplicate-keys” за замовчуванням. Це радше *безпека прототипів*, а не *унікальність ключів* як семантична вимога. [4]
Типові NestJS стеки (Express/Fastify за замовчуванням)
Більшість сетапів покладаються на стандартний JSON-парсинг, а потім застосовують валідацію (DTO/class-validator/zod). Але якщо дублікати вже «схлопнуті» під час парсингу, валідатор бачить лише фінальну форму — і трюк з дублями взагалі може бути невидимим.
Кастомні middleware / ручні перевірки
Іноді команди латають це ад-хок middleware. Зазвичай це дає неузгоджену поведінку по роутам, крихкі інтеграції з адаптерами (Express vs Fastify) і провали в тестовому покритті. Ми хотіли чистий, повторно використовуваний, Nest-native підхід.
@pas7/nestjs-strict-json
Наш фокус: виявляти й відхиляти JSON із дублікатами ключів рано і послідовно, з прогнозованою поведінкою по всьому NestJS застосунку. Це про “strict input contracts”: fail fast, fail loudly, і нормальна спостережуваність.
Що реально каже стандарт
RFC 8259 попереджає: імена в об’єктах мають бути унікальними, а якщо ні — поведінка не є інтероперабельною. Тобто “воно ж парситься” — не критерій; критерій — *передбачуваність у всьому стеку інструментів*. [1]
Дослідження з безпеки йдуть далі: різниця в парсингу/нормалізації між компонентами може створювати реальні вразливості (JSON interoperability issues). Дублікати ключів — частий інгредієнт таких невідповідностей. [3]
Як @pas7/nestjs-strict-json допомагає на практиці
Ідея проста: гарантувати, що request JSON — це *однозначна мапа* (без дублікатів ключів) ще до того, як він потрапить у контролери, DTO-валідацію чи business logic.
• Відхиляти дублікати ключів рано (до валідації/логіки).
• Тримати поведінку сталою між середовищами (local/staging/prod).
• Робити фейли явними й дебажними (зрозуміла помилка замість тихого overwrite).
• Nest-friendly інтеграція (підхід, який відчувається як Nest, а не «рандомний скрипт»).
Стратегія впровадження (не зламайте прод випадково)
Якщо у вас вже є клієнти «в полі», строгі перевірки треба розгортати акуратно. Безпечний шлях:
• Почніть з режиму лише звітування (логувати випадки дублікатів) на короткий період.
• Пофіксьте/повідомте найбільш проблемні клієнти: дублікати часто виникають через баги серіалізаторів.
• Поступово вмикайте strict rejection по групах роутів (auth/admin першими).
• Зробіть це платформною політикою: “duplicate keys — невалідний input”. Зафіксуйте це в API контракті.
Про PAS7 Studio (чому ми це open-source'нули)
Ми будуємо performance-first web продукти й backend системи, і постійно стикаємось із тим самим: команди витрачають час на дебаг «неможливих станів», які виникають через неоднозначний input. Strict JSON — маленький запобіжник, який прибирає цілий клас проблем.
Тому ми й відкрили @pas7/nestjs-strict-json: щоб строгість була легкою, послідовною і тестованою в NestJS проєктах.
Джерела та референси
Ключові стандарти та security-референси, використані в матеріалі.
FAQ
JSON-стандарт попереджає, що неунікальні імена ведуть до непередбачуваної/неінтероперабельної поведінки; багато реалізацій приймають це і залишають останнє значення. Саме цей mismatch і робить це ризиком. [1][2]
secure-json-parse передусім про захист від prototype poisoning (__proto__/constructor.prototype). Це важливий шар для цієї категорії, але це не те саме, що вимога унікальності ключів у JSON-об’єктах. [4]
Валідація зазвичай відбувається *після* парсингу, тому часто бачить лише фінальну форму об’єкта після схлопування дублікатів. Strict JSON валідація має зловити неоднозначність раніше.
Почніть із режиму лише звітування для payload’ів з дублікатами, пофіксьте топ-клієнтів, потім поступово вмикайте суворе відхилення по групах роутів. Закріпіть правило як частину API-контракту.
Хочете безпечніші NestJS API? Почніть зі строгих input контрактів
Якщо ваш бекенд “secure by DTO”, strict parsing — це відсутній перший крок: валідуйте вже після того, як payload став однозначним.