مجوز گستردهتر از وظیفه است
دسترسی کامل به دیسک (FDA) در macOS یک مجوز واحد TCC (شفافیت، رضایت و کنترل) است که موانع خواندن سندباکس را در کل دایرکتوری خانه برمیدارد. در عمل، یک تأییدیه شامل مخزن Mail، دایرکتوریهای پروفایل Safari و Chrome، کیچین ورود، پایگاه داده Messages و هرگونه اعتبارنامه توسعهدهنده در ~/.aws، ~/.ssh یا ~/.config میشود. کاربر یک دیالوگ و یک کلید را میبیند. سیستم یک بیت را میبیند.
این بیت پایدار است. از راهاندازی مجدد جان سالم به در میبرد، برای هر فراخوانی آینده باینری امضاشده اعمال میشود و با نحوه راهاندازی فرآیند محدود نمیشود. ایجنتی که سهشنبه نیاز به خواندن یک پوشه پروژه داشت، جمعه همان مجوز را دارد وقتی از او خواسته میشود یک PDF از دایرکتوری دانلود را خلاصه کند.
بارهای کاری ایجنت رویدادمحور هستند. یک اجرا آغاز، برنامه، مجموعهای از فراخوانیهای ابزار و پایانی دارد. شکاف بین آنچه اجرا نیاز دارد و آنچه مجوز اجازه میدهد، سطح ریسک است و در macOS این شکاف در حال حاضر کل دایرکتوری خانه است.
چرا مدل برنامهای نمیگنجد
برنامههای کلاسیک macOS مجموعه ویژگیهای پایدار و قابل حسابرسی دارند. یک ویرایشگر عکس تصاویر را میخواند. یک کلاینت ایمیل مخزن ایمیل را میخواند. بازبینان میتوانند درباره مجوز استدلال کنند زیرا رفتار توسط هدف محصول محدود میشود.
مجموعه خواندن یک ایجنت در زمان اجرا توسط یک برنامهریز تعیین میشود. همان باینری، دو بار فراخوانی شده، میتواند در یک جلسه یک صفحهگسترده و در جلسه بعد یک فایل کیچین را بخواند، زیرا برنامه از پرامپت و محیط تولید میشود. هیچ مانیفست ایستایی وجود ندارد که توصیف کند فرآیند به چه چیزی دست خواهد زد.

این حالت شکست تزریق پرامپت را تغییر میدهد. در یک برنامه متعارف، تزریق ممکن است باعث خروجی بد شود. در ایجنتی که FDA دارد، تزریق یک مجوز مشروع را به مسیر استخراج داده تبدیل میکند بدون هیچ ارتقای سطح دسترسی: مدل از قبل مجاز به خواندن اعتبارنامههاست و ابزار شبکه از قبل مجاز به ارسال بایتهاست. مهاجم نیازی به شکستن سندباکس ندارد؛ او باید برنامه را هدایت کند.
در همین حال، از کاربر خواسته میشود درباره دیالوگی استدلال کند که میگوید «دسترسی به همه فایلها» در حالی که وظیفه «خلاصه کردن این پوشه» است. دیالوگ نمیتواند وظیفه را بیان کند زیرا سیستمعامل وظیفه را نمیداند. بنابراین رضایت به معنای خاصی که مهم است، آگاهانه نیست: به تصمیمی که کاربر واقعاً میگیرد محدود نمیشود. پوشش سختگیرانهتر شدن این کنترلها توسط اپل بر تجربه توسعهدهنده برنامه متمرکز بوده است (The Verge، TechCrunch)؛ مورد ایجنت از نظر ساختاری متفاوت است زیرا موجودیت درخواستکننده یک مجموعه ویژگی ثابت نیست.
جایگزینی در محدوده وظیفه
کنترل باید از یک مجوز دودویی سیستمعامل به یک قرارداد قابلیت در محدوده وظیفه منتقل شود. مجوز سیستمعامل به سقف تبدیل میشود؛ چارچوب ایجنت به نقطه اجرایی تبدیل میشود که آن را محدود میکند.
یک مکانیزم مشخص: صدور یک دسته محدود برای هر اجرا. دسته یک رکورد کوچک با چهار فیلد است.
- مسیرها. یک لیست مجاز صریح از دایرکتوریها یا فایلها، که در زمان برنامهریزی حل میشود، نه در زمان مجوز. سیملینکها حل میشوند و مسیر حلشده بررسی میشود.
- پنجره زمانی. یک انقضای زمان دیواری. پس از آن، دسته بیاثر است حتی اگر فرآیند هنوز زنده باشد.
- بودجه بایت. یک سقف خواندن تجمعی. وقتی بودجه تمام شود، خواندنهای بعدی بهصورت بسته شکست میخورند نه اینکه بیصدا کوتاه شوند.
- وضعیت پایانی. یک قاعده لغو در هنگام تکمیل. وقتی اجرا به وضعیت پایانی میرسد (موفقیت، شکست، تایماوت، لغو)، دسته نابود میشود و رکورد حسابرسی مهر و موم میشود.
handle = broker.issue(
paths=["~/work/reports/q3"],
ttl_seconds=600,
byte_budget=64 * led"],
)

