پرش به محتوای اصلی
پرش به محتوای مقاله

«مسدودسازی بازنویسی مفسر»؛ استراتژی جدید Astral برای امنیت پایتون

·۶ مرداد ۱۴۰۵۱۱ دقیقه مطالعه
نسخه ۰.۱۲.۰ ابزار uv منتشر شد: بهبودهای مهم در مدیریت وابستگی پایتون و سرعت نصب بسته‌ها
نسخه ۰.۱۲.۰ ابزار uv منتشر شد: بهبودهای مهم در مدیریت وابستگی پایتون و سرعت نصب بسته‌ها
اشتراک‌گذاری
واقعاً چه چیز جدید است؟

مسدودسازی سخت‌گیرانه و غیرقابل‌تغییرِ هرگونه تلاش برای بازنویسی مفسر پایتون توسط بسته‌ها و حذف کامل پشتیبانی از فرمت‌های فشرده‌سازی منسوخ مانند bzip2 و xz.

اگر شما یک توسعه‌دهنده پایتون هستید که سرعت را فدای امنیت نمی‌کنید، باید بدانید که محیط‌های اجرای کد شما اکنون در برابر حملات پیشرفته‌تر ایمن شده‌اند. هدف اصلی نسخه 0.12.0 ابزار uv که در ۲۸ ژوئیه ۲۰۲۶ منتشر شد، تبدیل این ابزار از یک نمونه‌ی سریع به یک محصول صنعتی است که امنیت را در اولویت قرار می‌دهد. نیروهای محرک پشت این انتشار، «صحت و ایمنی» (Correctness and safety) هستند.

طبق اعلام Astral، این به‌روزرسانی با پیاده‌سازی بررسی‌های سخت‌گیرانه، از بسته‌های مخرب که سعی می‌کنند مفسر پایتون را بازنویسی یا جایگزین کنند، جلوگیری می‌کند. با این اقدام، Astral راهی به‌طور قابل توجهی امن‌تر برای مدیریت محیط‌ها در اختیار توسعه‌دهندگان پایتون قرار داده است. از زمان انتشار نسخه 0.11.0 در ماه مارس، تمرکز تیم روی تجمیع تغییرات برای بهبود ایمنی عمومی و سازگاری با مشخصات فنی بوده است. هرچند اکثر کاربران بدون نیاز به تغییرات خاصی ارتقا می‌کنند، اما بسیاری از به‌روزرسانی‌ها به‌دلیل احتیاط بالا، «شکننده» (Breaking Changes) علامت‌گذاری شده‌اند.

برای اکثر کاربران، ارتقا بدون درز (Seamless) خواهد بود، اما این نسخه چندین تغییر شکننده را برای تضمین سازگاری با مشخصات فعلی معرفی می‌کند. این تغییرات لبه‌های اکوسیستم را هدف قرار داده‌اند؛ جایی که فرمت‌های قدیمی و عملکردهای ناامن اغلب باعث ایجاد آسیب‌پذیری می‌شوند. برای کسانی که از Backend ساخت uv استفاده می‌کنند، هیچ تغییر شکننده در پیکربندی وجود ندارد، هرچند کاربران باید جدول [build-system] خود را به‌روز کنند تا uv_build 0.12 را اجازه دهد (به عنوان مثال: uv_build>=0.11.32,<0.13).

در دنیای مدیریت بسته‌ها، استنتاج (Inference) — مثل لحظه‌ای که یک آشپز طبق دستور پخت غذا را آماده می‌کند و دیگر در حال یادگیری نیست — در اینجا به معنای لحظهٔ نصب و اجرای بسته است. تصور کنید یک بسته مخرب سعی کند فایل باینری واقعی پایتون شما را طی فرآیند نصب با یک نسخه آلوده جایگزین کند. uv اکنون این اقدام را یک شکست بحرانی (Critical failure) می‌بیند و هر فایل wheel که تلاش کند فایل‌هایی را روی مفسر نصب کند، مسدود می‌کند. این شامل گونه‌های حساس به حروف کوچک و بزرگ مانند "Python.exe" در ویندوز یا macOS نیز می‌شود. به نقل از مستندات Astral، این اقدام حفره‌های امنیتی را می‌بندد که در آن‌ها نقاط ورود (Entry points) در فایل‌های wheel با نام "Python" (با تغییر حروف) یا فایل‌هایی در مسیرهای .data/scripts و .data/data/bin/python می‌توانستند بررسی‌های امنیتی را دور بزنند. uv اکنون نام‌هایی مانند Python ،python.py و Python.exe و همچنین سایر نام‌های رزرو شده مفسر و گونه‌های نسخه‌بندی شده را رد می‌کند. کاربران نمی‌توانند از این بررسی‌ها صرف‌نظر کنند؛ فایل‌های wheel آسیب‌دیده باید مجدداً ساخته شوند.

