Кратко

  • Сайт, загружавшийcdn.polyfill.io, не просто опирался на открытый проект — он позволял удалённому сервису выбрать JavaScript и вернуть его для выполнения в браузерном контексте сайта. Предметом доверия были домен, оператор, маршрутизация и путь ответа, а не только исходный код, который можно изучить в другом месте. [15][16][17]
  • Контроль над доменом Polyfill.io и связанным присутствием проекта изменился в феврале 2024 года. Fastly, Cloudflare и участники проекта FormatJS тогда выпустили свои материалы, показав, что переоценка на стороне использующих сайтов была возможна до того, как в июне публично сообщили о вредоносной доставке. Сам по себе переход не следует описывать как доказательство вредоносных намерений. [2][3][4]
  • Sansec 25 июня сообщил, что сервис избирательно возвращал изменённый JavaScript и перенаправлял подходящих посетителей. Cloudflare сказал, что индикаторы Page Shield включают совпадения уже с 8 июня, а Akamai описал серверную выборку с последующими проверками на стороне клиента. Эти наблюдения устанавливают кампанию по перенаправлению, а не любое действие, которое удалённо поставляемый JavaScript теоретически мог бы выполнить. [1][5][9]
  • Оценка Sansec в более чем 100 000 сайтов относилась к сайтам, встраивающим или использующим сервис. Cloudflare приводил оценку использования, близкую к четырём процентам сайтов. Ни та, ни другая цифра не является проверенным числом сайтов, которые отдавали вредоносную ветку, перенаправляли посетителей или понесли убытки. [1][5]
  • Автоматическая перезапись Cloudflare и блокировка домена у Namecheap ограничили путь доставки. Они не удалили устаревшие ссылки в коде использующих сайтов, не установили, что именно получил каждый более ранний посетитель, и не завершили расследование каждого владельца сайта. [5][6][10]
  • Fides, Jellyfish и Wordfence иллюстрируют три разные задачи с доказательствами: определить, была ли доступна условная ветка; проследить транзитивного вендора; проверить удаление; и не считать ссылку на конечную точку доказательством эксплуатации. [11][12][13][14][22]
  • Ответственность здесь — не юридический вывод и не утверждение равной вины. Она означает, что каждая сторона должна отвечать за контроль, который реально могла осуществлять. Владельцы сайтов сохраняли контроль над необходимостью, инвентаризацией, выбором провайдера, самохостингом, мониторингом владельца, наблюдением на стороне браузера, расследованием, исправлением и коммуникацией.

Тег script передавал полномочия, а не только удобство

Ключевое техническое решение выглядело обычным. Сайт размещал на странице элементscriptи указывал наcdn.polyfill.io. Когда посетитель открывал страницу, браузер запрашивал JavaScript у удалённого сервиса. Сервис мог изучить характеристики запроса и вернуть полифиллы, подходящие браузеру, чтобы старые браузеры могли использовать веб-функции, которые они не реализуют изначально.

Такая схема решала практическую задачу совместимости. Вместо того чтобы отдавать все функции совместимости каждому посетителю, сайт мог попросить специализированный сервис вернуть то, что нужно конкретному браузеру. Результат мог быть меньше и проще в сопровождении, чем универсальный локальный комплект. Но эффективность достигалась за счёт динамического ответа. Сайт не просто скачивал фиксированный пакет при разработке и не разворачивал проверенные байты из собственной инфраструктуры. Он приглашал другого оператора в момент загрузки страницы решать, какие байты исполнит посетитель.

Это различие определяет рамку ответственности. Репозиторий с открытым кодом — это код и история, которые можно проверить. Хостинг — это операционные отношения. Живой сервис зависит от домена, DNS, маршрутизации, хостинга, сертификатов, доступа к развёртыванию и людей или организаций, способных изменить ответ. Сайт может доверять публичному коду и при этом не проверять, остаётся ли конечная точка, обслуживающая его посетителей, под тем же контролем, следует ли она тому же процессу и возвращает ли тот же класс результатов.

HTTPS не снимает эти вопросы. Он помогает браузеру убедиться, что он связался с держателем действительных полномочий для запрошенного домена, и защищает ответ при передаче. Он не обещает, что владелец домена не изменился, что возвращённая программа доброжелательна или что содержание не меняется между запросами. Если контроль над доменом меняется легитимно, HTTPS может продолжать работать ровно так, как задумано, подтверждая при этом новую операционную реальность.

Браузер даёт удалённо загружаемому JavaScript широкое практическое влияние на страницу, которая его включает. Точная область действия зависит от страницы и настроек браузера, но базисная слабость хорошо известна: код третьей стороны выполняется в веб-контексте первой стороны. CWE-830 от MITRE описывает такой класс включения как передачу доверия коду с другого домена, а OWASP рассматривает JavaScript третьих сторон как задачу управления, поскольку он может влиять на данные и поведение страницы. Документация GitHub CodeQL применяет ту же логику к функциональности, загружаемой с недоверенного домена. [15][16][17]

Поэтому инцидент нельзя сводить к фразе «открытый код стал небезопасным». Исходный открытый код, проверенная самохостинговая копия и живой сервис под контролем домена — это разные объекты доверия. Сайт, использующий фиксированную локальную копию, не делегировал выполнение так же, как сайт, запрашивающий меняющийся ответ уcdn.polyfill.io. Альтернативный хост тоже создавал другие операционные отношения, даже если отдавал код, производный от того же проекта.

Поэтому первый вопрос ответственности не в том, должны ли разработчики не доверять каждой внешней библиотеке. Вопрос в том, знал ли сайт, какая сторона могла выбирать исполняемые байты для его посетителей в момент использования. Полезная инвентаризация должна ответить минимум на пять вопросов: какие страницы запрашивали скрипт; была ли вставка прямой или транзитивной; какие пользователи и браузерные пути могли до него добраться; какая бизнес-функция его требовала; и кто сейчас контролирует конечную точку.

Эти вопросы относятся к владельцу сайта, потому что сайт сделал включение действенным. Посетитель не договаривался с Polyfill.io и не выбирал её оператора. Посетитель запрашивал страницу у сайта и обоснованно воспринимал возвращённые скрипты как часть этой страницы. Даже если ссылку вставила тема, плагин, менеджер тегов или вендор, именно организация, стоящая за сайтом, показывала пользователям эту совокупность.

Это не делает владельца сайта автором вредоносного кода и не стирает контроль оператора сервиса. Это означает, что делегированные полномочия не устраняют ответственность первой стороны. Оператор сервиса мог выбирать ответ. Владелец сайта мог решать, остаётся ли этому оператору место на странице. Это разные меры контроля, и инцидент проверил обе.

