งูต้นฉบับใช้กรอบวัดตรวจเส้นทางโฟลเดอร์ครบจากต้นถึงไฟล์ โดยทางลัดหนึ่งเส้นถูกกั้นไว้

Python pathlib.full_match: ตรวจ Path ทั้งเส้นโดยไม่เผลอรับไฟล์นอกกฎ

พี่โชว์Engineering

การ validate path ด้วย substring หรือ suffix อย่างเดียวมักรับเส้นทางเกินกฎ PurePath.full_match ตรวจ glob pattern กับ path ทั้งเส้น เหมาะกับ allowlist ที่ต้องการพูดว่า “ไฟล์ Python ใต้ src เท่านั้น” ครับ

ต่างจาก match ที่รองรับการจับจากด้านขวาในบางรูปแบบ full_match ต้องให้ pattern ครอบ path ทั้งหมด และเพราะใช้ PurePath ตัวอย่างนี้ไม่อ่าน filesystem จึงทดสอบกฎได้อย่าง deterministic

from __future__ import annotations

import unittest
from pathlib import PurePosixPath


def is_source_file(raw: str) -> bool:
    path = PurePosixPath(raw)
    return path.full_match("src/**/*.py") and ".." not in path.parts


class FullMatchTests(unittest.TestCase):
    def test_accepts_nested_python_source(self):
        self.assertTrue(is_source_file("src/app/main.py"))

    def test_rejects_other_roots_and_suffixes(self):
        self.assertFalse(is_source_file("tests/app/main.py"))
        self.assertFalse(is_source_file("src/app/main.py.bak"))

    def test_rejects_parent_traversal(self):
        self.assertFalse(is_source_file("src/../secrets/key.py"))


if __name__ == "__main__":
    unittest.main()

glob matching ไม่ใช่ security sandbox: มันไม่ resolve symlink และไม่ได้พิสูจน์ว่า path จริงอยู่ใต้ root สำหรับ input ที่จะใช้เปิดไฟล์ ต้อง resolve กับ base directory แล้วตรวจ containment อีกชั้น รวมถึงกำหนด flavor ให้ตรงระบบ (PurePosixPath หรือ PureWindowsPath)

Recap

  • ใช้ full_match เมื่อ policy ต้องครอบ path ทั้งเส้น
  • ทดสอบ root ผิด, suffix หลอก และ ..
  • เลือก path flavor ให้ตรงรูปแบบ input
  • resolve และตรวจ containment ก่อนเปิดไฟล์ที่ไม่เชื่อถือ