---
title: 'Güvenlik Başlıkları'
source: 'https://academia.sh/tr/kurslar/frontend-kalitesi/guvenlik-basliklari'
course: 'Frontend Kalitesi'
language: tr
updated: '2026-08-17T18:09:22+00:00'
license: 'CC BY-SA 4.0'
---

# Güvenlik Başlıkları

Taşıma güvenliğinin zorlanması, çerçevelemenin sınırlanması, referans bilgisinin daraltılması, tür tahmininin kapatılması ve kaynak yalıtımı; eksikleri bulan bir yapılandırma denetleyicisi.

Önceki üç ders belirli saldırı sınıflarına karşı belirli katmanlar kurdu. Bu ders, tek bir
sınıfa bağlı olmayan ama hepsinin etkisini azaltan bir kümeyi ele alır: yanıt başlıklarıyla
bildirilen ve tarayıcının uyguladığı kısıtlar.

Bu başlıkların ortak özelliği, uygulama kodunda değil sunucu yapılandırmasında
yaşamalarıdır. Bir sürüm çıkarken gözden kaçmaları kolaydır, çünkü hiçbir işlevi
bozmazlar; yokluklarının gözlenebilir sonucu yalnız bir şeyler ters gittiğinde ortaya
çıkar. Dersin sonundaki denetleyici bu görünmezliği giderir.

## Taşıma Güvenliğinin Zorlanması

İnternet Nasıl Çalışır kursundaki HTTPS'in Rolü dersi şifreli taşımanın gizlilik, bütünlük
ve kimlik doğrulama sağladığını kurmuştu. Uygulama tümüyle şifreli sunuluyor olsa bile bir
boşluk kalır: kullanıcı adresi şemasız yazdığında ilk istek şifresiz gidebilir ve
yönlendirmeden önce araya girilebilir.

`Strict-Transport-Security` başlığı bu boşluğu kapatır. Tarayıcıya, bildirilen süre boyunca
bu konağa yalnız şifreli bağlanmasını söyler; şemasız yazılan adres ağa çıkmadan
dönüştürülür. Üç bileşeni vardır. `max-age` sürenin saniye cinsinden uzunluğudur ve
anlamlı bir koruma için uzun tutulur. `includeSubDomains` kuralı alt alanlara yayar; bu
olmadan bir alt alan şifresiz kalabilir ve çerez kapsamı üzerinden uygulamayı etkiler.
Üçüncü bileşen, konağı tarayıcılara gömülü listeye kaydeden ön yükleme bildirimidir; ilk
isteği de kapsar, ama geri alınması yavaştır ve tüm alt alanların şifreli sunulmasını
kalıcı olarak taahhüt eder.

Başlığın şifresiz bir yanıtta gönderilmesinin bir etkisi yoktur ve olmamalıdır: aksi
takdirde araya giren biri, konağı erişilemez kılan bir kayıt yazdırabilirdi.

## Çerçevelemenin Sınırlanması

Kuzey Yamaç Ölçüm İstasyonu arayüzü, istasyon konumunu gösteren bir harita çerçevesi gömer.
Bu, çerçevelemenin bir yönüdür. Öteki yön, uygulamanın kendisinin başka bir sayfa
tarafından çerçevelenmesidir ve savunma gerektiren yön budur.

Görünmez kılınmış bir çerçeve içine alınan bir sayfa, kullanıcının gördüğü başka bir
arayüzün altında durur. Kullanıcı gördüğü düğmeye tıkladığını sanırken çerçeve içindeki
sayfanın bir denetimine tıklar; oturum kendisine ait olduğu için işlem gerçekleşir. Bu
sınıfın adı **tıklama hırsızlığıdır (clickjacking)** ve savunması, belgenin kimler
tarafından çerçevelenebileceğini bildirmektir.

İki mekanizma vardır. `X-Frame-Options` başlığı `DENY` veya `SAMEORIGIN` değerlerini alır
ve tek bir karar bildirir. İçerik güvenlik politikasının `frame-ancestors` yönergesi ise
kaynak listesi kabul eder ve daha ayrıntılıdır: yalnız belirli kaynakların çerçevelemesine
izin verilebilir. Yönergeyi anlayan bir gerçekleştirimde yönerge kazanır; ikisini birlikte
yazmak, yalnız birini anlayan gerçekleştirimlerde de koruma sağlar.

## Referans Bilgisinin Daraltılması

Bir bağa tıklandığında veya bir alt kaynak yüklendiğinde tarayıcı, isteğe hangi sayfadan
gelindiğini bildiren bir başlık ekler. Öntanımlı davranış, tam adresi göndermeye kadar
gidebilir. Ölçüm istasyonunda bu, `.../istasyon/kuzey-yamac?olcum=4417` biçimindeki bir
adresin yol ve sorgu bileşenlerinin üçüncü bir tarafa sızması demektir.

