OWASP 2024
التحقق من الإدخال والتسلسل
تحقّق من جهة الخادم والعميل ثم قم بتسلسل المخرجات بدقة.
التحقق باستخدام Zod داخل Server Action
ts
'use server'
import { z } from 'zod'
import { db } from '@/lib/db'
import { revalidatePath } from 'next/cache'
const schema = z.object({
title: z.string().min(3).max(120),
content: z.string().min(1),
})
export async function createSecurePost(formData: FormData) {
const parsed = schema.safeParse({
title: formData.get('title'),
content: formData.get('content'),
})
if (!parsed.success) throw new Error('Invalid input')
await db.post.create({ data: parsed.data })
revalidatePath('/posts')
}الحماية من الحقن
استخدم استعلامات مُعلمة واهرب مخرجات HTML دائمًا.
استعلامات مُعلمة (مثال Prisma)
ts
// ⚠️ Anti-pattern (concatenation)
// await prisma.$queryRawUnsafe(`SELECT * FROM users WHERE email = '${email}'`)
// ✅ Parameterized
const users = await prisma.$queryRaw`SELECT * FROM users WHERE email = ${email}`المصادقة والجلسات والكوكيز
طبّق خصائص آمنة وأعمارًا محدودة للجلسات.
كوكيز HttpOnly/secure + SameSite
ts
import { cookies } from 'next/headers'
import { serialize } from 'cookie'
export function setSessionCookie(token: string) {
cookies().set(
'session',
token,
{
httpOnly: true,
secure: true,
sameSite: 'lax',
maxAge: 60 * 60, // 1h
path: '/',
}
)
}ترويسات الأمان
اضبط CSP و HSTS وبقية الترويسات على مستوى المنصة.
next.config.js — ترويسات أمان (Edge أو Node)
ts
// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
async headers() {
return [
{
source: '/(.*)',
headers: [
{ key: 'Strict-Transport-Security', value: 'max-age=63072000; includeSubDomains; preload' },
{ key: 'X-Content-Type-Options', value: 'nosniff' },
{ key: 'X-Frame-Options', value: 'DENY' },
{ key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' },
{ key: 'Permissions-Policy', value: 'camera=(), microphone=(), geolocation=()' },
{ key: 'Content-Security-Policy', value: "default-src 'self'; img-src 'self' data:; script-src 'self'; style-src 'self' 'unsafe-inline'" },
],
},
]
},
}
module.exports = nextConfigCSRF و SameSite
احمِ عمليات التعديل عبر توكن وتحقق من origin/referer.
CSRF token داخل Server Action
ts
'use server'
import { cookies, headers } from 'next/headers'
export async function mutateWithCsrf(formData: FormData) {
const token = formData.get('csrf_token')
const cookie = cookies().get('csrf')?.value
const origin = headers().get('origin')
if (!token || token !== cookie) throw new Error('CSRF invalid')
if (!origin?.startsWith('https://votre-domaine.tld')) throw new Error('Origin invalid')
// ... mutation
}تخزين الأسرار
اعزل الأسرار في مدير الأسرار، ولا تضعها في الكود أو السجلات.
أمثلة لحقن الأسرار في CI
bash
# GitHub Actions
echo "API_KEY=${{ secrets.API_KEY }}" >> $GITHUB_ENV
# Vercel
# vercel env add API_KEY production
# vercel env pull .env.localCI/CD آمن
أدرج SCA/SAST/DAST وتواقيع artifacts والموافقات اليدوية.
Pipeline DevSecOps (مقتطف)
yaml
jobs:
build:
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npm audit --audit-level=high
- name: CodeQL
uses: github/codeql-action/analyze@v3
- name: Container scan
uses: aquasecurity/trivy-action@0.18.0
deploy:
needs: [build]
environment: production
steps:
- name: Approvals
uses: some/action-manual-approval@v1التسجيل والكشف
أنشئ سجلات منظمة وقابلة للربط ومتوافقة مع SIEM.
Logger منظم وآمن للـ PII
ts
import pino from 'pino'
const logger = pino({ level: 'info', redact: ['req.headers.authorization', 'user.email'] })
export function logRequest(req: { id: string; path: string; ip: string }) {
logger.info({ reqId: req.id, path: req.path, ip: req.ip }, 'http_request')
}الخلاصة
تقليل سطح الهجوم يجمع بين نظافة الكود، الإعدادات المتينة، وأتمتة DevSecOps. الأمثلة أعلاه تشكل أساسًا عمليًا للالتزام بـ OWASP Top 10 2024.