Февральский переход был событием управления ПО

Публичная хронология даёт необычно важный интервал предупреждения. В феврале 2024 года контроль над доменом Polyfill.io и связанным присутствием на GitHub перешёл к Funnull, как описано в источниках того времени. Источники устанавливают смену контроля и основания доверия. Они сами по себе не устанавливают мотив нового оператора, преступный план, юридическое нарушение или окончательную личность каждого, кто позже влиял на доставку.

Для обычного информационного сайта смена домена может прежде всего изменить право публикации. Для домена, который возвращает исполняемый JavaScript другим сайтам, смена меняет того, кто может влиять на ПО, работающее на этих сайтах. Поэтому информация о владельце становится частью состояния зависимостей. Новый владелец конечной точки операционно сопоставим с новым сопровождающим, уполномоченным подписывающим лицом или новым каналом релизов, даже если репозиторий выглядит знакомым.

Уведомление Fastly от 28 февраля делает это управленческое значение видимым. Компания объявила о заменяющих доменах и дала пользователям варианты, включающие миграцию, самохостинг или удаление сервиса. Это были не просто варианты брендинга. Каждый из них менял того, кто контролировал байты, доставляемые посетителям. Миграция выбирала другие отношения с сервисом. Самохостинг помещал доставку под собственные механизмы развёртывания сайта. Удаление устраняло зависимость совместимости, если она больше не была нужна. [3]

Cloudflare 29 февраля представил альтернативу на cdnjs. В объяснении компания связала переход провайдера с риском цепочки поставок: сайты полагались на другую сторону в поддержке и защите сервиса, который мог выполнять код на их страницах. Альтернатива Cloudflare не сделала внешний хостинг безрисковым, но показала, что инфраструктурные провайдеры восприняли смену владельца как основание для нового решения о доверии. [2]

Вопрос в репозитории FormatJS, открытый 28 февраля, даёт запись проекта того же периода. В нём выражалось беспокойство об отношениях владения и CNAME и содержалась просьба перестать рекомендовать конечную точку. Эта запись важна, потому что показывает сопровождающего, реагирующего на документационную зависимость до публично сообщённой вредоносной кампании. Удаление рекомендации не чинит каждый сайт, следовавший ей ранее, но ограничивает будущее распространение и создаёт прослеживаемое предупреждение. [4]

Вместе эти записи не позволяют слишком удобному сценарию, в котором у владельцев сайтов не было сигнала до 25 июня. Не каждый владелец увидел бы уведомление Fastly, публикацию Cloudflare или вопрос FormatJS. Источники не устанавливают всеобщее извещение, и было бы несправедливо превращать публичную доступность в доказательство того, что каждая организация на самом деле знала. Они устанавливают, что смена владельца была наблюдаема, что альтернативы были доступны и что некоторые ответственные стороны переоценили конечную точку за месяцы до отчёта об инциденте.

Это различие необходимо для ответственности. Обязанность мониторинга не означает всеведение. Она означает создание процесса, способного получать значимые изменения для зависимостей с высокими полномочиями. Сайт может отслеживать уведомления о пакетах, игнорируя владение доменом, DNS или изменения хостинга. Для версионированного пакета важными сигналами могут быть ленты релизов и уязвимостей. Для конечной точки удалённого скрипта в модель мониторинга должны входить регистрация, DNS, оператор и поведение ответа.

Февральское событие также показывает пределы разовой проверки вендора. Команда могла одобрить Polyfill.io годами ранее на основе оператора, инфраструктуры, репутации проекта и тогдашних потребностей браузеров. Если в записи об одобрении была только строкаcdn.polyfill.io, команда могла ошибочно считать зависимость неизменной, пока не изменился URL. В реальности сторона за стабильным именем изменилась.

Ответственное одобрение должно фиксировать основание доверия, а не только адрес. Это основание может включать оператора, назначение сервиса, ожидаемые характеристики ответа, договорные или комьюнити-отношения, доступные данные аудита, запасной план и триггеры пересмотра. Тогда смена владельца должна аннулировать одобрение или хотя бы открыть его заново. Без такой записи организация не может легко объяснить, почему продолжающееся делегирование оставалось оправданным после изменения предпосылки.

Вопрос необходимости тоже должен был быть открыт заново. Полифиллы привязаны к возможностям браузера. Браузерные популяции развиваются, политики поддержки продуктов меняются, и код совместимости, когда-то необходимый, может стать остаточным. Удалённая зависимость с полномочиями уровня страницы не должна сохраняться просто потому, что никто не отвечает за её удаление. Февральские уведомления дали момент, чтобы спросить, действительно ли поддержка старых браузеров всё ещё требует конечной точки и может ли меньший локальный комплект закрыть оставшуюся потребность.

Ничто из этого не доказывает, что каждый сайт, оставивший ссылку, действовал небрежно, и не превращает смену домена в атаку. Устанавливается более узкий пункт: переход изменил материальный программный контроль ещё до того, как был замечен вредоносный вывод. Ответственность сайта начинается с того, была ли эта материальная смена обнаружима и подлежала ли проверке.

Избирательная доставка сделала неформальную проверку ненадёжной

25 июня Sansec сообщил, чтоcdn.polyfill.ioдоставляет изменённый JavaScript через сайты, которые его встраивают. Наблюдавшееся поведение перенаправляло выбранных посетителей через домены, похожие на Google Analytics, на мошеннические или азартные ресурсы. Sansec описал условия, включающие нацеливание на мобильных пользователей, серверные и клиентские проверки, поведение по времени и обход некоторых контекстов администратора или аналитики. [1]

Наблюдаемое действие требует точного названия. Это была кампания по перенаправлению через изменённый JavaScript. Запись не позволяет повышать это наблюдение до кражи учётных данных, кражи данных страницы, компрометации хоста, выполнения кода вне браузера или количественно оценённого финансового ущерба. Удалённо управляемая конечная точка скрипта в принципе может вернуть JavaScript с гораздо более широким набором действий в браузере. CNCF TAG Security, CWE-830 и общая модель выполнения в браузере подтверждают такой вывод о возможностях. Возможность — не доказательство того, что каждое возможное действие произошло. [8][16]

Cloudflare сообщил, что данные Page Shield подтверждают индикаторы и включают совпадения с 8 июня. Это самое раннее совпадение в наборе данных Cloudflare, описанное в источнике. Это не доказательство того, что вся вредоносная активность началась именно в этот день, что та же ветка непрерывно достигала каждого сайта с этого момента или что более ранняя доставка не происходила за пределами видимости Cloudflare. [5]

