وقتی ماجرای کارزار Deadbugz در اوت ۲۰۲۶ منتشر شد، اولین سؤال بیشتر تیمها این بود: «ما هم آسیب دیدیم؟» بیشترشان جوابی نداشتند. آن سرور MCP مخرب در سه فراخوانی اول مثل یک ابزار ساده برای قالببندی متن رفتار میکرد و تازه بعد از آن دستورهایی را که برای agent میفرستاد عوض میکرد. تیمی که چیزی جز «سرور وصل شد» لاگ نکرده بود، هیچ سابقهای نداشت از اینکه سرور چه گفت، agent بعدش چه کرد و به کدام فایلها دست زد. این راهنما همان تنظیمات لاگی است که کاش قبل از ممیزی MCP خودمان داشتیم: چه چیزی را ثبت کنید، کجا، و تا کی نگه دارید.
لاگ ممیزی MCP باید چه چیزهایی داشته باشد؟
لاگ ممیزی MCP باید اینها را ثبت کند: هر بار اجرای سرور با دستور دقیق و نسخهاش، هر تعریف ابزاری که سرور میفرستد و هر تغییری در آن، هر فراخوانی ابزار با آرگومانها و اندازهٔ نتیجه، هویت و scopeهای توکن پشت هر فراخوانی، و درخواستهای شبکهٔ خروجی. با کنار هم گذاشتن اینها میشود بازسازی کرد که agent چه کرد و از طرف چه کسی.
چرا لاگهای معمولی برنامه حملات MCP را نمیبینند
سرور MCP از دو کانال به سیستمهای شما راه دارد. کد اجرا میکند، و برای agent متن میفرستد، مثل نام ابزارها، توضیحاتشان و قالبهای prompt، که مدل آنها را دستور حساب میکند. بیشتر لاگها، اگر اصلاً باشند، فقط کانال اول را پوشش میدهند. محمولهٔ Deadbugz از کانال دوم آمد: دستورهای تازه در پاسخهای بعدی tools/list و prompts/get، بعد از اینکه یک شمارنده به سه فراخوانی رسید. موقع نصب هیچ چیز مشکوک به نظر نمیرسید. فقط لاگی که حرفهای سرور و زمان تغییرشان را نگه دارد، این را نشان میداد.
راهنمای security best practices خود پروتکل هم در چند جا همین را میگوید. سرویسهای proxy که سرورهای محلی را بالا میآورند باید «همهٔ استفادهها از stdio transport را برای پایش امنیتی لاگ کنند». سرورها باید رویدادهای افزایش scope را «همراه با correlation ID» ثبت کنند. کلاینتها باید «URLهای مشکوک authorization را لاگ کنند». و این سند هشدار میدهد که token passthrough ردّ ممیزی را خراب میکند، چون سرور دیگر نمیتواند کلاینتها را از هم تشخیص دهد و لاگهای پاییندست هویت اشتباه را نشان میدهند.
رویدادهایی که ارزش لاگ کردن دارند
| رویداد | فیلدهایی که باید ثبت شوند | چه چیزی را لو میدهد |
|---|---|---|
| اجرای سرور | دستور کامل با آرگومانها، نسخهٔ پکیج یا commit hash، فایل پیکربندیای که از آن آمده، کاربری که سرور با آن اجرا میشود | اجرای بدون نسخهٔ ثابت، سرورهایی که با یک pull request اضافه شدهاند، دستوری که عوض شده |
| تعریف ابزارها | hash و متن کامل هر پاسخ tools/list و prompts/list در هر نشست، با زمان | توضیحاتی که بعد از تأیید یا بعد از چند فراخوانی تغییر میکنند |
| فراخوانی ابزار | نام ابزار، سرور، آرگومانها (با حذف اسرار)، اندازهٔ نتیجه، مدت، خطا | ابزار قالببندیای که ناگهان فایل میخواند، الگوهای غیرعادی آرگومان |
| هویت و scopeها | کاربر انسانی، شناسهٔ نشست agent، audience و scopeهای توکن، correlation ID | توکنهایی با دسترسی بیش از حد، token passthrough، فراخوانیهایی که معلوم نیست مال کیست |
| افزایش scope | scope درخواستشده، بخشی که واقعاً داده شد، ابزاری که باعثش شد | بالا رفتن تدریجی دسترسی در طول یک نشست |
| درخواستهای خروجی | میزبان مقصد، پورت، حجم ارسالی، سرور یا ابزاری که درخواست را زد | خروج بیسروصدای داده، درخواست به آدرسهای metadata مثل 169.254.169.254 |
| دسترسی به فایل بیرون از پروژه | مسیر، خواندن یا نوشتن، پروسه | خواندن ~/.ssh، فایلهای اعتبارنامهٔ ابری، تاریخچهٔ shell |
تعریف ابزارها را لاگ کنید، نه فقط فراخوانیها را
این همان موردی است که بیشتر تیمها از قلم میاندازند. خروجی کامل tools/list و prompts/list را در شروع هر نشست ذخیره کنید، و دوباره بعد از چند فراخوانی، و hashها را با هم مقایسه کنید. تغییر توضیحات سروری که قبلاً تأیید کردهاید باید هشدار بدهد و دوباره به تأیید یک آدم نیاز داشته باشد؛ این همان توصیهای است که Pillar Security بعد از Deadbugz به سازندگان کلاینتهای MCP کرد. نگه داشتن متن کامل، نه فقط hash، برای تحقیق بعدی مهم است، چون همان توضیح تغییرکرده مدرک ماجراست.
لاگها کجا نگه داشته شوند
نه روی همان ماشینی که agent رویش اجرا میشود، و نه جایی که agent بتواند در آن بنویسد. اگر بشود agent را به پاک کردن فایلها کشاند، میشود به پاک کردن لاگ خودش هم کشاند. رویدادها را همان لحظه به بیرون از میزبان بفرستید. یک الگوی عملی: کلاینت MCP یا یک proxy محلی کوچک برای هر رویداد یک خط JSON در stdout بنویسد و log shipper فعلیتان آن را جمع کند، همانطور که لاگ کانتینرها باید به stdout برود، نه فایل. رویدادهای شبکه را بهتر است از یک egress proxy بگیرید تا از خود agent، چون پروسهای که نفوذ شده، خروج دادهاش را خودش گزارش نمیکند.
قبل از ذخیره، اسرار را حذف کنید
آرگومانها و نتیجههای ابزار دقیقاً همان چیزهایی را دارند که مهاجم دنبالش است: توکن، محتوای فایل، اطلاعات مشتری. الگوهای شناختهشدهٔ اسرار را قبل از نوشتن حذف کنید، بهطور پیشفرض به جای نتیجهٔ کامل فقط اندازهاش را نگه دارید، و محتوای کامل را فقط برای ابزارهایی که حساس علامت زدهاید، در مخزنی با دسترسی محدودتر ذخیره کنید. لاگ ممیزیای که اعتبارنامه نشت بدهد، خودش حادثهٔ بعدی میشود.
لاگهای MCP را تا کی نگه داریم
دستکم به اندازهٔ بقیهٔ لاگهای امنیتیتان، و آنقدر که فاصلهٔ بین حمله و افشای عمومیاش را پوشش دهد. pull requestهای Deadbugz روز ۱۰ اوت باز شدند و گزارشش ۱۲ اوت منتشر شد؛ کارزارهای دیگر ماهها بعد رو میشوند. اگر سیاست پاسخ به حادثهٔ شما از قبل برای لاگهای احراز هویت و endpoint دورهٔ نگهداری تعیین کرده، همان را به کار ببرید و برای ابزارهای هوش مصنوعی دورهٔ کوتاهتری درست نکنید.
یک راهاندازی حداقلی برای تیم کوچک
- از همهٔ سرورهای MCP فهرست بگیرید و نسخهٔ هر کدام را ثابت کنید، مثل چکلیست ممیزی ما.
- اجرای سرورها را داخل یک wrapper بگذارید تا دستور دقیق، نسخه و کاربر در هر نشست یک بار ثبت شود.
- در شروع نشست و بعد از فراخوانی سوم از tools/list و prompts/list عکس فوری بگیرید و با هر تغییر hash هشدار بدهید.
- هر فراخوانی ابزار را با آرگومانهای پاکسازیشده و اندازهٔ نتیجه لاگ کنید و کاربر انسانی و شناسهٔ نشست را رویش بزنید.
- ترافیک agent را از یک egress proxy با فهرست مجاز عبور دهید و لاگهایش را بیرون از میزبان نگه دارید.
همین اصل شکل ساخت دستیارهای داخلی ما را هم تعیین میکند: دستیار نباید قدرتی بیشتر از آدمی که برایش کار میکند داشته باشد، و هر پاسخ باید تا منبعش قابل ردیابی باشد. بخش دسترسی را در محدود کردن دستیار هوش مصنوعی داخلی به دسترسی همان کسی که سؤال میپرسد نوشتهایم. در FanMind، دستیار اسناد ما، درخواستهای خروجی از یک تونل با فهرست مجاز رد میشوند و اسناد محرمانه بهطور پیشفرض از ایندکس هوش مصنوعی کنار گذاشته میشوند. این هم سطح حمله را کوچک نگه میدارد و هم حجم لاگ را.
لاگ به شما میگوید چه اتفاقی افتاد. محدود کردن دسترسی agent تعیین میکند چقدر میتواند اتفاق بیفتد؛ مطلب AgentCorruption و دسترسیهای agentهای هوش مصنوعی را ببینید.
پرسشهای متداول
برای سرورهای MCP چه چیزهایی را لاگ کنم؟
هر اجرای سرور با دستور دقیق، نسخه و کاربر؛ متن کامل و hash هر پاسخ tools/list و prompts/list؛ هر فراخوانی ابزار با آرگومانهای پاکسازیشده و اندازهٔ نتیجه؛ کاربر انسانی، شناسهٔ نشست و scopeهای توکن پشت هر فراخوانی؛ رویدادهای افزایش scope؛ و درخواستهای شبکهٔ خروجی که سرور یا agent میزند.
چرا باید تعریف ابزارهای MCP را لاگ کرد؟
چون نام ابزارها، توضیحات و قالبهای prompt دستورهایی هستند که مدل اجرا میکند، و ممکن است بعد از تأیید یک سرور عوض شوند. سرور Deadbugz فقط بعد از سه فراخوانی ابزار محتوای ارسالیاش را تغییر داد. مقایسهٔ عکسهای فوری tools/list و prompts/list در طول نشست تنها راه دیدن این تغییر و اثبات این است که به agent چه گفته شد.
آیا مشخصات MCP لاگ ممیزی را الزامی کرده است؟
یک قالب واحد برای لاگ ممیزی تعریف نکرده، ولی security best practices آن در چند جا لاگ کردن را توصیه میکند: proxyها همهٔ استفادهها از stdio transport را برای پایش امنیتی لاگ کنند، سرورها رویدادهای افزایش scope را با correlation ID ثبت کنند، و کلاینتها URLهای مشکوک authorization را لاگ کنند. همچنین هشدار میدهد که token passthrough به ردّ ممیزی آسیب میزند.
لاگهای ممیزی MCP کجا ذخیره شوند؟
بیرون از میزبانی که agent رویش اجرا میشود و دور از دسترسی نوشتن agent، تا agentی که هدایتش را به دست گرفتهاند نتواند آنها را پاک کند. رویدادها را به صورت خطوط JSON در stdout بنویسید و با pipeline فعلی لاگتان منتقل کنید، و رویدادهای شبکه را از یک egress proxy بگیرید، چون پروسهٔ نفوذشده ترافیک خروجی خودش را با اطمینان گزارش نمیکند.
منابع
- Model Context Protocol: Security Best Practices
- Pillar Security: Deadbugz, an active MCP supply-chain campaign (۱۲ اوت ۲۰۲۶)
مشخصهٔ ژوئیهٔ ۲۰۲۶ مسیریابی و احراز مجوز را عوض کرد: راهنمای مشخصهٔ MCP 2026-07-28 را ببینید.