`Referrer-Policy` başlığı bu davranışı daraltır. Değerler bir eksen üzerinde durur: hiçbir
şey göndermeyen uçtan, tam adresi gönderen uca kadar. Dengeli seçim, aynı kaynağa tam
adresi, başka kaynaklara yalnız kaynak dizgisini gönderen ve şifreliden şifresize geçişte
hiçbir şey göndermeyen değerdir. Analiz ihtiyacı bu bilgiyi gerektiriyorsa, bilgi
başlıktan değil uygulamanın kendi ölçümünden alınır.

## Tür Tahmininin Kapatılması

Bir yanıtın içerik türü eksik veya yanlışsa, tarayıcı gövdeye bakıp türü tahmin edebilir.
Kullanıcıların dosya yüklediği bir uygulamada bu tahmin bir açığa dönüşür: metin olarak
sunulmak istenen bir yükleme, işaretleme gibi yorumlanırsa aynı kaynakta belge olarak
çalışır.

`X-Content-Type-Options: nosniff` başlığı tahmini kapatır ve tarayıcıyı bildirilen türe
uymaya zorlar. Başlık tek başına yetmez; bildirilen türün doğru olması, kullanıcı
yüklemelerinin ayrı bir kaynaktan sunulması ve indirme olarak işaretlenmesi aynı savunmanın
parçalarıdır.

## Kaynak Yalıtımı ve Yetenek İzni

`Cross-Origin-Resource-Policy` başlığı, bir kaynağın başka kaynaklarca gömülüp
gömülemeyeceğini bildirir. Değeri `same-origin` olduğunda, kaynak yalnız kendi kaynağının
belgelerinde kullanılabilir. Bu, verinin başka bir belgenin bellek alanına çekilmesini
sınırlayan bir kısıttır.

Aynı ailede iki başlık daha bulunur: belgenin açtığı ve kendisini açan pencerelerle
tarayıcı bağlamı paylaşımını kesen başlık ve gömülen kaynakların açık izin bildirmesini
zorunlu kılan başlık. İkisi birlikte **kaynak yalıtımı (cross-origin isolation)** adı
verilen durumu kurar. Bu durum bazı yeteneklerin ön koşuludur ve yeteneklerin
kullanılmadığı bir uygulamada zorunlu değildir; gereksiz yere açıldığında meşru gömme
işlemlerini kırar.

Web'in Temelleri ve HTML kursunda tanıtılan **yetenek izni (permission policy)** ise ayrı
bir eksendir: belgenin ve gömdüğü çerçevelerin hangi aygıt yeteneklerini kullanabileceğini
sayar. Harita çerçevesinin konum yeteneğine ihtiyacı yoksa, çerçeveye o yetenek verilmez.

## Yapılandırmayı Denetlemek

Bu başlıkların hepsi tek tek doğru yazılabilir ve bir sürüm sonra biri düşebilir. Denetimi
kural kümesine dönüştürmek, düşen başlığı görünür kılar.

```js
// basliklar.mjs — yanit basliklarini kural kumesine gore denetler
const BIR_YIL = 31536000;

const KURALLAR = [
  {
    ad: 'tasima guvenligi',
    denetle: (b) => {
      const deger = b['strict-transport-security'];
      if (!deger) return 'Strict-Transport-Security yok';
      const sure = Number(/max-age=(\d+)/.exec(deger)?.[1] ?? 0);
      if (sure < BIR_YIL) return `max-age ${sure} saniye, bir yildan kisa`;
      if (!/includeSubDomains/i.test(deger)) return 'includeSubDomains yok, alt alanlar disarida';
      return null;
    },
  },
  {
    ad: 'icerik guvenlik politikasi',
    denetle: (b) => {
      const deger = b['content-security-policy'];
      if (!deger) return 'Content-Security-Policy yok';
      if (/script-src[^;]*'unsafe-inline'/.test(deger)) return "script-src icinde 'unsafe-inline' var";
      if (!/frame-ancestors/.test(deger)) return 'frame-ancestors yonergesi yok';
      return null;
    },
  },
  {
    ad: 'cerceveleme',
    denetle: (b) =>
      b['x-frame-options'] || /frame-ancestors/.test(b['content-security-policy'] ?? '')
        ? null
        : 'cerceveleme sinirlanmamis',
  },
  {
    ad: 'tur tahmini',
    denetle: (b) => (b['x-content-type-options'] === 'nosniff' ? null : 'X-Content-Type-Options: nosniff yok'),
  },
  {
    ad: 'referans politikasi',
    denetle: (b) => {
      const deger = b['referrer-policy'];
      if (!deger) return 'Referrer-Policy yok';
      const gevsek = ['unsafe-url', 'no-referrer-when-downgrade', 'origin-when-cross-origin'];
      return gevsek.includes(deger) ? `gevsek deger: ${deger}` : null;
    },
  },
  {
    ad: 'kaynak paylasim politikasi',
    denetle: (b) => (b['cross-origin-resource-policy'] ? null : 'Cross-Origin-Resource-Policy yok'),
  },
  {
    ad: 'oturum cerezi',
    denetle: (b) => {
      const deger = b['set-cookie'];
      if (!deger) return null;
      const eksik = ['HttpOnly', 'Secure', 'SameSite'].filter((n) => !new RegExp(n, 'i').test(deger));
      return eksik.length ? `cerez nitelikleri eksik: ${eksik.join(', ')}` : null;
    },
  },
];

function denetle(ad, basliklar) {
  const bulgular = KURALLAR.map((k) => [k.ad, k.denetle(basliklar)]).filter(([, b]) => b !== null);
  console.log(`\n${ad}: ${bulgular.length} bulgu`);
  for (const [kural, bulgu] of bulgular) console.log('  -', `${kural}:`, bulgu);
  if (bulgular.length === 0) console.log('  - bulgu yok');
}

const ilkYayin = {
  'content-type': 'text/html; charset=utf-8',
  'strict-transport-security': 'max-age=86400',
  'content-security-policy': "default-src 'self'; script-src 'self' 'unsafe-inline'",
  'referrer-policy': 'unsafe-url',
  'set-cookie': 'olcum_oturum=abc; Path=/',
};

const duzeltilmis = {
  'content-type': 'text/html; charset=utf-8',
  'strict-transport-security': 'max-age=31536000; includeSubDomains',
  'content-security-policy': "default-src 'self'; script-src 'self' 'nonce-r4k2'; frame-ancestors 'none'",
  'x-frame-options': 'DENY',
  'x-content-type-options': 'nosniff',
  'referrer-policy': 'strict-origin-when-cross-origin',
  'cross-origin-resource-policy': 'same-origin',
  'set-cookie': 'olcum_oturum=abc; Path=/; HttpOnly; Secure; SameSite=Lax',
};

denetle('ilk yayin', ilkYayin);
denetle('duzeltilmis yapilandirma', duzeltilmis);
```