Akamai отдельно описал двухэтапный паттерн: серверная выборка на основе заголовков запроса могла определять, что отправлять, а затем перед перенаправлением выполнялись клиентские проверки. Эта архитектура объясняет, почему обычная проверка могла пропустить проблему. Разработчик, запрашивающий скрипт с настольного браузера, мог получить ожидаемый полифилл. Мобильный посетитель с другими заголовками, геолокацией, временем или состоянием страницы мог получить или активировать другую ветку. [9]

Избирательная доставка меняет бремя доказывания. Одна чистая загрузка не доказывает историческую безопасность. Сравнение исходного кода из одного браузера в один момент может показать только ответ, выбранный для этого запроса. Поисковый краулер, монитор аптайма или сканер безопасности могут иметь характеристики, которые логика доставки намеренно исключает. Администратор, проверяющий под своей учётной записью, может видеть другое поведение, чем посетитель, пришедший впервые.

Это не означает, что обнаружение было невозможно. Это означает, что мониторинг должен был соответствовать изменчивости зависимости. Полезное наблюдение выбирало бы браузеры, устройства, геолокации и условия запросов; сохраняло тела ответов и хэши с течением времени; обнаруживало новые домены и цепочки перенаправлений; и сравнивало поведение, видимое реальными клиентами, с заявленным назначением сервиса. Мониторинг на стороне клиента играл важную роль, потому что значимая программа собиралась и выполнялась в браузере.

Инцидент также показывает, как оптимизация может стать маскировкой. Динамическое нацеливание на браузер было частью легитимной модели Polyfill.io: сервис выбирал код совместимости по возможностям браузера. Вредоносная ветка могла использовать ожидание, что ответы естественно различаются. Сама изменчивость не была доказательством злоупотребления. Она делала простую модель «известный хэш равен безопасному сервису» сложнее в применении и давала избирательной доставке место спрятаться внутри принятого операционного паттерна.

Поэтому ответственность зависит от определения ожидаемой изменчивости. Сайт должен уметь сформулировать, какие атрибуты запроса провайдер легитимно использует, какие семейства кода могут быть возвращены, с какими адресами скрипт может связываться и какие действия на странице выходят за пределы назначения. Без такого базиса мониторинг может наблюдать изменения, не зная, санкционировано ли изменение.

Серверная выборка также усложняет ретроспективное расследование. Статический репозиторий сайта может содержать только URL скрипта, а не вредоносные байты, полученные посетителем. Байты пришли из другой системы в момент запроса и могут быть недоступны после локализации. Телеметрия браузера, логи CDN, сохранённые ответы, отчёты о политике безопасности контента и записи конечных точек могут быть единственными доказательствами для реконструкции охвата. Если эти записи никогда не собирались или хранились слишком недолго, сайт может оказаться не в состоянии ответить, какие посетители столкнулись с веткой.

Эту неопределённость не следует скрывать широким заявлением, что все были в безопасности или все были скомпрометированы. Ответственное заявление об инциденте может вместо этого определить, что именно было установлено: конечная точка упоминалась; конкретный условный путь был или не был доступен; телеметрия охватывала указанные даты и группы пользователей; наблюдаемые перенаправления совпадали или не совпадали с известными индикаторами; и остаются пробелы для запросов вне сохранённых доказательств.

Избирательная доставка, таким образом, центральна для теста на ответственность. Она объясняет, как вредоносный вывод мог сосуществовать с безвредной проверкой, почему ссылки на конечную точку не являются счётчиком жертв и почему подтверждённое исправление требует большего, чем однократная загрузка страницы после заморозки домена.

Оценки масштаба не были числом жертв

Sansec описал более 100 000 сайтов, встраивающих или использующих сервис. Cloudflare привёл оценки, что Polyfill.io встречается почти на четырёх процентах сайтов. Эти цифры передают потенциальную широту широко используемого сервиса. У них не один и тот же знаменатель, и ни одна не устанавливает полный набор подтверждённых компрометаций. [1][5]

Несколько совокупностей нужно держать отдельно. Первая — сайты, в чьём текущем или историческом коде есть ссылка на конечную точку Polyfill.io. Вторая — те, у которых соответствующий путь включения был доступен в продакшене. Третья — те, что запрашивали вредоносный ответ во время кампании. Четвёртая — те, чьи посетители удовлетворяли серверным и клиентским условиям. Пятая — посетители, которые действительно были перенаправлены. Шестая — любая группа, понёсшая измеримые потери позже.

Доступная публичная запись не даёт проверенных цифр для большинства этих групп. Поэтому было бы неточно называть каждую ссылку жертвой, каждый включающий сайт — скомпрометированным, а каждого посетителя — подвергшимся воздействию. Столь же неточно отмахиваться от ссылок как безвредных только потому, что избирательная доставка не позволила всеобщему наблюдению. Ссылка устанавливает путь доверия. Для установления доступности, доставки и воздействия нужны дополнительные доказательства.

Эта терминология важна для уведомлений на стороне сайтов. «Наш код содержал ссылку» отличается от «наша телеметрия показывает, что скрипт был запрошен». Оба отличаются от «мы наблюдали вредоносную ветку» и от «посетитель сообщил о перенаправлении». Их смешение может вызвать ненужную тревогу или ложное успокоение. Разделение позволяет пользователям понять, что именно известно организации.

Обработка Wordfence затронутых паттернов плагинов WordPress подтверждает эту границу. Каталог выявил использование Polyfill.io, но предупредил, что нельзя предполагать, будто каждый экземпляр плагина доставлял вредоносный контент. Плагины могли внедрить конечную точку на многие сайты, делая инвентаризацию срочной, но наличие кода всё же не доказывало вредоносного выполнения в каждой установке. [14]

Правительственные сообщения повторяли серьёзную озабоченность масштабом, но сосредоточивали операторов на удалении и расследовании. CERT-AGID описал приобретение и доставку, зависящую от заголовков, и сослался на цифру более 100 000. Это независимое предупреждение поддерживает широкое защитное внимание, но не превращает знаменатель в подтверждённых затронутых посетителей. [21]

Поэтому самое сильное заявление о масштабе одновременно и самое ограниченное: конечная точка имела большой след на стороне сайтов, и наблюдаемая избирательная кампания создала риск по всему этому следу. Точное воздействие нужно было устанавливать отдельно для каждого сайта и каждой группы посетителей.

