تصور کنید برنامهنویسی هستید که برای تسریع پروژه، بخشهای زیادی از کد را به هوش مصنوعی سپردهاید و حالا متوجه میشوید هر کاربر ثبتنامشده میتواند صورتحسابهای تمام مشتریان شما را ببیند. این کابوس امنیتی، نتیجهٔ یکی از خطرناکترین خطاهای منطقی در کدهای تولیدشده توسط هوش مصنوعی است.
طبق راهنمای فنی منتشرشده در ۲۵ اوت ۲۰۲۶ در وبسایت dev.to، ریشهٔ این مشکل در نادیده گرفتن تفاوت میان «احراز هویت» (Authentication) و «مجوز دسترسی» (Authorization) است. بسیاری از توسعهدهندگان تصور میکنند اگر درخواستی از فیلتر احراز هویت عبور کند، سیستم امن است؛ اما احراز هویت فقط تایید میکند که کاربر «کیست»، در حالی که مجوز دسترسی تعیین میکند که آیا آن کاربر خاص اجازهٔ دسترسی به یک منبع خاص را دارد یا خیر. مدلهای هوش مصنوعی اغلب در بخش اول (احراز هویت) عالی عمل میکنند، اما در بخش دوم (مجوز دسترسی) بهطور خاموش و نامحسوس کوتاهی میکنند.
این نقص منجر به ایجاد آسیبپذیری BOLA (Broken Object Level Authorization) یا همان IDOR (Insecure Direct Object Reference) میشود. در یک سناریوی BOLA، کاربر میتواند شناسهی یک منبع را در URL تغییر دهد — مثلاً /invoices/123 را به /invoices/124 تبدیل کند — و بدون هیچ مانعی، دادههای خصوصی مشتری دیگری را مشاهده کند. اگر تغییر این ID به کاربر اجازه دهد صورتحساب شخص دیگری را ببیند، یعنی احراز هویت هیچ نقشی در محافظت از دادهها نداشته است.
همانطور که در تحلیلهای قبلی ما دربارهی امنیت مدلهای بازمتن اشاره کردیم، مدلها تمایل دارند الگوهای رایج را تکرار کنند بدون آنکه منطقِ پشت آنها را درک کنند.
کالبدشکافی باگهای هوش مصنوعی
ابزارهای هوش مصنوعی روی الگوهای متداول برنامهنویسی آموزش دیدهاند و معمولاً کدهایی با این ساختار تولید میکنند:
- یک بررسی احراز هویت:
return head :unauthorized unless current_user - یک جستوجوی منبع:
@invoice = Invoice.find(params[:id])
به نقل از گزارش dev.to، هر یک از این خطوط بهتنهایی درست هستند، اما ترکیب آنها بیپروا است. کد تایید میکند که کاربر وارد حساب خود شده است، اما هرگز نمیپرسد: «آیا این صورتحساب متعلق به این کاربر است؟»
چرا هوش مصنوعی این الگو را تکرار میکند؟
مدلهای کدنویسی در بازتولید الگوهای استاندارد بسیار موفقاند. یک اکشن در کنترلر که رکوردی را بر اساس ID بارگذاری میکند، یک الگوی استاندارد است. همچنین بررسی احراز هویت که در صورت عدم وجود کاربر، هدر unauthorized را برمیگرداند نیز یک الگوی استاندارد است.
مشکل اینجاست که هوش مصنوعی این دو الگوی رایج را بدون تحلیل رابطهی میان «کاربر احراز هویتشده» و «شیء در حال بارگذاری» در کنار هم قرار میدهد. شکست در اینجا به معنای نبود کامل امنیت نیست، بلکه به این معناست که امنیت وجود دارد اما روی منبع خاص اعمال نمیشود. همین موضوع باعث میشود شناسایی این باگ در بازبینیهای سریع بسیار دشوار باشد، زیرا کد کوتاه است، خوانایی بالایی دارد و فاقد آسیبپذیریهای آشکار مانند تزریق کد (Injection) است.
شکست تستهای خودکار
مجموعهٔ تستهای تولیدشده توسط هوش مصنوعی اغلب این سوءتفاهم را تقویت میکنند. مدل معمولاً تستی مینویسد که تایید کند کاربر احراز هویتشده میتواند به صورتحساب «خودش» دسترسی داشته باشد. این مسئله نشان میدهد که چرا تستهای عملکردی بهتنهایی برای کدهای AI کافی نیستند و میتوانند لایههای امنیتی را نادیده بگیرند.
برای مثال، یک تست معمولی تولیدشده توسط AI ممکن است به این شکل باشد:it "returns an invoice for an authenticated user" do sign_in(user); get "/invoices/#{invoice.id}"; expect(response).to have_http_status(:ok) end
وقتی این تست سبز میشود، توسعهدهنده دچار احساس امنیت کاذب میشود. اما این تست تقریباً هیچ چیزی دربارهٔ مجوز دسترسی (Authorization) ثابت نمیکند.
برای شناسایی BOLA، توسعهدهندگان باید «تست منفی» (Negative Testing) را اجرا کنند. این کار مستلزم یک مورد تست خاص است: تایید اینکه یک کاربر وارد شده، «نمیتواند» به صورتحساب متعلق به کاربر دیگری دسترسی یابد. یک تست ضروری باید به این شکل باشد:it "does not allow a user to access another user's invoice" do sign_in(user); get "/invoices/#{other_users_invoice.id}"; expect(response).to have_http_status(:not_found) end
بدون این تست، یک مجموعه تست سبز رنگ تقریباً هیچ چیزی را درباره امنیت واقعی منبع ثابت نمیکند. در واقع، یک مجموعه تست میتواند با وفاداری کامل، همان سوءتفاهمی را تایید کند که در وهله اول باعث تولید آن کد ناقص شده است.
پیادهسازی الگوی امن
امنترین راه برای جلوگیری از این مشکل، محدود کردن دسترسی به دادهها بر اساس محدودهٔ (Scope) مجاز کاربر است. بهجای جستوجوی سراسری در دیتابیس، کد باید منبع را از طریق رابطهی کاربر پیدا کند.
بهعنوان مثال، استفاده از @invoice = current_user.invoices.find(params[:id]) تضمین میکند که خودِ عملیات جستوجو، مرز مالکیت را رعایت کند. در این حالت، اگر منبع خارج از محدوده کاربر باشد، کوئری بلافاصله شکست میخورد. در واقع، منبع از همان ابتدا خارج از محدوده قابل جستوجو قرار میگیرد، بهجای آنکه بعداً در یک دستور if با شکست مواجه شود.
مرزهای مجوز دسترسی
در حالی که محدوده current_user یک راهکار رایج است، اما پیادهسازی آن بسته به پیچیدگی سیستم متفاوت است. مرزهای مجوز دسترسی میتوانند از طریق موارد زیر اعمال شوند:
- اشیاء سیاستگذاری (Policy objects)
- محدودههای مستاجری (Tenant scopes)
- سرویسهای مجوز (Permission services)
- قوانین دامنه (Domain rules)
پیادهسازی خاص کمتر اهمیت دارد و آنچه حیاتی است، پاسخ به این سوال در بازبینی است: «آیا میتوانم مسیر مجوز کاربر را تا آخرین شیء مورد دسترسی ردیابی کنم؟» اگر این ردپایی وجود ندارد، باید با آن به عنوان یک یافتهی امنیتی (Security Finding) برخورد کرد.
پروتکل بازبینی امنیتی
بازبینی کدهای هوش مصنوعی نیازمند تغییر در نوع پرسش است. بهجای پرسیدن «آیا احراز هویت وجود دارد؟»، بازبینها باید بپرسند: «آیا مجوز دسترسی برای این عملیات دقیق روی این منبع خاص اعمال شده است؟»
این عبارت دقیق، بازبین را از تکیه به حضور آرامبخش میانافزارها (Middleware)، بررسی نقشها و کمککنندههای احراز هویت دور میکند. بر اساس گزارش dev.to، یک مسیر دسترسی امن باید به این شکل قابل ردیابی باشد:
درخواست $ \rightarrow $ کاربر احراز هویتشده $ \rightarrow $ تصمیم مجوز دسترسی $ \rightarrow $ منبع خاص $ \rightarrow $ دسترسی به داده
اگر پرشی مستقیم از کاربر احراز هویتشده به یک دستور سراسری مانند Model.find(params[:id]) وجود داشته باشد، کد تا زمانی که خلاف آن ثابت نشود، یک یافته امنیتی است. پاسخ «احراز هویت در جای دیگری مدیریت شده است» پذیرفتنی نیست، مگر اینکه بازبین دقیقاً بررسی کند کجا و چگونه این کار انجام شده است.
پرامپتنویسی پیشرفته برای امنیت
برای کاهش این ریسک، توسعهدهندگان میتوانند از پرامپتهای صریحی استفاده کنند که هوش مصنوعی را مجبور میکند در نقش یک «کاربر بدخواه اما معتبر» عمل کند؛ یعنی کاربری که از قبل اعتبارنامهها (Credentials) را دارد اما قصد تخطی دارد.
این رویکرد پاسخهای ساده را حذف کرده و مدل را مجبور میکند به دنبال موارد زیر بگردد:
- دستکاری پارامترها (Parameter manipulation)
- جایگزینی ID اشیاء (Object ID substitution)
- ارتقای غیرمجاز سطح دسترسی (Permission escalation)
- ترکیب دو رفتار جزئی برای ایجاد یک آسیبپذیری جدی
در یکی از بخشهای «بررسی عمیق امنیتی»، پرامپتی استفاده شده که از AI میخواهد هر منبعی که با ID دسترسی پیدا میکند را بازبینی کرده و شناسایی کند چه کسی اجازه دسترسی به آن را دارد، در حالی که صراحتاً به AI هشدار میدهد که احراز هویت را بهتنهایی به عنوان مجوز دسترسی تلقی نکند. این پرامپت از AI میخواهد برای هر یافته، شدت خطر، شماره فایل/خط، مسیر اکسپلویت و یک اصلاح حداقلی ارائه دهد.
برای جلوگیری از توهم (Hallucination) — یعنی وقتی مدل با اطمینان چیزی را میگوید که وجود ندارد — پرامپت به AI دستور میدهد که فرضهای خود را درباره میانافزارها یا پیشفرضهای فریمورک ذکر کرده و آنها را برای تایید علامتگذاری کند، بهجای آنکه بر اساس پیکربندیهای خیالی، آسیبپذیری ابداع کند.
نقاط پرخطر برای بازبینی
بیشترین زمان بازبینی باید صرف بخشهایی شود که تفاوت میان «وارد شدن به سیستم» و «اجازه داشتن» در آنها بیشترین تضاد را دارد، از جمله:
- رکوردهای متعلق به کاربر
- حسابها و سازمانها
- دادههای چندمستاجری (Multi-tenant)
- بخشهای صورتحساب و قابلیتهای مدیریت (Admin)
- خروجیها (Exports) و دسترسی به فایلها
- APIهایی که ID شیء را میپذیرند
- جابهای پسزمینه (Background jobs) که به نمایندگی از کاربران عمل میکنند
- هر عملیاتی که شامل دادههای مشتری است
این الگوی شکست، یکی از اجزای اصلی مرحله «بررسی عمیق امنیتی» (دور دوم) در پروتکل بازبینی کد AI است. این موضوع تاکید میکند که باگهای AI همیشه خطاهای نحوی دراماتیک مانند eval() یا افشای رمزها در متن ساده نیستند؛ بلکه اغلب رابطههای گمشده میان «این کاربر»، «این عملیات» و «این منبع» هستند. این نوع نقصهای منطقی مشابه حفرههای امنیتی در مدلهای تأیید اقدام است که در آن سیستم به اشتباه اجازه دسترسی یا تایید عملیاتی را میدهد.
گام بعدی شما
- تمام متدهای
findیاgetکه از ورودی کاربر (params) استفاده میکنند را در پروژه خود بررسی کنید. - تستهای منفی را به چرخه CI/CD خود اضافه کنید تا دسترسیهای غیرمجاز بهصورت خودکار شناسایی شوند.
- در پرامپتهای بازبینی کد، صراحتاً از مدل بخواهید تفاوت Authentication و Authorization را در هر تابع بررسی کند.
اما داستان سختافزاری این تحول حتی شگفتانگیزتر است — به تحلیل ما دربارهی تراشههای Blackwell مراجعه کنید.




گفتگو