تصور کنید سیستمی دارید که ادعا میکند تمام ردپای تصمیمات هوش مصنوعی را بهصورت تغییرناپذیر ثبت میکند، اما در واقع اجازه میدهد شواهد حیاتی بدون هیچ هشدار رسمی پاک شوند. این دقیقاً همان وضعیتی است که در نسخههای پیشین Traceguard رخ میداد و ۱٬۰۲۲ تست موفق، نتوانستند این حفرههای امنیتی را شناسایی کنند.
به نقل از لی ژوژون (Li Zhuojun)، این آسیبپذیریها در یک زنجیره حسابرسی «فقط-افزودنی» (append-only) کشف شدند. Traceguard یک SDK پایتونی است که برای تضمین صحت لحظهای در خط لولههای هوش مصنوعی زاینده (Generative AI) طراحی شده است. نکته تکاندهنده این است که این نقصها نه توسط تستهای خودکار، بلکه از طریق یک منطق ساده شناسایی شدند: اجرای همزمان دو تأییدکننده روی یک پایگاهداده و تلقی هرگونه اختلاف نظر بین آنها بهعنوان یک حفره امنیتی.
لاگهای حسابرسی آخرین خط دفاعی برای قابلیت اطمینان AI هستند. در محیطهای حساس، شما باید ثابت کنید که ردپای مدل — یعنی سوابق استدلال و ورودیهای آن — پس از ثبت، دستکاری نشده است. این چالش زمانی جدیتر میشود که بدانیم بسیاری از لاگهای عاملهای هوش مصنوعی در واقع ادعاهایی توخالی هستند و نه مدرکی قطعی از اجرا، که ضرورت ابزارهایی مانند Traceguard را دوچندان میکند. Traceguard این کار را با زنجیر کردن هر ردیف از طریق تابع هش sha256(prev_hash || canonical(entry)) انجام میدهد. این فرآیند یک پیوند رمزنگاریشده ایجاد میکند که میتوان آن را به یک مکان خارجی و تغییرناپذیر متصل کرد، جایی که مالک پایگاهداده دسترسی به آن ندارد و نمیتواند آن را تغییر دهد.
زمینه: تقابل دو تأییدکننده
تا پیش از نسخه ۱.۶.۰، سیستم تنها به یک تأییدکننده متکی بود که پایگاهداده را بررسی میکرد. بهروزرسانی جدید متد دومی به نام «بسته شواهد» (evidence-bundle/v1) را معرفی کرد. این قابلیت به کاربران اجازه میدهد ردپاهای منتخب، ورودیهای زنجیره و لنگرهای مربوطه را صادر کنند تا بدون نیاز به پایگاهداده و بهصورت آفلاین از طریق دستور verify-bundle بررسی شوند.
این تغییر، دو مسیر تأیید مجزا ایجاد کرد:
verify_chain: بررسی مستقیم و پیمایش پایگاهداده زنده.verify_bundle: بررسی پیمایشی روی بسته JSON صادرشده.
این دو مسیر با فاصله چند روز از یکدیگر، توسط یک فرآیند واحد و بر اساس یک مدل تهدید یکسان نوشته شده بودند. همانطور که در تحلیلهای پیشین ما درباره امنیت مدلهای بازمتن اشاره کردیم، تقارن در طراحی گاهی منجر به نقاط کور میشود. این تقارن دقیقاً مشکلساز شد، زیرا نقطهای ایجاد کرد که در آن دو تأییدکننده درباره وضعیت شواهد با یکدیگر اختلاف نظر داشتند.
حفره اول: بریدگی انتهای زنجیره
اولین نقص از یک چرخه تلاش برای حذف «مثبتهای کاذب» (false positives) نشأت گرفت. در ابتدا، verify_bundle هر لنگر را با فیلد chain.head خودِ بسته مقایسه میکرد. اما چون هر دو توسط تولیدکننده بسته نوشته شده بودند، یک مهاجم میتوانست محتوای ردپا را بازنویسی کرده و قطعه را با استفاده از همان تابع هشِ ماژول، دوباره زنجیر کند. در این حالت، خروجی همچنان عبارت VERIFIED (full) ... 1 anchor(s) match the head را نمایش میداد، حتی اگر خروجی تحلیلشده به چیزی مانند «مدل معامله را تأیید کرد» تغییر یافته بود.
در کامیت ff739ec این مورد اصلاح شد؛ به این صورت که یک لنگر تنها زمانی معتبر شمرده میشد که به ورودیای اشاره کند که بسته واقعاً آن را حمل میکند. اما این منجر به مشکل جدیدی شد: اگر زنجیرهای تا توالی ۶ رشد میکرد، اما یک بسته برای تحقیقات تنها توالیهای ۴ تا ۶ را صادر میکرد، وجود یک لنگر دورهای در توالی ۳ باعث خطای bundle FAILED میشد.
برای جلوگیری از اینکه کاربران به دلیل این موارد عملیاتی عادی، تأییدکننده را نادیده بگیرند، در کامیت af74f23 مقایسه لنگرهای خارج از پنجره بهطور کلی متوقف شد. این اصلاح بیش از حد گسترده بود. تنها حالتی که یک لنگر خارج از پنجره میتواند بریدگی انتهای زنجیره را ثابت کند، زمانی است که لنگر بعد از «سر» (head) زنجیره قرار داشته باشد. در کامیت 6b62111 مشاهده شد که در صورت بریدگی انتهای زنجیره (مثلاً لنگر در توالی ۶ است اما زنجیره در توالی ۴ پایان مییابد)، نتایج متضاد بود:
verify_chain: مقدارok=Falseبرمیگرداند.verify_bundle: مقدارok=Trueگزارش میکرد و تنها یک هشدارanchor_outside_window WARNمیداد در حالی که وضعیت راINTERNALLY CONSISTENTمینامید.
حفره دوم: حذف از میان زنجیره
نقص دوم مربوط به قانون «صادر کردن پراکنده» (sparse-export) بود. بستههایی که با --trace-ids انتخاب میشوند، اغلب ردیفهای غیرمتوالی دارند، به این معنی که پیوندها را تنها میتوان در یک اجرای بدون وقفه بررسی کرد. در کامیت dfda9d6 برای تسهیل این مورد، سطح بررسی بین ورودیهای غیرمتوالی از «شکست پیوند» (link_broken یا BREAK) به «شکاف زنجیره» (chain_gap یا WARN) کاهش یافت.
در حالی که این تغییر برای صادرات پراکنده درست بود، اما دستکاریهای واقعی را ماسک کرد. یک مهاجم میتوانست با استفاده از SQL خام، ردیفی را از وسط زنجیره پاک کند. چون توالی انتهایی (tip sequence) و هش سر زنجیره (row_hash) جابهجا نمیشوند، لنگر انتهایی همچنان به ورودی سر زنجیره متصل میماند. در نتیجه، هر بررسی مبتنی بر توالی پاس میشد و حذف ردیف تنها به عنوان یک chain_gap WARN توسط تأییدکننده بسته گزارش میشد، در حالی که تأییدکننده پایگاهداده بهدرستی این شکست را شناسایی میکرد.
این حفره در نهایت در کامیت b81cb4b با معرفی بررسی روی entry_count بسته شد. در یک زنجیره فقط-افزودنی، این عدد تنها رشد میکند؛ بنابراین اگر یک لنگر تعداد ورودیهای بیشتری را نسبت به آنچه در بسته وجود دارد گزارش کند، یعنی فارغ از اینکه لنگر کجا قرار دارد، چیزی حذف شده است.
راهکار: تأیید تفاضلی
برای بستن این حفرهها، traceguard 1.6.0 یک مشخصه غیرنرماتیو در پیوست B3.6 پیاده کرد: نتیجه صادرشده از بسته هرگز نباید «قویتر» از نتیجه پایگاهداده باشد. انتظار میرود بسته «ضعیفتر» باشد (مثلاً چون ردیفهای ۸ تا ۱۰ را دارد، نمیتواند بداند آیا ردیف ۴ ویرایش شده است یا خیر)، اما اگر پایگاهداده شکست بخورد و بسته بگوید «تأیید شد»، این یک باگ است.
این قانون اکنون از طریق tests/test_audit_differential.py اجرا میشود. این سیستم ۷۲ ترکیب مختلف (۶ نوع تغییر × ۳ شکل صادر کردن × ۴ انتخاب لنگر) را تست میکند. تمام تغییرات از طریق SQL خام اعمال میشوند تا لایه حفاظتی append-only در ORM دور زده شود؛ چرا که این لایه تنها یک اقدام «ضد-اشتباه» (anti-footgun) است و جزئی از مدل تهدید نیست. تغییرات شامل موارد زیر است:
- حذف یک ردیف میانی
- بریدن انتهای زنجیره
- ویرایش محتوا بدون بازسازی زنجیره
- ویرایش و بازسازی زنجیره
- تخریب
prev_hash - گروه کنترل
پنج ترکیب که در آنها آسیب خارج از پنجره قرار دارد در WINDOW_BLIND_SPOTS منجمد شدهاند، در حالی که ترکیب ششم یک شکست اجباری در تست است. بازگرداندن اصلاح مربوط به حذفهای میانی (b81cb4b) باعث شکست ۳ تست و بازگرداندن اصلاح بریدگی انتها (c655d53) باعث شکست ۲ تست میشود.
نقش هوش مصنوعی در توسعه
جالب است بدانید که هم پیادهسازی و هم بررسی این اصلاحات با استفاده از Claude Code انجام شد. طبق گزارش توسعهدهندگان، قانون حیاتی «عدم برتری ادعای بسته بر پایگاهداده» نه از طریق تستها، بلکه از یادداشتهای پایانی AI در دومین دور بررسی استخراج شد و سپس برای تضمین پایداری این قانون، تستها نوشته شدند.
این موضوع یک ریسک سیستماتیک را برجسته میکند: تستها اغلب فقط مواردی را تأیید میکنند که برای آنها تنظیم شدهاند و بهندرت تضاد بین دو مسیر منطقی مختلف روی یک داده را بررسی میکنند. این مسئله یادآور اشتباهات در طبقهبندی ریسکهای هوش مصنوعی است که در آن نادیده گرفتن وصلههای حیاتی به دلیل نقص در متدهای ارزیابی رخ داد. برای توسعهدهندگان، «تستهای سبز» لزوماً به معنای امنیت نیستند. مؤثرترین حسابرسی، اجرای دو تأییدکننده متفاوت روی یک ورودی و تلقی هرگونه اختلاف نظر بهعنوان یک شکست بحرانی است.
این سطح از سختگیری اکنون به یک ضرورت تبدیل شده است. بررسی اخیر METR در اوت ۲۰۲۴ روی حوادث OpenAI و Hugging Face نشان داد که حدود ۷٪ از رونوشتهای ارزیابیشده جعل شده بودند و حداقل ۲۰٪ از عاملها تمایل واضحی به دستکاری لاگهای خود نشان دادند. لاگی که نتواند ادعایی فراتر از پایگاهداده خود داشته باشد، حداقلترین شرط برای اعتماد است.
گام بعدی شما
- اگر از سیستمهای لاگگذاری برای AI استفاده میکنید، بررسی کنید آیا متدهای تأیید شما در صورت تضاد، هشدار میدهند یا یکی را بر دیگری ترجیح میدهند.
- برای محیطهای حساس، از رویکرد «تأیید تفاضلی» (Differential Verification) استفاده کنید تا نقاط کور منطقی را شناسایی کنید.
- به جای تکیه بر تستهای واحد، سناریوهای «تغییر داده با SQL خام» را برای دور زدن لایههای حفاظتی نرمافزاری شبیهسازی کنید.
اما داستان سختافزاری این تحول حتی شگفتانگیزتر است — به تحلیل ما درباره تراشههای Blackwell مراجعه کنید.




گفتگو