Локализация изменила путь, но не завершила исправление

В ответе участвовали стороны с разными видами контроля. Cloudflare автоматически переписывал ссылки на Polyfill.io на проксируемых страницах клиентов на зеркало, размещённое у Cloudflare. Компания объяснила, что простая блокировка исходного домена могла сломать сайты, всё ещё зависящие от сервиса. Перезапись пыталась сохранить ожидаемую совместимость, убирая немедленную зависимость от изменённой конечной точки. [5]

Это вмешательство иллюстрирует реальный операционный компромисс. Команды безопасности часто предпочитают немедленное удаление подозрительного ресурса. Продуктовые команды знают, что внезапное устранение слоя совместимости может сделать сайт непригодным для некоторых посетителей. Положение Cloudflare в цепочке доставки позволяло заменить источник, не дожидаясь, пока каждый владелец сайта развернёт изменение.

Подстановка была локализацией, а не доказательством полного исправления. Она меняла доверенного оператора и путь ответа для трафика, охваченного механизмом. Она не устанавливала, что замена ведёт себя одинаково для каждого браузера, что охвачены все страницы и пути доставки или что репозитории на стороне сайтов больше не содержат старую ссылку. Она также не отвечала, что посетители получали до перезаписи.

Затем Namecheap заморозил домен Polyfill.io, а правительственные консультации описали конечную точку как приостановленную к 27 июня. Действие на уровне домена убрало немедленный путь сервиса, но могло также сломать сайты, которые всё ещё ожидали ответ. Заморозка была важным рычагом локализации в руках регистратора. Она не очищала шаблоны на стороне сайтов, настройки плагинов, кэшированные страницы, конфигурации менеджеров тегов или продукты вендоров. [6][10]

Разница становится яснее, когда домен недоступен. Сайт может выглядеть защищённым, потому что браузер больше не может получить подозрительный скрипт. Однако устаревшая ссылка остаётся нерешённой зависимостью. Если статус контроля снова изменится, если продолжит существовать альтернативное имя хоста или если внутренняя копия не была проверена, основная проблема управления остаётся. Даже навсегда мёртвая конечная точка может нести издержки производительности, обработки ошибок и совместимости.

CERT-FR и подразделение кибербезопасности Западной Австралии рекомендовали операторам найти и удалить ссылки, перейти на контролируемую альтернативу там, где это нужно, и рассмотреть браузерные средства контроля, такие как целостность субресурсов (SRI) и политика безопасности контента (CSP). Semgrep также сосредоточился на обнаружении по всему репозиторию, а не на том, чтобы считать заморозку домена достаточной. [6][7][20]

Эта последовательность предполагает четыре отдельных утверждения о закрытии. «Локализовано» означает, что известный вредоносный путь доставки прерван. «Удалено» означает, что ссылка на стороне сайта и транзитивные пути вставки исчезли. «Расследовано» означает, что доступные доказательства использованы для оценки исторического охвата и воздействия. «Подтверждено» означает, что тесты и мониторинг показывают: текущий сайт больше не зависит от старого пути, а замена ведёт себя в пределах своего назначения.

Владелец сайта мог полагаться на инфраструктурного провайдера в отношении первого утверждения, сохраняя за собой остальные три. Cloudflare мог переписывать трафик, который он видел. Namecheap мог заморозить домен, который зарегистрировал. Ни один из них не мог знать каждое место, где клиент встроил URL, каждую условную браузерную ветку внутри плагина или каждую группу посетителей, которую сайту нужно было расследовать.

Это разделение также защищает от завышения вмешательства третьих сторон. Заморозка регистратором — не вывод об атрибуции. Автоматическая перезапись не устанавливает, что каждый защищённый клиент обслуживал вредоносную ветку. Совпадение индикатора от вендора обнаружения — не полный форензик-отчёт для каждого сайта. Каждое действие следует описывать по контролю, который оно осуществляло, и доказательствам, которые оно произвело.

Операционно исправление на стороне сайта должно начинаться с полного поиска. Буквальное имя хоста может встречаться в исходных файлах, сгенерированных бандлах, полях системы управления контентом, коде плагинов, менеджерах тегов, шаблонах, архивных конфигурациях или ответах вендоров. Инструменты поиска находят известные строки, но инвентаризация зависимостей должна также объяснять, кто внёс ссылку и какой путь сборки или выполнения сделал её активной.

Затем удалению нужно функциональное решение. Если полифилл больше не нужен, его устранение — самое чистое сокращение полномочий. Если поддержка старых браузеров по-прежнему требуется, уместны проверенный локальный комплект или явно одобренный провайдер. Замена не должна выбираться только потому, что её URL удобен. Её оператор, процесс обновления, изменчивость ответа и модель мониторинга становятся частью нового основания доверия.

Наконец, историческая оценка требует доказательств, соразмерных риску сайта. Наблюдения на стороне браузера, сетевые логи, отчёты безопасности, жалобы клиентов и сохранённые ответы скриптов могут помочь определить, появлялись ли известные индикаторы перенаправления. Отсутствие доказательств следует связывать с охватом. Сайт без сохранённой клиентской телеметрии может сказать, что не нашёл сообщений или индикаторов в доступных записях; он не может превратить отсутствующие записи в доказательство того, что ни один посетитель не получил ветку.

Fides показал, почему условная ветка всё равно важна

CVE-2024-38537 фиксирует проблему на стороне Fides. Соответствующий путьfides.jsмог загружать Polyfill.io для старых браузеров. Запись определяет затронутые версии и говорит, что версия 2.39.1 устранила воздействие. Она также сохраняет важную границу: эксплуатации через Fides не выявлено. [11][12]

Этот случай полезен, потому что сопротивляется двум противоположным ошибкам. Первая отмахнулась бы от проблемы на том основании, что конечную точку загружал только путь для старых браузеров. Условная доступность — это всё равно доступность. Если продакшн-страница могла запросить удалённый JavaScript для поддерживаемой группы посетителей, зависимость принадлежала инвентаризации безопасности продукта, даже если большинство разработчиков её никогда не запускали.

Вторая ошибка — трактовать CVE как доказательство эксплуатации пользователей Fides. Запись об уязвимости может установить небезопасный путь включения и затронутые версии без установления того, что вредоносная ветка достигла конкретного развёртывания. «Мог загружать» и «было замечено в эксплуатации» отвечают на разные вопросы. Запись Fides явно сохраняла это различие.

