امنیت وابستگیها: کدی که خودتان ننوشتهاید

یک آزمایش ساده روی هر پروژهٔ وب امروزی: تعداد خط کدی که تیم شما نوشته را با تعداد خط کدی که در پوشهٔ وابستگیها نصب شده مقایسه کنید. نسبت معمولاً چیزی بین یک به بیست تا یک به دویست است.
یعنی بیش از نود درصد کدی که روی سرور شما اجرا میشود را کسی نوشته که نمیشناسیدش، و شما مسئول امنیتش هستید.
این نه استدلالی علیه استفاده از کتابخانه است — نوشتن همهچیز از صفر بدترین گزینه است — و نه دلیلی برای وحشت. دلیلی است برای اینکه وابستگیها را مثل بقیهٔ کد مدیریت کنید، نه مثل چیزی که یکبار نصب میشود و فراموش.
سه ریسک، که یکیشان بیشتر از دوتای دیگر مهم است
۱. آسیبپذیری شناختهشده در بستهای که استفاده میکنید. رایجترین. کسی مشکلی در کتابخانهای پیدا کرده، منتشر شده، نسخهٔ اصلاحشده هم موجود است — و سامانهٔ شما هنوز روی نسخهٔ قدیمی است. این نود درصد ماجراست.
۲. بستهٔ رهاشده. کتابخانهای که سه سال است بهروز نشده. آسیبپذیری فعلی شاید نداشته باشد، ولی وقتی پیدا شود کسی نیست که درستش کند. این ریسک تدریجی است و در تصمیم اولیه نادیده گرفته میشود.
۳. بستهٔ مخرب. بستهای که عمداً کد بد دارد، یا حساب نگهدارندهاش ربوده شده. نادر، ولی وقتی رخ میدهد جبرانش سخت است — چون کد در زمان نصب یا بیلد اجرا میشود، نه در زمان اجرای برنامه.
بیشتر تیمها انرژیشان را روی سومی میگذارند چون خبرساز است، و اولی را که تقریباً همهٔ حادثههای واقعی از آن میآید نادیده میگیرند.
اول: بدانید چه چیزی داخل است
نمیشود چیزی را که فهرست نشده امن نگه داشت. اولین قدم یک فهرست ماشینخوان از همهٔ اجزای نرمافزار است — نام، نسخه، مجوز، و اینکه مستقیم استفاده میشود یا وابستگی وابستگی است.
تقریباً همهٔ اکوسیستمها این را از فایل قفل خودشان تولید میکنند. نکته این است که فهرست باید در بیلد تولید شود، نه دستی — فهرستی که سه ماه پیش صادر شده، فهرست چیزی است که سه ماه پیش منتشر شده بود.
و آن فایل قفل را در مخزن نگه دارید. بدون آن، دو بیلد از یک commit میتوانند دو مجموعهٔ متفاوت از کد باشند. این همان چیزی است که در خط لولهٔ قابل اعتماد به آن «بیلد بازگشتپذیر» میگوییم و از سرعت انتشار مهمتر است.
دوم: اسکن خودکار، ولی با فیلتر
اسکنر وابستگی را در خط لوله بگذارید. راهاندازیاش نیمروز است و بازدهش از هر کار امنیتی دیگری بیشتر.
اما یک هشدار: اسکنر بدون اولویتبندی، بعد از دو هفته نادیده گرفته میشود. تیمی که هر روز چهل هشدار میگیرد، هیچکدام را نمیخواند — و این از نداشتن اسکنر بدتر است، چون حس پوشش کاذب میدهد.
سه سؤالی که یک هشدار را از سطح «مهم» به «فوری» میبرد:
آیا کد آسیبپذیر واقعاً اجرا میشود؟ بستهای که فقط در ابزار توسعه استفاده میشود و به سرور تولید نمیرود، شدتش همان نیست.
آیا از بیرون قابل رسیدن است؟ آسیبپذیری در مسیری که فقط با دسترسی مدیر اجرا میشود، با آسیبپذیری در تجزیهٔ ورودی صفحهٔ ورود یکی نیست.
آیا اکسپلویت عمومی دارد؟ این تفاوت بین «این هفته» و «در بهروزرسانی بعدی» است.
معیار عددی شدت که ابزارها میدهند، نقطهٔ شروع است نه تصمیم. تصمیم را دفتر یافتههای امنیتی نگه میدارد، با دلیل.
سوم: بهروزرسانی دورهای، نه واکنشی
این بند بیشترین تفاوت را میسازد و کمترین توجه را میگیرد.
تیمی که وابستگیها را فقط وقتی خبر بد آمد بهروز میکند، در بدترین لحظهٔ ممکن با بزرگترین جهش نسخه روبهرو میشود: باید از نسخهٔ دو سال پیش به امروز برسد، با تغییرات ناسازگار، در حالی که ساعت در حال شمارش است.
تیمی که ماهی یک بار بهروزرسانی جزئی انجام میدهد، وقتی خبر بد بیاید یک ارتقای کوچک جلوی رویش دارد.
این کار فقط با یک چیز ممکن است: تست خودکاری که به آن اعتماد دارید. بهروزرسانی وابستگی بدون تست، قمار است — و به همین دلیل است که تست رگرسیون در عمل یک رویهٔ امنیتی هم هست، نه فقط رویهٔ کیفیت.
چهارم: کمتر بردارید
ارزانترین راه امن نگه داشتن یک وابستگی، نداشتنش است.
پیش از افزودن بستهای برای کاری که سی خط کد است، سه چیز را نگاه کنید: چند وابستگی دیگر با خودش میآورد، آخرین انتشارش کِی بوده، و چند نفر نگهداریاش میکنند.
آن اولی مهمترین است. بستهای که خودش چهل وابستگی میآورد، چهل تصمیمی است که شما نگرفتهاید. این همان محاسبهای است که در انتخاب فناوری برای استارتاپ هم مطرح است، فقط یک سطح پایینتر.
و در سمت مرورگر یک هزینهٔ دوم هم دارد: هر کتابخانهای که به بستهٔ نهایی اضافه میشود، سرعت صفحه را پایین میآورد. امنیت و کارایی اینجا در یک جهتاند.
و یک نکته دربارهٔ بستههای داخلی
سازمانهایی که کتابخانهٔ مشترک داخلی دارند، معمولاً همهٔ این رویهها را برای بستههای بیرونی اجرا میکنند و برای بستههای خودشان هیچکدام را — با این استدلال که «مال خودمان است».
بستهٔ داخلی که سه سال بهروز نشده و نگهدارندهاش از شرکت رفته، دقیقاً همان ریسک بستهٔ رهاشدهٔ بیرونی را دارد، با این تفاوت که هیچکس هشدارش را نمیدهد. مالکیت مکتوب برای بستههای داخلی همان کاری را میکند که فهرست اجزا برای بیرونیها.
کوتاهترین شکل عملی
اگر امروز هیچکدام را ندارید، به این ترتیب اضافه کنید:
۱. فایل قفل در مخزن باشد. ۲. اسکنر وابستگی در خط لوله، با آستانهای که بیلد را روی «بحرانی» متوقف کند و بقیه را فقط گزارش دهد. ۳. یک بازهٔ ماهانه برای بهروزرسانی جزئی. ۴. یک نفر مسئول برای هر وابستگی حیاتی.
بند اول و دوم یک روز کار است. بند سوم و چهارم عادت است، و همان است که در سال دوم تفاوت را میسازد. جایگاه این کار در کل مسیر تولید، در امنیت در همهٔ مراحل آمده.