Güvenlikle İlişkili Standartlar
Bazı kodlama standardı ihlalleri sadece bir stil meselesidir. Bu bölüm bunlardan biri olmayanları ele alıyor — sadece okunabilirliği değil, sitenin gerçek güvenliğini riske atan hatalar.
1. Çıktıyı Escape Etmek
Sayfaya yazdırılan ve bir kullanıcıdan gelen her şey — bir form alanı, bir query string, yüklenen bir dosyanın adı — çıktı verilmeden önce escape edilmelidir, yoksa başka birinin tarayıcısında çalışmayı bekleyen bir script injection'a dönüşür.
<script>alert('test')</script>Böyle bir değer olduğu gibi yazdırılırsa script çalışır. Twig'in otomatik escaping'i (Twig Standartları bölümünde ele alındı) şablon çıktısı için bunu otomatik olarak hallediyor; markup'ı doğrudan oluşturan PHP kodu ise ham girdiyi bir string'e eklemek yerine Html::escape() ya da Xss::filter()'a başvurur.
2. İzin Verilen HTML'i Temizlemek
Her şeyin durağan metne escape edilmesi gerekmez — bir body alanına genelde bazı HTML'lere izin verilir, hepsine değil. Xss::filter(), güvenli etiketlerden oluşan bir allow-list dışındaki her şeyi siler; bu da temizlemek ile değeri hiç yazdırmamak arasındaki farktır.
// ✅ Doğru: sınırlı bir etiket kümesi kalıyor, geri kalanı siliniyor.
$safe_markup = Xss::filter($user_submitted_html, ['a', 'em', 'strong']);3. Çevrilebilir Metinlerde Placeholder Kullanımı
t() ve $this->t(), birleştirilmiş bir string yerine bir placeholder array'i alır ve placeholder'ın önek karakteri onun nasıl işleneceğini belirler: @value düz metin olarak escape edilir, %value escape edilip vurgu için sarmalanır, :value ise escape edilmeden eklenir — bu özellikle zaten güvenli olduğu bilinen bir URL için ayrılmıştır.
// ❌ Yanlış: kullanıcı girdisi doğrudan metne ekleniyor.
$this->t('Welcome ' . $username);
// ✅ Doğru: placeholder değeri Drupal otomatik olarak escape eder.
$this->t('Welcome @username', [
'@username' => $username,
]);4. Form API ve CSRF Koruması
Form API ile kurulan bir form, modülün ekstra bir şey yapmasına gerek kalmadan Drupal'ın oluşturup doğruladığı bir token sayesinde otomatik olarak CSRF koruması kazanır — bu da tek bir buton kadar küçük bir şey için bile bir formun her zaman ham HTML yerine Form API ile kurulmasının bir nedeni daha.
5. Access Kontrolleri
Hassas bir şey gösteren ya da yapan bir route, block ya da özel bir mantık, bir link gösterilmediği için arkasındaki route'a ulaşılamayacağını varsaymak yerine access'i açıkça kontrol eder. Entity işlemleri $entity->access('view') (ya da update, delete) üzerinden geçer; route'lar ise gereksinimlerini routing YAML'ında tanımlar.
// ❌ Yanlış: gizli linkin yeterli koruma olduğunu varsayıyor.
public function build() {
return ['#markup' => $this->renderSensitiveData()];
}
// ✅ Doğru: access gerçekten kontrol ediliyor.
public function build() {
if (!\Drupal::currentUser()->hasPermission('view sensitive data')) {
throw new AccessDeniedHttpException();
}
return ['#markup' => $this->renderSensitiveData()];
}6. Dosya Yüklemelerini Doğrulama
Yüklenen bir dosya, bir deny-list'e değil her zaman açık bir extension allow-list'e karşı doğrulanır; File ve Image alan tiplerinin birlikte geldiği validator'lar da yaygın durumları (extension, dosya boyutu, görsel boyutları) her modülde yeniden icat edilmesine gerek kalmadan karşılar.
$validators = [
'FileExtension' => ['extensions' => 'gif png jpg jpeg'],
'FileSizeLimit' => ['fileLimit' => '5 MB'],
];