اگر امروز کدهای تولیدشده توسط هوش مصنوعی را بدون بازبینی مستقیم به محیط عملیاتی میفرستید، احتمالاً درهای پشتی سرور خود را برای مهاجمان باز گذاشتهاید. کدها ممکن است در ظاهر بهدرستی کار کنند، اما منطق آنها بهندرت برای استقرار امن مناسب است. این تنش در یک راهنمای فنی که در ۳۰ اوت ۲۰۲۶ در وبسایت dev.to منتشر شد، برجسته شد؛ این گزارش فاش کرد که دستیارهای هوش مصنوعی بهطور سیستماتیک بخشهای «کسلکننده» مهندسی نرمافزار — بهویژه مدیریت اسرار (Secrets)، بهداشت وابستگیها و بررسیهای احراز هویت — را حذف میکنند. این موضوع در کنار ریسکهای نفوذ عاملهای هوش مصنوعی از طریق مستندات وبسایتها که پیشتر بررسی شد، نشان میدهد که اعتماد کورکورانه به خروجیهای AI میتواند حفرههای امنیتی جدی ایجاد کند.
این اتفاق به این دلیل رخ میدهد که مدل زبانی بزرگ (LLM) — مثل کتابخانهداری که میلیاردها صفحه را خوانده و حالا با همان لحن کتابها جواب میدهد — برای «مسیر موفق» (Happy Path) بهینه شده است. یعنی مدل تضمین میکند ویژگی مورد نظر در شرایط ایدهآل کار کند، اما لبههای تیز و موارد استثنایی (Edge Cases) که منجر به رخنه امنیتی میشوند را نادیده میگیرد. برای توسعهدهندگانی که در حال Vibe Coding (کدنویسی بر اساس حس و شهود بدون ساختار سختگیرانه) روی پروژههای جانبی هستند، این وضعیت توهم خطرناکی از تکمیل پروژه ایجاد میکند؛ جایی که یک رابط کاربری زیبا، یک بکاند کاملاً باز و آسیبپذیر را میپوشاند. نویسنده اشاره میکند که این الگوها بهصورت کیفی از مخازن کد خود او توصیف شدهاند؛ اینها آمار نیستند، بلکه چکلیستی از اشتباهات تکراری هستند.
تصور کنید دکمهای برای «حذف همه دادهها» پشت یک صفحه ورود پنهان شده است. از نظر توسعهدهنده، این ویژگی امن است چون کاربر ابتدا باید وارد شود تا دکمه را ببیند. اما اگر مسیر API مربوطه فاقد بررسی نشست (Session) در سمت سرور باشد، هر کاربری با یک دستور ساده curl میتواند بدون ورود به سیستم و بدون دیدن رابط کاربری، کل پایگاه داده را پاک کند.
مشکل نشت اسرار (Secret Leakage)
یکی از رایجترین شکستها، باقی ماندن کلیدهای محرمانه در تاریخچه گیت است. توسعهدهندگان اغلب یک کلید API را در فایل .env قرار میدهند تا ویژگی را تست کنند، سپس این فایل را به .gitignore اضافه میکنند و تصور میکنند ایمن هستند. اما چون گیت تاریخچه را حفظ میکند، آن کلید برای همیشه در کامیتهای قبلی در دسترس میماند و هر کسی به مخزن دسترسی داشته باشد میتواند آن را بازیابی کند.
طبق مستندات این راهنما، برای شناسایی این موارد باید یک جستوجوی بازگشتی (recursive grep) برای الگوهای رایج مانند api_key ،secret ،token ،password یا BEGIN PRIVATE KEY در پسوندهای پشتیبانیشده شامل .js ،.ts ،.jsx ،.tsx ،.py ،.env ،.json ،.yml و .yaml اجرا کنید.
برای یافتن کلیدهای پنهان در تاریخچه، نویسنده پیشنهاد میکند بررسی کنید که آیا فایل .env هرگز کامیت شده است یا خیر؛ این کار با دستور git log --all --full-history -- "*.env" ".env" انجام میشود. همچنین میتوان برای جستوجوی شکلهای خاص کلیدها (مانند کلیدهای AKIA در سبک AWS یا رشتههای هگزادسیمال عمومی) از دستور git rev-list --all | xargs git grep -nE "AKIA[0-9A-Z]{16}|[a-f0-9]{32,}" استفاده کرد.
اگر کلیدی پیدا شد، تنها راه حل واقعی «چرخش کلید» (Key Rotation) یا تغییر فوری آن است؛ زیرا آن کلید باید «سوخته» تلقی شود. پاکسازی تاریخچه گیت از طریق ابزارهایی مانند git filter-repo یک وظیفه تکمیلی است که میتواند بعداً انجام شود، اما اولویت اول باید ابطال کلید قدیمی باشد.
افشای دادهها در سمت کلاینت
فریمورکهای فرانتاند از پیشوندهای خاصی برای علامتگذاری متغیرهای امن در مرورگر استفاده میکنند. در Next.js این پیشوند NEXT_PUBLIC_ است؛ سایر فریمورکها از VITE_ ،REACT_APP_ یا PUBLIC_ استفاده میکنند. دستیارهای هوش مصنوعی بهکرات در مدیریت اینها اشتباه میکنند و بهطور تصادفی یک کلید خصوصی نقش سرویس (Service-role) را با یک پیشوند عمومی در یک فراخوانی fetch قرار میدهند.
این اشتباه باعث میشود کلید خام به مرورگر هر بازدیدکنندهای ارسال شود و از طریق View Source یا تب Network در ابزارهای توسعه مرورگر قابل مشاهده باشد. برای مثال، استفاده از Authorization: Bearer ${process.env.NEXT_PUBLIC_SERVICE_KEY} در یک fetch سمت کلاینت، کلید شما را در معرض دید جهانی قرار میدهد.
قوانین پیشوندهای عمومی:
- قاعده کلی: پیشوند
PUBLICیعنی «من مشکلی ندارم که تمام دنیا این را بخوانند». - موارد امن: کلیدهای منتشرشدنی یا ناشناس (Anonymous Keys) که دقیقاً برای استفاده در سمت کلاینت طراحی شدهاند.
- موارد ناامن: کلیدهای نقش سرویس (Service-role)، کلیدهای خصوصی API و هر چیزی که قادر به خواندن یا نوشتن دادههای کاربران دیگر باشد.
توسعهدهندگان باید کدهای سمت کلاینت خود را برای این پیشوندها grep کنند و هر مورد را برای کلماتی مانند "secret"، "service"، "admin" یا "private" بررسی کنند. هر عملیات حساس باید به یک مسیر سرور (Server Route) یا اکشن سرور (Server Action) منتقل شود تا اطمینان حاصل شود که مرورگر هرگز مقدار خام را نمیبیند.
شکاف در حفاظهای احراز هویت (Auth Guard)
مسیرهای API تولیدشده توسط AI اغلب فاقد تایید نشست هستند. یک اشتباه رایج این است که توسعهدهنده به رابط کاربری برای محافظت از مسیر تکیه میکند، نه به خودِ هندلر مسیر. یک LLM ممکن است مسیری مانند app/api/admin/users/route.ts بسازد که صرفاً db.user.findMany() را برمیگرداند بدون اینکه هیچ بررسی احراز هویتی انجام دهد، و در نتیجه آن را به یک URL عمومی تبدیل کند که هر کسی با دانستن آدرس به آن دسترسی دارد.
برای شناسایی این شکافها، توسعهدهندگان باید تمام فایلهای زیر پوشه /api/ را لیست کرده و بپرسند: «اگر غریبهای بدون کوکی به این URL درخواست بفرستد، چه اتفاقی میافتد؟»
- ریسک: نقاط انتهایی مانند
/api/admin/usersممکن است لیست کامل کاربران را به درخواستهای احرازنشده برگردانند. - راهکار: پیادهسازی بررسی نشست در ابتدای هندلر. کد باید ابتدا نشست را تایید کرده و در صورت نبود آن، خطای
401 Unauthorizedیا در صورت نبود نقش ادمین، خطای403 Forbiddenبرگرداند، پیش از آنکه هرگونه دادهای واکشی شود.
برای یافتن این موارد بهصورت خودکار، نویسنده پیشنهاد میکند از دستور find برای مکانیابی تمام فایلهای route.* در دایرکتوری API استفاده کنید و سپس با grep -rL فایلهایی را بیابید که در آنها هیچ اشارهای به کمکهای نشست یا احراز هویت مانند getSession ،auth() ،requireUser یا verifyToken نشده است.
آسیبپذیریهای وابستگیها
از آنجا که مدلهای زبانی روی دادههای گذشته آموزش دیدهاند، اغلب نسخههایی از پکیجها را پیشنهاد میکنند که در زمان آموزش محبوب بودهاند اما اکنون دارای CVEهای (آسیبپذیریهای شناختهشده) هستند. این یعنی AI ممکن است کدی را پیشنهاد دهد که از کتابخانهای قدیمی استفاده میکند که حفرههای امنیتی شناختهشدهای دارد.
توسعهدهندگان میتوانند از npm audit --audit-level=high برای یافتن آسیبپذیریهای جدی استفاده کنند و از npm audit fix برای ارتقاهای خودکار و امن بهره ببرند. با این حال، نویسنده نسبت به اجرای کورکورانه npm audit fix --force هشدار میدهد، زیرا این دستور میتواند نسخههای اصلی (Major) را تغییر داده و باعث شکستگی کد (Breaking Changes) و از کار افتادن برنامه شود.
برای رویکردی جامعتر و مستقل از اکوسیستم (بهویژه برای کاربران pnpm یا yarn)، ابزار OSV-Scanner گوگل پیشنهاد میشود که فایلهای lock (مانند package-lock.json) را با پایگاه داده باز OSV تطبیق میدهد. چون CVEهای جدید بهطور مداوم منتشر میشوند، بازرسی وابستگیها نباید یک بار در ابتدای پروژه باشد، بلکه باید به یک عادت زمانبندیشده تبدیل شود.
«سهگانه خاموش» شکستهای عملیاتی
سه مورد خاص وجود دارد که چون در زمان توسعه خطایی نمیدهند و برنامه بهظاهر درست کار میکند، مستقیماً به محیط عملیاتی میروند:
۱. Wildcards در CORS: تنظیم Access-Control-Allow-Origin روی * به معنای «اجازه برای همه» است. این موضوع برای APIهای واقعاً عمومی و فقط-خواندنی مشکلی ندارد، اما به محض اینکه یک نقطه انتهایی دادههای خاص کاربر را مدیریت کند، به یک مشکل بزرگ تبدیل میشود. مبدأها (Origins) باید محدود به سایتهای خاصی باشند که سرویس را ارائه میدهند.
۲. نبود محدودیت نرخ (Rate Limits): بدون محدودیت بر اساس IP، یک اسکریپت ساده میتواند مسیرهای ورود، صفحات ثبتنام یا نقاط انتهایی مبتنی بر LLM را بمباران کند. مورد اخیر بهویژه خطرناک است زیرا اگر API شما به یک مدل زبانی متصل باشد، این حملات میتواند بهسرعت هزینههای API شما را به شدت افزایش دهد.
۳. نشت خطاهای مفصل: برگرداندن err.stack یا error.message به کلاینت، نقشهای از ساختار داخلی سرور، نام فایلها و خطوط کد را در اختیار مهاجم قرار میدهد.
توسعهدهندگان باید کدهای خود را برای err.stack ،error.message یا console.log(err) جستوجو کنند. الگوی درست این است که خطای کامل در سمت سرور لاگ شود و یک پیام عمومی (مانند "خطایی در سرور رخ داد") به همراه یک Request ID به کلاینت برگردانده شود تا در صورت نیاز، توسعهدهنده بتواند خطا را در لاگها پیدا کند.
گام بعدی شما: روتین بازرسی
برای سیستماتیک کردن این فرآیند، نویسنده یک بازرسی دو مرحلهای را پیشنهاد میکند. یک تریاژ ۵ دقیقهای که باید قبل از هر Push اجرا شود و بر موارد زیر تمرکز کند:
- اسرار در Working Tree: جستوجوی
api_key،secret،tokenوpasswordدر فایلهای.js،.tsو.py. - تاریخچه گیت: بررسی اینکه آیا
.envهرگز از طریقgit log --all --onelineکامیت شده است یا خیر. - نشتهای کلاینت: جستوجوی
NEXT_PUBLIC_،VITE_یاREACT_APP_در ترکیب با کلمات حساس. - بازرسی سطح بالا: اجرای
npm audit --audit-level=high.
قبل از ارسال کد برای کاربران واقعی، یک بررسی عمیق ۱۵ دقیقهای لازم است. این شامل تایید دستی هر مسیر API برای وجود Auth Guard، محدود کردن مبدأهای CORS، پیادهسازی Rate Limit روی نقاط انتهایی احراز هویت و پرداخت، و جایگزینی پیامهای خطای خام با لاگهای سروری است. در نهایت، هر کلیدی که در مرحله تریاژ پیدا شد باید فوراً چرخانده شود.
برای کسانی که این فرآیند تکراری است، ابزار ShipSafeScan برای اتوماسیون جستوجوی اسرار، بررسی وابستگیها و بازرسی حفاظهای مسیر در مخازن عمومی گیتهاب توسعه یافته است. اگرچه این ابزار نمیتواند جایگزین بازبینی انسانی دقیق شود، اما یک شروع سریع فراهم میکند.
این تغییر در رویکرد، توسعهدهنده را از اعتماد به خروجی AI به سمتی میبرد که با کد AI به عنوان یک پیشنویس برخورد کند که نیاز به بازرسی امنیتی اجباری دارد. شکستها در کدهای AI بهندرت عجیب و غریب هستند؛ آنها حذفهای کسلکنندهای هستند که یک چکلیست کسلکننده میتواند آنها را شناسایی کند.




گفتگو