Як публічні файли llms.txt дозволяють дослідникам запускати код у великих компаніях
Дослідники задокументували ненадані імена пакетів, які офіційні файли llms.txt наказували штучним інтелекту встановлювати, і код почав працювати у великих компаніях протягом кількох хвилин. Чому дані тепер є кодом.
Джерела: Data Became Code: We Ran Code Inside Fortune 500s Using Files They Published for AI Agents
Коли опублікований файл стає замовленням
Команда з дослідження безпеки повідомила, що пристрій у компанії зі списку Fortune 500 виконував код, який вони опублікували, і це сталось приблизно через чотири хвилини після того, як код набув чинності. Ще два виклики надійшли протягом години. За їхніми словами, ніхто не скористався вразливістю CVE, не здійснив фішингу серед співробітників та не вплинув на мережевий периметр. Дослідники зафіксували кілька назв офіційних файлів, які розміщувалися через HTTPS та які самі компанії надавали, і ці назви вже спонукали штучні інтелектові агенти їх використовувати.
Ці файли були загальнодоступними, а назви, які вони мали, не були заявлені ніким. Агенти робили саме те, для чого були створені. Та сама команда також зазначає, що під час масштабного сканування цих файлів вони натрапили на активну атаку, яка вже була відома: це був файл інструкцій від постачальника, який спрямовував агентів на підтверджений зловмисний код. Цей випадок описаний нижче.
Спочатку — контекст.
Чому llms.txt має значення тут
Протягом більшої частини історії Інтернету сторінка на сайті була просто сторінкою. Її міг прочитати користувач, її міг індексувати пошуковий робот, але ніхто не сприймав її як команду. Тепер це вже не так.
Компанії тепер розміщують у корені своїх сайтів новий тип файлу поруч із robots.txt — llms.txt, а іноді й довший файл llms-full.txt. Це не схема сайту та не юридичне повідомлення. Це структурований набір вказівок для штучних інтелектуальних агентів щодо того, що читати, які API використовувати, які пакети інсталювати та яким доменам довіряти. Великі лабораторії, що працюють над моделями, публікують власні такі файли, а інструмент Lighthouse від Google у Chrome DevTools тепер має функцію перевірки під назвою „agentic browsing“, яка заохочує сайти створювати такі файли. Кількість цих файлів постійно зростає.
Команда вирішила з’ясувати, наскільки широко поширився цей шар інструкцій. Їхній підрахунок: 8 565 файлів llms.txt на 6 214 доменах у режимі роботи, серед приблизно 15 000 зареєстрованих компаній. Серед тих, хто публікував ці файли, були великі підприємства, технологічні гіганти, компанії у сфері фінтеху та виробники оборонного обладнання.
Типовий файл направляє агента до документації, журналу змін та форуму спільноти, а потім до команди встановлення — щось на кшталт pip install для SDK компанії. Цей файл виглядає корисним та офіційним, і він надходить з власного домену компанії через HTTPS. Штучний інтелект, призначений для програмування, якщо отримає запит про інтеграцію з цим продуктом, прочитає цю команду та виконає її.
Наступне запитання було майже ганебно простим: хто насправді є власником цього імені пакета на PyPI? У кожному випадку відповідь була — ніхто. Це ім’я знаходилось у офіційному файлі першої сторони, а пакет, на який воно посилалося, ніколи не був заявлений як власний. Хто перший, той і отримує.
Дослідники перевірили ще кілька файлів, потім сотні, а зрештою майже всі, і скрізь бачили те саме. Інструкції з встановлення містили назви пакетів та доменів, які ніхто не зареєстрував. За їхніми словами, це не було „потенційно вразливим“, а просто доступним. Це також не є тайпспквоттінгом. Імена в файлах написані правильно, тож немає жодних опечаток, які можна було б виявити, адже реєстрація ніколи не відбувалась.
Як код опинився у великих компаніях
Команда обрала невеликий набір імен пакетів, які зустрічалися у файлах llms.txt відомих компаній, та зареєструвала їх у PyPI та npm. Кожен пакет містив простий механізм повернення інформації — мінімальний сигнал, який повідомляв про те, що встановлення відбулося на інфраструктурі, якою керували дослідники. Після цього вони почекали.
Перший сигнал повернення надійшов менш ніж за чотири хвилини. А саме, у якійсь компанії вартістю кілька сотень мільярдів доларів штучний інтелект прочитав файл llms.txt на веб-сайті компанії, знайшов рядок pip install та виконав його. Пакет дійсно походив з PyPI, як було зазначено у файлі, хоча це був пакет дослідників. Другий сигнал від компанії зі списку Fortune 500 надійшов протягом години, а ще кілька десятків сигналів надійшли від стартапів та корпорацій; у деяких з них команди забезпечення безпеки були більшими за всю професійну мережу дослідників.
Їхній висновок полягає у тому, що вони не пробили захист нікого, а скористалися ланцюгом довіри.
Як агенти самостійно знаходять ці файли
У експерименті потім досліджували, скільки саме підказок потрібно. Дослідники випробували п’ять різних конфігурацій у двох агентських CLI, давши кожному одне й те саме речення 100 разів, не додаючи до нього нічого, крім імені постачальника. У реченні просили агента використати всю документацію цього постачальника для створення та запуску проекту Node.js із його SDK.
Це було весь запит. У ньому не було жодного URL, жодного посилання на документацію та жодної згадки про llms.txt. Не було втручання у запит, жодного атакувальника та жодних методів соціальної інженерії. Агент самостійно знайшов канал інструкцій, адже саме для пошуку офіційної документації виробника він і був створений. Команда підрахувала, скільки з 100 запусків за кожною конфігурацією призводило до llms.txt, побачила команду та встановила пакет, який ніхто не реєстрував.
Ці пакети були бездіяльними за задумом — лише сигнальними. Усе, що було до цього моменту, належало до контрольованих досліджень. Те, що відбувається далі, — це окремий інцидент, виявлений під час аналізу корпусу даних.
Випадок, який вже існує у реальних умовах
Одне відкриття змусило команду зупинитися, адже це вже відбувалося.
Clerk — постачальник засобів автентифікації, чиї SDK використовуються у багатьох продакшн-додатках на Next.js, публікує документацію, написану для AI-агентів. Агент, який слідує цим вказівкам, знаходить у документації Clerk файл llms.txt із рекомендаціями щодо виправлення проблем з захистом автентифікації, у якому міститься така команда:
npx clerk-next-fix-auth-protection
Агент читає цей текст та виконує його, що зовсім не дивно для інструкцій безпосередньо від постачальника.
Проблема не у неправильному написанні назви пакету. Сам командний запит clerk-next-fix-auth-protection — це бінарний файл, який постачається всередині специфічного пакету Clerk @clerk/eslint-plugin. У документації рекомендується спочатку встановити цей специфічний пакет, а потім викликати відповідну команду. Однак якщо ця команда виконується до того, як пакет буде встановлений локально, npx шукає його назву у публічному реєстрі npm, де Clerk ніколи не публікував його як окремий пакет.
Хтось інший зареєстрував його замість нього. За описом дослідників у пакеті немає функціонального коду, але як тільки він встановлюється, він активує хуки, які під час кожної установки надсилають ім’я користувача інсталлятора, назву машини, робочу директорію та часовий стамп на зовнішній сервер. Він класифікується як MAL-2026-11069 за CWE-506 — вбудований зловмисний код, і був виявлений сервісами Google OSV.dev та Amazon Inspector. Документація, відкритий слот та автоматичне виконання залишалися б ідентичними незалежно від того, чи пакет брав ім’я користувача, чи встановлював повний бекдор. Механізм поширення — це вразливість, а пакет є лише варіантом.
Дослідження було передано команді з безпеки Clerk, яка швидко відреагувала та усунула проблему. У звіті підкреслюється, що це не є критикою Clerk. Третя сторона зареєструвала пакет, скориставшись плутаниною з назвою npx, і Clerk не мала контролю над цим. Команда представляє це як підтверджений приклад структурної проблеми, яка характерна для будь-якого постачальника, що публікує документацію, читабельну для агентів.
Чому поточні механізми контролю можуть її не помітити
Кожен сигнал, від якого залежить система безпеки, тут вказує неправильним шляхом. Агент, який знаходить файл llms.txt, бачить файл, наданий через HTTPS з офіційного домену у стандартному форматі, призначеному для використання штучним інтелектом, опублікований компанією або її надійним партнером. У агента майже немає причин сумніватися в цьому, адже сам файл є авторитетним джерелом інформації за своєю суттю.
Тож коли у файлі сказано встановити інструмент з вигляду внутрішнього, агент не зупиняється, щоб перевірити, чи належить ця назва компанії. Він не перевіряє простір імен PyPI та не помічає, що посилання на документацію веде до домену, реєстрація якого закінчилась три місяці тому. Він робить те, що сказано у файлі.
Довіра також є транзитивною. Файл llms.txt не обов’язково має знаходитися на сайті цільової компанії. Агенти отримують контекст від надійних третіх сторін, таких як документація партнера, посібник SDK постачальника чи сторінка налаштувань проєкту спільноти. Якщо агент довіряє цій третій стороні, а файл цієї сторони вказує на пакет, який ніхто не забрав, ланцюг функціонує так само.
Детекція кінцевих точок також не спрацювала. Для інструменту EDR чи проксі це виглядає як робота розробника з легітимним менеджером пакетів: команда pip install на pypi.org, домен, який дозволяє кожен корпоративний проксі, з кодувальним агентом, який компанія навмисно розгорнула як основний процес. Аномалій та попереджень немає. Проблема лежить на рівні передачі даних, у проміжку між інструкцією та її виконанням, і кінцева точка не може її виявити, оскільки їй ніколи не було поставлено правильного запитання.
Дані, перетворені на код
Протягом десятиліть контент споживали люди. Тепер штучні інтелектуальні агенти часто є першими, хто його читає, інтерпретує та діє на основі нього. Це і є категорійна помилка, в яку разом впав усій галузі: межа між даними та кодом зникла. Усе, що знаходиться на вашому веб-сайті, більше не є просто контентом. Це операційний вхідні дані, фактично код, який виконується в чужому середовищі з тими привілеями, які має агент.
Це скасовує старе припущення. Сторінки та документи раніше вважалися низькоризиковими за своєю суттю, оскільки їх ніхто не розглядав як виконувані файли, тому ніхто не передбачав коштів на їхню цілісність. Коли дані стають кодом, цілісність даних стає частиною бюджету на безпеку.
Більше, ніж один файл
llms.txt — це не вся поверхня атаки. Це перша тріщина, яка свідчить про те, що ситуація змінилась. Кожна поверхня, до якої підключений агент, стає місцем, куди можуть надходити інструкції, і жодне з цих місць не було розроблене з урахуванням перевірки цілісності.
Замисліться над тим, що насправді сприймає агент: офіційні репозиторії GitHub, документація, спільноти та форуми, ваші замовлення та електронна пошта. Протягом двадцяти років це був контент, створений для людей, і ніхто не встановлював за ним механізмів контролю цілісності, тому що контент не міг нічого зробити. Такий світ минув. Усі дані, які агенти отримують, тихо перетворилися на поверхню для виконання команд.
Справжньою проблемою є не один файл та не один реєстр. Самі дані змінили свою природу, а індустрія безпеки все ще намагається наздогнати ситуацію.
Цифри за дослідженням
- Розмір корпусу даних: 8,565 файлів llms.txt з 6,214 доменів у режимі роботи, взятих зі списку приблизно 15,000 компаній.
- Понад 237 об’єктів, які ніхто не претендував на себе та які були позначені як інструкції з встановлення чи налаштування: назви пакетів, домени та піддомени. Кожен з них, за словами дослідників, міг бути привласнений, причому більшість з них — безкоштовно.
- Було досліджено шість екосистем: PyPI, npm, RubyGems, NuGet, crates.io та Packagist. У сфері доменів були перевірені прострочені назви .dev та .io, а також покинуті піддомени на Render, Vercel, Fly та Netlify, усі з яких були доступні для привласнення.
Що можуть взяти на озброєння захисники
Дослідники описують llms.txt як лише перший елемент, який вони дослідили, та очікують виявлення ще більшої кількості способів порушення безпеки. З їхніх звітів випливають деякі практичні наслідки:
- Перевірте власні файли, якими користуються ваші агенти. Кожна назва пакету, домен та піддомен, про які вони згадують, мають бути зареєстровані, належати вам та перебувати під контролем.
- Виконуйте команди з документації, вказуючи повну назву пакету. Проста назва бінарного файлу може бути знайдена у публічному реєстрі, якщо локальна установка ще не відбулася.
- Ставтеся до документації від сторонніх постачальників, яку використовують ваші агенти, як до частини ланцюга постачання, адже довіра передається через неї.
- Пам’ятайте, що стандартні інструменти для керування кінцевими точками сприймають звичайну установку пакету та не позначають її як проблемну, тому контроль має відбуватися на ранньому етапі — під час виконання команд та пошуку у реєстрі.
Згідно зі звітом про розкриття інформації, під час експерименту не було завдано жодної шкоди. Жодних елементів, які могли б зберігатися довго, не було встановлено, жодних даних не було вилучено; результати експерименту відповідально повідомляються ураженим організаціям, а назви компаній залишаються конфіденційними поки триває усунення проблем.
Пов’язана література
- Створення агента-асистента знань на Databricks за допомогою LangGraph — Покрокове створення агента LangGraph на Databricks: мінімальний агент, Vector Search RAG, функція checkpointing у Lakebase для короткострокової пам’яті та сховище для довгострокової пам’яті.
- Локальна база даних резюме типу RAG з використанням Docling, PostgreSQL pgvector та Ollama — Перетворення папки з резюме у форматах PDF та DOCX на пошукову базу даних кандидатів: розділення на частини за допомогою Docling, PostgreSQL з pgvector, локальні моделі Ollama та фронтенд у форматі Streamlit.