همان‌طور که در تحلیل‌های قبلی ما درباره‌ی امنیت مدل‌های بازمتن اشاره کردیم، تجهیز ابزارهای زیرساختی به لایه‌های حفاظتی، تنها راه مقابله با حملات زنجیره تأمین است. در این راستا، ساختار پروژه‌ها نیز استاندارد شده است. یکی از کاربردی‌ترین تغییرات در این نسخه، بازگشت به پیش‌فرض «بسته‌بندی‌شده» (packaged-init) برای دستور uv init است. این اقدام باعث تثبیت ویژگی پیش‌نمایش packaged-init شد.

  • یکپارچگی سیستم ساخت: پروژه‌های ایجاد شده از طریق uv init اکنون به‌طور خودکار یک سیستم ساخت را با استفاده از Backend داخلی uv_build تعریف می‌کنند. این کار باعث بازگشت به یک چیدمان بهینه (Best-practice layout) می‌شود که در نسخه v0.3 وجود داشت، در v0.4 به‌دلیل سردرگمی پیرامون سیستم hatchling حذف شد و اکنون با یکپارچگی تنگاتنگ با uv دوباره معرفی شده است.
  • تغییرات چیدمان: کد منبع اکنون به‌صورت پیش‌فرض در دایرکتوری src/example قرار می‌گیرد، به جای چیدمان قبلی بدون بسته (unpackaged) که فقط شامل main.py و pyproject.toml بود. پیش از این، یک چیدمان بدون بسته می‌توانست وابستگی‌ها را تعریف کند، اما خودش در محیط مجازی نصب نمی‌شد.
  • قابلیت اجرا: خروجی شامل یک ورودی [project.scripts] به نام example است. این به پروژه اجازه می‌دهد از طریق تست‌ها وارد (Import) شود، به عنوان یک وابستگی نصب شود و به عنوان یک دستور اجرا گردد (مثلاً با دستورات $ uv init example و $ cd example و $ uv run example). خروجی حاصل عبارت "Hello from example!" خواهد بود.

اگر چیدمان قدیمی و بدون بسته را ترجیح می‌دهید، همچنان می‌توانید از پرچم uv init --no-package example استفاده کنید. پروژه‌های موجود تحت تأثیر این تغییر قرار نمی‌گیرند.

برای سخت‌تر کردن نفوذ، Astral سطح حمله را با حذف پشتیبانی از روش‌های فشرده‌سازی منسوخ و تثبیت ویژگی پیش‌نمایش "publish-require-normalized" کاهش داد.

  • فرمت‌های آرشیو: این ابزار اکنون توزیع‌های منبعی (Source distributions) را که از فرمت‌های .tar.bz2 و .tar.xz استفاده می‌کنند، رد می‌کند و طبق استاندارد PEP 625، فرمت .tar.gz را الزامی می‌سازد. این رد کردن حتی زمانی که این فرمت‌ها در یک Lockfile موجود ارجاع شده باشند، اعمال می‌شود. توزیع‌های منبع .zip قدیمی برای سازگاری با نسخه‌های پیشین همچنان پشتیبانی می‌شوند.
  • محدودیت‌های فشرده‌سازی: فایل‌های Wheel و آرشیوهای ZIP تنها به روش‌های فشرده‌سازی stored، DEFLATE یا zstd محدود شده‌اند. فشرده‌سازی‌های Bzip2، LZMA و XZ دیگر پذیرفته نمی‌شوند تا وابستگی‌ها و قرار گرفتن در معرض بسته‌های غیرقابل اعتماد کاهش یابد. هیچ راهی برای غیرفعال کردن این بررسی‌ها وجود ندارد.
  • نرمال‌سازی (Normalization): هنگام انتشار، دستور uv publish اکنون توزیع‌هایی با نام‌های فایل غیرنرمال را نادیده می‌گیرد. برای مثال، یک wheel برای نسخه 1.01.0 باید نام example-1.1.0-py3-none-any.whl را داشته باشد نه example-1.01.0-py3-none-any.whl.

