Функция f()
использует eval()
(или что-то столь же опасное) с данными, которые я создал и сохранил local_file
на компьютере, на котором запущена моя программа:
import local_file
def f(str_to_eval):
# code....
# ....
eval(str_to_eval)
# ....
# ....
return None
a = f(local_file.some_str)
f()
безопасен для запуска, так как строки, которые я ему предоставляю, мои.
Однако, если я когда-нибудь решу использовать его для чего-то небезопасного (например, пользовательского ввода), все может пойти ужасно неправильно . Кроме того, если local_file
перестанет быть локальным, это создаст уязвимость, так как мне нужно будет доверять машине, которая также предоставляет этот файл.
Как я должен убедиться, что я никогда не «забуду», что эта функция небезопасна в использовании (если не соблюдены определенные критерии)?
Примечание: eval()
опасно и обычно может быть заменено чем-то безопасным.
python
vulnerabilities
Парадокс ферми
источник
источник
Ответы:
Определите тип для украшения «безопасных» входов. В вашей функции
f()
утверждайте, что аргумент имеет этот тип, или выведите ошибку. Будьте достаточно умны, чтобы никогда не определять ярлыкdef g(x): return f(SafeInput(x))
.Пример:
Несмотря на то, что это легко обойти, это усложняет случайность. Люди могут критиковать такую драконовскую проверку типа, но они упустят момент. Поскольку
SafeInput
тип - это просто тип данных, а не объектно-ориентированный класс, который можно разделить на подклассы, проверка на идентичность типа сtype(x) is SafeInput
более безопасна, чем проверка на совместимость с типомisinstance(x, SafeInput)
. Так как мы хотим применить определенный тип, игнорирование явного типа и просто неявная типизация утки здесь также не являются удовлетворительными. В Python есть система типов, поэтому давайте использовать ее для выявления возможных ошибок!источник
assert
удаляется автоматически, так как я буду использовать оптимизированный код Python. Нечто подобноеif ... : raise NotSafeInputError
будет необходимо.eval()
метод вSafeInput
, чтобы вам не требовалась явная проверка типов. Дайте методу имя, которое не используется ни в одном из ваших других классов. Таким образом, вы все равно можете высмеять все это для целей тестирования.eval
есть доступ к локальным переменным, возможно, код зависит от того, как он изменяет переменные. Перемещая eval в другой метод, он больше не сможет изменять локальные переменные.SafeInput
конструктор получит имя / дескриптор локального файла и выполнит само чтение, гарантируя, что данные действительно поступают из локального файла.Как однажды заметил Джоэл, заставьте неправильный код выглядеть неправильно (прокрутите вниз до раздела «Реальное решение», или, что еще лучше, прочитайте его полностью; оно того стоит, даже если оно обращается к переменной вместо имен функций). Поэтому я скромно предлагаю переименовать вашу функцию в нечто вроде
f_unsafe_for_external_use()
- вы, скорее всего, сами придумаете какую-нибудь схему аббревиатур.Редактировать: я думаю, что предложение Амона является очень хорошим, основанным на ОО вариантом на ту же тему :-)
источник
В дополнение к предложению @amon, вы также можете подумать о комбинировании здесь шаблона стратегии и шаблона объекта метода.
И тогда «нормальная» реализация
И реализация admin-input-eval
(Примечание: на примере реального мира я мог бы привести лучший пример).
источник