تخطَّ إلى المحتوى

os.Root

وصول لنظام الملفات محصور بمجلّد os.Root

os.Root يمنح وصولًا لنظام الملفات محصورًا داخل شجرة مجلّد واحد فقط — أي مسار يحاول الهروب منها، حتى عبر رابط رمزي symlink، يفشل بخطأ بدل الوصول لملف خارج الحدود المقصودة.

os.OpenRoot(dir) تفتح جذرًا جديدًا من النوع *Root، بتوابع تشبه حزمة os المعتادة (Open، Create، Mkdir، ReadFile، WriteFile، Stat...) لكن كل مسار يُحسَب نسبيًا من الجذر ومحصور بداخله. بعكس os.DirFS التي لا تمنع الهروب عبر رابط رمزي symlink يشير خارج الشجرة، os.Root يرفض فعليًا أي عملية تحاول تجاوز الحدود — مفيد جدًا عند التعامل مع مسارات قادمة من مستخدم غير موثوق (اسم ملف مرفوع، إدخال بنموذج).

أُضيفت بـ Go 1.24 استجابة مباشرة لثغرات تجاوز المسار (path traversal) الشائعة في تطبيقات تتعامل مع ملفات المستخدمين.

الصياغة

func OpenRoot(name string) (*Root, error)
func (r *Root) Open(name string) (*File, error)
func (r *Root) FS() fs.FS

📄 مثال

root, err := os.OpenRoot("./uploads")
if err != nil {
  log.Fatal(err)
}
defer root.Close()

data, err := root.ReadFile(userSuppliedName)   // لا يمكنه الهروب من ./uploads مهما كان المسار
if err != nil {
  log.Fatal(err)
}

أهم النقاط

العنصرالوظيفة
os.OpenRoot(dir)يفتح جذرًا جديدًا محصورًا بمجلّد dir، يجب إغلاقه بـ Close (غالبًا عبر defer)
root.ReadFile(name)يقرأ ملفًا داخل الجذر فقط — مسار يحاول الخروج، حتى عبر symlink، يعيد خطأ
root.FS()يحوّل الجذر لواجهة fs.FS عادية، بنفس الحماية من الهروب

💡 نصائح عملية

  • استخدم os.Root دائمًا عند التعامل مع مسارات قادمة من مستخدم (اسم ملف مرفوع، إدخال بنموذج ويب) بدل os.Open المباشر
  • أغلق الجذر بـ defer root.Close() فور فتحه، تمامًا كملف عادي

⚠️ أخطاء شائعة

  • الاعتماد على فحص يدوي للمسار (منع "..") ظنًّا أنه كافٍ لمنع الهروب — الروابط الرمزية symlink قد تتجاوز هذا الفحص، وos.Root وحده يمنعها فعليًا
  • استخدام os.DirFS ظنًّا أنه يوفّر نفس الحماية — DirFS لا يمنع الهروب عبر symlink بعكس os.Root

خصائص ذات صلة

🎓 تريد فهم الصورة الكاملة خطوة بخطوة؟ ابدأ من مسار GO الكامل بالعربي.