امنیت برای بررسی هش (Hash-checking) نیز تشدید شده است. هنگام استفاده از --require-hashes در یک فایل requirements.txt ،uv اکنون این دستور را به‌طور سخت‌گیرانه‌ای اجرا می‌کند و به‌گونه‌ای عمل می‌کند که گویی این پرچم در خط فرمان پاس داده شده است. نیازمندی‌هایی که پین نشده‌اند یا هش ندارند، اکنون رد می‌شوند. کاربران تا زمانی که این دستور حضور دارد نمی‌توانند از آن صرف‌نظر کنند؛ آن‌ها یا باید هر نیازمندی را با == پین کرده و هش آن را ارائه دهند یا --require-hashes را به‌طور کامل حذف کنند.

علاوه بر این، اکنون هش‌های «فقط MD5» رد می‌شوند، زیرا MD5 در برابر تصادم (Collision) مقاوم نیست. برای حالت بررسی هش، داشتن حداقل یک دسته‌بندی امن (Secure digest) مانند SHA-256 اکنون اجباری است. در حالی که تأیید هش معمولی بدون --require-hashes همچنان از MD5 پشتیبانی می‌کند، نیازمندی‌های هش‌شده‌ای مانند anyio==4.0.0 --hash=md5:420d85e19168705cdf0223621b18831a رد خواهند شد مگر اینکه یک هش امن نیز ارائه شود. هش‌های امن را می‌توان مستقیماً در نیازمندی یا در یک فایل محدودکننده (Constraints file) متناظر ارائه کرد.

تحلیلگرین اشاره می‌کنند که مدیریت وابستگی‌ها اکنون بصری‌تر شده است و به حالت «در صورت نیاز» (if-necessary) برای نسخه‌های پیش‌انتشار (Pre-releases) منتقل شده است. پیش از این، uv از حالت «در صورت نیاز یا صریح» (if-necessary-or-explicit) استفاده می‌کرد که نیازمند آن بود که صلاحیت پیش‌انتشار پیش از شروع تحلیل شناخته شود. این بدان معنا بود که یک نیازمندی پیش‌انتشار ترانزیتی (مثلاً example>=2.0.0b1) با شکست مواجه می‌شد، حتی اگر نسخه‌ای سازگار وجود داشت، مگر اینکه کاربر آن را صراحتاً به عنوان یک نیازمندی مستقیم اضافه می‌کرد یا پیش‌انتشارها را در کل گراف وابستگی‌ها مجاز می‌کرد.

اکنون، uv ابتدا تلاش می‌کند کاندیداهای پایدار را بیابد و تنها در صورتی که هیچ نسخه پایداری محدودیت‌ها را برآورده نکرد، به سراغ نسخه‌های پیش‌انتشار می‌رود. این رفتار uv را با pip هم‌راستا می‌کند. کاربران همچنان می‌توانند این رفتار را از طریق چندین پرچم کنترل کنند:

  • --prerelease disallow: انصراف از انتخاب خودکار پیش‌انتشار.
  • --prerelease allow: در نظر گرفتن پیش‌انتشارها بدون اولویت دادن به نسخه‌های پایدار.
  • --prerelease explicit: اجازه پیش‌انتشار فقط برای نیازمندی‌های مستقیمی که صراحتاً به یکی از آن‌ها اشاره کرده‌اند.

حالت قدیمی «در صورت نیاز یا صریح» اکنون یک نام مستعار (Alias) منسوخ شده است و در نسخه‌های آینده حذف خواهد شد.

