اگر شما یک توسعهدهنده پایتون هستید که سرعت را فدای امنیت نمیکنید، باید بدانید که محیطهای اجرای کد شما اکنون در برابر حملات پیشرفتهتر ایمن شدهاند. هدف اصلی نسخه 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/بهره ببرید.
اما داستان سختافزاری اجرای این ابزارها در مقیاس بزرگ، ابعاد پیچیدهتری دارد — به تحلیل ما دربارهی بهینهسازی حافظه در محیطهای توسعه مراجعه کنید.




گفتگو