بسیاری از تیمهای فنی پس از مشاهدهی نمونههای نفوذ به مدلهای زبانی، با نوشتن یک عبارت باقاعدهی ساده در ورودی چتبات، تصور میکنند جلوی حملات تزریق پرامپت (Prompt Injection) را گرفتهاند. با این حال، مهاجم با کوچکترین تغییر در واژگان یا استفاده از روشهای رمزگذاری مانند Base64، این دفاع صوری را دور میزند؛ چرا که چنین سدهایی هیچگاه با معیارهای عددی و دادههای آزمایشی استاندارد سنجیده نشدهاند.
حل اصولی این چالش مستلزم پیادهسازی شناساگری مهندسیشده و سنجشپذیر است. در این درس یاد میگیرید که چگونه یک خط لولهی چندلایه شامل پیشپردازش و خنثیسازی انکودینگها، قواعد انطباق زیررشتهای و الگوهای منعطف ریجکس بسازید. در نهایت، با استفاده از ماتریس درهمریختگی، دقت (Precision) و بازخوانی (Recall) را برای دستههای مختلف ارزیابی میکنید تا بهجای تصمیمگیری بر اساس حدس و گمان، عملکرد سیستم دفاعی را با دادههای تجربی رصد کنید.
شناساگر (Detector) تابعی است که با دریافت پرامپت، میزان اطمینان و دستهبندی موضوعی برمیگرداند. هر چیزی غیر از این، صرفاً یک حسوحال مبهم است.
مسئله
تیمی در شبکههای اجتماعی مطلبی دربارهی یک جیلبریک (Jailbreak یا شکستن قفل ایمنی) میخواند، یک عبارت باقاعده (Regex) ساده مثل r"ignore (all )?previous" مینویسد، آن را به پروداکشن میفرستد و اسمش را دفاع در برابر تزریق پرامپت (Prompt injection) میگذارد. دو هفته بعد، همان حمله با عبارت "disregard the prior" پیاده میشود؛ ریجکس آن را رد میکند و تیم مدل را مقصر میداند. این شناساگر هیچوقت در برابر هیچ معیاری سنجیده نشده بود. هیچکس دقت (Precision) آن را نمیداند. هیچکس از بازخوانی (Recall) آن خبر ندارد. هیچکس نمیداند چه دستههایی را پوشش میدهد. این ریجکس صرفاً یک تکه (Patch) نمایشی برای ایجاد حس امنیت کاذب است.
نسخهی صادقانهی یک شناساگر، تابعی با رفتار قابلاندازهگیری است. این تابع با دریافت یک پرامپت، میزان اطمینانی در بازهی [0, 1] و مناسبترین دستهبندی موضوعی را برمیگرداند. فریمورک با دریافت یک مجموعهدادهی برچسبخورده، شناساگر را روی تکتک نمونههای آزمایشی اجرا میکند، نتایج را برای هر دسته به مثبت واقعی، مثبت کاذب، منفی واقعی و منفی کاذب تفکیک میکند و در نهایت دقت و بازخوانی را گزارش میدهد. تیم با دیدن دقت و بازخوانی تصمیم میگیرد چه چیزی را روانهی پروداکشن کند، اسپرینت بعدی را صرف چه کاری کند و دست از حدس و گمان برمیدارد.
در این پروژهی پایانی، یک شناساگر چندلایه میسازیم: قواعد قطعی زیررشتهای، ریجکسهای سطح توکن، و یک مرحلهی نرمالسازی که پیش از اجرای قواعد، انکودینگهای ساده (base64، rot13، leet و نویسههای با عرض صفر) را رمزگشایی (Decode) میکند. هر لایه بهطور مستقل قابل بازبینی است. هر قاعده ادعای پوشش مشخصی برای هر دسته دارد. رانر سیستم یک ماتریس درهمریختگی (Confusion Matrix) به ازای هر دسته و یک فایل CSV تولید میکند که درسهای بعدی میتوانند نمودار آن را رسم کنند.
مفاهیم کلیدی
شناساگر در اینجا فهرستی از اشیای Rule است. هر قاعده یک name، یک category و تابعی بهشکل score(prompt) -> float in [0, 1] دارد. یک قاعده یا فعال میشود یا نمیشود. وقتی فعال شد، امتیاز آن همان میزان اطمینانش است. بخش تجمیعکننده امتیازهای تکتک قواعد را در قالب یک حکم نهایی (Verdict) فشرده میکند که شامل category (دستهای با بالاترین امتیاز) و confidence (بیشترین امتیاز در آن دسته) است. پرامپتی که هیچ قاعدهای برایش فعال نشود، امتیاز 0.0 میگیرد و برچسب benign (بیخطر) میخورد.
سه لایه داریم که به ترتیب اعمال میشوند:
-
نرمالسازی (Normalize). حذف نویسههای با عرض صفر و کنترلکنندههای جهت متن (Bidi). ساخت یک نسخهی کاری با حروف کوچک. رمزگشایی توکنهایی که شبیه base64، rot13 یا hex هستند. جایگزینی ارقام لیتاسپیک (Leet-speak) با حروف معادلشان. پرامپت اصلی را در کنار نسخهی نرمالشده نگه میداریم؛ چون برخی قواعد باید بایتهای خام را بررسی کنند (وجود نویسههای با عرض صفر، خود یک سیگنال هشدار است).
-
قواعد زیررشتهای (Substring rules). الگوهای دستنویسی مثل
"ignore previous"،"as an unrestricted"،"answer starting with"یا"sure, here is". هر الگو یک دسته و یک امتیاز پایه دارد. این قاعده روی متن خام یا نرمالشده اجرا میشود. -
قواعد ریجکس (Regex rules). الگوهای سطح توکن که خانوادهای از حملات را پوشش میدهند. الگوی
r"\bignor\w*\s+(all|prior|previous|earlier)\b"خانوادهای از دستورهای نادیدهگرفتن پرامپت قبلی را پوشش میدهد. الگویr"\b(decode|rot13|base64|hex)\b.*\banswer\b"ترفندهای مبتنی بر انکودینگ را شکار میکند. هر ریجکس شامل یک دسته و یک امتیاز پایه است.
رانرِ محاسبهی معیارها، دستسازه (Artifact) ردهبندی درس 82 را میگیرد، شناساگر را روی تکتک نمونهها اجرا میکند و دقت و بازخوانی هر دسته را به دست میآورد. برچسب دستهی هر پرامپت، همان دستهی نمونهی آزمایشی است؛ دستهی پیشبینیشدهی شناساگر نیز دستهی حکم نهایی است. مثبت واقعی برای دستهی C یعنی دستهی نمونه برابر C و دستهی پیشبینی هم C باشد. مثبت کاذب یعنی دستهی نمونه برابر C نباشد ولی دستهی پیشبینی C باشد. منفی کاذب یعنی دستهی نمونه برابر C باشد ولی دستهی پیشبینی C نباشد (یا benign باشد). این رانر فهرستی از پرامپتهای بیخطر را هم میگیرد تا مثبتهای کاذب روی متنهای سالم نیز ارزیابی شوند.
این شناساگر بهتنهایی گیت ایمنی نیست، بلکه فقط یکی از چندین سیگنالی است که گیت نهایی ترکیب خواهد کرد. شناساگر طبق طراحی خود، در دستههای ترفند انکودینگ و لغو دستورالعمل به سمت بازخوانی بالاتر تمایل دارد و دقت متوسط در دستهی نقشآفرینی (Role-play) را میپذیرد؛ چرا که حملات نقشآفرینی مرز باریکی با درخواستهای قانونی نویسندگی خلاق دارند و گیت ایمنی برای موارد مرزی از سیگنالهای دیگر (موتور قوانین، طبقهبند) استفاده خواهد کرد.
ساخت سیستم
بخش بارگذاری مجموعهداده، فایل outputs/taxonomy.json از درس 82 را میخواند. قواعد بهشکل داده و نه کد در فایل code/rules.py قرار دارند. هر قاعده یک دیکشنری است که کلیدهای name، category، score و یکی از دو مورد substring یا regex را دارد. کلاس شناساگر آنها را یک بار کامپایل میکند.
مرحلهی نرمالسازی از re.sub و codecs در کتابخانهی استاندارد پایتون استفاده میکند. نرمالسازی Base64 تلاش میکند هر توکن بالای 16 نویسه را که شبیه base64 است رمزگشایی کند؛ در صورت موفقیت، توکن را با رشتهی رمزگشاییشدهی UTF-8 جایگزین میکند. نرمالسازی Rot13 با استفاده از codecs.encode(text, 'rot_13') یک خروجی کاندید میسازد و فقط زمانی آن را نگه میدارد که تعداد واژههای معنادار آن بیشتر از ورودی باشد (یک روش هیوریستیک سبک با تکیه بر فهرستی کوچک از کلمات توکار).
رانر معیارها یک گزارش JSON شامل دقت، بازخوانی، F1 و شمارشهای خام برای هر دسته تولید میکند. شناساگر در مواجهه با برخی نمونهها عمداً اشتباه میکند (بهویژه پرامپتهای نقشآفرینی که بیخطر به نظر میرسند)؛ گزارش این موضوع را بهجای پنهانکردن، کاملاً شفاف نشان میدهد.
شیوهی استفاده
دستور python3 main.py را اجرا کنید. این دمو ردهبندی را لود میکند، شناساگر را روی تکتک نمونهها و همچنین مجموعهای از پرامپتهای بیخطرِ تعریفشده در benign.py اجرا میکند و معیارهای تفکیکشدهی هر دسته را در خروجی مینویسد. فایل outputs/detector_report.json دستسازهای است که گیت ایمنی درس 87 به آن تکیه میکند.
تحویل پروژه
فایل outputs/skill-prompt-injection-detector.md ساختار قواعد و نحوهی اضافه کردن یک قاعدهی جدید را مستند میکند.
تمرینها
- خانوادهای از قواعد برای قاچاق کانتکست (Context-smuggling: دستورهای پنهان در JSON خروجی ابزارها) اضافه کنید. میزان بهبود بازخوانی و هزینهی مثبتهای کاذب روی پرامپتهای بیخطر را اندازه بگیرید.
- سهم هر قاعده را حساب کنید: برای هر قاعده بشمارید که اگر حذف شود، چند مثبت واقعی از دست میرود. سپس قواعد را بر اساس سهم نهاییشان مرتب کنید.
- یک پیچ تنظیم آستانه (
confidence_threshold) اضافه کنید. مقدار آن را از 0 تا 1 تغییر دهید و نمودار دقت-بازخوانی را برای هر دسته رسم کنید.
اصطلاحات کلیدی
| اصطلاح | کاربرد رایج | معنای دقیق |
|---|---|---|
| شناساگر (detector) | مدلی که جلوی حملات را میگیرد | تابعی که دسته و میزان اطمینان را برمیگرداند و با دقت و بازخوانی ارزیابی میشود |
| نرمالسازی (normalize) | یک مرحلهی پیشپردازش | تبدیلی که توکنهای مخفی را برای بررسی در قواعد بعدی آشکار میکند |
| ماتریس درهمریختگی (confusion matrix) | یک جدول 2 در 2 | تفکیک TP ،FP ،TN و FN به ازای هر دسته که برای محاسبهی دقت و بازخوانی استفاده میشود |
| دقت (precision) | درستیِ کلی | نسبت تشخیصهای درست به کل موارد شناساییشده: TP / (TP + FP) |
| بازخوانی (recall) | پوشش کلی | نسبت حملات شکارشده به کل حملات موجود: TP / (TP + FN) |
مطالعهی بیشتر
درسهای 84 تا 87 از این سرفصل. شناساگری که اینجا ساختیم، در کنار فیلتر توکن، طبقهبند و موتور قوانین، یکی از چهار سیگنالی است که گیت نهایی سرتاسری از آنها بهره میبرد.