بهبودهای دیگری نیز در لایه‌های رابط و محیطی دیده می‌شود. چندین محافظت ایمنی و کیفیت زندگی در این نسخه تثبیت شده‌اند، از جمله "target-workspace-discovery"، "venv-safe-clear" و "init-project-flag".

  • کشف پروژه: اجرای دستور uv run project/script.py اکنون پروژه را نسبت به دایرکتوری اسکریپت کشف می‌کند، نه نسبت به دایرکتوری کاری فعلی (CWD). برای بازگشت به رفتار اصلی، کاربران می‌توانند از uv run --project . other-project/script.py استفاده کنند.
  • حفاظت از Venv: دستور uv venv --clear اکنون از حذف دایرکتوری‌هایی که حاوی یک محیط مجازی نیستند، خودداری می‌کند. پیش از این، uv یک هشدار می‌داد اما همچنان دایرکتوری را پاک می‌کرد. کاربران می‌توانند این مورد را با پرچم --force بازنگری کنند (مثلاً: uv venv --clear --force ./not-a-virtualenv).
  • مقداردهی اولیه پروژه: پرچم --project اکنون در هنگام مقداردهی اولیه پروژه رد می‌شود. قبلاً دستور uv init --project example هشدار می‌داد و به هر حال مقداردهی می‌کرد. این اکنون یک خطا (Error) است. کاربران باید از uv init example یا uv init --directory example برای تغییر دایرکتوری کاری استفاده کنند.
  • اعتبارسنجی مسیر پروژه: uv اکنون مسیرهای --project گمشده یا نامعتبر را رد می‌کند. دستوراتی مانند uv run --project missing python بلافاصله با شکست مواجه می‌شوند. ارسال --project path/to/pyproject.toml همچنان پشتیبانی می‌شود و دایرکتوری والد فایل را انتخاب می‌کند.
  • مدیریت SSL: این ابزار اکنون بازنویسی‌های صریح گواهینامه از طریق SSL_CERT_FILE یا SSL_CERT_DIR را رعایت می‌کند. پیش از این، uv اگر این متغیرها به مسیرهای گمشده، غیرقابل دسترس یا خالی اشاره می‌کردند، آن‌ها را نادیده می‌گرفت. اکنون هر مقدار غیرخالی، ریشه‌های پیش‌فرض را جایگزین می‌کند. اگر هیچ گواهینامه معتبری بارگذاری نشود، درخواست‌های HTTPS برای دانلود بسته‌ها یا اسکریپت‌های ریموت (از جمله GitHub Gists) بلافاصله شکست می‌خورند.
  • سازگاری با Pip: یک پرچم جدید --cert <path> برای دستورات uv pip در دسترس است (مثلاً: uv pip install --cert ./company-ca.pem example). بسته PEM ارائه شده، تمام منابع گواهینامه دیگر، از جمله گواهینامه‌های سیستم را برای آن فراخوانی خاص جایگزین می‌کند.
  • ایمنی Symlink: ابزار uv اکنون اگر در حین کشف با یک Symlink شکسته برای .venv مواجه شود، متوقف شده و خطا گزارش می‌کند، به جای اینکه آن را نادیده بگیرد و در دایرکتوری‌های والد جستجو کند. این کار از تغییر غیرمنتظره محیط‌های اجدادی توسط uv pip install جلوگیری می‌کند. همچنین خطاهای دسترسی (Permission failures) در هنگام خواندن متادیتای محیط مجازی بلافاصله گزارش می‌شوند.

در نهایت، اعتبارسنجی فایل‌های pylock.toml به شدت افزایش یافته است. uv اکنون چندین نیازمندی از مشخصات فنی را اعتبارسنجی می‌کند:

  • آرایه بسته‌ها: آرایه packages باید حضور داشته باشد. پیش از این، نبود این آرایه به عنوان یک Lockfile خالی تلقی می‌شد که می‌توانست منجر به حذف کل محیط توسط uv pip sync شود. یک آرایه صراحتاً خالی مانند packages = [] همچنان معتبر است.
  • قراردادهای نام‌گذاری: نام فایل‌های Lockfile باید pylock.toml یا یک گونه تک‌نامی مانند pylock.dev.toml باشد. نام‌های نامعتبر مانند pylock..toml یا pylock.foo.bar.toml اکنون رد می‌شوند.
  • اندازه آرتیفکت: اگر یک wheel یا توزیع منبع اندازه ای را اعلام کند، آرتیفکت دانلود شده یا کش شده باید با آن اندازه مطابقت داشته باشد. پیش از این، اگر هش درست بود، اندازه نادرست پذیرفته می‌شد. در حالی که اندازه‌های ایندکس بسته همچنان توصیه ای (Advisory) هستند، اما عدم تطابق در زمانی که اندازه اعلام شده باشد، منجر به شکست خواهد شد.

