Mert Özen Her Satırda Daha İleri
Güvenlik Frontend Güvenliği — #09

Angular 11'den 22'ye ve Tarayıcılarda Frontend Güvenliğinde Değişenler

Mert Özen 8 Kas 2026 13 dk 2 görüntülenme
Angular 11'den 22'ye ve Tarayıcılarda Frontend Güvenliğinde Değişenler

Angular 11'den 22'ye güvenlik özelliklerinin çoğu yeni major'larla değil patch'lerle geldi; eski bir projeyi denetlerken major'a değil tam sürüme bakmak gerekiyor. Bu yazıda Trusted Types'tan autoCsp'ye ve SSR allowedHosts'a kadar her özelliğin geldiği sürümü paket tarball'larından doğruluyor, 22.0.8'de XSRF header'ının gönderilmediğini headless Chrome'da gösteriyor, tarayıcılardaki değişiklikleri topluyor ve çalıştırılabilir bir denetim script'i çıkarıyoruz.

Sürüm notu: Bu yazıdaki örnekler Angular 22.2 ve 22.0, Node.js 24 ve headless Chrome 156 ile denenmiştir.

Önce Tahmin Et

Bookstore'un web uygulaması Angular 22.0.8'de. app.config.ts'de provideHttpClient() yok, çünkü Angular 21'den beri HttpClient root'ta kendiliğinden sağlanıyor ve inject(HttpClient) doğrudan çalışıyor. Sunucu sayfayla birlikte XSRF-TOKEN cookie'sini set ediyor, component açılışta bir sipariş POST ediyor:

import { HttpClient } from '@angular/common/http';
import { Component, inject, signal, VERSION } from '@angular/core';

@Component({
  selector: 'app-root',
  template: `<p>Angular {{ version }}: {{ status() }}</p>`,
})
export class App {
  private readonly http = inject(HttpClient);
  protected readonly version = VERSION.full;
  protected readonly status = signal('pending');

  constructor() {
    this.http.post<{ id: number }>('/api/orders', { bookId: 1, quantity: 2 })
      .subscribe(order => this.status.set(`order ${order.id} created`));
  }
}

Angular dokümanı, XSRF (Cross-Site Request Forgery) korumasının varsayılan olarak açık olduğunu ve HttpClient'ın cookie'deki değeri X-XSRF-TOKEN header'ına koyduğunu söylüyor. Bu istekte header gider mi? Aynı kodu 22.2.5 ile build edersen sonuç değişir mi?

Cevabı aşağıda gerçek bir koşuyla göreceğiz; kısa hâli şu: 22.0.8'de gitmiyor, 22.2.5'te gidiyor. Serinin bu son yazısında Angular 11'den 22'ye ve tarayıcılarda, CSP (Content Security Policy), Trusted Types ve SSR (Server-Side Rendering) dahil güvenlik açısından neyin değiştiğini sürüm sürüm topluyor, sonunda eski bir Angular projesini denetlemek için çalıştırılabilir bir kontrol listesi çıkarıyoruz.

Sürüm Sürüm Angular

Sürüm numaralarını changelog'dan aldım, ama ilk geldikleri sürümü paketin kendisinden de doğruladım. Changelog bazen backport'ları ve yeniden adlandırmaları karıştırıyor; npm'deki tarball ise yalan söylemiyor:

#!/bin/sh
# Bir API adının yayımlanmış paket tarball'ında kaç kez geçtiğini yazdırır.
# Kullanım: ./check-first-version.sh <package> <version> <pattern>
curl -sL "https://registry.npmjs.org/$1/-/$(basename "$1")-$2.tgz" | tar -xzO | grep -c "$3"
@angular/core 10.2.0 createPolicy: 0
@angular/core 11.0.0 createPolicy: 8
@angular/core 15.2.0 CSP_NONCE: 0
@angular/core 16.0.0 CSP_NONCE: 7
@angular/ssr 21.1.4 allowedHosts: 0
@angular/ssr 21.1.5 allowedHosts: 41

