گیتهاب اکشنز؛ ضعیفترین حلقه زنجیره تأمین نرمافزار
خلاصهٔ کاملتر
اگه حوادث امنیتی بزرگ زنجیره تأمین نرمافزار متنباز رو از هجده ماه گذشته زیر ذرهبین بذاریم، تقریباً همهشون به یه جای مشترک ختم میشن: یه فایل YAML توی پوشه .github/workflows. جالب اینجاست که در تمام این حوادث، هیچ باگی از گیتهاب اکشنز سوءاستفاده نشده — همه چیز دقیقاً طبق مستندات کار کرده. مشکل اینه که فیچرهایی که هر کدوم به تنهایی مفیدن، وقتی کنار هم میذاریشون میتونن ترکیب خطرناکی بسازن.
اولین حادثه بزرگ این زنجیره به پروژه spotbugs در نوامبر ۲۰۲۴ برمیگرده. این پروژه یه ورکفلو داشت با تریگر pull_request_target که کدِ فورکهای ناشناس رو چکاوت و بیلد میکرد. این تریگر برای کارهایی مثل لیبل زدن به پول ریکوئستها طراحی شده، اما مشکلش اینه که با دسترسی کامل به سیکرتهای ریپوی اصلی اجرا میشه. یه مهاجم از این طریق به توکن شخصی یه مینتینر دسترسی پیدا کرد، و اون توکن دسترسی به reviewdog داشت — که چهار ماه بعد زمینهساز حادثه بزرگتری شد.
یه ماه بعد، Ultralytics از همین مسیر آلوده شد ولی با یه پیچش: مهاجم مستقیم به کردنشالهای پابلیش دسترسی نداشت، پس به جاش یه کش آلوده گذاشت. وقتی ورکفلوی رسمی انتشار اون کش رو بازیابی کرد، پیلود اجرا شد و دو نسخه از ultralytics با یه ماینر ارز دیجیتال داخلشون روی PyPI منتشر شد.
ماجرای tj-actions در مارس ۲۰۲۵ که CISA برایش اطلاعیه داد، شاید معروفترین این حوادث باشه. با توکنی که از spotbugs دزدیده شده بود، مهاجم یه کامیت مخرب به reviewdog زد و تگ v1 رو بهش اشاره داد. چون tj-actions/changed-files این اکشن رو با تگ (نه هش) ارجاع داده بود، و ۲۳ هزار ریپو هم به changed-files وابسته بودن، همهشون یه اسکریپت اجرا کردن که سیکرتهای رانر رو توی لاگهای عمومی بیلد میریخت. مشکل اساسی اینه که تگهای گیت قابل جابجایی هستن و هر کسی با دسترسی write میتونه اونها رو جابجا کنه.
در ماجرای s1ngularity مربوط به پکیجهای nx، مشکل از یه چیز سادهتر شروع شد: interpolation مستقیم عنوان پول ریکوئست توی یه اسکریپت شل. وقتی مهاجم یه عنوان مخرب با command substitution گذاشت، اون کد با دسترسی به توکن انتشار npm اجرا شد. نتیجه؟ نسخههای آلودهای که دنبال کردنشالهای ابزارهای AI روی ماشینهای توسعهدهندهها میگشتن و بیش از پنج هزار ریپوی خصوصی رو موقتاً عمومی کردن.
تا اوایل ۲۰۲۶ دیگه مهاجمان حوادث رو یهبهیه پیدا نمیکردن، بلکه کمپینهای سازمانیافته راه انداختن. عملیات prt-scan شش هفته طی مارس و آوریل صدها پول ریکوئست با ظاهر معقول باز کرد تا ورکفلوهای آسیبپذیر رو شناسایی و اکسپلویت کنه. حتی Trivy هم دوبار در سه هفته کامپرومایز شد — بار دوم با توکنهایی که از دور اول دزدیده شده بودن، که باعث شد حتی کاربرانی که به تگ قدیمی پین کرده بودن هم آسیبپذیر باشن.
آخرین نمونه، elementary-data بود: یه اکانت دو روزه یه کامنت گذاشت، ورکفلوی issue_comment اون رو مستقیم توی bash اجرا کرد، و چون هیچ بلاک permissions تعریف نشده بود GITHUB_TOKEN دسترسی write داشت. ظرف ده دقیقه، بدون اینکه هیچ مینتینری چیزی تأیید کنه یا بیدار باشه، یه ویل آلوده روی PyPI و یه image روی GHCR منتشر شد.
نکات کلیدی:
- تریگر pull_request_target اگه با checkout کد فورک ترکیب بشه، دسترسی کامل به سیکرتهای ریپو رو به کد ناشناس میده
- تگهای اکشنها مثل v1 مثل هر تگ گیتی قابل جابجایی هستن؛ پین کردن به SHA هش تنها راه مطمئنه
- interpolation مستقیم ورودی کاربر (مثل عنوان PR یا بدنه کامنت) توی اسکریپت شل، تزریق کد رو ممکن میکنه
- کش گیتهاب اکشنز مرزهای اعتماد رو بیصدا رد میکنه
- GITHUB_TOKEN در ریپوهای ایجادشده قبل از فوریه ۲۰۲۳ بهصورت پیشفرض دسترسی write داره
- هیچکدام از این مشکلات باگ نیستن — همه طبق مستندات کار میکنن و گیتهاب تاکنون پیشفرضهای اساسی رو تغییر نداده