مدیریت مفسرهای پایتون نیز شاهد تغییر منطق بوده است. دستور uv python install 3.12 --reinstall اکنون نسخه‌های پچ (Patch versions) خاصی را که از قبل روی سیستم هستند، مجدداً نصب می‌کند. برای مثال، اگر پایتون 3.12.6 و 3.12.7 نصب باشند، هر دو دوباره نصب می‌شوند. این با رفتار قبلی متفاوت است که به عنوان راهی برای نصب آخرین پچ عمل می‌کرد. برای دریافت آخرین نسخه پچ موجود، کاربران اکنون باید از پرچم --upgrade استفاده کنند. ترکیب --upgrade --reinstall تنها آخرین پچ را مجدداً نصب می‌کند.

علاوه بر این، توزیع‌های قدیمی PyPy که فقط به عنوان آرشیوهای bzip2 در دسترس بودند، دیگر برای نصب پشتیبانی نمی‌شوند. تنها آخرین انتشار PyPy برای هر نسخه جزئی (Minor version) پشتیبانی شده از طریق آرشیوهای فشرده gzip در دسترس است. به عنوان مثال، دستور uv python list 3.10 --all-versions آخرین PyPy 3.10 را نشان می‌دهد اما پچ‌های قدیمی‌تر bzip2-only را حذف می‌کند.

چندین تغییر کوچک‌تر نیز تجربه توسعه‌دهنده را بهبود بخشیده است:

  • ایندکس‌های نسبی: گزینه --directory اکنون مسیرهای نسبی --index ،--default-index ،--index-url ،--extra-index-url و --find-links را به‌درستی نسبت به دایرکتوری انتخاب شده حل می‌کند. برای مثال، uv add --directory project --index ./packages example اکنون از project/packages استفاده می‌کند.
  • مسیرهای مطلق: هنگام استفاده از uv add ،مسیرهای مطلق و URLهای file:// به جای تبدیل به مسیرهای نسبی پروژه، در pyproject.toml و uv.lock حفظ می‌شوند. URLهایی که حاوی متغیرهای گسترش یافته (Expanded variables) هستند، رفتار مسیر نسبی خود را حفظ می‌کنند.
  • اعتبارسنجی گروه‌ها: دستور uv lock --upgrade-group اکنون اعتبارسنجی می‌کند که گروه درخواست شده در پروژه، اعضای Workspace یا گروه‌های سطح Workspace وجود داشته باشد. پیش از این، حتی اگر گروه وجود نداشت، دستور به‌طور خاموش موفق می‌شد. tool.uv.dev-dependencies قدیمی همچنان گروه dev را تامین می‌کند.
  • شناخت Conda: محیط‌های فرزند Conda با نام‌های base یا root اکنون به‌درستی از طریق مسیرهایشان شناخته می‌شوند و دیگر فرض نمی‌شود که محیط پایه جهانی (Global base) هستند. این ویژگی به عنوان "special-conda-env-names" تثبیت شده است. کاربران می‌توانند با درخواست صریح مفسر از طریق --python /path/to/python از این مورد انصراف دهند.
  • پاکسازی یادداشت‌ها: هنگام استفاده از uv pip compile --no-annotate ،بخش انتهایی (Footer) که بسته‌های حذف شده از طریق --unsafe-package را لیست می‌کرد، اکنون به‌درستی حذف می‌شود.

این انتشار نشان‌دهنده تعهد Astral به انتقال uv از یک پروتوتایپ سریع به یک ابزار درجه صنعتی است که سرعت را فدای ایمنی نمی‌کند. با اجرای استانداردهایی مانند PEP 625 و مسدود کردن بازنویسی مفسر، آن‌ها در حال رسیدگی به رایج‌ترین بردارهای حملات زنجیره تأمین در اکوسیستم پایتون هستند. تمام آرتیفکت‌های این نسخه شامل گواهینامه‌هایی (Attestations) هستند که با GitHub Artifact Attestations تولید شده‌اند و با استفاده از GitHub CLI قابل تأیید هستند.