Aynı yöntemle withNoXsrfProtection'ın @angular/common 15.0.0'da, autoCsp'nin @angular/build 19.0.0'da geldiğini ve HttpClient'ın 21.0.0'da providedIn: 'root' olduğunu gördüm. Tablo, denetimde bakacağın yerle birlikte:

SürümTarihDeğişiklikDenetimde ne ara
11.0.0Kasım 2020Trusted Types desteği, angular policy'siCSP'de require-trusted-types-for var mı
15.0.0Kasım 2022provideHttpClient, withXsrfConfiguration, withNoXsrfProtectionwithNoXsrfProtection kullanımı
16.0.0Mayıs 2023ngCspNonce ve CSP_NONCEstyle-src'de 'unsafe-inline'
18.0.0Mayıs 2024HttpClientModule ve HttpClientXsrfModule deprecatedNgModule tabanlı HttpClient yapılandırması
19.0.0Kasım 2024security.autoCspangular.json
21.0.0Kasım 2025HttpClient root'ta sağlanıyorprovideHttpClient() olmadan kullanım
21.1.5, 20.3.17, 19.2.21Şubat 2026SSR'da allowedHosts ve NG_ALLOWED_HOSTSwildcard ve *
21.2.9, 20.3.25, 19.2.25Nisan 2026trustProxyHeadersproxy arkasında X-Forwarded-*
22.0.0Haziran 2026Tanınmayan Host için 400CSR (Client-Side Rendering) fallback'e güvenen deploy
22.1.0, 21.2.19Temmuz 2026Root'taki HttpClient'a XSRF interceptor'ı21.0.0 ile 21.2.18 arası ve 22.0.x

Trusted Types ve CSP tarafının uygulamasını serinin "Trusted Types'ı Production'a Almak" ve "Angular'a Strict CSP Uygulamak" yazılarında, SSR tarafını "Angular SSR Güvenliği" yazısında yaptık. Burada odak, hangi sürümde neyin olmadığı.

2025 ve 2026: Advisory Yılı

Tablonun son satırlarına bakınca bir şey göze çarpıyor: Angular'ın güvenlik özelliklerinin çoğu son bir yılda yeni sürümle değil, patch'le geldi. GitHub Advisory Database'de Angular paketleri için 2026'da yayımlanmış 38 advisory var: 1 critical, 24 high, 13 medium. Bunlar üç kümeye ayrılıyor.

Birinci küme SSR ve SSRF (Server-Side Request Forgery). Şubat 2026'da critical olarak işaretlenen CVE (Common Vulnerabilities and Exposures) kaydı CVE-2026-27739, Angular SSR'ın Host ve X-Forwarded-* header'larına doğrulamadan güvendiğini ve göreli HttpClient isteklerinin bu sayede başka bir host'a yönlendirilebildiğini anlatıyor. allowedHosts bu düzeltmeyle geldi. Arkasından gelen advisory'ler bu yeni kontrolün kenarlarını kapattı: Nisan'da protocol-relative ve backslash içeren URL'ler (Uniform Resource Locator; CVE-2026-41423), Mayıs'ta hostname hijacking (CVE-2026-46417), Haziran'da CVE-2026-50168. Sonuncusu öğretici: allowedHosts kontrolü WHATWG (Web Hypertext Application Technology Working Group) URL parser'ıyla, sunucudaki emüle DOM (Document Object Model) ise daha esnek Domino parser'ıyla çalışıyordu; evil.com:80:80 gibi bozuk bir host birincisinde parse edilemeyip kontrolü atlıyor, ikincisinde kabul ediliyordu. Düzeltme 21.2.15, 20.3.22 ve 19.2.23'te geldi; advisory'ye göre 18.2.14 ve öncesi için düzeltme yok.