# every read goes through the handle, not the filesystem
blob = handle.read("~/work/reports/q3/summary.md")
هر خواندن در مرز دسته ثبت میشود، که مسیر حسابرسی را بهازای هر وظیفه میکند نه هر باینری. وقتی چیزی اشتباه میشود، سؤال «این اجرا به چه چیزی دست زد» پاسخ مستقیمی دارد بهجای بازسازی از تلهمتری سطح فرآیند.
مبادله واقعی است و ارزش بیان صریح را دارد. یک کارگزار که خواندنها را واسطه میکند یک مؤلفه اضافه میکند که میتواند شکست بخورد، و بودجه بایتی که بیش از حد محدود باشد کارهای طولانی مشروع را متوقف میکند. بنابراین چارچوب باید بودجه را برای برنامهریز آشکار کند تا ایجنت بتواند قبل از برخورد با دیوار درخواست تمدید کند، نه اینکه محدودیت را بهعنوان استثنا در میانه اجرا کشف کند. این قطعات متحرک بیشتری از یک کلید TCC است، و هزینه معنادار کردن مجوز است.
این برای توسعهدهندگان ایجنت macOS چه معنایی دارد
برای دنیایی طراحی کنید که در آن مجوز گسترده discouraged است. انتخابگر سند، بوکمارکهای امنیتی محدود و مجوزهای هر دایرکتوری را به یک تأییدیه FDA ترجیح دهید. بوکمارکی که به یک پوشه اشاره میکند قابلیت محدودتری از خواندن کل دایرکتوری خانه است و میتواند در هر اجرا ذخیره و دوباره اعتبارسنجی شود.
فرض کنید مجوز در یک اعلان برای کاربر قابل مشاهده خواهد بود و آن اعلان را معنادار کنید. اگر سیستم نشان میدهد «این ایجنت پایگاه داده Messages شما را خواند»، ایجنت باید بتواند بگوید کدام وظیفه باعث آن شد و داده برای چه استفاده شد. اعلانی که کاربر نمیتواند روی آن اقدام کند، او را به نادیده گرفتن اعلانها عادت میدهد، که کنترل را برای هر برنامه دیگر تنزل میدهد.
برای لغو در میانه اجرا برنامهریزی کنید. یک دسته میتواند منقضی شود، یک بوکمارک میتواند کهنه شود، کاربر میتواند مجوز را در حین کار ایجنت خاموش کند. ایجنت باید قابل ازسرگیری باشد نه کشنده: برنامه را چکپوینت کنید، مرحلهای که قابلیت خود را از دست داد علامت بزنید و یا یک دسته جدید با محدوده محدودتر درخواست کنید یا با یک نتیجه جزئی بهصورت تمیز متوقف شوید. برخورد با لغو بهعنوان خرابی، یک کنترل امنیتی را به یک حادثه قابلیت اطمینان تبدیل میکند، که همین باعث غیرفعال شدن کنترلها میشود.
نکته گستردهتر این است که واحد اعتماد باید با واحد کار مطابقت داشته باشد. یک اجرای ایجنت واحد کار است. طول عمر یک باینری نیست. تا زمانی که مدل مجوز این را منعکس نکند، هر ایجنت در macOS تنها یک تزریق پرامپت از خواندن بیش از آنچه وظیفهاش نیاز داشت فاصله دارد.