برای توسعه‌دهندگان، این به معنای افزایش اندک اصطکاک هنگام تعامل با بسته‌های قدیمی، اما کاهش قابل توجه ریسک به خطر افتادن محیط است. تغییر به سمت چیدمان استاندارد src/ همچنین به پر کردن شکاف بین اسکریپت‌های ساده و کتابخانه‌های قابل توزیع کمک می‌کند.

برای اطمینان از سازگاری پروژه‌های خود، باید Lockfileهای خود را برای هش‌های MD5 بازرسی کرده و بررسی کنید که آیا هیچ یک از وابستگی‌های داخلی شما به آرشیوهای .tar.bz2 متکی هستند یا خیر.

گام بعدی شما

  • فایل‌های requirements.txt خود را بررسی کنید و تمام هش‌های MD5 را با SHA-256 جایگزین کنید.
  • اگر از توزیع‌های قدیمی .tar.bz2 استفاده می‌کنید، آن‌ها را به .tar.gz تبدیل کنید تا در نسخه‌های جدید با خطا مواجه نشوید.
  • ساختار پروژه‌های جدید خود را با uv init به‌روز کنید تا از استاندارد src/ بهره ببرید.

اما داستان سخت‌افزاری اجرای این ابزارها در مقیاس بزرگ، ابعاد پیچیده‌تری دارد — به تحلیل ما درباره‌ی بهینه‌سازی حافظه در محیط‌های توسعه مراجعه کنید.

چرا این موضوع مهم است؟

این تغییرات با تکیه بر استانداردهای PEP و حذف پروتکل‌های ناامن، ریسک حملات جایگزینی مفسر (Interpreter Overwrite) را به‌طور کامل حذف می‌کند. اعتبار این رویکرد از تطبیق دقیق با استانداردهای جهانی توزیع پایتون می‌آید که امنیت محیط‌های توسعه را تضمین می‌کند.

تأثیر برای ایران

برنامه‌نویسان ایرانی که از uv برای مدیریت محیط‌های ایزوله استفاده می‌کنند، باید هش‌های MD5 پروژه‌های قدیمی خود را به‌روز کنند تا با خطای توقف نصب مواجه نشوند.

·نگاه ما
تحریریه دات‌هوش

Astral با این به‌روزرسانی، استراتژی «سرعت به هر قیمت» را کنار گذاشت و به سمت «پایداری صنعتی» حرکت کرد. حذف فرمت‌های قدیمی و سخت‌گیری روی هش‌ها نشان می‌دهد که ابزار uv اکنون می‌خواهد جایگزین استاندارد برای محیط‌های سازمانی (Enterprise) شود، جایی که امنیت زنجیره تأمین بر سرعت نصب اولویت دارد. این یک چرخش از یک ابزار کاربردی برای توسعه‌دهندگان به یک زیرساخت امنیتی برای سازمان‌هاست.

منابع

این گزارش با خط‌لولهٔ خودکار دات‌هوش از منابع معتبر جهانی تدوین و زیر نظر تحریریه منتشر شده است. روش کار ما

گفتگو

پنج‌شنبه‌های هوش‌محور

بسته‌ی هفتگی دات‌هوش

۵ خبر، ۲ ابزار، ۱ پرامپت در هر شماره. به‌زودی راه‌اندازی می‌شود — هر پنج‌شنبه صبح.

خبر کلیدی
ابزار کاربردی
پرامپت حرفه‌ای
تحلیل پژوهش
به‌زودی
زاویه‌ی ایرانی
به‌زودی
تمرین این هفته
به‌زودی

راهنماهای دات‌هوش

راهنماهای کاربردیِ دات‌هوش برای کار با هوش مصنوعی — از همین‌جا شروع کنید:

دات‌هوش

راهنمای فارسی هوش مصنوعی — با نگاه به ایران

اخبار روزانه، معرفی ابزارها و مدل‌ها، و آموزشِ کار با هوش مصنوعی؛ همیشه با این پرسش که از ایران چه چیزی کار می‌کند و چه چیزی نه.