İkinci küme sanitization. SVG (Scalable Vector Graphics) animation attribute'ları, MathML URL'leri, i18n attribute binding'leri, two-way binding'ler ve concrete host'lardaki host binding'ler üzerinden XSS (Cross-Site Scripting) advisory'leri art arda geldi. Çoğunun ortak noktası, sanitizer'ın bir attribute'u ya da binding'i doğru security context'e koymaması. Kod tarafında yapacağın tek şey yamayı almak; bu yüzden sürüm takibi denetimin ilk maddesi.

Üçüncü küme HttpClient. Kasım 2025'te CVE-2025-66035 ile XSRF token'ının //evil.example gibi protocol-relative URL'lere gönderilmesi kapatıldı (21.0.1, 20.3.14, 19.2.16). Sonra tam tersi bir sorun düzeldi: bazı yollarda token hiç gönderilmiyordu. Açılıştaki soru bu ikinci türden.

Bir de takvim değişti. angular.dev'deki sürüm tablosuna göre v22 Haziran 2027'ye kadar active, Haziran 2028'e kadar LTS (Long-Term Support); v21'in LTS'i Haziran 2027'de, v20'ninki 28 Kasım 2026'da bitiyor ve v2–v19 artık desteklenmiyor. Major sürümler v22'den sonra yılda bire iniyor. Bu, v19 ve öncesinde kalan bir projenin yukarıdaki advisory'lerin hiçbirinin yamasını resmî olarak almayacağı anlamına geliyor.

Bir Regresyonu Gerçekten Görmek

Açılıştaki component'i iki sürümle build ettim ve küçük bir Node sunucusuyla servis ettim. Sunucu sayfayla birlikte açıkça sahte bir token'ı cookie olarak set ediyor ve POST'ta header'ı logluyor:

// Kullanım: node xsrf-server.mjs <dist-klasörü> <port>
import http from 'node:http';
import { readFile } from 'node:fs/promises';
import { join, extname } from 'node:path';

const [dir, port] = process.argv.slice(2);
const types = { '.html': 'text/html; charset=utf-8', '.js': 'text/javascript', '.css': 'text/css' };

http.createServer(async (req, res) => {
  const path = new URL(req.url, 'http://localhost').pathname;
  if (req.method === 'POST' && path === '/api/orders') {
    const token = req.headers['x-xsrf-token'];
    console.log(`POST /api/orders x-xsrf-token=${token ?? '(missing)'}`);
    res.writeHead(token === 'dev-only-xsrf-token' ? 201 : 403, { 'Content-Type': 'application/json' });
    res.end(token ? '{"id":42}' : '{"error":"xsrf"}');
    return;
  }
  const file = extname(path) ? join(dir, path) : join(dir, 'index.html');
  try {
    const body = await readFile(file);
    const headers = { 'Content-Type': types[extname(file)] ?? 'application/octet-stream' };
    if (file.endsWith('index.html')) headers['Set-Cookie'] = 'XSRF-TOKEN=dev-only-xsrf-token; Path=/; SameSite=Strict';
    res.writeHead(200, headers).end(body);
  } catch {
    res.writeHead(404).end();
  }
}).listen(Number(port), '127.0.0.1', () => console.log(`listening on http://localhost:${port}`));

Headless Chrome 156 ile iki build'i açtım. Önce 22.2.5:

[status] 200
[eval] "Angular 22.2.5: order 42 created"
POST /api/orders x-xsrf-token=dev-only-xsrf-token