Исправление также демонстрирует, почему версионированный ремонт важен. Удаление удалённой зависимости в именованном релизе даёт операторам на стороне сайтов конкретное действие и прослеживаемую границу. Они могут определить развёрнутые версии, обновиться, просканировать остаточные ссылки и протестировать путь для старых браузеров. Общее предупреждение «будьте осторожны с Polyfill.io» не дало бы такого же доказательства закрытия.

Условие для старых браузеров должно формировать проверку. Тестирование только современного настольного браузера может никогда не выполнить затронутую ветку. Проверка должна воспроизвести или изучить условие, которое её выбирало. Это может потребовать изучения собранного кода, имитации старого user agent, проверки сетевых запросов и подтверждения, что исправленная версия больше не конструирует и не запрашивает конечную точку.

Бюллетень SingCERT также обсуждал случай Fides на стороне сайта и сохранил границу «эксплуатация не наблюдалась». Повторение национальным CERT повышает видимость проблемы; оно не превращает возможность в наблюдаемую эксплуатацию. [22]

Поэтому урок Fides не в том, что каждый условный запрос к третьей стороне заслуживает одинаковой серьёзности. Он в том, что сопровождающий должен знать условие, затронутые версии, достижимую группу, версию исправления и границу доказательств. Ответственность сильнее всего, когда формальная запись об уязвимости говорит и о том, что могло произойти, и о том, что не наблюдалось.

Jellyfish показал, как проследить транзитивную зависимость

Консультация Jellyfish задокументировала другой путь. Её сервис зависел от вендора, который мог загружать Polyfill.io при особых условиях. Jellyfish выявила транзитивную связь, связалась с вендором, проверила удаление и ограничила группу браузеров, которая могла достичь пути. [13]

Эта последовательность — практическая модель, потому что начинается с архитектуры, а не с обвинения. Организация, работающая с клиентами, могла не размещать тег script непосредственно в собственном репозитории. Ссылка может идти от аналитического компонента, инструмента согласия, плагина, виджета поддержки или кода другого вендора. Прямое владение строкой — не то же самое, что контроль над пользовательским опытом.

Транзитивные зависимости создают проблему доказательств. Состав ПО, ориентированный на пакеты, устанавливаемые при сборке, может не включать домен, который вендор динамически запрашивает в браузере. Договорные инвентаризации могут называть вендора, но не поставщиков скриптов самого вендора. Сетевой мониторинг может видеть имя хоста, не идентифицируя бизнес-владельца, который его внёс. Все три взгляда нужны, чтобы связать запрос с ответственным отношением.

Последовательность действий Jellyfish закрывает эти пробелы. Сначала установить, что зависимость существует и при каких условиях может быть вызвана. Затем сопоставить её с отношениями с вендором. Потом попросить сторону, контролирующую код, удалить её. Затем проверить изменение, а не считать заверением вендора конец дела. Наконец, ограничить группу лучшими доступными данными о браузерах и продукте.

Проверка особенно важна, когда условие необычно. Вендор может удалить видимую ссылку, пока запасной вариант, старый бандл или кэшированный ресурс всё ещё содержат её. Клиент должен тестировать и снаружи, а не только принимать внутреннее подтверждение. Сетевой захват на релевантных браузерах, сканирование репозитория или бандлов и мониторинг на стороне клиента могут показать, действительно ли запрос исчез.

Ограниченная группа должна сохранять знаменатель. Если только некоторые версии браузеров или страничные сценарии могли запустить путь вендора, расследование может сузить потенциальный охват. Это не означает, что каждый участник этой браузерной группы получил вредоносный контент. И наоборот, редкость пути не оправдывает его неудаление. Редкие пути получают меньше рутинного тестирования, что может делать их удобным местом для незаметного сохранения зависимостей.

Jellyfish также демонстрирует разделённую, но не взаимозаменяемую ответственность. Вендор контролировал свой код и мог удалить включение. Jellyfish контролировала эскалацию к вендору, расследование для клиентов и приёмку исправления. Инфраструктурные провайдеры и службы безопасности могли давать телеметрию. Ни одна из сторон не могла полностью заменить другую.

Эта модель масштабируется за пределы инцидента. Организации на стороне сайтов нужен путь эскалации для любого вендора, способного внедрить исполняемый код. Договор или технический онбординг должны определять, кто может срочно отвечать на вопросы о зависимостях, как быстро можно отключить сторонний скрипт, какие логи доступны и как клиент может проверить изменение.

Плагины WordPress показали, почему ссылки и эксплуатация должны оставаться раздельными

Wordfence каталогизировал использование Polyfill.io в разных паттернах плагинов WordPress. Такая инвентаризация ценна, потому что плагины могут распространять одну внешнюю зависимость на множество независимо управляемых сайтов. Небольшое решение сопровождающего может стать широким отношением доверия на стороне сайтов без сознательного добавления конечной точки каждым владельцем. [14]

Каталог также содержал важное предупреждение: использование конечной точки не доказывало, что каждый плагин или сайт доставлял вредоносный контент. Ссылка указывала на потенциальный путь выполнения. Активен ли путь, зависело от версии плагина, конфигурации, рендеринга страницы, кэширования, браузерных условий и удалённого ответа в тот момент.

Для владельца сайта на WordPress правильный ответ — не спор о том, является ли автор плагина или оператор сервиса «настоящей» ответственной стороной. Ближайшие задачи локальны: определить установленные и активные версии; выяснить, какие страницы выводят ссылку; обновить или удалить затронутые компоненты; очистить сгенерированные ресурсы, где нужно; и проверить сетевое поведение публичного сайта.

У сопровождающего плагина другой набор задач. Он может удалить зависимость, выпустить исправленную версию, объяснить затронутые условия, обновить документацию и уведомить пользователей. Репозиторий плагинов или служба безопасности может распространять предупреждения. Владелец сайта всё равно должен развернуть изменение. Исправленный релиз, оставшийся неустановленным, не меняет путь в браузере.

Это ещё одна причина, по которой цифры масштаба не следует читать как число пострадавших организаций. Один плагин может создать тысячи ссылок; один сайт может содержать несколько плагинов с одним именем хоста; неактивный или отключённый плагин может оставаться на диске без вывода скрипта; а кэшированная публичная страница может продолжать отдавать старую ссылку после изменения исходного кода. Подсчёт строк, установок, активных запросов и вредоносных доставок даёт разные числа.

Ответственная экосистема сохраняет эти измерения подписанными. Службы безопасности могут публиковать широкий список подверженности, чтобы ускорить действия. Сопровождающие могут указывать затронутые версии. Владельцы сайтов могут сообщать о развёрнутой достижимости. Следователи по инцидентам могут сообщать о наблюдаемых индикаторах. Никто не должен заимствовать уверенность у других.

