Валидация вложенного пути в файловой системе

Условие сравнивает дочерний путь с родителями исходного пути, то есть проверка направлена неверно. Для /home/user/app/ и dir1/dir2 оно истинно и возбуждает PermissionDenied, хотя путь находится внутри.

Короткий ответ

Что ответить на собеседовании

Условие сравнивает дочерний путь с родителями исходного пути, то есть проверка направлена неверно. Для /home/user/app/ и dir1/dir2 оно истинно и возбуждает PermissionDenied, хотя путь находится внутри.

Подробный разбор

Ответ с пояснениями

Условие

Опишите, какую именно проверку осуществляет условный оператор и при каких значениях переменных условие будет истинным.

# model.path: pathlib.Path
# model.path = pathlib.Path("/home/user/app/")
# PERMITTED_SUBPATH = "dir1/dir2"

if model.path / PERMITTED_SUBPATH not in model.path.parents:
    raise django.core.exceptions.PermissionDenied()

Ответ

Условие сравнивает дочерний путь с родителями исходного пути, то есть проверка направлена неверно. Для /home/user/app/ и dir1/dir2 оно истинно и возбуждает PermissionDenied, хотя путь находится внутри.

model.path.parents содержит /home/user, /home и /, но не /home/user/app/dir1/dir2. Для проверки вложенности сначала нормализуйте обе стороны:

base = model.path.resolve()
candidate = (base / PERMITTED_SUBPATH).resolve()
if not candidate.is_relative_to(base):
    raise PermissionDenied()

Нужно импортировать PermissionDenied из django.core.exceptions. is_relative_to допускает равенство base; при необходимости запретите его отдельно. resolve учитывает symlinks, но не устраняет гонку их изменения между проверкой и открытием; для недоверенной файловой системы нужны безопасные операции относительно дескриптора каталога.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее