مسمومسازی کش GitHub Actions: چطور از ریپوزیتوریات محافظت کنی
خلاصهٔ کاملتر
مسمومسازی کش GitHub Actions (Cache Poisoning) یه حمله زنجیرهایست که از ۲۰۲۴ پروژههای متنباز بزرگ رو هدف گرفته. ایده اصلی سادهست: وقتی CI یه repo وابستگیها رو نصب میکنه، نتیجه رو در یه «کش» با یه کلید مشخص (معمولاً هش فایل lock) ذخیره میکنه. مشکل اینجاست که این کش بین همه workflowها — از PR معمولی تا انتشار پکیج — به اشتراک گذاشته میشه و هیچ ایزولاسیون پیشفرضی ندارد. مهاجم اگه بتونه یه بار کد مخرب رو در این کش بنویسه، دفعه بعد که workflow انتشار اجرا میشه، کد مهاجم روی runner لود میشه — درست قبل از هر مرحله دیگهای.
دو روش اصلی برای نوشتن در کش وجود داره: روش اول، نوشتن مستقیم — مهاجم یه workflow با دسترسی بالا رو فریب میده تا کدش اجرا بشه (مثل pull_request_target که به PR فورکشده دسترسی secrets میده). روش دوم، پاککردن و جایگزینی — چون کشهای موجود قابل بازنویسی نیستن، مهاجم ۱۰ گیگابایت آشغال آپلود میکنه تا مکانیزم LRU گیتهاب کش اصلی رو حذف کنه، بعد نسخه مسموم رو با همون کلید مینویسه. ابزار Cacheract از Adnan Khan این فرآیند رو اتوماتیک میکنه.
چی باید توی ریپوت ممیزی کنی؟ شش بررسی اصلی وجود داره: اول، هر workflow با trigger pull_request_target که کد PR رو checkout میکنه — این «Pwn Request» نام داره و همون چیزیه که TanStack رو زمین زد. دوم، workflowهایی که ورودیهای غیرقابلاعتماد مثل عنوان ایشو یا متن کامنت رو مستقیم در run: استفاده میکنن. سوم، هر workflow با id-token: write که توانایی انتشار پکیج داره. چهارم، actionهای شخص ثالثی که به جای commit SHA به یه tag مثل @v4 پین شدن — چون tagها قابل تغییرن و همین روش tj-actions/changed-files رو به بیش از ۲۳ هزار workflow آلوده کرد.
# before
- uses: pnpm/action-setup@v3
# after
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v3.0.0برای رفع مشکل، اولویتبندی مهمه. اول pull_request_target رو به pull_request تبدیل کن — این trigger با دسترسی read-only و بدون secrets روی fork PR اجرا میشه. دوم، کش رو در workflowهای انتشار کاملاً غیرفعال کن — release workflowها کم اجرا میشن و چند ثانیه صرفهجویی در نصب ارزش این ریسک رو نداره. سوم، هر action شخص ثالثی رو به commit SHA پین کن. چهارم، ورودیهای مشکوک رو هرگز مستقیم در shell استفاده نکن؛ به جاش از environment variable استفاده کن:
# bad
- run: echo "Triaging issue: ${{ github.event.issue.title }}"
# good
- run: echo "Triaging issue: $TITLE"
env:
TITLE: ${{ github.event.issue.title }}از ابزار zizmor یا actionlint هم میتونی به عنوان یه PR check اجباری استفاده کنی تا الگوهای خطرناک رو قبل از merge شناسایی کنه. در نهایت، OIDC trusted publishing (جایگزین توکنهای استاتیک npm) رو پیاده کن، 2FA بر پایه SMS رو حذف کن، و فایلهای کانفیگ AI agent رو مثل source code با CODEOWNERS محافظت کن.
نکات کلیدی:
- کش GitHub Actions بین همه workflowها مشترکه و هیچ ایزولاسیون پیشفرضی نداره
- pull_request_target که کد PR رو checkout میکنه مهمترین نقطه ورود حملهست
- actionهای پینشده به tag (مثل @v4) در برابر حملات زنجیره تامین آسیبپذیرن؛ از commit SHA استفاده کن
- workflowهای انتشار با id-token: write نباید از کش مشترک با PR workflow استفاده کنن
- ورودیهای کاربر (عنوان ایشو، متن کامنت) هرگز نباید مستقیم در shell یا prompt AI تزریق بشن
- ابزار zizmor میتونه این الگوهای خطرناک رو به صورت استاتیک قبل از merge شناسایی کنه




