نقد تند به OpenCode: فیلتر دستورها اصلاً کار نمیکنه
خلاصهٔ کاملتر
نویسنده OpenCode رو با یک مدل محلی تست کرده و نتیجهاش نقدی تنده: به گفتهٔ او این ابزار که محبوبترین عامل کدنویسی اوپنسورسه و روی گیتهاب ۱۶۱ هزار ستاره داره، در اساس یک ابزار وبمحوره که خروجی مدل رو به شل میفرسته، و همهٔ ایرادهایی که میشمرد در همون لولهٔ وسط قرار دارن. خودش تصریح میکنه این نوشته افشای امنیتی نیست و بررسیاش روی نسخهٔ گیت baef5cd4 انجام شده؛ متن رو هم به دو بخش «آزاردهنده» و «هشدارآمیز» تقسیم میکنه.
بخش آزاردهنده با کش پرامپت شروع میشه. سرورهای مدل محلی طولانیترین پیشوند کششده رو پیدا میکنن و فقط بقیه رو ارزیابی میکنن، پس هر تغییر در ابتدای کانتکست یعنی ارزیابی کامل از نو — که به گفتهٔ نویسنده روی یک M4 Max با مدل ۲۷ میلیاردی میتونه ده دقیقه پرِفیل باشه. اما OpenCode روی هر نوبت SSE فایلسیستم رو گلاب میکنه و AGENTS.md رو دوباره میخونه، نتایج ابزارها رو هرز میکنه، و از همه بامزهتر تاریخ روز رو در پرامپت سیستمی نوبت صفر میذاره؛ یعنی اگه نیمهشب کار کنی، کش کامل از دست میره.
خودِ هرزبری (pruning) هم به نظرش بد پیاده شده: نتیجهٔ ابزارها بیشتر از فاصلهٔ ثابت const PRUNE_PROTECT = 40_000 عقبتر از سر نوشتن بیقید حذف میشن و هیچ محافظتی برای خواندههای اول کانتکست نیست. سناریوی نمونهاش اینه: مدل اول یک اسپک رو میخونه، بعد کدهای مرتبط رو، بعد تو وسط کار قطعش میکنی تا هدایتش کنی، و همون قطع کردن باعث حذف کامل اسپک از کانتکست میشه — پس کد بدون اسپک نوشته میشه. نتیجهٔ ابزار skill تنها چیزیه که هیچوقت هرز نمیشه.
کمپکشن هم به نظرش نه خوب پیاده شده و نه با هرزبری خوب تعامل میکنه، چون پرامپت خلاصهسازی رو بهجای انتهای سشن به ابتداش میچسبونه و کل سشن باید از صفر پرِفیل بشه. راهحل خودش صریحتره: به مدل بگو یادداشتهاش رو روی دیسک بنویسه و سشن تازهای شروع کن — زشت ولی کارآمد، و خروجیاش فایلیه که میتونی ادیت یا در چند سشن استفاده کنی. به گفتهٔ او کمپکشن یک انتزاع نشتیه که میخواد پنجرهٔ محدود کانتکست رو بینهایت جلوه بده.
در بخش هشدارآمیز، اولین ایراد «ریموتمحور» بودنه: OpenCode پیشفرض به مدل ریموت وصل میشه، مستنداتش نمونهٔ سادهای برای مدل محلی نداره و اگه تنظیمات رو اشتباه بزنی بیصدا سر همون مدل ریموت میری. به گفتهٔ نویسنده روی نصب تازه، اجرای opencode و زدن یک حرف و اینتر کافیه تا یک مدل ریموت به شل محلی ماشینت وصل بشه؛ و اگه اولین پیام مبهم باشه مدل معمولاً دایرکتوری جاری رو گلاب میکنه و فایلها رو میخونه — و هر چیزی که بخونه در درخواست بعدی آپلود میشه.
اصل ماجرا اما به فیلتر دستورهای bash برمیگرده. نویسنده git رو ممنوع کرده بود، با تنظیمی به این شکل:
"permission": {
"bash": { "git *": "deny" }
}این قاعده با پارس کردن دستور به AST توسط گرامر bash در tree-sitter، پیمایش نودهای دستور و تطبیق با regex کار میکنه. نتیجهاش اینه که دستور ساده بلاک میشه ولی به گفتهٔ نویسنده از راههای متعددی رد میشه: با مسیر مطلق باینری، با ساختن یک alias و صدا زدن اسم جدید، با گذاشتن اسم دستور در متغیر محیطی، با here-doc، با رمزگشایی یک رشتهٔ Base64، یا با یک تکخطی پایتون که همون کار رو با subprocess انجام میده. جمعبندیاش صریحه: فیلتر متنی دستورها بیفایدهست و فقط حس دروغین امنیت میده.
مشکل با اجازههای ذخیرهشده بدتر هم میشه: وقتی برای یک دستور گزینهٔ Always رو بزنی، اجازه روی پیشوند دستور ذخیره میشه و روی دیسک برای سشنهای بعدی هم میمونه. یعنی اگه یکبار به یک دستور پایتون بیخطر اجازه بدی، بعدش هر تکخطی پایتونی — از جمله خوندن کلید خصوصی SSH — بیپرسش اجرا میشه. علاوه بر این، مجموعهای از دستورهای جابهجایی دایرکتوری کاملاً از بررسی اجازه معافاند، حتی اگه در تنظیماتت همهچیز رو رد کرده باشی.
کنترل مسیر فایلها هم شکنندهست: OpenCode فقط برای فهرست کوتاهی از دستورها مسیرها رو اعتبارسنجی میکنه و فرض میگیره بقیه به فایل دست نمیزنن، پس خوندن یک فایل در /tmp پرامپت میگیره ولی یک تکخطی پایتون که کل درخت فایلسیستم رو پاک میکنه هیچ پرامپتی نمیگیره. جالبتر اینکه در AST، نود ریدایرکت خواهرِ نود دستوره نه فرزندش، پس مسیر مقصد ریدایرکت هیچوقت اعتبارسنجی نمیشه. آخرین موردش هم تعداد زیاد مسیرهای خودارتقایی ابزاره، از جمله گرفتن اسکریپت نصب از سایت و اجرای مستقیمش.
نکات کلیدی:
- به گفتهٔ نویسنده OpenCode در اساس خروجی مدل رو به شل میفرسته و ایرادها در همون لولهان
- فیلتر متنی دستورها با alias، مسیر مطلق، متغیر محیطی یا here-doc دور میزنه
- گزینهٔ Always اجازه رو روی پیشوند دستور و روی دیسک ذخیره میکنه
- اعتبارسنجی مسیر فقط برای فهرست کوتاهی از دستورها اجرا میشه؛ نود ریدایرکت بررسی نمیشه
- نصب تازه با یک حرف و اینتر یک مدل ریموت رو به شل محلی وصل میکنه
- کش پرامپت مرتب باطل میشه، حتی بهخاطر تاریخ روز در پرامپت نوبت صفر




