مقدمة: لماذا تعتبر أمان تطبيقات TypeScript أمرًا بالغ الأهمية
TypeScript هي طبقة فوق JavaScript تضيف الكتابة الثابتة (static typing) والإمكانيات الحديثة. ومع ذلك، فإن الكتابة الثابتة لا تضمن الأمان. يمكن أن تؤدي أخطاء التحقق من الصحة، والمعالجة غير الصحيحة لإدخال المستخدم، والثغرات الأمنية في التبعيات (dependencies) إلى هجمات خطيرة. في هذه المقالة، سنستعرض أهم 10 ثغرات أمنية شائعة في تطبيقات TypeScript، وسنقدم أمثلة على الأكواد ونوضح كيفية تجنبها.
1. البرمجة النصية عبر المواقع (XSS)
تحدث هجمات XSS عندما يقوم المهاجم بحقن سكريبت ضار في صفحة الويب. لا يوفر TypeScript حماية تلقائية من ذلك.
مثال على كود ضعيف
function renderUserInput(input: string): string {
return `<div>${input}</div>`;
}
// المهاجم يرسل: <script>alert('XSS')</script>
الحل
استخدم هروب رموز HTML (escaping) أو مكتبات مثل DOMPurify:
import DOMPurify from 'dompurify';
function renderUserInputSafe(input: string): string {
const sanitized = DOMPurify.sanitize(input);
return `<div>${sanitized}</div>`;
}
2. حقن SQL (SQL Injection)
إذا كنت تستخدم TypeScript مع قواعد البيانات، فإن دمج السلاسل النصية غير المنضبط في استعلامات SQL يمكن أن يؤدي إلى تسرب البيانات.
مثال على كود ضعيف
async function getUser(id: string): Promise<User | null> {
const query = `SELECT * FROM users WHERE id = '${id}'`;
return await db.query(query);
}
الحل
استخدم الاستعلامات ذات المعلمات (prepared statements):
async function getUserSafe(id: string): Promise<User | null> {
const query = 'SELECT * FROM users WHERE id = $1';
return await db.query(query, [id]);
}
3. تلوث النموذج الأولي (Prototype Pollution)
هذه الثغرة الأمنية مميزة لـ JavaScript/TypeScript. يمكن للمهاجم تغيير النموذج الأولي (prototype) للكائن، مما يؤثر على جميع الكائنات في وقت التشغيل (runtime).
مثال على كود ضعيف
function merge(target: any, source: any) {
for (const key in source) {
if (source.hasOwnProperty(key)) {
target[key] = source[key];
}
}
}
const user = { name: 'Alice' };
merge(user, JSON.parse('{"__proto__": {"isAdmin": true}}'));
// الآن جميع الكائنات لديها isAdmin: true
الحل
تحقق من المفاتيح بحثًا عن الخصائص الخطرة واستخدم الأدوات المساعدة الآمنة:
function safeMerge(target: Record<string, any>, source: Record<string, any>) {
for (const key in source) {
if (key === '__proto__' || key === 'constructor' || key === 'prototype') continue;
target[key] = source[key];
}
}
4. تزوير الطلب عبر المواقع (CSRF)
تجبر هجمات CSRF المستخدم على تنفيذ إجراءات غير مرغوب فيها على موقع ويب تمت مصادقته عليه.
الحل باستخدام TypeScript
// توليد رمز CSRF
import crypto from 'crypto';
function generateCsrfToken(): string {
return crypto.randomBytes(32).toString('hex');
}
// التحقق في middleware
function csrfMiddleware(req: Request, res: Response, next: NextFunction) {
const token = req.headers['x-csrf-token'];
if (token !== req.session.csrfToken) {
return res.status(403).json({ error: 'CSRF validation failed' });
}
next();
}
5. إلغاء التسلسل غير الآمن (Insecure Deserialization)
يمكن أن يؤدي استخدام JSON.parse() أو eval() على بيانات غير موثوقة إلى تنفيذ كود عشوائي.
مثال ضعيف
function processData(data: string) {
const obj = eval('(' + data + ')');
// ...
}
النهج الآمن
function processDataSafe(data: string) {
try {
const obj = JSON.parse(data);
// التحقق الإضافي من النوع
if (typeof obj !== 'object' || obj === null)