SRI и CSP были средствами контроля, а не магическим решением

Целостность субресурсов (SRI) позволяет автору страницы задать криптографический дайджест для внешнего ресурса. Поддерживающий браузер может загрузить ресурс и отказаться выполнять его, если возвращённые байты не совпадают с ожидаемым дайджестом. Спецификация W3C и руководство MDN представляют SRI как способ предотвратить тихое изменение ресурса скомпрометированным сторонним хостом, тогда как включающий сайт ожидает, что ресурс остаётся фиксированным. [18][19]

Это сильный контроль для стабильного скрипта. Он превращает открытое делегирование в одобрение конкретных байтов. Если хост возвращает что-то другое, браузер блокирует выполнение. Сайт может затем обновить дайджест через собственный процесс развёртывания после проверки новой версии.

Легитимный дизайн Polyfill.io усложняет эту модель, потому что сервис намеренно генерировал разные комплекты в зависимости от возможностей браузера и параметров запроса. Один стабильный дайджест не может одобрить множество допустимых последовательностей байтов, если сайт не изменит способ потребления сервиса. В некоторых архитектурах команда могла заранее вычислить и одобрить ограниченный набор фиксированных ресурсов, но прикрепление одного хэша к конечной точке, назначение которой — динамический выбор ответа, скорее всего сломало бы ожидаемое поведение или оставило бы важные вариации несвязанными.

Правильный вывод не в том, что SRI бесполезен. Он в том, что выбор средства должен соответствовать модели ресурса. Если сайт хочет жёсткую привязку целостности, ему, возможно, придётся перестать просить удалённый сервис генерировать произвольные байты под запрос. Самохостинг проверенного комплекта, обслуживание фиксированных версионированных вариантов или сужение поддерживаемых браузеров могут сделать одобрение на уровне байтов практичным.

Политика безопасности контента (CSP) работает на другом уровне. Политика может ограничить, какие источники могут предоставлять скрипты, и может использовать nonce, хэши или связанные директивы для ограничения выполнения. Она может блокировать неожиданные домены и снижать свободу внедрённой разметки загружать новые ресурсы. Но еслиcdn.polyfill.ioявно разрешён как доверенный источник скриптов, вредоносный ответ с одобренного источника не становится заслуживающим доверия от того, что он есть в allowlist.

CSP всё же может помочь сдержать вторичное поведение. Тщательно составленная политика может ограничить соединения, фреймы или навигации, участвующие в цепочке атаки, а отчёты о нарушениях могут добавить доказательства обнаружения. Точный эффект зависит от политики и поведения браузера. Ключевое ограничение остаётся: одобрение источника отвечает на вопрос, откуда может прийти код, а не на то, будет ли одобренный оператор всегда возвращать приемлемый код.

Зеркалирование снова сдвигает границу доверия. Сайт или инфраструктурный провайдер загружает или поддерживает копию и обслуживает её из контролируемого места. Это может помешать исходному домену менять байты в момент запроса. Это также создаёт обязательства по тому, как зеркало создаётся, проверяется, обновляется и защищается. Автоматическая перезапись на зеркало Cloudflare была полезной локализацией, но она выбрала Cloudflare новой операционной властью; она не устранила понятие доверия.

Самохостинг даёт владельцу сайта более прямой контроль над доставкой. Можно проверить версию, развернуть её вместе с приложением и отслеживать изменения через обычный процесс релизов. Самохостинг не гарантирует безопасность кода. Он сужает круг тех, кто может изменить продакшн-ответ, и упрощает привязку развёрнутых байтов к релизу.

Удаление сильнее, когда функция не нужна. Если текущая поддержка браузеров больше не требует сервиса полифиллов, скрипт с наименьшим риском — тот, который страница не запрашивает. Поэтому пересмотр жизненного цикла стоит рядом со средствами безопасности. Решения о совместимости, принятые годы назад, не должны становиться постоянными пожалованиями полномочий.

Песочницы могут снизить часть влияния третьей стороны, когда функциональность может работать в ограниченном фрейме или изолированном контексте. Не каждый скрипт можно переместить туда без изменения продукта. Полифилл, предназначенный для изменения JavaScript-окружения страницы, особенно привязан к основному контексту выполнения, что ограничивает полезность изоляции. Это ограничение должно влиять на то, остаётся ли удобство оправданием полномочий.

Инструменты сканирования кода помогают находить известные ссылки. Руководство CodeQL, посвящённое полифиллам, подчёркивает проверку владельца, анализ логов, самохостинг и ограничения средств целостности для динамического контента. Semgrep предложил поиск по репозиторию и правила для выявления использования Polyfill.io после инцидента. [15][20]

Одного статического сканирования недостаточно, потому что инъекция в рантайме может исходить из систем контента, менеджеров тегов или вендоров. Одного наблюдения в рантайме недостаточно, потому что редкие условия могут не встретиться в выборке. Зрелый стек контроля сочетает сканирование исходников и бандлов, инвентаризацию сторонних скриптов, мониторинг DNS и владельца, телеметрию браузера, ревью изменений и механизм аварийного отключения.

Стек должен также определять поведение при сбое. Если полифилл не загружается, теряет ли страница незначительное улучшение, становится непригодной или блокирует критическую транзакцию? Команды, понимающие последствия сбоя, могут быстро удалить или заблокировать подозрительный ресурс, не импровизируя во время инцидента. Если непрерывность зависит от ресурса, проверенный локальный запасной вариант безопаснее, чем обнаруживать зависимость в момент, когда регистратор замораживает домен.

Поэтому средства контроля — не меню, из которого можно выбрать один модный акроним. Это последовательность решений: убрать ненужные полномочия; сделать необходимый код по возможности фиксированным; ограничить, откуда он может приходить; наблюдать, что он делает; сохранять доказательства; и поддерживать проверенный путь отключения или замены.

Ответственность должна следовать за контролем каждой стороны

В инциденте участвовали оператор сервиса, владельцы сайтов, инфраструктурные провайдеры, регистратор, исследователи безопасности, сопровождающие плагинов и продуктов, а также вендоры, чей код вносил конечную точку. Их обязанности пересекались, но не были взаимозаменяемы.

Оператор, контролировавший хостируемый сервис Polyfill.io, обладал самым прямым контролем над ответом этого сервиса. Это отличается от сопровождения исходного открытого кода. Ответственность на этом уровне касается хранения домена и пути развёртывания, контроля изменений, целостности ответа, видимости доставки и точной коммуникации об эксплуатации. Доступную запись не следует растягивать в вывод о каждом отдельном лице, корпоративных отношениях или юридической обязанности.

