Тест на СДВГ изнутри: реверс-инжиниринг раскрыл скрытый трекинг фокуса
Автор блога nullpt.rs рассказывает личную историю. Одной ночью во время разговора с друзьями внимание привлекли звёзды: из-за светового загрязнения их обычно не разглядеть, а тут получилось увидеть их отчётливо. В ту же ночь на Amazon был заказан телескоп, так у автора обычно и появляются новые увлечения, но ни одно из них не задерживалось надолго. После того как один из друзей поделился недавно поставленным диагнозом аутизма, было принято решение пройти обследование на СДВГ.
Психиатр объяснила, что необследованный СДВГ может сопровождаться депрессией и тревожностью, и предупредила, что во время самого онлайн-теста отвечать на вопросы не сможет. Ссылка «Begin Test» пришла на почту.
Тест выглядел как flash-игра начала 2000-х: задача, нажимать пробел, когда на экране появляется карточка с тремя красными сердечками, и ничего не делать в остальных случаях. Ни таймера, ни счёта на экране не было, только мелькающие карточки; постепенно к ним добавлялись другие картинки-отвлекающие факторы, а затем и звуки, плач младенца, полицейская сирена. К концу теста, когда экзамен начал казаться бесконечным, нажатия на пробел стали хаотичными, лишь бы поскорее закончить.
Во время прохождения теста через DevTools браузера были сохранены все скрипты страницы и исходящие запросы. Разбор кода показал: обработчик keyup фиксирует каждое нажатие пробела с точной меткой времени (в массиве Context.spacePressArray.clickTimes), а любую другую клавишу, кроме пробела и Enter, записывает отдельно как «плохое» нажатие (badClickTimes). Отдельные обработчики onBlur/focus отслеживают потерю фокуса окна, например, при переключении на другую вкладку, включают предупреждающий сигнал и суммируют время вне фокуса.
Контент теста также подстраивается под возраст испытуемого: для детей ролик идёт на 15 кадрах в секунду со звуками птиц, боулинга, световых мечей и самолётов, для взрослых, на 24 кадрах в секунду со звуками плача младенца, автомобильной аварии и полицейской сирены. При этом итоговый пакет данных, уходящий на сервер, содержит только тайминги нажатий пробела, тайминги «плохих» нажатий и суммарное время вне фокуса, никакой записи видео или звука. Сам алгоритм, переводящий эти данные в диагностические баллы, в клиентском коде найден не был.
На официальной странице теста нашлось описание методики: рассчитываются стандартизированные Z-показатели по четырём параметрам, внимательность (Attentiveness), своевременность реакции (Timeliness), гиперреактивность (Hyper-Reactivity) и импульсивность (Impulsiveness), нормированные по группе, подобранной по возрасту и полу. На странице подробно расписано, что означает каждый из четырёх параметров.
Первые результаты оказались настолько нетипичными, что психиатр напрямую спросила, не пытались ли обмануть тест, и предложила пересдачу при условии, что обмана не было. На пересдаче основное внимание уделялось тому, чтобы действительно сосредоточиться на задаче, а не спамить пробел. При дальнейшем изучении сохранённого кода обнаружилась функция sendParentReportToClinic, отправляющая на сервер клиники идентификатор теста и e-mail клиники, то есть именно так результаты, судя по всему, передаются от площадки к психиатру.
Название самого теста, его разработчика и клиники в посте не раскрываются. Итоговый диагноз или числовой результат ни по первому прохождению, ни по пересдаче в тексте не приводится, автор рассказывает только о процессе реверс-инжиниринга и не подтверждает, была ли в тесте намеренная ловушка для тех, кто открывает DevTools.
Ключевые факты
- Тест реализован как flash-подобная HTML5-игра: нужно нажимать пробел при появлении карточки с тремя красными сердечками, а посторонние картинки и звуки (плач младенца, сирена) отвлекают от задачи.
- Код теста фиксирует каждое нажатие пробела и каждое «неверное» нажатие (любая другая клавиша, кроме пробела и Enter), а также отслеживает потерю фокуса окна, например, при переключении на другую вкладку, с включением предупреждающего сигнала.
- Контент подстраивается под возраст: у детей ролик идёт на 15 кадрах в секунду со звуками птиц, боулинга, световых мечей и самолётов, у взрослых, на 24 кадрах в секунду со звуками плача младенца, аварии и полицейской сирены.
- Итоговый пакет данных, уходящий на сервер, содержит только тайминги нажатий пробела, тайминги «плохих» нажатий и суммарное время вне фокуса; сам алгоритм подсчёта четырёх диагностических Z-показателей (внимательность, своевременность, гиперреактивность, импульсивность) в клиентском коде не найден.
- Первые результаты оказались настолько нетипичными, что психиатр заподозрила попытку обмана и предложила пересдачу; при пересдаче внимание сознательно удерживалось на задаче, а не спамился пробел.
Почему это важно
История показывает разрыв между тем, что психиатрический тест демонстрирует пациенту, и тем, что происходит «под капотом»: клиентский код фиксирует не только целевой сигнал, нажатия пробела по сигналу, но и побочные метрики: потерю фокуса окна, «плохие» нажатия, реакцию на посторонние отвлекающие звуки и картинки, о которых пациента прямо не предупреждают. При этом даже медицинский диагностический инструмент можно разобрать обычными браузерными DevTools, ничего не взламывая.
Кому это важно
Тем, кто проходит подобные цифровые психиатрические или когнитивные тесты и хочет понимать, что именно измеряется и передаётся дальше. Разработчикам систем онлайн-тестирования и диагностики, как пример того, что вся логика на стороне клиента открыта для разбора любым пользователем с DevTools. Специалистам по приватности медицинских веб-приложений, которых интересует скрытая телеметрия, сбор данных, явно не упомянутых в описании теста.
Как это применить
Сама история, не инструкция, но демонстрирует рабочий приём: сохранить исходный код страницы и исходящие запросы через DevTools ещё во время работы приложения, а затем разобрать логику по event-обработчикам, различиям между возрастными группами и составу итогового пакета данных. Тем, кто разрабатывает подобные тесты, стоит учитывать: любая клиентская логика может быть точно так же прочитана пользователем, поэтому чувствительные механизмы, детекцию обмана, веса шкал, держать на клиенте рискованно.
Можно ли доверять
Это личный пост в блоге nullpt.rs, без подтверждения со стороны производителя теста или клиники, их названия в тексте не раскрываются. Технические детали подкреплены прямыми выдержками кода и дословной цитатой с официальной страницы теста про Z-показатели, что делает техническую часть проверяемой. При этом итоговые баллы или диагноз ни по одному из двух прохождений в источнике не приводятся, поэтому это стоит читать как задокументированный личный случай, а не как независимо подтверждённый разбор.
Риски и подводные камни
Поскольку алгоритм подсчёта Z-показателей в клиентском коде не найден, непонятно, как именно потеря фокуса или «плохие» нажатия конвертируются в диагностические баллы, это снижает интерпретируемость результата для самого пациента. Скрытая фиксация потери фокуса и посторонних нажатий не была явно раскрыта до начала теста. А вопрос психиатра о попытке обмана показывает: аномальные паттерны в данных, вызванные банальной усталостью от неограниченного по времени задания, рискуют быть приняты за жульничество.
«Стандартизированные Z-показатели рассчитываются по четырём параметрам внимания: внимательность, своевременность реакции, гиперреактивность и импульсивность. Показатели нормируются по группе, подобранной по возрасту и полу.»
— официальная страница теста