Команда реагування на інциденти Rust 20 серпня видалила з crates.io шкідливі версії arrayref 0.3.10, internment 0.8.7 та append-only-vec 0.1.9. Кожен отруєний реліз підтягував шкідливу залежність proc-macro1, чий сценарій збірки завантажував і запускав корисне навантаження під час компіляції проєкту Cargo. Розробникам потрібно перевірити фактичні версії у lock-файлах, локальні кеші Cargo та історію збірок CI, а не лише оновити залежність і вважати інцидент закритим. [1]
Вирішальна межа — чи запускалася збірка. Наявність відповідного крейта у Cargo.lock або ~/.cargo/registry/cache доводить, що шкідливу версію було обрано або завантажено, але сама по собі не доводить виконання її сценарію збірки. Якщо робоча станція розробника або CI-runner справді збирав проєкт з однією зі шкідливих версій, вважайте хост скомпрометованим і змініть із чистої системи всі секрети, до яких він мав доступ.
Які версії Rust-крейтів були шкідливими?
| Видалений реліз | Час доступності та поточна дія |
|---|---|
arrayref 0.3.10 | Був доступний 86 хвилин — з 07:15:00 до 08:41:40 UTC. Зафіксуйте або оберіть довірений реліз на кшталт 0.3.9, а потім перевірте lock-файл і кожен кеш локальних та CI-збірок. |
internment 0.8.7 | Був доступний 90 хвилин — з 07:34:07 до 09:04:11 UTC. Використовуйте довірений реліз на кшталт 0.8.6 і з’ясуйте, чи потрапила отруєна версія на хост збірки. |
append-only-vec 0.1.9 | Був доступний 107 хвилин — з 07:37:49 до 09:25:24 UTC. Використовуйте довірений реліз на кшталт 0.1.8 і перевірте пряме та транзитивне підтягування залежності. |
proc-macro1, proc-macro-en, aovine, arone, aronenao або tinymember | Команда Rust видалила всі версії цих контрольованих атакувальником або пов’язаних крейтів. Будь-який збіг потребує перевірки; не плутайте proc-macro1 з легітимним proc-macro2. |
Вікна публікації були короткими, але загальна кількість завантажень не дорівнює кількості заражених комп’ютерів. Застосунки з чистим зафіксованим lock-файлом могли й надалі використовувати безпечну версію, навіть коли атакувальник позначив її як вилучену. Найвищий ризик мають свіже розв’язання залежностей, оновлення lock-файлів, незакріплені збірки, теплі кеші з видаленим релізом і будь-яка збірка після вибору однієї з цих версій.
Як працював шкідливий ланцюг під час збірки
Атакувальнику не потрібно було ховати шкідливу логіку у видимих макросах arrayref. Версія 0.3.10 додала залежність від схожого за назвою пакета proc-macro1. Cargo збирає оголошені залежності, навіть якщо батьківський крейт їх не викликає, тому шкідливий build.rs запускався під час компіляції. Сценарій відновлював адресу завантаження, вимикав звичайну перевірку TLS-сертифіката, отримував навантаження для відповідної платформи та запускав його як відокремлений процес. [2]
На Unix-подібних системах перший етап записувався як /tmp/rust-setup. У Windows дослідники вказали шлях %TEMP%\rust-setup.ps1, запуск через %TEMP%\rust-setup-launch.vbs і wscript.exe. Дослідники відтворили завантаження корисного навантаження під час контрольованої збірки. Тому успішну компіляцію з отруєною залежністю слід розглядати як виконання коду, а не як невикористаний вразливий пакет у проєкті. [3]
Перевірте lock-файли та кеші Cargo
- Перевірте всі репозиторії. Знайдіть у збережених і згенерованих
Cargo.lockтри точні шкідливі версії та будь-яку назву з переліку видалених крейтів атакувальника. - Перевірте кеші розробників і CI. Команда Rust надала наведену нижче команду. Запустіть її для кожного облікового запису розробника, self-hosted runner, шару контейнера та відновленого CI-кешу, де міг збиратися Rust-код.
find ~/.cargo/registry/cache -type f \( \
-name 'append-only-vec-0.1.9.crate' -o \
-name 'arrayref-0.3.10.crate' -o \
-name 'internment-0.8.7.crate' -o \
-name 'proc-macro1-*.crate' -o \
-name 'proc-macro-en-*.crate' -o \
-name 'aovine-*.crate' -o \
-name 'arone-*.crate' -o \
-name 'aronenao-*.crate' -o \
-name 'tinymember-*.crate' \
\) -print- Відокремте завантаження від виконання. Збіг у кеші означає, що крейт завантажувався. Зіставте його з історією команд, журналами збірок, часом завдань, відновленням кешу та артефактами, щоб визначити, чи запускалися
cargo build,cargo test, пакування або інший етап компіляції. - Перевірте мережеві й файлові ознаки. Шукайте в історії вихідних з’єднань адресу
23.254.165.112на портах9089або443. Перевірте згадані файли першого етапу для Unix і Windows, але не вважайте їх відсутність доказом того, що навантаження не запускалося.
Що робити, якщо отруєна Rust-збірка запускалася
- Припиніть повторне використання хоста. Ізолюйте робочу станцію розробника або self-hosted runner від чутливих мереж. Зупиніть уражений pipeline, але збережіть журнали збірки, lock-файли, кеші, телеметрію процесів і мережеві записи.
- Визначте доступні секрети. Складіть перелік токенів GitHub і GitLab, токенів публікації crates.io, хмарних облікових даних, SSH-ключів, ключів підпису, секретів розгортання, даних реєстрів пакетів, матеріалів гаманців і змінних середовища, доступних користувачу або CI-завданню.
- Змінюйте дані з чистої системи. Відкличте сесії та замініть потенційно розкриті облікові дані у правильній послідовності. Заміна токена на підозрілому хості може передати новий секрет активному шкідливому ПЗ.
- Перебудуйте середовище. Замініть тимчасові runner-и довіреними образами, перевстановіть постійні хости, якщо їхню цілісність неможливо підтвердити, очистьте отруєні кеші Cargo та vendored-копії, а залежності відновіть із довірених lock-файлів.
- Перезберіть результати. Вважайте бінарні файли, інсталятори, контейнери та підписані артефакти, створені після отруєної збірки, недовіреними, доки їх не буде перезібрано на чистій інфраструктурі й перевірено походження.
На Windows-станції розробника повне сканування Gridinsoft Anti-Malware після ізоляції може допомогти знайти виявлені навантаження, елементи автозапуску, заплановані завдання, служби та інші механізми закріплення. Чистий результат сканування не скасовує можливе викрадення токенів і не доводить, що відокремлений процес ніколи не запускався, тому заміна облікових даних і довірена перебудова залишаються окремими кроками.
Видалення з crates.io не очищає систему
Видалення шкідливих релізів припиняє звичайні нові завантаження, але теплий кеш Cargo, каталог із vendored-залежностями, шар контейнера або дзеркало внутрішнього реєстру можуть зберегти файли. Оновлення Cargo.toml також не очищає машину, де сценарій збірки вже виконувався. Перевірте фактичну версію, видаліть збережені копії, дослідіть хост, змініть доступні секрети й перезберіть уражені артефакти.
Легітимний крейт proc-macro2 не є шкідливим пакетом із цього інциденту. Збіг назв важливий: широкий пошук за “proc macro” може спричинити зайву реакцію. Перед ескалацією звіряйте точні назви й версії. Інший кросекосистемний інцидент описано в матеріалі про TrapDoor у npm, PyPI та crates.io, а стаття про злам пакета Jscrambler пояснює, чому заміна секретів має йти після визначення факту виконання, а не замість нього.
Джерела
- Rust Security Response Team. “Supply chain attack on arrayref.” Rust Blog, 20 серпня 2026 року. Уражені релізи, час видалення та перевірка кешу.
- jhobern. “Malware: arrayref 0.3.10 executes a remote payload at build time via typosquatted proc-macro1.” RustSec Advisory Database, issue 3161, 20 серпня 2026 року. Початковий звіт, поведінка build.rs та індикатори.
- Sai Likhith. “Rust Supply-Chain Attack: arrayref, internment, and append-only-vec Poisoned by the proc-macro1 Build-Time Dropper.” StepSecurity, оновлено 20 серпня 2026 року. Відтворення виконання, ланцюг залежностей і реагування.