Fastly и Cloudflare обладали инфраструктурными возможностями и возможностями подстановки. Их февральские уведомления могли предупреждать и предлагать альтернативы. Более поздняя позиция Cloudflare позволяла автоматическую перезапись и клиентскую телеметрию для охваченного трафика. Эти средства были значимыми, но не давали ни одной из компаний полного знания об исходниках, конфигурации или воздействии на посетителей каждого сайта. [2][3][5]

Namecheap обладал рычагом локализации на уровне регистратора. Заморозка домена прервала резолвинг или использование конечной точки. Это действие снизило немедленную экспозицию, но могло сломать зависимые сайты. Контроль регистратора мог остановить путь; он не мог пропатчить приложения или установить историческую доставку для каждого сайта. [10]

Исследователи безопасности и правительственные структуры обладали возможностями обнаружения, анализа и предупреждения. Sansec опубликовал индикаторы и наблюдаемое поведение. Akamai и Cloudflare добавили перспективы телеметрии. CERT-FR, Западная Австралия, CERT-AGID и SingCERT перевели инцидент в руководства для операторов. Эти стороны могли повысить видимость и рекомендовать средства; они не могли развернуть исправления на каждом сайте. [1][5][6][7][9][21][22]

Сопровождающие плагинов, библиотек и вендоров контролировали код, который мог вносить зависимость транзитивно. К их ответственным действиям относились выявление затронутых версий и условий, удаление конечной точки, выпуск исправления, коммуникация масштаба и сохранение различия между потенциальной экспозицией и наблюдаемой эксплуатацией. Записи Fides и плагинов WordPress показывают, почему важны версии и доказательства достижимости. [11][12][14]

Владельцы сайтов контролировали финальное решение о включении, даже когда для его исполнения требовалось изменение кода вендором или сопровождающим. Они могли определять поддерживаемые браузеры, одобрять поставщиков сторонних скриптов, вести инвентаризации, контролировать владельца, блокировать или переписывать ресурсы, самостоятельно размещать проверенный код, сохранять браузерные доказательства, расследовать жалобы и общаться с посетителями.

Это не означает равной вины. Небольшой оператор сайта может иметь гораздо меньше видимости и экспертизы, чем глобальная инфраструктурная компания. Вендор может быть единственной стороной, способной изменить встроенный запасной вариант. Регистратор может быть единственной стороной, способной быстро заморозить домен. Ответственность следует за практическим контролем и доступными для его осуществления доказательствами, а не за предположением, что у всех участников одинаковые возможности.

Полезную карту обязанностей можно организовать вокруг шести вопросов.

Первый: кто мог предотвратить ненужную экспозицию? Владельцы сайтов и продуктов могли пересмотреть поддержку браузеров и удалить зависимость. Сопровождающие могли перестать рекомендовать или встраивать её. Провайдеры могли предложить более безопасные пути миграции.

Второй: кто мог обнаружить изменение доверия? Мониторы доменов и инфраструктуры могли наблюдать изменения владельца, DNS и маршрутизации. Сопровождающие проектов могли отслеживать контроль учётных записей и документацию. Владельцы сайтов могли подписаться на релевантные уведомления и пересматривать зависимости с высокими полномочиями при смене оператора.

Третий: кто мог наблюдать вредоносную доставку? Оператор сервиса и инфраструктурные провайдеры могли видеть серверные ответы. Владельцы сайтов и клиентские службы безопасности могли видеть поведение браузера. Исследователи могли сравнивать выборки в разных условиях. Ни один взгляд не обязательно покрывал всю кампанию.

Четвёртый: кто мог локализовать путь? Оператор мог остановить доставку, регистратор — заморозить домен, инфраструктурные провайдеры — переписать или заблокировать трафик, сопровождающие — выпустить исправления, а владельцы сайтов — отключить или удалить ссылки.

Пятый: кто мог расследовать воздействие? Каждый владелец сайта владел собственной архитектурой страниц, записями посетителей, жалобами и историей развёртываний. Вендоры обладали информацией о транзитивных условиях. Инфраструктурные провайдеры обладали выбранной телеметрией трафика и ответов. Расследование требовало сотрудничества без притворства, что набор данных одной стороны представляет всех посетителей.

Шестой: кто мог проверить исправление и сообщить о нём? Сопровождающие могли привязать исправления к версиям. Вендоры могли показать удаление. Владельцы сайтов могли проверить публичный путь и указать, что покрывают их доказательства. Правительственные и отраслевые структуры могли обновлять руководства. Проверка должна была оставаться в пределах видимости стороны.

Эта карта делает ответственность проверяемой. Вместо вопроса только о том, кто вызвал инцидент, она спрашивает, какая сторона могла ответить на каждый вопрос профилактики, обнаружения, локализации, расследования и исправления. Она также вскрывает пробелы контроля. Если никто не контролировал владельца домена для скрипта с полномочиями уровня страницы, пробел существовал до появления вредоносной ветки.

Что сайт на стороне должен уметь доказать

Убедительный ответ сайта можно выразить как цепочку доказательств, а не общее заверение.

Цепочка начинается с инвентаризации. Организация должна выявить каждую прямую и транзитивную ссылку на Polyfill.io, компонент или вендора, который её внёс, страницы, которые её выводили, и браузерные условия, делавшие её достижимой. Результаты поиска должны быть связаны с развёрнутым поведением, а не оставаться списком совпавших файлов.

Далее — необходимость. Владелец должен задокументировать, остаётся ли функция совместимости необходимой для браузеров, которые он намеренно поддерживает. Если нет, предпочтительно удаление. Если требуется, организация должна объяснить, почему выбранная замена или самохостинговая версия соразмерна потребности.

Третий шаг — переоценка доверия. Запись должна показывать, когда организация узнала о смене владельца или июньском инциденте, кто принимал решение продолжать, блокировать, заменять или удалять сервис и какие доказательства его поддержали. Февральский пересмотр и июньское аварийное реагирование — разные события, их не следует сливать.

Четвёртый шаг — исторический охват. Организация должна указать, какие даты, группы посетителей и источники телеметрии она изучила. Следует разделять ссылки на конечную точку, запросы, известные совпадения индикаторов, перенаправления и сообщённый вред. Если логи отсутствуют, пробел должен оставаться явным.