```
$ node basliklar.mjs

ilk yayin: 7 bulgu
  - tasima guvenligi: max-age 86400 saniye, bir yildan kisa
  - icerik guvenlik politikasi: script-src icinde 'unsafe-inline' var
  - cerceveleme: cerceveleme sinirlanmamis
  - tur tahmini: X-Content-Type-Options: nosniff yok
  - referans politikasi: gevsek deger: unsafe-url
  - kaynak paylasim politikasi: Cross-Origin-Resource-Policy yok
  - oturum cerezi: cerez nitelikleri eksik: HttpOnly, Secure, SameSite

duzeltilmis yapilandirma: 0 bulgu
  - bulgu yok
```

İlk yapılandırmanın kusurları tek tek küçüktür ve hiçbiri uygulamayı bozmaz: taşıma
kuralının süresi kısadır, politika satır içi koda izin verir, çerçeveleme sınırlanmamıştır,
oturum çerezi üç niteliğini de taşımaz. Bulgu listesi bunları tek bir çalıştırmada görünür
kılar.

Bu denetimin değeri, sürekli çalıştırılmasındadır. Yayın öncesi bir adım olarak
çalıştırıldığında, başlık düşüren bir yapılandırma değişikliği kendini bir sonraki güvenlik
gözden geçirmesinde değil, aynı gün gösterir. Kural kümesi de zamanla değişir; yeni bir
kural eklendiğinde bulgu listesinin uzaması beklenen davranıştır.

## Özet

- Güvenlik başlıkları sunucu yapılandırmasında yaşar ve eksiklikleri hiçbir işlevi
  bozmadığı için sessizce oluşur.
- `Strict-Transport-Security` ilk istek boşluğunu kapatır; `includeSubDomains` olmadan alt
  alanlar korumasız kalır.
- Çerçeveleme `X-Frame-Options` veya `frame-ancestors` yönergesiyle sınırlanır; ikincisi
  kaynak listesi kabul ettiği için daha ayrıntılıdır.
- `Referrer-Policy` yol ve sorgu bilgisinin dışarı sızmasını daraltır;
  `X-Content-Type-Options: nosniff` tür tahminini kapatır.
- Başlık kümesini denetleyen bir kural çözümleyicisi, düşen bir başlığı aynı gün görünür
  kılar; denetim yayın akışının bir adımı olarak çalıştırılır.

## Sonraki Adım

Buraya kadarki savunmalar uygulamanın kendi kodu ve kendi sunucusu üzerinde kuruldu.
Ölçüm arayüzü ise kendi yazmadığı kodu da çalıştırır: harita çerçevesi, ölçüm grafiğini
çizen dış betik, bağımlılık ağacındaki yüzlerce paket. Bu kodun her satırı, uygulamanın
kaynağının yetkileriyle çalışır. Sonraki ders üçüncü taraf kodun oluşturduğu riski, tedarik
zinciri boyunca nerede oluştuğunu ve alt kaynak bütünlüğü ile nasıl daraltılabileceğini
ele alır.