Sonra aynı kaynak kod, @angular/* 22.0.8 ile:

[console.error] Failed to load resource: the server responded with a status of 403 (Forbidden)
[console.error] ERROR Ht
[status] 200
[eval] "Angular 22.0.8: pending"
POST /api/orders x-xsrf-token=(missing)

Header gitmedi. Sebep changelog'da tek satır: 22.1.0 ve 21.2.19'daki "enable xsrf for root-provided HttpClient" düzeltmesi. Commit mesajına göre XSRF interceptor'ı, provideHttpClient() çağrılmadan kullanılan root HttpClient'ın factory'sine eklenmemişti. Yani 21.0.0'dan 21.2.18'e ve 22.0.x'te, dokümanın "varsayılan açık" dediği koruma bu yolda kapalıydı. Bu tür bir boşluğu test bulmaz, çünkü testler genelde provideHttpClientTesting() ile ayrı bir yapılandırma kurar. Yükseltemiyorsan düzeltme tek satır:

import { provideHttpClient } from '@angular/common/http';
import { ApplicationConfig, provideBrowserGlobalErrorListeners } from '@angular/core';
import { provideRouter } from '@angular/router';
import { routes } from './app.routes';

export const appConfig: ApplicationConfig = {
  providers: [
    provideBrowserGlobalErrorListeners(),
    provideRouter(routes),
    provideHttpClient(),
  ]
};
[eval] "Angular 22.0.8: order 42 created"
POST /api/orders x-xsrf-token=dev-only-xsrf-token

Açık provideHttpClient(), 22.0.8'de de header'ı gönderdi. Bunu bir alışkanlık olarak tut: varsayılana güvenmek yerine güvenlik davranışını kodda görünür yap. Sunucu tarafında token'ı doğrulamak senin işin; Angular yalnız istemci yarısını yapıyor.

Tarayıcılarda Değişenler

Trusted Types Şubat 2026'da Baseline oldu. web-features verisine göre "Baseline low" tarihi 24 Şubat 2026; destek Chrome 83, Firefox 148 ve Safari 26. Yani require-trusted-types-for 'script' artık yalnız Chromium'da çalışan bir ek katman değil. Desteklemeyen eski bir tarayıcı direktifi yok sayar ve Angular'ın kendi sanitization'ı devrede kalır.

HTML (HyperText Markup Language) Sanitizer API'nin (Application Programming Interface) Element.setHTML() method'u ise henüz Baseline değil: MDN (MDN Web Docs) uyumluluk verisine göre Chrome 146 ve Firefox 148'de var, Safari'de yok. Chrome 156'da kısa bir sayfayla denedim:

const review = document.getElementById('review');
const input = '<b>Great book</b><img src=x onerror="alert(1)"><script>alert(2)<\/script>';

console.log('trustedTypes:', typeof window.trustedTypes?.createPolicy);
console.log('setHTML:', typeof Element.prototype.setHTML);
console.log('Sanitizer:', typeof window.Sanitizer);

if (typeof review.setHTML === 'function') {
  review.setHTML(input);
  console.log('setHTML result:', review.innerHTML);
}
[console.log] trustedTypes: function
[console.log] setHTML: function
[console.log] Sanitizer: function
[console.log] setHTML result: <b>Great book</b>

Varsayılan yapılandırmada <img> ve <script> tamamen atıldı; ayrı bir denemede javascript: ile başlayan href de silindi. Safari desteği gelene kadar setHTML'i feature detection ile ve DOMPurify gibi bir library'nin yerine değil, yanına koy.

Cookie tarafında beklenen kırılma gelmedi. Google 17 Ekim 2025'te Privacy Sandbox teknolojilerinin çoğunu (Topics, Protected Audience, Attribution Reporting, IP (Internet Protocol) Protection, Related Website Sets ve diğerleri) emekliye ayırdığını, Chrome'da kullanıcıya third-party cookie seçimi sunan mevcut yaklaşımı koruyacağını açıkladı. CHIPS (Cookies Having Independent Partitioned State) ve FedCM (Federated Credential Management) devam ediyor. Pratik sonucu: third-party cookie'ye dayanan bir embed ya da SSO (Single Sign-On) akışı Chrome'da hâlâ çalışıyor, ama Safari ve Firefox'taki kısıtlamalar yerinde; tasarımını third-party cookie'ye bağlama.

Session çalınmasına karşı yeni yön DBSC (Device Bound Session Credentials). Google 9 Nisan 2026'da Chrome 146 ile Windows'ta genel kullanıma açtığını, macOS'un sonraki bir sürümde geleceğini yazdı. Session, TPM (Trusted Platform Module) gibi donanımda tutulan ve dışarı aktarılamayan bir anahtara bağlanıyor; çalınan cookie başka makinede işe yaramıyor. Standart W3C (World Wide Web Consortium) WebAppSec grubunda ilerliyor; diğer tarayıcılar için bir taahhüt görmedim. Bugün için ek katman, BFF (Backend for Frontend) ve kısa ömürlü session'ların yerine geçmez.

Eski Bir Projeyi Denetlemek

Yukarıdakileri elle hatırlamak yerine bir script'e döktüm. Bağımlılığı yok, bir Angular projesinin kökünde node_modules, angular.json, src ve .npmrc'ye bakıyor:

// Kullanım: node audit-angular-security.mjs <proje-klasörü>
import { readFile, readdir } from 'node:fs/promises';
import { existsSync } from 'node:fs';
import { join } from 'node:path';

const root = process.argv[2] ?? '.';
const results = [];
const report = (level, id, message) => results.push(`${level.padEnd(4)} ${id.padEnd(14)} ${message}`);

const readJson = async path => JSON.parse(await readFile(join(root, path), 'utf8'));
const parseVersion = v => v.split('.').map(Number);
const inRange = (v, from, to) => {
  const cmp = (a, b) => a[0] - b[0] || a[1] - b[1] || a[2] - b[2];
  return cmp(parseVersion(v), parseVersion(from)) >= 0 && cmp(parseVersion(v), parseVersion(to)) < 0;
};

async function sourceFiles(dir) {
  const files = [];
  for (const entry of await readdir(dir, { withFileTypes: true })) {
    const path = join(dir, entry.name);
    if (entry.isDirectory()) files.push(...await sourceFiles(path));
    else if (/\.(ts|html)$/.test(entry.name) && !entry.name.endsWith('.spec.ts')) files.push(path);
  }
  return files;
}

async function grep(pattern) {
  const hits = [];
  for (const file of await sourceFiles(join(root, 'src'))) {
    (await readFile(file, 'utf8')).split('\n').forEach((line, i) => {
      if (pattern.test(line)) hits.push(`${file.slice(root.length + 1)}:${i + 1}`);
    });
  }
  return hits;
}

// 1. Destek süresi (angular.dev/reference/releases, Kasım 2026)
const core = (await readJson('node_modules/@angular/core/package.json')).version;
const ltsEnds = { 22: '2028-06', 21: '2027-06', 20: '2026-11-28' };
const major = parseVersion(core)[0];
if (ltsEnds[major]) report('OK', 'support', `Angular ${core}, security fixes until ${ltsEnds[major]}`);
else report('FAIL', 'support', `Angular ${core} no longer receives security fixes`);

// 2. Root'ta sağlanan HttpClient için XSRF (21.2.19 ve 22.1.0'da düzeltildi)
const usesProvideHttpClient = (await grep(/provideHttpClient\(/)).length > 0;
const xsrfGap = inRange(core, '21.0.0', '21.2.19') || inRange(core, '22.0.0', '22.1.0');
if (xsrfGap && !usesProvideHttpClient) report('FAIL', 'xsrf', 'HttpClient used without provideHttpClient(): XSRF header is not sent');
else report('OK', 'xsrf', usesProvideHttpClient ? 'provideHttpClient() found' : 'root-provided HttpClient includes XSRF interceptor');

const xsrfOff = await grep(/withNoXsrfProtection|HttpClientXsrfModule\.disable/);
if (xsrfOff.length) report('WARN', 'xsrf-off', `XSRF protection disabled: ${xsrfOff.join(', ')}`);

// 3. Sanitizer bypass'ları ve doğrudan DOM sink'leri
const bypass = await grep(/bypassSecurityTrust(Html|Script|Style|Url|ResourceUrl)/);
if (bypass.length) report('WARN', 'bypass', bypass.join(', '));
const sinks = await grep(/\.(innerHTML|outerHTML)\s*=|insertAdjacentHTML|document\.write/);
if (sinks.length) report('WARN', 'dom-sink', sinks.join(', '));

// 4. CSP: statik hosting için autoCsp, SSR için nonce
const isSsr = existsSync(join(root, 'node_modules/@angular/ssr'));
const angularJson = await readJson('angular.json');
const project = Object.values(angularJson.projects)[0];
const autoCsp = project.architect.build.options?.security?.autoCsp;
const nonce = (await grep(/ngCspNonce|CSP_NONCE/)).length > 0;
if (isSsr) report(nonce ? 'OK' : 'WARN', 'csp', nonce ? 'nonce wiring found' : 'SSR app without ngCspNonce/CSP_NONCE');
else report(autoCsp ? 'OK' : 'WARN', 'csp', autoCsp ? 'security.autoCsp enabled' : 'security.autoCsp not enabled');

// 5. SSR host doğrulaması
if (isSsr) {
  const hosts = await grep(/allowedHosts/);
  const commonEngine = await grep(/CommonEngine/);
  report(hosts.length ? 'OK' : 'WARN', 'ssr-hosts',
    hosts.length ? `allowedHosts set: ${hosts.join(', ')}` : 'no allowedHosts in code; set NG_ALLOWED_HOSTS at deploy');
  if (commonEngine.length) report('WARN', 'ssr-engine', `CommonEngine in use: ${commonEngine.join(', ')}`);
}

// 6. npm kurulum policy'si (npm supply chain yazısına bak)
const npmrc = existsSync(join(root, '.npmrc')) ? await readFile(join(root, '.npmrc'), 'utf8') : '';
const pkg = await readJson('package.json');
report(/min-release-age/.test(npmrc) ? 'OK' : 'WARN', 'npm-age', /min-release-age/.test(npmrc) ? 'min-release-age set' : 'no min-release-age in .npmrc');
report(pkg.allowScripts || /ignore-scripts\s*=\s*true/.test(npmrc) ? 'OK' : 'WARN', 'npm-scripts',
  pkg.allowScripts ? 'allowScripts policy present' : /ignore-scripts/.test(npmrc) ? 'ignore-scripts=true' : 'no install script policy');

console.log(results.join('\n'));
process.exitCode = results.some(r => r.startsWith('FAIL')) ? 1 : 0;

Önce açılıştaki 22.0.8 projesi, provideHttpClient() eklenmeden önceki hâliyle:

OK   support        Angular 22.0.8, security fixes until 2028-06
FAIL xsrf           HttpClient used without provideHttpClient(): XSRF header is not sent
WARN csp            security.autoCsp not enabled
WARN npm-age        no min-release-age in .npmrc
WARN npm-scripts    no install script policy

Sonra ng new --ssr ile oluşturulmuş, hiç dokunulmamış bir Angular 22.2.5 SSR projesi:

OK   support        Angular 22.2.5, security fixes until 2028-06
OK   xsrf           root-provided HttpClient includes XSRF interceptor
WARN csp            SSR app without ngCspNonce/CSP_NONCE
WARN ssr-hosts      no allowedHosts in code; set NG_ALLOWED_HOSTS at deploy
WARN npm-age        no min-release-age in .npmrc
WARN npm-scripts    no install script policy

Yeni proje bile varsayılan hâliyle dört uyarı alıyor; bu Angular'ın kusuru değil, bu ayarların ortama bağlı olması. Client-only Bookstore projesinde angular.json'a "security": { "autoCsp": true } ekleyip, .npmrc'ye min-release-age=3 yazıp ve önceki yazıdaki gibi kurulum script'lerini npm install-scripts deny ile reddedip tekrar çalıştırdım:

OK   support        Angular 22.2.5, security fixes until 2028-06
OK   xsrf           root-provided HttpClient includes XSRF interceptor
OK   csp            security.autoCsp enabled
OK   npm-age        min-release-age set
OK   npm-scripts    allowScripts policy present

Build'in ürettiği index.html'de autoCsp'nin eklediği meta etiketi: script-src 'strict-dynamic' 'sha256-55O+w+DkRtC/tV9/VmCsljePVyEYJEhsMbYAfvv3N84=' https: 'unsafe-inline';object-src 'none';base-uri 'self';. Hash'i destekleyen tarayıcı 'unsafe-inline' ve https:'i yok sayar; onlar yalnız eski tarayıcılar için geri dönüş.

Üretimde Dikkat

Script bir başlangıç noktası, karar verici değil. Kaynakta string arıyor; bypassSecurityTrustHtml çağrısını bir wrapper'a saklayan kodu ya da değişkene atanmış bir sink'i kaçırır. Asıl güvence sürüm: support satırı FAIL veriyorsa diğer satırların yeşil olması bir şey ifade etmez, çünkü desteklenmeyen sürümlere yama gelmiyor; örneğin Ekim 2026'da yayımlanan CVE-2026-104871'in advisory'sinde 19.x için düzeltme sürümü yok. Denetimi CI (Continuous Integration) pipeline'ında çalıştır ve exit code 1'i build'i durduran bir adım yap; support tablosundaki tarihleri her major sürümde angular.dev'den güncelle.

Eski bir projeyi güncellerken sıra önemli. Önce desteklenen bir major'a çık, aynı gün en son patch'e geç, sonra SSR'da allowedHosts'u gerçek domain'lerle doldur ve 22.0.0'dan sonra tanınmayan host'ların 400 aldığını load balancer health check'leriyle birlikte test et. CSP ve Trusted Types'ı en sona, Report-Only ile başlayarak bırak.

Sık Düşülen Tuzaklar

Birincisi, "varsayılan açık" cümlesine güvenmek. XSRF örneğinde doküman doğruydu, kod bir yolda değildi. Güvenlik ayarlarını açıkça yaz: provideHttpClient(withXsrfConfiguration(...)), allowedHosts, autoCsp.

İkincisi, sadece major sürüme bakmak. "Angular 21 kullanıyoruz" cümlesi 21.0.0 da olabilir, 21.2.26 da; aradaki fark onlarca advisory. Denetimde node_modules/@angular/core/package.json'daki tam sürüme bak.

Üçüncüsü, allowedHosts: ['*']. Angular bunu destekliyor ama dokümanı yalnız host'u önündeki başka bir katman doğruluyorsa önerir. Load balancer'ı değiştirdiğin gün koruman sessizce gider.

Dördüncüsü, Baseline'ı "her kullanıcıda var" sanmak. Baseline low, son sürümlerde var demek; kurumsal ortamda güncellenmemiş tarayıcılar uzun süre kalır. Trusted Types ve setHTML ek katman, tek savunma değil.

Küçük Bir Deneme

★☆☆ Kendi projende node_modules/@angular/core/package.json'daki sürümü angular.dev'deki sürüm tablosuyla karşılaştır ve LTS bitiş tarihini ekibinin takvimine yaz.

★★☆ Denetim script'ini kendi projende çalıştır. Her WARN satırı için ya düzeltmeyi yap ya da neden geçerli olmadığını bir cümleyle README'ye yaz.

★★★ XSRF denemesini tekrarla: aynı component'i 21.2.18 ve 21.2.19 ile build et, headless Chrome'da açıp sunucu logunda header farkını gör, sonra bu kontrolü CI'da çalışan bir Playwright testine çevir.

Frontend Güvenliği serisi burada bitiyor. Tarayıcının güvenlik modelinden DOM sink'lerine, strict CSP'den Trusted Types'a, token saklamadan SSR ve supply chain'e kadar her yazı tarayıcı tarafının bir katmanını ele aldı. CSP header'ını ASP.NET Core'dan üretmek ve raporlama endpoint'ini kurmak gibi sunucu yarısı ilerideki "ASP.NET Core Güvenliği" serisinde.