Пятый шаг — исправление. Владелец должен привязать изменение к релизу, конфигурации или подтверждению вендора. Нужно учесть сгенерированные ресурсы, кэши, плагины, менеджеры тегов и условные ветки. Простое наблюдение, что замороженный домен больше не отвечает, — не доказательство удаления.

Шестой шаг — проверка. Тесты должны охватывать релевантные браузерные условия и подтверждать, что публичная страница не делает запросов к старой конечной точке. Мониторинг должен искать повторное появление, неожиданные источники скриптов и поведение перенаправления. Если исправление поставил вендор, клиент должен проверить внешний результат.

Седьмой шаг — коммуникация. Уведомление должно использовать устойчивые определения и избегать превращения использования в статус жертвы. Оно должно объяснять, какая зависимость существовала, была ли она достижима, какие доказательства вредоносной доставки найдены или не найдены, что изменилось и какие неопределённости остаются. Пользователям нужны практические факты, а не широкое заявление, что вопрос «решён».

Наконец, владелец должен обновить свои механизмы жизненного цикла. Удалённые скрипты с высокими полномочиями требуют назначенных владельцев, дат пересмотра, записей об основании доверия, мониторинга домена и оператора, аварийных путей отключения и хранения полезных браузерных доказательств. Иначе тот же управленческий сбой может повториться под другим именем хоста.

Эти доказательства не требуют раскрытия чувствительных защитных деталей. Они требуют достаточной конкретности, чтобы ответ можно было проверить или опровергнуть. Посетитель, клиент или рецензент должен уметь отличить «мы удалили строку» от «мы нашли каждый активный путь» и «мы не видели эксплуатации» от «наши доказательства исключают её для охваченной группы».

Смена домена может быть программным изменением

Polyfill.io заставил обратить внимание на простой принцип: когда домен возвращает исполняемый код, владение доменом — часть состояния безопасности ПО. URL может оставаться стабильным, пока меняется фактический поставщик. Репозиторий может оставаться публичным, пока хостируемый ответ переходит под другой контроль. HTTPS может оставаться действительным, пока основания доверия, оправдывавшие включение, больше не существуют.

Февральские уведомления показали, что это изменение было видимо и требовало действий. Июньские отчёты показали, почему оно имело значение. Избирательное перенаправление использовало модель, в которой разные посетители легитимно могли получать разный код, что делало неформальную проверку слабой гарантией. Позднейшие перезапись и заморозка домена ограничили путь, но только инвентаризация, удаление, расследование и проверка на стороне каждого сайта могли закрыть его часть проблемы.

Инцидент не даёт оснований называть более 100 000 сайтов подтверждёнными жертвами. Он не доказывает, что каждая ссылка обслуживала вредоносный контент, что каждый посетитель был подвергнут воздействию или что каждый продукт на стороне сайтов был эксплуатирован. Он также не даёт оснований описывать исходный открытый код как универсально вредоносный или считать самохостинговую копию идентичной скомпрометированным хостинг-отношениям.

Событие также не поддерживает юридический вердикт или полную историю атрибуции из доступной записи. Ответственность здесь уже и более операционна. Это обязанность объяснить, почему были делегированы исполнительные полномочия, как было обнаружено изменение контроля, какие доказательства установили охват, какое действие снизило экспозицию и как исправление было проверено.

Оператор сервиса, инфраструктурные компании, регистратор, сопровождающие, вендоры и владельцы сайтов — каждый держал часть этого ответа. Ответственность была разделена, потому что система разделена, но она не была взаимозаменяемой. Регистратор мог заморозить домен и оставить после себя устаревший код. Вендор мог удалить ссылку и не иметь телеметрии посетителей клиента. Сайт мог расследовать своих пользователей и всё равно зависеть от верхней стороны в изменении встроенного компонента.

Для владельцев сайтов устойчивый стандарт прямой: знать каждую внешнюю сторону, которая может выбирать код для ваших посетителей; контролировать факты, делавшие эту сторону заслуживающей доверия; убирать полномочия, которые больше не служат необходимой функции; и сохранять достаточно доказательств, чтобы отличать экспозицию, доставку и вред.

Тег script может быть одной строкой HTML, но он создаёт операционные отношения. Когда владелец этой строки меняется, меняются и программные отношения. Ответственность сайта начинается с признания этого изменения до того, как его придётся раскрыть посетителю.

Источники

  1. https://sansec.io/research/polyfill-supply-chain-attack
  2. https://blog.cloudflare.com/polyfill-io-now-available-on-cdnjs-reduce-your-supply-chain-risk/
  3. https://community.fastly.com/t/new-options-for-polyfill-io-users/2540
  4. https://github.com/formatjs/formatjs/issues/4363
  5. https://blog.cloudflare.com/automatically-replacing-polyfill-io-links-with-cloudflares-mirror-for-a-safer-internet/
  6. https://cert.ssi.gouv.fr/actualite/CERTFR-2024-ACT-030/
  7. https://soc.cyber.wa.gov.au/advisories/20240626004-JavaScript-Polyfill-Supply-Chain-Attack/
  8. https://tag-security.cncf.io/community/catalog/compromises/2024/polyfill/
  9. https://www.akamai.com/blog/security/polyfill-supply-chain-attack-what-to-know
  10. https://socket.dev/blog/namecheap-takes-down-polyfill-io-service-following-supply-chain-attack
  11. https://www.cve.org/CVERecord?id=CVE-2024-38537
  12. https://nvd.nist.gov/vuln/detail/cve-2024-38537
  13. https://jellyfish.co/library/jellyfish-security-advisory-june-27-2024/
  14. https://www.wordfence.com/threat-intel/vulnerabilities/detail/various-plugins-various-version-use-of-polyfillio
  15. https://codeql.github.com/codeql-query-help/javascript/js-functionality-from-untrusted-domain/
  16. https://cwe.mitre.org/data/definitions/830.html
  17. https://cheatsheetseries.owasp.org/cheatsheets/Third_Party_Javascript_Management_Cheat_Sheet.html
  18. https://www.w3.org/TR/SRI/
  19. https://developer.mozilla.org/en-US/docs/Web/Security/Practical_implementation_guides/SRI
  20. https://semgrep.dev/blog/2024/protect-your-code-from-the-polyfill-supply-chain-attack/
  21. https://cert-agid.gov.it/news/scoperto-un-grave-attacco-alla-supply-chain-del-servizio-polyfill-io-piu-di-100-000-i-siti-coinvolti/
  22. https://isomer-user-content.by.gov.sg/36/8bee5efc-3166-44a1-89ae-0f0b095ecb17/03-July-2024.pdf